@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
@@ -1,6 +1,6 @@
1
- import { J as MergedRelyIOConfig, A as ApiPath, a as ApiMethod, K as PathParamsOf, t as ApiResponse, W as Wire, s as RequestConfig, B as BaseContent, d as WhereClause, f as SortOptions, g as ContentQueryResult, Q as QueryOptions, C as CreateInput, U as UpdateInput, S as SDKError, x as BaseValidationError, w as ValidationViolation, N as components, O as paths, R as RelyIOConfig } from './index-C5mRBb6t.cjs';
2
- import { a as SchemaDefinition, b as SchemaContentTypeNames, h as SchemaAssetTypeNames, M as InferAssetType, c as SchemaSingletonNames, t as InferSingleton, g as SchemaSettingsGroupNames, E as InferSettingsGroup, e as SchemaQueryNames, f as SchemaLocaleCodes } from './define-schema-2xbHgtK-.cjs';
3
- import { J as InferContentType } from './define-content-type-CBfnTWSS.cjs';
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-d1Kz1e19.cjs';
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-1kr2HIzN.cjs';
3
+ import { Q as InferContentType, a6 as InferAssetType, a0 as InferSingleton } from './define-content-type-CDB3kyeA.cjs';
4
4
  import { DevUnreadableReason } from './dev-handshake/index.cjs';
5
5
 
6
6
  /**
@@ -130,6 +130,12 @@ declare class HttpClient {
130
130
  * The loop always makes one attempt. The incumbent's `while (attempt <
131
131
  * maxAttempts)` made none at `retryAttempts: 0` — a value the config validator
132
132
  * accepts — and then dereferenced an unassigned `lastError`.
133
+ *
134
+ * A request that would carry no `X-API-Key` makes none: it rejects with
135
+ * `MissingApiKeyError` before `fetch` is called, is not retried, and names
136
+ * `apiKey`. This is where a client built without a key learns it — the
137
+ * constructor accepts one so that a module-scope client can be evaluated by a
138
+ * build that holds no key (REL-1120).
133
139
  */
134
140
  request<T = unknown>(config: RequestConfig): Promise<ApiResponse<T>>;
135
141
  /**
@@ -196,8 +202,6 @@ declare class HttpClient {
196
202
  private mergeRequestConfig;
197
203
  private buildQueryString;
198
204
  private headersToObject;
199
- /** A backoff the caller's abort cuts short; the next attempt then refuses to send. */
200
- private sleep;
201
205
  private log;
202
206
  }
203
207
 
@@ -252,7 +256,14 @@ declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
252
256
  private childrenOptions?;
253
257
  private pageNumber?;
254
258
  private pageSizeValue?;
259
+ private requestHeaders?;
255
260
  constructor(httpClient: HttpClient, contentType: string, defaultLocale?: string | undefined);
261
+ /**
262
+ * Headers this query adds to the client's own, e.g. `X-RelyIO-Dataset` to list another dataset
263
+ * the key can see. A name the client already sends is replaced for this query only; the client
264
+ * is not changed.
265
+ */
266
+ headers(headers: Record<string, string>): this;
256
267
  /**
257
268
  * Add where conditions to the query
258
269
  */
@@ -454,6 +465,7 @@ declare class ContentByIdBuilder<T extends BaseContent = BaseContent> {
454
465
  private localesArray?;
455
466
  private fetchAllLocales;
456
467
  private childrenOptions?;
468
+ private requestHeaders?;
457
469
  constructor(httpClient: HttpClient, contentType: string, id: string, defaultLocale?: string | undefined);
458
470
  /**
459
471
  * Include related content in the response
@@ -471,6 +483,12 @@ declare class ContentByIdBuilder<T extends BaseContent = BaseContent> {
471
483
  * @param localeCodes - Array of locale codes to fetch
472
484
  */
473
485
  locales(localeCodes: string[]): this;
486
+ /**
487
+ * Headers this one read adds to the client's own, e.g. `X-RelyIO-Dataset` to read another dataset
488
+ * the key can see. A name the client already sends is replaced for this request only; the client
489
+ * is not changed.
490
+ */
491
+ headers(headers: Record<string, string>): this;
474
492
  /**
475
493
  * Fetch content in all available locales
476
494
  * Returns default locale at top level, others in _metadata.localizations
@@ -619,11 +637,13 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
619
637
  /**
620
638
  * Fetch a single content item by ID
621
639
  * @param id - Entry ID or slug
622
- * @param options - Fetch options (include, locale)
640
+ * @param options - Fetch options (include, locale, and `headers` this one request adds — e.g.
641
+ * `{ 'X-RelyIO-Dataset': 'staging' }` to read a dataset other than the client's)
623
642
  */
624
643
  fetchOne(id: string, options?: {
625
644
  include?: string[];
626
645
  locale?: string;
646
+ headers?: Record<string, string>;
627
647
  }): Promise<T | null>;
628
648
  /**
629
649
  * Fetch one entry **and the entity tag that read served**.
@@ -637,10 +657,16 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
637
657
  * `entityTag` is `undefined` when the response came from the cache: a cached
638
658
  * body cannot know the current version, and an absent tag beats a stale one
639
659
  * that would refuse the next write.
660
+ *
661
+ * Unlike {@link fetchOne}, a missing entry is not `null`: the service's
662
+ * `RESOURCE_NOT_FOUND` is thrown as it arrived, with the `kind` that says
663
+ * whether the entry, the content type or the schema was missing. `headers`
664
+ * are the ones this read adds, as for `fetchOne`.
640
665
  */
641
666
  fetchOneWithTag(id: string, options?: {
642
667
  include?: string[];
643
668
  locale?: string;
669
+ headers?: Record<string, string>;
644
670
  }): Promise<{
645
671
  entry: T;
646
672
  entityTag?: string;
@@ -654,25 +680,32 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
654
680
  /**
655
681
  * Create a new content item
656
682
  * @param data - Content data
657
- * @param options - Create options (slug, locale, parentId, sortOrder)
683
+ * @param options - Create options (slug, locale, parentId, sortOrder), and `headers` this one
684
+ * request adds — e.g. `{ 'X-RelyIO-Dataset': 'staging' }` to write a dataset other than the
685
+ * client's. They are sent, never put in the body; `idempotencyKey` still wins over an
686
+ * `Idempotency-Key` among them.
658
687
  */
659
688
  create(data: CreateInput<T>, options?: {
660
689
  slug?: string;
661
690
  locale?: string;
662
691
  parentId?: string;
663
692
  sortOrder?: number;
693
+ headers?: Record<string, string>;
664
694
  } & RetryableWriteOptions): Promise<T>;
665
695
  /**
666
696
  * Update a content item by ID (partial update)
667
697
  * @param id - Entry ID
668
698
  * @param data - Fields to update
669
- * @param options - Update options (slug, locale, parentId, sortOrder)
699
+ * @param options - Update options (slug, locale, parentId, sortOrder), and `headers` this one
700
+ * request adds, as for {@link create}. `ifMatch` and `idempotencyKey` win over the same
701
+ * header among them.
670
702
  */
671
703
  update(id: string, data: UpdateInput<T>, options?: {
672
704
  slug?: string;
673
705
  locale?: string;
674
706
  parentId?: string;
675
707
  sortOrder?: number;
708
+ headers?: Record<string, string>;
676
709
  } & ConditionalWriteOptions): Promise<T>;
677
710
  /**
678
711
  * Delete a content item by ID
@@ -1230,6 +1263,9 @@ interface SingletonFetchOptions {
1230
1263
  * Singleton client for managing singleton content operations
1231
1264
  * Provides a fluent API for singleton operations following the same pattern as ContentClient
1232
1265
  *
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.
1268
+ *
1233
1269
  * @example
1234
1270
  * ```typescript
1235
1271
  * const homepage = await client.singleton('homepage')
@@ -1241,9 +1277,10 @@ interface SingletonFetchOptions {
1241
1277
  declare class SingletonClient<T = unknown> {
1242
1278
  private httpClient;
1243
1279
  private singletonKey;
1280
+ private readonly defaultLocale?;
1244
1281
  private includeFields?;
1245
1282
  private localeValue?;
1246
- constructor(httpClient: HttpClient, singletonKey: string);
1283
+ constructor(httpClient: HttpClient, singletonKey: string, defaultLocale?: string | undefined);
1247
1284
  /**
1248
1285
  * Include reference fields in the response
1249
1286
  * @param fields - Reference field names to populate
@@ -1328,6 +1365,9 @@ interface SettingsFetchOptions {
1328
1365
  * Settings client for managing settings group operations
1329
1366
  * Provides a fluent API for settings operations following the same pattern as ContentClient
1330
1367
  *
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.
1370
+ *
1331
1371
  * @example
1332
1372
  * ```typescript
1333
1373
  * const emailConfig = await client.settings('email-config')
@@ -1339,9 +1379,10 @@ interface SettingsFetchOptions {
1339
1379
  declare class SettingsClient<T = unknown> {
1340
1380
  private readonly httpClient;
1341
1381
  private readonly groupId;
1382
+ private readonly defaultLocale?;
1342
1383
  private includeFields?;
1343
1384
  private localeValue?;
1344
- constructor(httpClient: HttpClient, groupId: string);
1385
+ constructor(httpClient: HttpClient, groupId: string, defaultLocale?: string | undefined);
1345
1386
  /**
1346
1387
  * Include reference fields in the response
1347
1388
  * @param fields - Reference field names to populate
@@ -1418,6 +1459,41 @@ declare class SettingsClient<T = unknown> {
1418
1459
  resetOptions(): this;
1419
1460
  }
1420
1461
 
1462
+ /**
1463
+ * Any schema the client can be typed by. `any` is deliberate: the client accepts whatever content
1464
+ * types, components, singletons, queries and settings groups a customer declares.
1465
+ *
1466
+ * This is the constraint `TypedRelyIOClient`'s `TSchema` carries, so `RegisteredSchema` is inferred
1467
+ * against the same one — `createClient` returns `TypedRelyIOClient<RegisteredSchema>`, and a schema
1468
+ * inferred against any wider alias would not be provably inside the client's bound.
1469
+ */
1470
+ type AnySchemaDefinition = SchemaDefinition<any, any, any, any, any>;
1471
+ /**
1472
+ * The seam `relyio generate-types` fills (`INV-SS-TYPES-INFERRED`).
1473
+ *
1474
+ * Empty here on purpose. The generated `schema.ts` augments it —
1475
+ *
1476
+ * ```ts
1477
+ * declare module '@relyio/sdk' {
1478
+ * interface Register {
1479
+ * schema: typeof schema
1480
+ * }
1481
+ * }
1482
+ * ```
1483
+ *
1484
+ * — and from then on `createClient({ apiKey })`, with no generic and no `schema:`, is typed by that
1485
+ * schema. The pattern is TanStack Router's. It is type-level only: nothing at runtime reads it.
1486
+ */
1487
+ interface Register {
1488
+ }
1489
+ /**
1490
+ * The schema the project registered through `Register`, or `undefined` when nothing did — which is
1491
+ * the untyped client, exactly as before the generator ran.
1492
+ */
1493
+ type RegisteredSchema = Register extends {
1494
+ schema: infer S extends AnySchemaDefinition;
1495
+ } ? S : undefined;
1496
+
1421
1497
  /**
1422
1498
  * Search mode for content queries
1423
1499
  */
@@ -1493,12 +1569,31 @@ type SimilarResponse<T = unknown> = Wire<'/v1/search/similar', 'post', SimilarRe
1493
1569
  * Filter conditions for search
1494
1570
  */
1495
1571
  type SearchFilter = Record<string, unknown>;
1572
+ /**
1573
+ * The content type names a search may be scoped to: the schema's where one types the client, any
1574
+ * name where none does.
1575
+ */
1576
+ type SearchTypeName<S extends AnySchemaDefinition | undefined> = S extends AnySchemaDefinition ? SchemaContentTypeNames<S> : string;
1577
+ /**
1578
+ * What a search over the content types `K` returns: their entries, typed by the schema
1579
+ * (`INV-SS-TYPES-INFERRED`) — or `T` unchanged where no schema types the client.
1580
+ */
1581
+ type SearchEntry<S extends AnySchemaDefinition | undefined, K extends SearchTypeName<S> = SearchTypeName<S>, T extends BaseContent = BaseContent> = S extends AnySchemaDefinition ? SchemaEntryOf<S, K & SchemaContentTypeNames<S>> : T;
1496
1582
  /**
1497
1583
  * Field projection for search results
1498
1584
  */
1499
1585
  type SearchFields<T> = {
1500
1586
  [K: string]: keyof T | string;
1501
1587
  };
1588
+ /**
1589
+ * One ordering of `POST /v1/search`'s results, as the route's `sort` array takes it.
1590
+ */
1591
+ interface SearchSort {
1592
+ /** Field path, or `_score` for relevance */
1593
+ field: string;
1594
+ /** Direction; the route's default is `desc` */
1595
+ direction: 'asc' | 'desc';
1596
+ }
1502
1597
  /**
1503
1598
  * Fluent builder for search queries
1504
1599
  *
@@ -1513,21 +1608,33 @@ type SearchFields<T> = {
1513
1608
  * .execute()
1514
1609
  * ```
1515
1610
  */
1516
- declare class SearchBuilder<T extends BaseContent = BaseContent> {
1611
+ declare class SearchBuilder<T extends BaseContent = BaseContent, S extends AnySchemaDefinition | undefined = undefined> {
1517
1612
  private readonly httpClient;
1613
+ private readonly defaultLocale?;
1518
1614
  private query;
1519
1615
  private searchOptions;
1520
- constructor(httpClient: HttpClient, query: string);
1616
+ private requestHeaders?;
1617
+ /**
1618
+ * @param defaultLocale - The client's locale (`withLocale()`), sent when `.locale()` names none
1619
+ */
1620
+ constructor(httpClient: HttpClient, query: string, defaultLocale?: string | undefined);
1521
1621
  /**
1522
- * Search within a single content type
1622
+ * Headers this search adds to the client's own, e.g. `X-RelyIO-Dataset` to search another
1623
+ * dataset the key can see. A name the client already sends is replaced for this search only.
1624
+ */
1625
+ headers(headers: Record<string, string>): this;
1626
+ /**
1627
+ * Search within a single content type. Where a schema types the client, the name is one of its
1628
+ * content types and the results are that type's entries.
1523
1629
  * @param contentType - Content type to search in
1524
1630
  */
1525
- in<K extends string>(contentType: K): SearchBuilder<T>;
1631
+ in<K extends SearchTypeName<S>>(contentType: K): SearchBuilder<SearchEntry<S, K, T>, S>;
1526
1632
  /**
1527
- * Search across multiple content types
1633
+ * Search across multiple content types. Where a schema types the client, the names are its content
1634
+ * types and the results are a union of their entries — every type's, for `'*'`.
1528
1635
  * @param contentTypes - Array of content types or '*' for all
1529
1636
  */
1530
- across(contentTypes: string[] | '*'): SearchBuilder<T>;
1637
+ across<K extends SearchTypeName<S>>(contentTypes: K[] | '*'): SearchBuilder<SearchEntry<S, K, T>, S>;
1531
1638
  /**
1532
1639
  * Add filter conditions
1533
1640
  * @param conditions - Filter conditions
@@ -1543,6 +1650,13 @@ declare class SearchBuilder<T extends BaseContent = BaseContent> {
1543
1650
  * @param projection - Field mapping
1544
1651
  */
1545
1652
  fields(projection: Record<string, string>): this;
1653
+ /**
1654
+ * Order the results by a field instead of by relevance. Called again, it adds a tie-breaker.
1655
+ * `_score` names relevance itself.
1656
+ * @param field - Field path to sort by (e.g. `updatedAt`, `pricing.basePrice`)
1657
+ * @param direction - `asc` or `desc` (the route's default is `desc`)
1658
+ */
1659
+ sort(field: string, direction?: 'asc' | 'desc'): this;
1546
1660
  /**
1547
1661
  * Limit number of results
1548
1662
  * @param count - Maximum results
@@ -1594,9 +1708,13 @@ declare class SearchBuilder<T extends BaseContent = BaseContent> {
1594
1708
  */
1595
1709
  declare class AutocompleteBuilder {
1596
1710
  private readonly httpClient;
1711
+ private readonly defaultLocale?;
1597
1712
  private query;
1598
1713
  private autocompleteOptions;
1599
- constructor(httpClient: HttpClient, query: string);
1714
+ /**
1715
+ * @param defaultLocale - The client's locale (`withLocale()`), sent when `.locale()` names none
1716
+ */
1717
+ constructor(httpClient: HttpClient, query: string, defaultLocale?: string | undefined);
1600
1718
  /**
1601
1719
  * Autocomplete within a content type
1602
1720
  * @param contentType - Content type to search
@@ -1649,14 +1767,29 @@ declare class AutocompleteBuilder {
1649
1767
  */
1650
1768
  declare class SimilarBuilder<T extends BaseContent = BaseContent> {
1651
1769
  private readonly httpClient;
1770
+ private readonly defaultLocale?;
1652
1771
  private sourceId;
1653
1772
  private similarOptions;
1654
- constructor(httpClient: HttpClient, sourceId: string);
1773
+ private requestHeaders?;
1774
+ /**
1775
+ * @param defaultLocale - The client's locale (`withLocale()`), sent when `.locale()` names none
1776
+ */
1777
+ constructor(httpClient: HttpClient, sourceId: string, defaultLocale?: string | undefined);
1778
+ /**
1779
+ * Headers this read adds to the client's own, e.g. `X-RelyIO-Dataset` to read another dataset
1780
+ * the key can see. A name the client already sends is replaced for this read only.
1781
+ */
1782
+ headers(headers: Record<string, string>): this;
1655
1783
  /**
1656
1784
  * Find similar content within a content type
1657
1785
  * @param contentType - Content type to search
1658
1786
  */
1659
1787
  in(contentType: string): this;
1788
+ /**
1789
+ * Find similar content across several content types, or `'*'` for every type
1790
+ * @param contentTypes - Array of content types or '*' for all
1791
+ */
1792
+ across(contentTypes: string[] | '*'): this;
1660
1793
  /**
1661
1794
  * Add filter conditions
1662
1795
  * @param conditions - Filter conditions
@@ -1712,12 +1845,17 @@ declare class SimilarBuilder<T extends BaseContent = BaseContent> {
1712
1845
  */
1713
1846
  declare class SearchClient {
1714
1847
  private readonly httpClient;
1715
- constructor(httpClient: HttpClient);
1848
+ private readonly defaultLocale?;
1849
+ /**
1850
+ * @param defaultLocale - The client's locale (`withLocale()`): every builder here sends it when
1851
+ * the query names none, as `content()`'s reads do
1852
+ */
1853
+ constructor(httpClient: HttpClient, defaultLocale?: string | undefined);
1716
1854
  /**
1717
1855
  * Start a search query
1718
1856
  * @param query - Search query string
1719
1857
  */
1720
- search<T extends BaseContent = BaseContent>(query: string): SearchBuilder<T>;
1858
+ search<T extends BaseContent = BaseContent, S extends AnySchemaDefinition | undefined = undefined>(query: string): SearchBuilder<T, S>;
1721
1859
  /**
1722
1860
  * Start an autocomplete query
1723
1861
  * @param query - Partial query to autocomplete
@@ -1836,6 +1974,7 @@ declare class BatchBuilder<TSchema = unknown> {
1836
1974
  private readonly httpClient;
1837
1975
  private operations;
1838
1976
  private defaultOptions;
1977
+ private requestHeaders;
1839
1978
  constructor(httpClient: HttpClient);
1840
1979
  /**
1841
1980
  * Add a create operation
@@ -1973,6 +2112,12 @@ declare class BatchBuilder<TSchema = unknown> {
1973
2112
  * Stop on first error (non-atomic mode)
1974
2113
  */
1975
2114
  stopOnError(): this;
2115
+ /**
2116
+ * Headers the batch request adds — e.g. `{ 'X-RelyIO-Dataset': 'staging' }` to write a dataset
2117
+ * other than the client's. They replace the client's own header of the same name for this
2118
+ * request alone, and apply to every operation in it: a batch is one request.
2119
+ */
2120
+ headers(headers: Record<string, string>): this;
1976
2121
  /**
1977
2122
  * Get the current list of operations
1978
2123
  */
@@ -2093,20 +2238,26 @@ interface FetchBlock {
2093
2238
  interface AggregateBlock {
2094
2239
  /** Source content type or query reference */
2095
2240
  source: string;
2241
+ /**
2242
+ * Filter conditions applied before grouping, in the Query DSL's spelling — bare operator names
2243
+ * (`{ price: { gte: 10 } }`), not the list route's `$gte`. A `$`-prefixed key is not an operator
2244
+ * in this dialect: the service reads the object as a nested field and drops it.
2245
+ */
2246
+ where?: Record<string, unknown>;
2096
2247
  /** Field to group by */
2097
2248
  by?: string | string[];
2098
- /** Metrics to compute */
2249
+ /** Metrics to compute, keyed by the name each one answers under */
2099
2250
  metrics: Record<string, AggregateMetric>;
2100
2251
  }
2101
2252
  /**
2102
- * Aggregate metric definition
2253
+ * 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.
2256
+ *
2257
+ * It used to be `{ fn, field? }`, a shape the service refuses on every request: the validator
2258
+ * tests the metric as a string, so an object arrives as `[object Object]`.
2103
2259
  */
2104
- interface AggregateMetric {
2105
- /** Aggregation function */
2106
- fn: 'count' | 'sum' | 'avg' | 'min' | 'max' | 'first' | 'last';
2107
- /** Field to aggregate (optional for count) */
2108
- field?: string;
2109
- }
2260
+ type AggregateMetric = `${string}.${'count' | 'sum' | 'avg' | 'min' | 'max'}`;
2110
2261
  /**
2111
2262
  * Search block for full-text/semantic search
2112
2263
  */
@@ -2265,10 +2416,15 @@ interface AdhocQueryResult<T = unknown> {
2265
2416
  */
2266
2417
  declare class AdhocQueryBuilder<T = unknown> {
2267
2418
  private readonly httpClient;
2419
+ private readonly defaultLocale?;
2268
2420
  private queryDef;
2269
2421
  private parameters;
2270
2422
  private options;
2271
- constructor(httpClient: HttpClient);
2423
+ /**
2424
+ * @param defaultLocale - The client's locale (`withLocale()`), sent as the `locale` parameter
2425
+ * when `.param('locale', …)` binds none
2426
+ */
2427
+ constructor(httpClient: HttpClient, defaultLocale?: string | undefined);
2272
2428
  /**
2273
2429
  * Add a fetch block to retrieve content
2274
2430
  * @param config - Fetch configuration
@@ -2427,7 +2583,12 @@ declare class AdhocQueryBuilder<T = unknown> {
2427
2583
  */
2428
2584
  declare class AdhocQueryClient {
2429
2585
  private readonly httpClient;
2430
- constructor(httpClient: HttpClient);
2586
+ private readonly defaultLocale?;
2587
+ /**
2588
+ * @param defaultLocale - The client's locale (`withLocale()`), sent as the `locale` parameter of
2589
+ * every query that binds none
2590
+ */
2591
+ constructor(httpClient: HttpClient, defaultLocale?: string | undefined);
2431
2592
  /**
2432
2593
  * Create a new query builder
2433
2594
  */
@@ -2437,8 +2598,13 @@ declare class AdhocQueryClient {
2437
2598
  * @param definition - Query definition
2438
2599
  * @param parameters - Parameter values
2439
2600
  * @param options - Execution options
2601
+ * @param request - `headers` this one request adds to the client's own, e.g. `X-RelyIO-Dataset`
2602
+ * to query another dataset the key can see. A name the client already sends is replaced for
2603
+ * this request only.
2440
2604
  */
2441
- execute<T = unknown>(definition: AdhocQueryDefinition, parameters?: Record<string, unknown>, options?: AdhocQueryOptions): Promise<AdhocQueryResult<T>>;
2605
+ execute<T = unknown>(definition: AdhocQueryDefinition, parameters?: Record<string, unknown>, options?: AdhocQueryOptions, request?: {
2606
+ headers?: Record<string, string>;
2607
+ }): Promise<AdhocQueryResult<T>>;
2442
2608
  /**
2443
2609
  * Quick fetch helper
2444
2610
  * @param contentType - Content type
@@ -2584,41 +2750,10 @@ interface ChangesOptions {
2584
2750
  */
2585
2751
  onExpired?: 'throw' | 'resync' | ((expired: ChangesExpiredError) => void | Promise<void>);
2586
2752
  }
2587
-
2588
- /**
2589
- * Any schema the client can be typed by. `any` is deliberate: the client accepts whatever content
2590
- * types, components, singletons, queries and settings groups a customer declares.
2591
- *
2592
- * This is the constraint `TypedRelyIOClient`'s `TSchema` carries, so `RegisteredSchema` is inferred
2593
- * against the same one — `createClient` returns `TypedRelyIOClient<RegisteredSchema>`, and a schema
2594
- * inferred against any wider alias would not be provably inside the client's bound.
2595
- */
2596
- type AnySchemaDefinition = SchemaDefinition<any, any, any, any, any>;
2597
- /**
2598
- * The seam `relyio generate-types` fills (`INV-SS-TYPES-INFERRED`).
2599
- *
2600
- * Empty here on purpose. The generated `schema.ts` augments it —
2601
- *
2602
- * ```ts
2603
- * declare module '@relyio/sdk' {
2604
- * interface Register {
2605
- * schema: typeof schema
2606
- * }
2607
- * }
2608
- * ```
2609
- *
2610
- * — and from then on `createClient({ apiKey })`, with no generic and no `schema:`, is typed by that
2611
- * schema. The pattern is TanStack Router's. It is type-level only: nothing at runtime reads it.
2612
- */
2613
- interface Register {
2753
+ interface ChangesHeadOptions {
2754
+ /** Cancels the request; the promise then rejects. */
2755
+ signal?: AbortSignal;
2614
2756
  }
2615
- /**
2616
- * The schema the project registered through `Register`, or `undefined` when nothing did — which is
2617
- * the untyped client, exactly as before the generator ran.
2618
- */
2619
- type RegisteredSchema = Register extends {
2620
- schema: infer S extends AnySchemaDefinition;
2621
- } ? S : undefined;
2622
2757
 
2623
2758
  /**
2624
2759
  * The key's project, as `GET /v1/project` describes it: organization, project, dataset and branch,
@@ -2707,7 +2842,7 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2707
2842
  * .execute()
2708
2843
  * ```
2709
2844
  */
2710
- content<K extends TSchema extends AnySchemaDefinition ? SchemaContentTypeNames<TSchema> : string>(contentType: K): TSchema extends AnySchemaDefinition ? ContentClient<InferContentType<TSchema['contentTypes'][K & keyof TSchema['contentTypes']]>> : ContentClient<BaseContent>;
2845
+ content<K extends TSchema extends AnySchemaDefinition ? SchemaContentTypeNames<TSchema> : string>(contentType: K): TSchema extends AnySchemaDefinition ? ContentClient<InferContentType<TSchema['contentTypes'][K & keyof TSchema['contentTypes']], TSchema>> : ContentClient<BaseContent>;
2711
2846
  /**
2712
2847
  * Get an asset client for a specific asset type.
2713
2848
  *
@@ -2726,7 +2861,7 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2726
2861
  * const heroUrl = await relyio.asset('productPhoto').file(photo._metadata.id).url({ variantId: 'hero' })
2727
2862
  * ```
2728
2863
  */
2729
- asset<K extends TSchema extends AnySchemaDefinition ? SchemaAssetTypeNames<TSchema> : string>(assetType: K): TSchema extends AnySchemaDefinition ? AssetClient<InferAssetType<NonNullable<TSchema['assetTypes']>[K & keyof NonNullable<TSchema['assetTypes']>]>> : AssetClient<BaseContent>;
2864
+ asset<K extends TSchema extends AnySchemaDefinition ? SchemaAssetTypeNames<TSchema> : string>(assetType: K): TSchema extends AnySchemaDefinition ? AssetClient<InferAssetType<NonNullable<TSchema['assetTypes']>[K & keyof NonNullable<TSchema['assetTypes']>], TSchema>> : AssetClient<BaseContent>;
2730
2865
  /**
2731
2866
  * Get a singleton client for a specific singleton key
2732
2867
  * Type-safe when schema is provided: autocompletes singleton names AND field names
@@ -2739,7 +2874,7 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2739
2874
  * .fetch()
2740
2875
  * ```
2741
2876
  */
2742
- singleton<K extends TSchema extends AnySchemaDefinition ? SchemaSingletonNames<TSchema> : string>(key: K): TSchema extends AnySchemaDefinition ? SingletonClient<InferSingleton<TSchema['singletonContentTypes'][K & keyof TSchema['singletonContentTypes']]>> : SingletonClient<unknown>;
2877
+ singleton<K extends TSchema extends AnySchemaDefinition ? SchemaSingletonNames<TSchema> : string>(key: K): TSchema extends AnySchemaDefinition ? SingletonClient<InferSingleton<TSchema['singletonContentTypes'][K & keyof TSchema['singletonContentTypes']], TSchema>> : SingletonClient<unknown>;
2743
2878
  /**
2744
2879
  * Get a settings client for a specific settings group
2745
2880
  * Type-safe when schema is provided: autocompletes settings group names AND field names
@@ -2751,9 +2886,12 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2751
2886
  * .fetch()
2752
2887
  * ```
2753
2888
  */
2754
- settings<K extends TSchema extends AnySchemaDefinition ? SchemaSettingsGroupNames<TSchema> : string>(groupId: K): TSchema extends AnySchemaDefinition ? SettingsClient<InferSettingsGroup<NonNullable<TSchema['settingsGroups']>[K & keyof NonNullable<TSchema['settingsGroups']>]>> : SettingsClient<unknown>;
2889
+ settings<K extends TSchema extends AnySchemaDefinition ? SchemaSettingsGroupNames<TSchema> : string>(groupId: K): TSchema extends AnySchemaDefinition ? SettingsClient<InferSettingsGroup<NonNullable<TSchema['settingsGroups']>[K & keyof NonNullable<TSchema['settingsGroups']>], TSchema>> : SettingsClient<unknown>;
2755
2890
  /**
2756
- * Start a search query with full-text, semantic, or hybrid search
2891
+ * Start a search query with full-text, semantic, or hybrid search.
2892
+ *
2893
+ * Where a schema types the client, the results are its entries — every content type's until
2894
+ * `in()` or `across()` narrows them (`INV-SS-TYPES-INFERRED`).
2757
2895
  *
2758
2896
  * @example
2759
2897
  * ```typescript
@@ -2765,7 +2903,7 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2765
2903
  * .execute()
2766
2904
  * ```
2767
2905
  */
2768
- search<T extends BaseContent = BaseContent>(query: string): SearchBuilder<T>;
2906
+ search<T extends BaseContent = SearchEntry<TSchema>>(query: string): SearchBuilder<T, TSchema>;
2769
2907
  /**
2770
2908
  * Start an autocomplete query for search suggestions
2771
2909
  *
@@ -2835,6 +2973,23 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2835
2973
  * ```
2836
2974
  */
2837
2975
  changes(options?: ChangesOptions): AsyncIterable<Change>;
2976
+ /**
2977
+ * The dataset's current position in the changes feed, as a cursor to start
2978
+ * `changes({ since })` or `followChanges(…, { since })` from. One
2979
+ * `GET /v1/changes` without a cursor: answered at once, holding nothing.
2980
+ *
2981
+ * Take it **before** you read what you will follow. A write your read did not
2982
+ * see is then after the position and replayed; opening the feed afterwards
2983
+ * without a `since` starts after it and misses it.
2984
+ *
2985
+ * @example
2986
+ * ```typescript
2987
+ * const since = await relyio.changesHead()
2988
+ * const post = await relyio.content('post').findById(id).execute()
2989
+ * for await (const change of relyio.changes({ since, ids: [id] })) { … }
2990
+ * ```
2991
+ */
2992
+ changesHead(options?: ChangesHeadOptions): Promise<string>;
2838
2993
  /**
2839
2994
  * Build and execute an ad-hoc query dynamically
2840
2995
  *
@@ -2927,7 +3082,10 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2927
3082
  getHttpClient(): HttpClient;
2928
3083
  /**
2929
3084
  * Create a locale-scoped client
2930
- * All content operations on the returned client will use the specified locale
3085
+ *
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.
2931
3089
  *
2932
3090
  * Type-safe when schema is provided: autocompletes valid locale codes!
2933
3091
  *
@@ -2935,9 +3093,10 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2935
3093
  * ```typescript
2936
3094
  * const spanish = relyio.withLocale('es-ES') // ← Autocompletes with schema!
2937
3095
  *
2938
- * // All operations use Spanish
3096
+ * // Reads use Spanish
2939
3097
  * const products = await spanish.content('product').query().execute()
2940
3098
  * const homepage = await spanish.singleton('homepage').fetch()
3099
+ * const results = await spanish.search('zapatos').execute()
2941
3100
  *
2942
3101
  * // Original client unchanged
2943
3102
  * const englishProducts = await relyio.content('product').query().execute()
@@ -3033,4 +3192,4 @@ declare function createClient<TSchema extends AnySchemaDefinition>(config: Typed
3033
3192
  */
3034
3193
  type ClientSchema<T extends TypedRelyIOClient<AnySchemaDefinition>> = T extends TypedRelyIOClient<infer TSchema> ? TSchema : never;
3035
3194
 
3036
- export { type SearchBlock as $, type ActiveSandbox as A, type AutocompleteSuggestion as B, type Change as C, type AutocompleteResponse as D, type ExtendedQueryResult as E, type SimilarResult as F, type SimilarResponse as G, HttpClient as H, type SearchFilter as I, type SearchFields as J, BatchClient as K, BatchBuilder as L, type BatchMethod as M, type BatchOperation as N, type BatchOptions as O, type Project as P, type BatchOperationResult as Q, type Register as R, type SandboxState as S, TypedRelyIOClient as T, type BatchSummary as U, type BatchResponse as V, AdhocQueryClient as W, AdhocQueryBuilder as X, type FetchBlock as Y, type AggregateBlock as Z, type AggregateMetric as _, type TypedClientConfig as a, type SimilarBlock as a0, type FilterValue as a1, type FullTextConfig as a2, type AdhocQueryDefinition as a3, type AdhocQueryOptions as a4, type QueryMetadata as a5, type AdhocQueryResult as a6, AssetClient as a7, AssetFileBuilder as a8, AssetUploadBuilder as a9, FileUploadError as aA, FileValidationError as aB, type FileValidationConstraints as aC, validateFile as aD, isAssetEntry as aa, type AssetVisibility as ab, type FileStatus as ac, type FileBackend as ad, type AssetFileBlock as ae, type AssetFileExtracted as af, type AssetUrls as ag, type AssetEntryResponse as ah, type PopulatedAssetReference as ai, type PresignInput as aj, type PresignResult as ak, type ConfirmInput as al, type ConfirmResult as am, type ResolveUrlInput as an, type ResolveUrlResult as ao, type CreateAssetOptions as ap, type WaitUntilReadyOptions as aq, type MultipartCreateResult as ar, type MultipartPart as as, type MultipartTarget as at, type UploadProgress as au, ResourceNotFoundError as av, ResourceConflictError as aw, ResourceExpiredError as ax, isResourceNotFound as ay, type FileErrorCode as az, type ClientSchema as b, createClient as c, type RegisteredSchema as d, type SendOptions as e, entityTagOf as f, type ConditionalWriteOptions as g, type RetryableWriteOptions as h, ChangesExpiredError as i, type ChangesOptions as j, type ChangesExpiredReason as k, ContentClient as l, SingletonClient as m, SettingsClient as n, ContentQueryBuilder as o, ContentByIdBuilder as p, type ChildrenOptions as q, type SingletonFetchOptions as r, type SettingsFetchOptions as s, SearchClient as t, SearchBuilder as u, AutocompleteBuilder as v, SimilarBuilder as w, type SearchMode as x, type SearchResultItem as y, type SearchResponse as z };
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 };