@relyio/sdk 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/LICENSE +201 -0
- package/README.md +314 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/chunk-2QUK2ZGD.js +738 -0
- package/dist/chunk-7W4MJXQ4.cjs +4429 -0
- package/dist/chunk-FJK7ZWKK.cjs +776 -0
- package/dist/chunk-HT6NFRM2.cjs +196 -0
- package/dist/chunk-I3ESNANB.js +177 -0
- package/dist/chunk-IY5LSKXU.js +3 -0
- package/dist/chunk-MWMSFIWN.cjs +17 -0
- package/dist/chunk-PPA2WWOH.cjs +4 -0
- package/dist/chunk-RJBIJ2ZK.js +4375 -0
- package/dist/chunk-XQ4QHWZE.js +13 -0
- package/dist/client/index.cjs +17 -0
- package/dist/client/index.d.cts +3 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +4 -0
- package/dist/define-schema-DHvUCKwj.d.cts +2101 -0
- package/dist/define-schema-DHvUCKwj.d.ts +2101 -0
- package/dist/index-B-KiFHbx.d.ts +2708 -0
- package/dist/index-BsUqCAu8.d.cts +7855 -0
- package/dist/index-BsUqCAu8.d.ts +7855 -0
- package/dist/index-DGWaawHt.d.cts +2708 -0
- package/dist/index.cjs +499 -0
- package/dist/index.d.cts +523 -0
- package/dist/index.d.ts +523 -0
- package/dist/index.js +148 -0
- package/dist/react/index.cjs +4 -0
- package/dist/react/index.d.cts +2 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +3 -0
- package/dist/schema/index.cjs +157 -0
- package/dist/schema/index.d.cts +223 -0
- package/dist/schema/index.d.ts +223 -0
- package/dist/schema/index.js +4 -0
- package/dist/types/index.cjs +6 -0
- package/dist/types/index.d.cts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +3 -0
- package/dist/utils/index.cjs +81 -0
- package/dist/utils/index.d.cts +87 -0
- package/dist/utils/index.d.ts +87 -0
- package/dist/utils/index.js +4 -0
- package/package.json +159 -0
|
@@ -0,0 +1,2708 @@
|
|
|
1
|
+
import { M as MergedRelyIOConfig, A as ApiPath, a as ApiMethod, G as PathParamsOf, r as ApiResponse, W as Wire, q as RequestConfig, B as BaseContent, c as WhereClause, e as SortOptions, f as ContentQueryResult, Q as QueryOptions, C as CreateInput, U as UpdateInput, S as SDKError, v as BaseValidationError, u as ValidationViolation, H as components, R as RelyIOConfig } from './index-BsUqCAu8.js';
|
|
2
|
+
import { x as SchemaDefinition, y as SchemaContentTypeNames, a6 as InferContentType, K as SchemaAssetTypeNames, at as InferAssetType, z as SchemaSingletonNames, ac as InferSingleton, J as SchemaSettingsGroupNames, an as InferSettingsGroup, G as SchemaQueryNames, H as SchemaLocaleCodes } from './define-schema-DHvUCKwj.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What a call site supplies beside the route it named.
|
|
6
|
+
*
|
|
7
|
+
* `path` is required exactly when the document's template has segments, and
|
|
8
|
+
* forbidden when it does not — so a call that forgot to scope a request, or one
|
|
9
|
+
* that scoped a request the route does not scope, is a compile error rather
|
|
10
|
+
* than a URL with a literal `{id}` in it.
|
|
11
|
+
*/
|
|
12
|
+
type SendOptions<P extends ApiPath, M extends ApiMethod<P>> = {
|
|
13
|
+
/** Query string values. The document declares none, so this stays untyped — see `api-routes.ts`. */
|
|
14
|
+
query?: Record<string, unknown>;
|
|
15
|
+
body?: unknown;
|
|
16
|
+
/** Request headers this call adds, e.g. `If-Match` / `Idempotency-Key` (API4). */
|
|
17
|
+
headers?: Record<string, string>;
|
|
18
|
+
signal?: AbortSignal;
|
|
19
|
+
timeout?: number;
|
|
20
|
+
} & ([PathParamsOf<P, M>] extends [never] ? {
|
|
21
|
+
path?: never;
|
|
22
|
+
} : {
|
|
23
|
+
path: PathParamsOf<P, M>;
|
|
24
|
+
});
|
|
25
|
+
/**
|
|
26
|
+
* Core HTTP client for the RelyIO SDK.
|
|
27
|
+
*
|
|
28
|
+
* `send` is **the** typed entry: it names a route by the path template the
|
|
29
|
+
* committed document declares, and returns that operation's body type with the
|
|
30
|
+
* payload typed as `T`. `readPayload` from `@relyio/api-contract/client` is
|
|
31
|
+
* then the one unwrap — there is no second spelling and no runtime test of
|
|
32
|
+
* which envelope arrived (`INV-API-CLIENT-IS-DERIVED`).
|
|
33
|
+
*
|
|
34
|
+
* The verb helpers below stay for the escape hatch `getHttpClient()` exposes;
|
|
35
|
+
* nothing inside the SDK uses them.
|
|
36
|
+
*/
|
|
37
|
+
declare class HttpClient {
|
|
38
|
+
private baseUrl;
|
|
39
|
+
private defaultHeaders;
|
|
40
|
+
private timeout;
|
|
41
|
+
private retryConfig;
|
|
42
|
+
private debug;
|
|
43
|
+
private logger?;
|
|
44
|
+
private config;
|
|
45
|
+
constructor(config: MergedRelyIOConfig);
|
|
46
|
+
/**
|
|
47
|
+
* Call a route the committed document declares, and get back the body that
|
|
48
|
+
* document says it serves.
|
|
49
|
+
*/
|
|
50
|
+
send<P extends ApiPath, M extends ApiMethod<P>, T = unknown>(path: P, method: M, options: SendOptions<P, M>): Promise<ApiResponse<Wire<P, M, T>>>;
|
|
51
|
+
/**
|
|
52
|
+
* Call a route and return its payload — `send` plus the one unwrap, which is
|
|
53
|
+
* what all but a handful of call sites want.
|
|
54
|
+
*/
|
|
55
|
+
fetchPayload<P extends ApiPath, M extends ApiMethod<P>, T = unknown>(path: P, method: M, options: SendOptions<P, M>): Promise<Wire<P, M, T> extends {
|
|
56
|
+
data: unknown;
|
|
57
|
+
} ? Wire<P, M, T>['data'] : never>;
|
|
58
|
+
/**
|
|
59
|
+
* Make an HTTP request with retry logic
|
|
60
|
+
*/
|
|
61
|
+
request<T = unknown>(config: RequestConfig): Promise<ApiResponse<T>>;
|
|
62
|
+
/**
|
|
63
|
+
* Make a GET request
|
|
64
|
+
*/
|
|
65
|
+
get<T = unknown>(url: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
66
|
+
/**
|
|
67
|
+
* Make a POST request
|
|
68
|
+
*/
|
|
69
|
+
post<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
70
|
+
/**
|
|
71
|
+
* Make a PUT request
|
|
72
|
+
*/
|
|
73
|
+
put<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
74
|
+
/**
|
|
75
|
+
* Make a DELETE request
|
|
76
|
+
*/
|
|
77
|
+
delete<T = unknown>(url: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
78
|
+
/**
|
|
79
|
+
* Make a PATCH request
|
|
80
|
+
*/
|
|
81
|
+
patch<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
82
|
+
/**
|
|
83
|
+
* Set default headers for all requests
|
|
84
|
+
*/
|
|
85
|
+
setDefaultHeaders(headers: Record<string, string>): void;
|
|
86
|
+
/**
|
|
87
|
+
* Set authentication token
|
|
88
|
+
*/
|
|
89
|
+
setAuthToken(token: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Get current default headers
|
|
92
|
+
*/
|
|
93
|
+
getDefaultHeaders(): Record<string, string>;
|
|
94
|
+
/**
|
|
95
|
+
* Update base URL
|
|
96
|
+
*/
|
|
97
|
+
setBaseUrl(baseUrl: string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Get current base URL
|
|
100
|
+
*/
|
|
101
|
+
getBaseUrl(): string;
|
|
102
|
+
private makeRequest;
|
|
103
|
+
/**
|
|
104
|
+
* Filter headers that browsers don't allow to be set manually
|
|
105
|
+
*/
|
|
106
|
+
private filterHeadersForBrowser;
|
|
107
|
+
/**
|
|
108
|
+
* Prepare request body based on content type and environment
|
|
109
|
+
*/
|
|
110
|
+
private prepareRequestBody;
|
|
111
|
+
private parseResponse;
|
|
112
|
+
private resolveUrl;
|
|
113
|
+
private mergeRequestConfig;
|
|
114
|
+
private buildQueryString;
|
|
115
|
+
private headersToObject;
|
|
116
|
+
private calculateRetryDelay;
|
|
117
|
+
private sleep;
|
|
118
|
+
private log;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Children population options
|
|
123
|
+
*/
|
|
124
|
+
interface ChildrenOptions {
|
|
125
|
+
/** Content types of children to include */
|
|
126
|
+
contentTypes?: string[];
|
|
127
|
+
/** Maximum children per entry */
|
|
128
|
+
limit?: number;
|
|
129
|
+
/** Recursion depth */
|
|
130
|
+
depth?: number;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Retained as an alias of {@link ContentQueryResult}.
|
|
134
|
+
*
|
|
135
|
+
* It used to add an optional `pagination: { page, pageSize, pageCount, total }`
|
|
136
|
+
* that the list route emitted only when `withCount` arrived — "a shape no
|
|
137
|
+
* generated type can describe", as that controller's own comment now puts it.
|
|
138
|
+
* API2 made the customer list the **cursor** dialect unconditionally
|
|
139
|
+
* (`INV-API-ONE-CUSTOMER-PAGE-DIALECT`), so no total reaches this surface and
|
|
140
|
+
* the extra member described a body the service cannot send.
|
|
141
|
+
*/
|
|
142
|
+
type ExtendedQueryResult<T extends BaseContent = BaseContent> = ContentQueryResult<T>;
|
|
143
|
+
/**
|
|
144
|
+
* Fluent query builder for content operations
|
|
145
|
+
* Provides a chainable API for building complex content queries
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* const products = await client.content('product')
|
|
150
|
+
* .query()
|
|
151
|
+
* .where({ status: 'active' })
|
|
152
|
+
* .locale('en')
|
|
153
|
+
* .fields(['id', 'title', 'price'])
|
|
154
|
+
* .include(['brand', 'categories'])
|
|
155
|
+
* .sort({ title: 'asc' })
|
|
156
|
+
* .limit(20)
|
|
157
|
+
* .execute()
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
|
|
161
|
+
private readonly httpClient;
|
|
162
|
+
private readonly contentType;
|
|
163
|
+
private readonly defaultLocale?;
|
|
164
|
+
private queryOptions;
|
|
165
|
+
private localeValue?;
|
|
166
|
+
private localesArray?;
|
|
167
|
+
private fetchAllLocales;
|
|
168
|
+
private fieldsProjection?;
|
|
169
|
+
private childrenOptions?;
|
|
170
|
+
private pageNumber?;
|
|
171
|
+
private pageSizeValue?;
|
|
172
|
+
constructor(httpClient: HttpClient, contentType: string, defaultLocale?: string | undefined);
|
|
173
|
+
/**
|
|
174
|
+
* Add where conditions to the query
|
|
175
|
+
*/
|
|
176
|
+
where(conditions: WhereClause<T>): this;
|
|
177
|
+
/**
|
|
178
|
+
* Select specific fields to return
|
|
179
|
+
*/
|
|
180
|
+
select(fields: (keyof T)[]): this;
|
|
181
|
+
/**
|
|
182
|
+
* Include related content in the response
|
|
183
|
+
*/
|
|
184
|
+
include(relations: string[]): this;
|
|
185
|
+
/**
|
|
186
|
+
* Add sorting to the query
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* // Object format
|
|
191
|
+
* .sort({ createdAt: 'desc', title: 'asc' })
|
|
192
|
+
*
|
|
193
|
+
* // Field and direction format
|
|
194
|
+
* .sort('createdAt', 'desc')
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
sort(field: string, direction: 'asc' | 'desc'): this;
|
|
198
|
+
sort(sortOptions: SortOptions<T>): this;
|
|
199
|
+
/**
|
|
200
|
+
* Sort by a specific field in ascending order
|
|
201
|
+
*/
|
|
202
|
+
sortAsc(field: keyof T | string): this;
|
|
203
|
+
/**
|
|
204
|
+
* Sort by a specific field in descending order
|
|
205
|
+
*/
|
|
206
|
+
sortDesc(field: keyof T | string): this;
|
|
207
|
+
/**
|
|
208
|
+
* Limit the number of results
|
|
209
|
+
*/
|
|
210
|
+
limit(count: number): this;
|
|
211
|
+
/**
|
|
212
|
+
* Set offset for pagination
|
|
213
|
+
*/
|
|
214
|
+
offset(count: number): this;
|
|
215
|
+
/**
|
|
216
|
+
* Set cursor for cursor-based pagination
|
|
217
|
+
*/
|
|
218
|
+
cursor(cursor: string): this;
|
|
219
|
+
/**
|
|
220
|
+
* Set locale for localized content
|
|
221
|
+
* @param locale - Locale code (e.g., 'en-US', 'de-DE', 'fr-FR')
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* // Fetch in Spanish
|
|
226
|
+
* .locale('es-ES')
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
locale(locale: string): this;
|
|
230
|
+
/**
|
|
231
|
+
* Fetch content in multiple specific locales
|
|
232
|
+
* Returns primary locale at top level, others in _metadata.localizations
|
|
233
|
+
*
|
|
234
|
+
* @param localeCodes - Array of locale codes to fetch
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const product = await client.content('product')
|
|
239
|
+
* .findById('prod_123')
|
|
240
|
+
* .locales(['en-US', 'es-ES', 'de-DE'])
|
|
241
|
+
* .execute()
|
|
242
|
+
*
|
|
243
|
+
* // Access: product.title (first locale)
|
|
244
|
+
* // Access: product._metadata.localizations['es-ES'].title
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
locales(localeCodes: string[]): this;
|
|
248
|
+
/**
|
|
249
|
+
* Fetch content in all available locales
|
|
250
|
+
* Returns default locale at top level, others in _metadata.localizations
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* const product = await client.content('product')
|
|
255
|
+
* .findById('prod_123')
|
|
256
|
+
* .allLocales()
|
|
257
|
+
* .execute()
|
|
258
|
+
*
|
|
259
|
+
* // Access: product.title (default locale)
|
|
260
|
+
* // Access: product._metadata.localizations['es-ES'].title
|
|
261
|
+
* // Access: product._metadata.availableLocales
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
allLocales(): this;
|
|
265
|
+
/**
|
|
266
|
+
* Select specific fields to return (projection)
|
|
267
|
+
* @param fieldNames - Array of field names to include
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```typescript
|
|
271
|
+
* .fields(['id', 'title', 'price', 'brand.name'])
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
fields(fieldNames: string[]): this;
|
|
275
|
+
/**
|
|
276
|
+
* Include children in results (for hierarchical content)
|
|
277
|
+
* @param options - Children options or boolean to enable with defaults
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```typescript
|
|
281
|
+
* // Include all children
|
|
282
|
+
* .children(true)
|
|
283
|
+
*
|
|
284
|
+
* // Include with options
|
|
285
|
+
* .children({ contentTypes: ['variant'], limit: 10 })
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
children(options: ChildrenOptions | boolean): this;
|
|
289
|
+
/**
|
|
290
|
+
* Set page number for page-based pagination
|
|
291
|
+
* @param pageNum - Page number (1-based)
|
|
292
|
+
*/
|
|
293
|
+
page(pageNum: number): this;
|
|
294
|
+
/**
|
|
295
|
+
* Set page size for page-based pagination
|
|
296
|
+
* @param size - Items per page
|
|
297
|
+
*/
|
|
298
|
+
pageSize(size: number): this;
|
|
299
|
+
/**
|
|
300
|
+
* Execute the query and return all matching results
|
|
301
|
+
*/
|
|
302
|
+
execute(): Promise<T[]>;
|
|
303
|
+
/**
|
|
304
|
+
* Execute the query and return the whole body — the items under `data`, the
|
|
305
|
+
* cursor facts under `page`.
|
|
306
|
+
*/
|
|
307
|
+
executeWithMeta(): Promise<ContentQueryResult<T>>;
|
|
308
|
+
/**
|
|
309
|
+
* Execute the query and return a single result (first match)
|
|
310
|
+
*/
|
|
311
|
+
first(): Promise<T | null>;
|
|
312
|
+
/**
|
|
313
|
+
* Get paginated results
|
|
314
|
+
*/
|
|
315
|
+
paginate(limit?: number): Promise<ContentQueryResult<T>>;
|
|
316
|
+
/**
|
|
317
|
+
* Create an async iterator for streaming results
|
|
318
|
+
*/
|
|
319
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
320
|
+
/**
|
|
321
|
+
* Execute the query and return all results as an array (for large datasets)
|
|
322
|
+
*/
|
|
323
|
+
all(): Promise<T[]>;
|
|
324
|
+
/**
|
|
325
|
+
* Clone the query builder
|
|
326
|
+
*/
|
|
327
|
+
clone(): ContentQueryBuilder<T>;
|
|
328
|
+
/**
|
|
329
|
+
* Get the current query options
|
|
330
|
+
*/
|
|
331
|
+
getQueryOptions(): QueryOptions<T>;
|
|
332
|
+
/**
|
|
333
|
+
* Execute the query and return the whole body.
|
|
334
|
+
*
|
|
335
|
+
* Identical to {@link executeWithMeta} now that the list serves one shape;
|
|
336
|
+
* kept as the name callers already import.
|
|
337
|
+
*/
|
|
338
|
+
executeWithMetaExtended(): Promise<ExtendedQueryResult<T>>;
|
|
339
|
+
/**
|
|
340
|
+
* `count()` and `exists()` are gone, and their absence is the honest answer
|
|
341
|
+
* rather than an omission (`INV-RD-CAPABILITY-IS-HONEST`).
|
|
342
|
+
*
|
|
343
|
+
* `count()` sent `withCount` and read `pagination.total`; API2 moved the
|
|
344
|
+
* customer list onto the **cursor** dialect, whose page facts are
|
|
345
|
+
* `{ nextCursor, hasMore }` and nothing else, so no total reaches this
|
|
346
|
+
* surface at all. Keeping the method would have meant either a request that
|
|
347
|
+
* always throws or a number assembled from a page the caller happened to
|
|
348
|
+
* fetch — a count of what was returned, presented as a count of what matched
|
|
349
|
+
* (rule 6). The plan's §3.3 listed `count` among six methods a type would
|
|
350
|
+
* repair; what the type actually shows is that the capability is no longer
|
|
351
|
+
* there. A caller that wants "is there at least one" fetches one and looks at
|
|
352
|
+
* `data.length`; a caller that wants a true total uses `POST /v1/search`,
|
|
353
|
+
* which is the offset dialect precisely because a facet-bearing result wants
|
|
354
|
+
* one (Decision 5).
|
|
355
|
+
*/
|
|
356
|
+
/**
|
|
357
|
+
* Build query parameters for the HTTP request
|
|
358
|
+
*/
|
|
359
|
+
private buildQueryParams;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Specialized query builder for finding by ID
|
|
363
|
+
*/
|
|
364
|
+
declare class ContentByIdBuilder<T extends BaseContent = BaseContent> {
|
|
365
|
+
private readonly httpClient;
|
|
366
|
+
private readonly contentType;
|
|
367
|
+
private readonly id;
|
|
368
|
+
private readonly defaultLocale?;
|
|
369
|
+
private includeRelations?;
|
|
370
|
+
private localeValue?;
|
|
371
|
+
private localesArray?;
|
|
372
|
+
private fetchAllLocales;
|
|
373
|
+
private childrenOptions?;
|
|
374
|
+
constructor(httpClient: HttpClient, contentType: string, id: string, defaultLocale?: string | undefined);
|
|
375
|
+
/**
|
|
376
|
+
* Include related content in the response
|
|
377
|
+
*/
|
|
378
|
+
include(relations: string[]): this;
|
|
379
|
+
/**
|
|
380
|
+
* Set locale for localized content
|
|
381
|
+
* @param locale - Locale code (e.g., 'en-US', 'de-DE', 'fr-FR')
|
|
382
|
+
*/
|
|
383
|
+
locale(locale: string): this;
|
|
384
|
+
/**
|
|
385
|
+
* Fetch content in multiple specific locales
|
|
386
|
+
* Returns primary locale at top level, others in _metadata.localizations
|
|
387
|
+
*
|
|
388
|
+
* @param localeCodes - Array of locale codes to fetch
|
|
389
|
+
*/
|
|
390
|
+
locales(localeCodes: string[]): this;
|
|
391
|
+
/**
|
|
392
|
+
* Fetch content in all available locales
|
|
393
|
+
* Returns default locale at top level, others in _metadata.localizations
|
|
394
|
+
*/
|
|
395
|
+
allLocales(): this;
|
|
396
|
+
/**
|
|
397
|
+
* Include children in results (for hierarchical content)
|
|
398
|
+
* @param options - Children options or boolean to enable with defaults
|
|
399
|
+
*/
|
|
400
|
+
children(options: ChildrenOptions | boolean): this;
|
|
401
|
+
/**
|
|
402
|
+
* Execute the query and return the content item
|
|
403
|
+
*/
|
|
404
|
+
execute(): Promise<T | null>;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* API4's two request headers, exposed the way the SDK's ergonomics already
|
|
409
|
+
* expose everything else: as options on the call, not as raw headers.
|
|
410
|
+
*
|
|
411
|
+
* `apps/services/api` declares them on exactly six and seven routes
|
|
412
|
+
* respectively (`CONDITIONAL_WRITE_HEADERS` / `RETRYABLE_WRITE_HEADERS` in that
|
|
413
|
+
* service's `contract/routes.ts`), and the API4 closeout is explicit that the
|
|
414
|
+
* ten `/file/*` routes and `POST /batch` declare **neither**, because they
|
|
415
|
+
* write through `@relyio/asset-files` and the batch planner and would silently
|
|
416
|
+
* ignore the header. So these options are on the six and seven methods that
|
|
417
|
+
* reach them and nowhere else: a client that could pass `ifMatch` to a route
|
|
418
|
+
* that ignores it has been told a lie no gate can catch
|
|
419
|
+
* (`INV-RD-CAPABILITY-IS-HONEST`).
|
|
420
|
+
*
|
|
421
|
+
* The tag itself comes from `X-Entity-Tag`, which the single-entity reads serve
|
|
422
|
+
* and the list routes deliberately do not — one header cannot name every
|
|
423
|
+
* member's per-locale version. `entityTagOf` reads it off the response the SDK
|
|
424
|
+
* already returns, so the round trip is "read one, write it back" with no
|
|
425
|
+
* assembly from `_metadata` in between
|
|
426
|
+
* (`INV-API-CONDITIONAL-WRITE-IS-REACHABLE`).
|
|
427
|
+
*/
|
|
428
|
+
interface RetryableWriteOptions {
|
|
429
|
+
/**
|
|
430
|
+
* A caller-chosen key that makes a retry of **this** write safe.
|
|
431
|
+
*
|
|
432
|
+
* A replay inside the service's window returns the original outcome rather
|
|
433
|
+
* than applying twice. The service derives that response from committed state
|
|
434
|
+
* pinned to the recorded version — it does not store bytes — so a replay after
|
|
435
|
+
* the version has been pruned is refused `RESOURCE_EXPIRED` rather than
|
|
436
|
+
* answered from a stale copy.
|
|
437
|
+
*/
|
|
438
|
+
idempotencyKey?: string;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* The six routes that additionally take `If-Match`.
|
|
442
|
+
*
|
|
443
|
+
* A creation has no prior entity to precondition on, so `POST /v1/{contentType}`
|
|
444
|
+
* takes `Idempotency-Key` and not this — which is why the two option types are
|
|
445
|
+
* separate rather than one optional-everything bag.
|
|
446
|
+
*/
|
|
447
|
+
interface ConditionalWriteOptions extends RetryableWriteOptions {
|
|
448
|
+
/**
|
|
449
|
+
* The `X-Entity-Tag` value a prior read served, sent back as `If-Match`.
|
|
450
|
+
*
|
|
451
|
+
* The write applies only if that locale of that entry is still at the version
|
|
452
|
+
* the tag names; otherwise the service refuses `RESOURCE_CONFLICT` and names
|
|
453
|
+
* both versions.
|
|
454
|
+
*/
|
|
455
|
+
ifMatch?: string;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* The entity tag a single-entity read served, or `undefined` where the route
|
|
459
|
+
* serves none — a list, or a cache HIT, which cannot know the current version
|
|
460
|
+
* and honestly says nothing rather than serving a stale tag.
|
|
461
|
+
*/
|
|
462
|
+
declare function entityTagOf(response: {
|
|
463
|
+
headers: Record<string, string>;
|
|
464
|
+
}): string | undefined;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Content fetch options
|
|
468
|
+
*/
|
|
469
|
+
interface ContentFetchOptions<T extends BaseContent = BaseContent> {
|
|
470
|
+
/** Filter conditions */
|
|
471
|
+
where?: WhereClause<T>;
|
|
472
|
+
/** Maximum entries to return */
|
|
473
|
+
limit?: number;
|
|
474
|
+
/** Entries to skip (offset pagination) */
|
|
475
|
+
offset?: number;
|
|
476
|
+
/** Sort configuration */
|
|
477
|
+
sort?: Record<string, 'asc' | 'desc'>;
|
|
478
|
+
/** Reference fields to populate */
|
|
479
|
+
include?: string[];
|
|
480
|
+
/** Locale for localized content */
|
|
481
|
+
locale?: string;
|
|
482
|
+
/** Fields to select (projection) */
|
|
483
|
+
fields?: string[];
|
|
484
|
+
/** Children population options */
|
|
485
|
+
children?: ChildrenOptions | boolean;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Content client for managing content operations
|
|
489
|
+
* Provides CRUD operations and query building for a specific content type
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* ```typescript
|
|
493
|
+
* const products = client.content('product')
|
|
494
|
+
*
|
|
495
|
+
* // Query with fluent API
|
|
496
|
+
* const active = await products.query()
|
|
497
|
+
* .where({ status: 'active' })
|
|
498
|
+
* .locale('en')
|
|
499
|
+
* .include(['brand'])
|
|
500
|
+
* .limit(20)
|
|
501
|
+
* .execute()
|
|
502
|
+
*
|
|
503
|
+
* // Quick fetch
|
|
504
|
+
* const all = await products.fetchAll()
|
|
505
|
+
* ```
|
|
506
|
+
*/
|
|
507
|
+
declare class ContentClient<T extends BaseContent = BaseContent> {
|
|
508
|
+
private readonly httpClient;
|
|
509
|
+
private readonly contentType;
|
|
510
|
+
private readonly defaultLocale?;
|
|
511
|
+
constructor(httpClient: HttpClient, contentType: string, defaultLocale?: string | undefined);
|
|
512
|
+
/**
|
|
513
|
+
* Create a new query builder for this content type
|
|
514
|
+
*/
|
|
515
|
+
query(): ContentQueryBuilder<T>;
|
|
516
|
+
/**
|
|
517
|
+
* Find content by ID with fluent options
|
|
518
|
+
*/
|
|
519
|
+
findById(id: string): ContentByIdBuilder<T>;
|
|
520
|
+
/**
|
|
521
|
+
* Fetch all content items
|
|
522
|
+
* @param locale - Optional locale for localized content
|
|
523
|
+
*/
|
|
524
|
+
fetchAll(locale?: string): Promise<T[]>;
|
|
525
|
+
/**
|
|
526
|
+
* Fetch content with query options
|
|
527
|
+
*/
|
|
528
|
+
fetch(options?: ContentFetchOptions<T>): Promise<T[]>;
|
|
529
|
+
/**
|
|
530
|
+
* Fetch a single content item by ID
|
|
531
|
+
* @param id - Entry ID or slug
|
|
532
|
+
* @param options - Fetch options (include, locale)
|
|
533
|
+
*/
|
|
534
|
+
fetchOne(id: string, options?: {
|
|
535
|
+
include?: string[];
|
|
536
|
+
locale?: string;
|
|
537
|
+
}): Promise<T | null>;
|
|
538
|
+
/**
|
|
539
|
+
* Fetch one entry **and the entity tag that read served**.
|
|
540
|
+
*
|
|
541
|
+
* This is the read half of a conditional write. `X-Entity-Tag` is minted from
|
|
542
|
+
* `(entryUid, locale, localeVersion)` and is exactly what `If-Match` takes,
|
|
543
|
+
* so a caller reads here, edits, and hands the same string back to `update`
|
|
544
|
+
* — with nothing to assemble in between
|
|
545
|
+
* (`INV-API-CONDITIONAL-WRITE-IS-REACHABLE`).
|
|
546
|
+
*
|
|
547
|
+
* `entityTag` is `undefined` when the response came from the cache: a cached
|
|
548
|
+
* body cannot know the current version, and an absent tag beats a stale one
|
|
549
|
+
* that would refuse the next write.
|
|
550
|
+
*/
|
|
551
|
+
fetchOneWithTag(id: string, options?: {
|
|
552
|
+
include?: string[];
|
|
553
|
+
locale?: string;
|
|
554
|
+
}): Promise<{
|
|
555
|
+
entry: T;
|
|
556
|
+
entityTag?: string;
|
|
557
|
+
}>;
|
|
558
|
+
/**
|
|
559
|
+
* Fetch the first content item matching the conditions
|
|
560
|
+
* @param where - Filter conditions
|
|
561
|
+
* @param locale - Optional locale
|
|
562
|
+
*/
|
|
563
|
+
fetchFirst(where?: WhereClause<T>, locale?: string): Promise<T | null>;
|
|
564
|
+
/**
|
|
565
|
+
* Create a new content item
|
|
566
|
+
* @param data - Content data
|
|
567
|
+
* @param options - Create options (slug, locale, parentId, sortOrder)
|
|
568
|
+
*/
|
|
569
|
+
create(data: CreateInput<T>, options?: {
|
|
570
|
+
slug?: string;
|
|
571
|
+
locale?: string;
|
|
572
|
+
parentId?: string;
|
|
573
|
+
sortOrder?: number;
|
|
574
|
+
} & RetryableWriteOptions): Promise<T>;
|
|
575
|
+
/**
|
|
576
|
+
* Update a content item by ID (partial update)
|
|
577
|
+
* @param id - Entry ID
|
|
578
|
+
* @param data - Fields to update
|
|
579
|
+
* @param options - Update options (slug, locale, parentId, sortOrder)
|
|
580
|
+
*/
|
|
581
|
+
update(id: string, data: UpdateInput<T>, options?: {
|
|
582
|
+
slug?: string;
|
|
583
|
+
locale?: string;
|
|
584
|
+
parentId?: string;
|
|
585
|
+
sortOrder?: number;
|
|
586
|
+
} & ConditionalWriteOptions): Promise<T>;
|
|
587
|
+
/**
|
|
588
|
+
* Delete a content item by ID
|
|
589
|
+
*/
|
|
590
|
+
delete(id: string, options?: ConditionalWriteOptions): Promise<void>;
|
|
591
|
+
/**
|
|
592
|
+
* Check if content exists by ID
|
|
593
|
+
*/
|
|
594
|
+
exists(id: string): Promise<boolean>;
|
|
595
|
+
/**
|
|
596
|
+
* Get version history for one locale of an entry.
|
|
597
|
+
*
|
|
598
|
+
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
599
|
+
* schema default, no fallback is applied, and a locale with no history returns an empty array
|
|
600
|
+
* rather than another locale's rows. Every row names the locale it belongs to.
|
|
601
|
+
*/
|
|
602
|
+
versions(id: string, options?: {
|
|
603
|
+
limit?: number;
|
|
604
|
+
locale?: string;
|
|
605
|
+
}): Promise<Array<T & {
|
|
606
|
+
versionNumber: number;
|
|
607
|
+
locale: string;
|
|
608
|
+
}>>;
|
|
609
|
+
/**
|
|
610
|
+
* Get a specific version of an entry.
|
|
611
|
+
*
|
|
612
|
+
* `locale` defaults to the schema default. Version numbers are per locale, so version 2 is
|
|
613
|
+
* different content in each one.
|
|
614
|
+
*/
|
|
615
|
+
version(id: string, versionNumber: number, options?: {
|
|
616
|
+
locale?: string;
|
|
617
|
+
}): Promise<T | null>;
|
|
618
|
+
/**
|
|
619
|
+
* Revert one locale of an entry to a previous version.
|
|
620
|
+
*
|
|
621
|
+
* `locale` is **required**, and that is not a convention: versions are numbered per locale, so
|
|
622
|
+
* `versionNumber` alone is ambiguous, and defaulting it would silently revert the wrong
|
|
623
|
+
* translation. Only that locale's fields change — shared fields and every other locale are left
|
|
624
|
+
* untouched.
|
|
625
|
+
*
|
|
626
|
+
* The restore is validated as strictly as a publish, so it cannot publish invalid content, and it
|
|
627
|
+
* records a new version of its own rather than rewinding the counter — so the revert is auditable
|
|
628
|
+
* and itself reversible.
|
|
629
|
+
*/
|
|
630
|
+
restore(id: string, versionNumber: number, locale: string, options?: ConditionalWriteOptions): Promise<T>;
|
|
631
|
+
/**
|
|
632
|
+
* Get children of a hierarchical entry
|
|
633
|
+
* @param id - Parent entry ID
|
|
634
|
+
* @param options - Fetch options
|
|
635
|
+
*/
|
|
636
|
+
children(id: string, options?: {
|
|
637
|
+
depth?: number;
|
|
638
|
+
include?: string[];
|
|
639
|
+
locale?: string;
|
|
640
|
+
}): Promise<T[]>;
|
|
641
|
+
/**
|
|
642
|
+
* Get the content type name
|
|
643
|
+
*/
|
|
644
|
+
getContentType(): string;
|
|
645
|
+
/**
|
|
646
|
+
* Create a new ContentClient for a different content type
|
|
647
|
+
*/
|
|
648
|
+
ofType<U extends BaseContent = BaseContent>(contentType: string): ContentClient<U>;
|
|
649
|
+
/**
|
|
650
|
+
* Create a new ContentClient with a different default locale
|
|
651
|
+
*/
|
|
652
|
+
withLocale(locale: string): ContentClient<T>;
|
|
653
|
+
/**
|
|
654
|
+
* Get the current default locale
|
|
655
|
+
*/
|
|
656
|
+
getDefaultLocale(): string | undefined;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Upload/processing error taxonomy (plan 17, 00b Step 4).
|
|
661
|
+
*
|
|
662
|
+
* A **thin customer-side mirror** of the realtime-contracts `FileErrorCode`
|
|
663
|
+
* (correction C6 — the SDK must not import the server/Studio contracts package).
|
|
664
|
+
* Keep the members in sync with `@relyio/realtime-contracts`.
|
|
665
|
+
*/
|
|
666
|
+
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';
|
|
667
|
+
/**
|
|
668
|
+
* A failure during the upload protocol (presign / PUT / multipart / confirm) or
|
|
669
|
+
* surfaced by the server's processing pipeline. Carries a typed {@link FileErrorCode}
|
|
670
|
+
* and a `retriable` hint so callers (and `upload()`'s bounded auto-retry) can
|
|
671
|
+
* decide whether to retry on the same entry.
|
|
672
|
+
*/
|
|
673
|
+
declare class FileUploadError extends SDKError {
|
|
674
|
+
readonly code: FileErrorCode;
|
|
675
|
+
readonly retryable: boolean;
|
|
676
|
+
constructor(code: FileErrorCode, message: string, options?: {
|
|
677
|
+
retriable?: boolean;
|
|
678
|
+
statusCode?: number;
|
|
679
|
+
cause?: Error;
|
|
680
|
+
});
|
|
681
|
+
getUserMessage(): string;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Client-side file validation failure (MIME/size/etc.) raised **before** any
|
|
685
|
+
* bytes leave the machine (UX only — the server presign stays authoritative).
|
|
686
|
+
*/
|
|
687
|
+
declare class FileValidationError extends BaseValidationError {
|
|
688
|
+
readonly code = "FILE_VALIDATION_ERROR";
|
|
689
|
+
constructor(message: string, violations?: ValidationViolation[], cause?: Error);
|
|
690
|
+
getUserMessage(): string;
|
|
691
|
+
}
|
|
692
|
+
/** Constraints `validateFile` checks a file against (subset of the schema upload gate). */
|
|
693
|
+
interface FileValidationConstraints {
|
|
694
|
+
/** Allowed MIME types (exact match). */
|
|
695
|
+
allowedMimeTypes?: string[];
|
|
696
|
+
/** Max size in bytes. */
|
|
697
|
+
maxSizeBytes?: number;
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Validate a file against explicit constraints, returning typed violations.
|
|
701
|
+
*
|
|
702
|
+
* The customer SDK does not carry a `SchemaReader` (that lives in the Studio
|
|
703
|
+
* layer), so callers pass the constraints they want enforced client-side; the
|
|
704
|
+
* server presign remains the authority. Returns an empty array when valid.
|
|
705
|
+
*/
|
|
706
|
+
declare function validateFile(file: {
|
|
707
|
+
type?: string;
|
|
708
|
+
size?: number;
|
|
709
|
+
}, constraints?: FileValidationConstraints): ValidationViolation[];
|
|
710
|
+
|
|
711
|
+
/** Delivery visibility for a file binding (gateway-enforced, no byte relocation). */
|
|
712
|
+
type AssetVisibility = 'public' | 'protected' | 'private';
|
|
713
|
+
/** Binary lifecycle status — independent of the entry's publishing status. */
|
|
714
|
+
type FileStatus = 'pending_upload' | 'uploading' | 'processing' | 'ready' | 'failed';
|
|
715
|
+
/** Storage backend: `r2` = image + file kinds, `stream` = video kind. */
|
|
716
|
+
type FileBackend = 'r2' | 'stream';
|
|
717
|
+
/** Extracted media metadata (Phase 1 basics + Phase 2 enrichment, plans 15–19). */
|
|
718
|
+
interface AssetFileExtracted {
|
|
719
|
+
width?: number;
|
|
720
|
+
height?: number;
|
|
721
|
+
format?: string;
|
|
722
|
+
duration?: number;
|
|
723
|
+
hasAlpha?: boolean;
|
|
724
|
+
isAnimated?: boolean;
|
|
725
|
+
orientation?: number;
|
|
726
|
+
placeholder?: string;
|
|
727
|
+
dominantColor?: string;
|
|
728
|
+
palette?: string[];
|
|
729
|
+
exif?: Record<string, unknown>;
|
|
730
|
+
video?: {
|
|
731
|
+
codec?: string;
|
|
732
|
+
bitrate?: number;
|
|
733
|
+
framerate?: number;
|
|
734
|
+
audioTracks?: unknown[];
|
|
735
|
+
};
|
|
736
|
+
pageCount?: number;
|
|
737
|
+
text?: string;
|
|
738
|
+
safety?: {
|
|
739
|
+
nsfwScore?: number;
|
|
740
|
+
flagged?: boolean;
|
|
741
|
+
categories?: string[];
|
|
742
|
+
};
|
|
743
|
+
[key: string]: unknown;
|
|
744
|
+
}
|
|
745
|
+
/** Customer-facing file binding block on an asset entry. */
|
|
746
|
+
interface AssetFileBlock {
|
|
747
|
+
status: FileStatus;
|
|
748
|
+
backend: FileBackend;
|
|
749
|
+
fileName: string;
|
|
750
|
+
mimeType?: string | null;
|
|
751
|
+
size?: number | null;
|
|
752
|
+
/** Advisory client-computed SHA-256 (duplicate detection only). */
|
|
753
|
+
hash?: string | null;
|
|
754
|
+
visibility: AssetVisibility;
|
|
755
|
+
extracted?: AssetFileExtracted;
|
|
756
|
+
/** 0..1 normalized smart-crop anchor (written by plan 18). */
|
|
757
|
+
focalPoint?: {
|
|
758
|
+
x: number;
|
|
759
|
+
y: number;
|
|
760
|
+
};
|
|
761
|
+
/** Phase-2 enrichment status — independent of `status` (plan 15). */
|
|
762
|
+
enrichment?: {
|
|
763
|
+
status: 'pending' | 'running' | 'complete' | 'partial' | 'failed';
|
|
764
|
+
};
|
|
765
|
+
/** File-kind malware scan status (plan 19). */
|
|
766
|
+
scan?: {
|
|
767
|
+
status: 'pending' | 'clean' | 'infected' | 'error' | 'skipped';
|
|
768
|
+
};
|
|
769
|
+
/** Processing progress (e.g. video encoding %) + terminal error. */
|
|
770
|
+
processing?: {
|
|
771
|
+
stage?: string;
|
|
772
|
+
progress?: number;
|
|
773
|
+
error?: {
|
|
774
|
+
code?: string;
|
|
775
|
+
message?: string;
|
|
776
|
+
retriable?: boolean;
|
|
777
|
+
};
|
|
778
|
+
};
|
|
779
|
+
/** Video playback readiness. */
|
|
780
|
+
playback?: {
|
|
781
|
+
ready?: boolean;
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Computed gateway delivery URLs (the reserved `urls` key). Always served from
|
|
786
|
+
* `cdn.relyio.net`. Image bindings expose `original` + `variants`; video bindings
|
|
787
|
+
* expose `playback`/`poster`/`download`. Present only when `file.status` is
|
|
788
|
+
* `ready` — otherwise the response omits `urls` and callers read `file.status`.
|
|
789
|
+
*/
|
|
790
|
+
interface AssetUrls {
|
|
791
|
+
/** Image: canonical original delivery URL. */
|
|
792
|
+
original?: string;
|
|
793
|
+
/** Image: variant id → delivery URL map. */
|
|
794
|
+
variants?: Record<string, string>;
|
|
795
|
+
/** Video: HLS/DASH manifest URL. */
|
|
796
|
+
playback?: string;
|
|
797
|
+
/** Video: poster image URL. */
|
|
798
|
+
poster?: string;
|
|
799
|
+
/** Video: downloadable MP4 URL (when enabled). */
|
|
800
|
+
download?: string;
|
|
801
|
+
[key: string]: unknown;
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* An asset entry response: schema fields at the top level plus the reserved
|
|
805
|
+
* `file` + `urls` blocks and `_metadata`. `T` carries the inferred field shape.
|
|
806
|
+
*/
|
|
807
|
+
type AssetEntryResponse<T extends BaseContent = BaseContent> = T & {
|
|
808
|
+
file?: AssetFileBlock;
|
|
809
|
+
urls?: AssetUrls;
|
|
810
|
+
};
|
|
811
|
+
/** Request a single upload target for the binding. */
|
|
812
|
+
interface PresignInput {
|
|
813
|
+
/** Original file name (required). */
|
|
814
|
+
fileName: string;
|
|
815
|
+
/** MIME type the client will upload with. */
|
|
816
|
+
contentType?: string;
|
|
817
|
+
/** File size in bytes (early upload-gate validation). */
|
|
818
|
+
size?: number;
|
|
819
|
+
/** Locale to target for file-localized asset types. */
|
|
820
|
+
locale?: string;
|
|
821
|
+
/** Advisory client-computed SHA-256 (duplicate detection). */
|
|
822
|
+
hash?: string;
|
|
823
|
+
}
|
|
824
|
+
/** Single upload target returned by `presign`. */
|
|
825
|
+
interface PresignResult {
|
|
826
|
+
backend: FileBackend;
|
|
827
|
+
/** `put` = single PUT / Stream POST; `multipart` = resumable R2 session (plan 17). */
|
|
828
|
+
mode?: 'put' | 'multipart';
|
|
829
|
+
/** R2 presigned PUT (image/file) or Stream direct-creator URL (video). */
|
|
830
|
+
uploadUrl?: string;
|
|
831
|
+
method: 'PUT' | 'POST';
|
|
832
|
+
headers?: Record<string, string>;
|
|
833
|
+
/** Object key for the binding — present for R2 (needed to drive multipart). */
|
|
834
|
+
objectKey?: string;
|
|
835
|
+
storageVersion?: number;
|
|
836
|
+
/** Multipart upload id — present only for `mode: 'multipart'`. */
|
|
837
|
+
uploadId?: string;
|
|
838
|
+
/** Multipart part size in bytes — present only for `mode: 'multipart'`. */
|
|
839
|
+
partSize?: number;
|
|
840
|
+
expiresAt: string;
|
|
841
|
+
locale?: string;
|
|
842
|
+
}
|
|
843
|
+
/** Result of opening a multipart session (`file(uid).createMultipart()`). */
|
|
844
|
+
interface MultipartCreateResult {
|
|
845
|
+
uploadId: string;
|
|
846
|
+
objectKey: string;
|
|
847
|
+
partSize: number;
|
|
848
|
+
storageVersion: number;
|
|
849
|
+
locale?: string;
|
|
850
|
+
}
|
|
851
|
+
/** A single uploaded part (`{ PartNumber, ETag }` ordering for `complete`). */
|
|
852
|
+
interface MultipartPart {
|
|
853
|
+
partNumber: number;
|
|
854
|
+
etag: string;
|
|
855
|
+
size?: number;
|
|
856
|
+
}
|
|
857
|
+
/** Target a multipart session in subsequent ops. */
|
|
858
|
+
interface MultipartTarget {
|
|
859
|
+
uploadId: string;
|
|
860
|
+
objectKey: string;
|
|
861
|
+
locale?: string;
|
|
862
|
+
}
|
|
863
|
+
/** Upload progress tick handed to `.onProgress()`. */
|
|
864
|
+
interface UploadProgress {
|
|
865
|
+
/** `upload` for client → storage bytes. */
|
|
866
|
+
phase: 'upload';
|
|
867
|
+
/** Bytes transferred so far. */
|
|
868
|
+
loaded: number;
|
|
869
|
+
/** Total bytes (when known). */
|
|
870
|
+
total: number;
|
|
871
|
+
/** 0–100 integer. */
|
|
872
|
+
progress: number;
|
|
873
|
+
}
|
|
874
|
+
/** Acknowledge a completed client upload. */
|
|
875
|
+
interface ConfirmInput {
|
|
876
|
+
locale?: string;
|
|
877
|
+
hash?: string;
|
|
878
|
+
}
|
|
879
|
+
/** Result of `confirm`. */
|
|
880
|
+
interface ConfirmResult {
|
|
881
|
+
accepted: boolean;
|
|
882
|
+
}
|
|
883
|
+
/** Resolve a single gateway delivery URL. */
|
|
884
|
+
interface ResolveUrlInput {
|
|
885
|
+
locale?: string;
|
|
886
|
+
/** Named image variant id. */
|
|
887
|
+
variantId?: string;
|
|
888
|
+
/** Video delivery target. */
|
|
889
|
+
purpose?: 'playback' | 'poster' | 'download';
|
|
890
|
+
}
|
|
891
|
+
/** Result of `url`. `expiresAt` is omitted for `public` bindings. */
|
|
892
|
+
interface ResolveUrlResult {
|
|
893
|
+
url: string;
|
|
894
|
+
expiresAt?: string;
|
|
895
|
+
}
|
|
896
|
+
/** Options when creating an asset entry. */
|
|
897
|
+
interface CreateAssetOptions {
|
|
898
|
+
slug?: string;
|
|
899
|
+
locale?: string;
|
|
900
|
+
/** Original file name (also settable at presign). */
|
|
901
|
+
fileName?: string;
|
|
902
|
+
/** Initial delivery visibility (default `public`). */
|
|
903
|
+
visibility?: AssetVisibility;
|
|
904
|
+
/** Auto-publish the entry when the file becomes ready (default `true`). */
|
|
905
|
+
publish?: boolean;
|
|
906
|
+
}
|
|
907
|
+
/** Options for {@link AssetClient.update}: the entry route takes both API4 headers. */
|
|
908
|
+
type UpdateAssetOptions = {
|
|
909
|
+
slug?: string;
|
|
910
|
+
locale?: string;
|
|
911
|
+
} & ConditionalWriteOptions;
|
|
912
|
+
/** Options for {@link AssetFileBuilder.waitUntilReady}. */
|
|
913
|
+
interface WaitUntilReadyOptions {
|
|
914
|
+
/** Locale of the binding to watch. */
|
|
915
|
+
locale?: string;
|
|
916
|
+
/** Total time to wait before giving up (ms). Default 60000. */
|
|
917
|
+
timeoutMs?: number;
|
|
918
|
+
/** Delay between polls (ms). Default 1500. */
|
|
919
|
+
pollIntervalMs?: number;
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* Operations on a single asset entry's file binding, backed by the
|
|
923
|
+
* `/{assetType}/{entryUid}/file/*` routes (plan 06 §2).
|
|
924
|
+
*/
|
|
925
|
+
declare class AssetFileBuilder<T extends BaseContent = BaseContent> {
|
|
926
|
+
private readonly httpClient;
|
|
927
|
+
private readonly assetType;
|
|
928
|
+
private readonly entryUid;
|
|
929
|
+
private readonly defaultLocale?;
|
|
930
|
+
constructor(httpClient: HttpClient, assetType: string, entryUid: string, defaultLocale?: string | undefined);
|
|
931
|
+
/**
|
|
932
|
+
* The path parameters every `/file/*` route on this builder takes.
|
|
933
|
+
*
|
|
934
|
+
* The path *template* is the document's; only these two values are the
|
|
935
|
+
* builder's, so a route that gains or loses a segment is a compile error here
|
|
936
|
+
* rather than a hand-built string that silently misses.
|
|
937
|
+
*/
|
|
938
|
+
private get target();
|
|
939
|
+
private withLocale;
|
|
940
|
+
/**
|
|
941
|
+
* Issue a single upload target — an R2 presigned PUT (image/file) or a
|
|
942
|
+
* Cloudflare Stream direct-creator URL (video). Resumable multipart is plan 17.
|
|
943
|
+
*/
|
|
944
|
+
presign(input: PresignInput): Promise<PresignResult>;
|
|
945
|
+
/**
|
|
946
|
+
* Acknowledge a completed client upload (kicks off the fast-path intake for
|
|
947
|
+
* R2; a no-op for Stream, whose readiness is webhook-driven).
|
|
948
|
+
*/
|
|
949
|
+
confirm(input?: ConfirmInput): Promise<ConfirmResult>;
|
|
950
|
+
/** Open an R2 multipart session for a large file (standalone of `presign`). */
|
|
951
|
+
createMultipart(input: PresignInput): Promise<MultipartCreateResult>;
|
|
952
|
+
/** Presign a single part PUT (1-based `partNumber`). */
|
|
953
|
+
signPart(target: MultipartTarget & {
|
|
954
|
+
partNumber: number;
|
|
955
|
+
}): Promise<{
|
|
956
|
+
url: string;
|
|
957
|
+
}>;
|
|
958
|
+
/** List parts already uploaded (cross-session resume). */
|
|
959
|
+
listParts(target: MultipartTarget): Promise<MultipartPart[]>;
|
|
960
|
+
/** Finalize a multipart session. */
|
|
961
|
+
completeMultipart(target: MultipartTarget & {
|
|
962
|
+
parts: MultipartPart[];
|
|
963
|
+
}): Promise<{
|
|
964
|
+
ok: boolean;
|
|
965
|
+
etag?: string;
|
|
966
|
+
}>;
|
|
967
|
+
/** Abort a multipart session, freeing staged parts. */
|
|
968
|
+
abortMultipart(target: MultipartTarget): Promise<{
|
|
969
|
+
aborted: boolean;
|
|
970
|
+
}>;
|
|
971
|
+
/**
|
|
972
|
+
* Resolve a single gateway delivery URL for the requested locale/variant/purpose.
|
|
973
|
+
* Throws if the binding is not `ready`.
|
|
974
|
+
*/
|
|
975
|
+
url(input?: ResolveUrlInput): Promise<ResolveUrlResult>;
|
|
976
|
+
/**
|
|
977
|
+
* Update the binding's delivery visibility (token-based; no byte relocation —
|
|
978
|
+
* a downgrade purges the gateway cache). Returns the refreshed asset entry.
|
|
979
|
+
*/
|
|
980
|
+
updateVisibility(visibility: AssetVisibility, options?: {
|
|
981
|
+
locale?: string;
|
|
982
|
+
}): Promise<AssetEntryResponse<T>>;
|
|
983
|
+
/**
|
|
984
|
+
* Set the binding's normalized (0..1, origin top-left) smart-crop focal point
|
|
985
|
+
* (plan 18) so `cover`/`crop` variants frame the subject. Per locale for
|
|
986
|
+
* file-localized asset types; token-based (no byte change). Returns the
|
|
987
|
+
* refreshed asset entry.
|
|
988
|
+
*/
|
|
989
|
+
setFocalPoint(focalPoint: {
|
|
990
|
+
x: number;
|
|
991
|
+
y: number;
|
|
992
|
+
}, options?: {
|
|
993
|
+
locale?: string;
|
|
994
|
+
}): Promise<AssetEntryResponse<T>>;
|
|
995
|
+
/**
|
|
996
|
+
* Remove the file binding, clean up the underlying bytes, and purge the
|
|
997
|
+
* gateway cache. The asset entry itself is preserved.
|
|
998
|
+
*/
|
|
999
|
+
delete(options?: {
|
|
1000
|
+
locale?: string;
|
|
1001
|
+
}): Promise<void>;
|
|
1002
|
+
/**
|
|
1003
|
+
* Poll the asset entry until its file binding reaches `ready` (resolves with
|
|
1004
|
+
* the ready entry) or `failed` (throws). Times out after `timeoutMs`.
|
|
1005
|
+
*/
|
|
1006
|
+
waitUntilReady(options?: WaitUntilReadyOptions): Promise<AssetEntryResponse<T>>;
|
|
1007
|
+
}
|
|
1008
|
+
/**
|
|
1009
|
+
* High-level one-shot upload: create draft entry → presign → PUT bytes →
|
|
1010
|
+
* confirm → (optionally) wait for `ready`. Handles the common image/file flow
|
|
1011
|
+
* (single R2 PUT). For advanced/resumable flows (large files, video tus,
|
|
1012
|
+
* progress) use the lower-level `file(uid)` builder — full upload resilience is
|
|
1013
|
+
* plan 17.
|
|
1014
|
+
*/
|
|
1015
|
+
declare class AssetUploadBuilder<T extends BaseContent = BaseContent> {
|
|
1016
|
+
private readonly httpClient;
|
|
1017
|
+
private readonly assetType;
|
|
1018
|
+
private readonly file;
|
|
1019
|
+
private readonly defaultLocale?;
|
|
1020
|
+
private _fileName?;
|
|
1021
|
+
private _visibility?;
|
|
1022
|
+
private _locale?;
|
|
1023
|
+
private _publish?;
|
|
1024
|
+
private _content;
|
|
1025
|
+
private _slug?;
|
|
1026
|
+
private _waitForReady;
|
|
1027
|
+
private _waitOptions;
|
|
1028
|
+
private _onProgress?;
|
|
1029
|
+
private _validate?;
|
|
1030
|
+
private _maxPartRetries;
|
|
1031
|
+
constructor(httpClient: HttpClient, assetType: string, file: Blob, defaultLocale?: string | undefined);
|
|
1032
|
+
/** Subscribe to client → storage upload progress (single PUT + multipart). */
|
|
1033
|
+
onProgress(callback: (_progress: UploadProgress) => void): this;
|
|
1034
|
+
/**
|
|
1035
|
+
* Validate the file client-side (UX only) against explicit constraints before
|
|
1036
|
+
* any bytes leave the machine. Rejects instantly with a {@link FileValidationError}.
|
|
1037
|
+
*/
|
|
1038
|
+
validate(constraints: FileValidationConstraints): this;
|
|
1039
|
+
/** Bounded per-part retry attempts for multipart (default 3). */
|
|
1040
|
+
maxPartRetries(attempts: number): this;
|
|
1041
|
+
/** Set the original file name (defaults to `file.name` for `File` inputs). */
|
|
1042
|
+
filename(name: string): this;
|
|
1043
|
+
/** Set the initial delivery visibility (default `public`). */
|
|
1044
|
+
visibility(visibility: AssetVisibility): this;
|
|
1045
|
+
/** Target locale for file-localized asset types. */
|
|
1046
|
+
locale(locale: string): this;
|
|
1047
|
+
/** Suppress (or enable) auto-publish on ready. */
|
|
1048
|
+
publish(publish: boolean): this;
|
|
1049
|
+
/** Set the asset's metadata field values (e.g. `{ alt: '...' }`). */
|
|
1050
|
+
content(content: Record<string, unknown>): this;
|
|
1051
|
+
/** Set an explicit slug for the new entry. */
|
|
1052
|
+
slug(slug: string): this;
|
|
1053
|
+
/** Wait until the file binding becomes `ready` before resolving. */
|
|
1054
|
+
waitForReady(options?: boolean | Omit<WaitUntilReadyOptions, 'locale'>): this;
|
|
1055
|
+
/** Execute the full upload flow and resolve with the asset entry. */
|
|
1056
|
+
execute(): Promise<AssetEntryResponse<T>>;
|
|
1057
|
+
/** Single presigned PUT (≤ 50 MB / Stream POST). */
|
|
1058
|
+
private uploadSingle;
|
|
1059
|
+
/**
|
|
1060
|
+
* Resumable R2 multipart: slice into `partSize` chunks, skip already-uploaded
|
|
1061
|
+
* parts (resume via `list-parts`), PUT each remaining part with bounded retry,
|
|
1062
|
+
* then `complete`. Aborts the session on unrecoverable failure.
|
|
1063
|
+
*/
|
|
1064
|
+
private uploadMultipart;
|
|
1065
|
+
/** PUT a single part, retrying transient failures up to `_maxPartRetries`. */
|
|
1066
|
+
private putPartWithRetry;
|
|
1067
|
+
private emitProgress;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Client for a single asset type. Mirrors {@link ContentClient} (CRUD + query
|
|
1071
|
+
* over the same dynamic `/{assetType}` routes — assets are `entryType: 'asset'`
|
|
1072
|
+
* entries) and adds the `file(uid)` sub-resource builder + an `upload()` helper.
|
|
1073
|
+
*/
|
|
1074
|
+
declare class AssetClient<T extends BaseContent = BaseContent> {
|
|
1075
|
+
private readonly httpClient;
|
|
1076
|
+
private readonly assetType;
|
|
1077
|
+
private readonly defaultLocale?;
|
|
1078
|
+
constructor(httpClient: HttpClient, assetType: string, defaultLocale?: string | undefined);
|
|
1079
|
+
/** Create a query builder for this asset type. */
|
|
1080
|
+
query(): ContentQueryBuilder<AssetEntryResponse<T>>;
|
|
1081
|
+
/** Find an asset entry by id (or slug) with fluent options. */
|
|
1082
|
+
findById(id: string): ContentByIdBuilder<AssetEntryResponse<T>>;
|
|
1083
|
+
/** Fetch a single asset entry by id (or slug), or `null` if not found. */
|
|
1084
|
+
fetchOne(id: string, options?: {
|
|
1085
|
+
include?: string[];
|
|
1086
|
+
locale?: string;
|
|
1087
|
+
}): Promise<AssetEntryResponse<T> | null>;
|
|
1088
|
+
/** Fetch the first asset entry matching the conditions, or `null`. */
|
|
1089
|
+
fetchFirst(where?: WhereClause<AssetEntryResponse<T>>, locale?: string): Promise<AssetEntryResponse<T> | null>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Create a new asset entry as a draft. The binary is uploaded separately via
|
|
1092
|
+
* `file(uid)` (or use the high-level `upload()` helper), and the entry
|
|
1093
|
+
* auto-publishes when its file becomes ready (unless `publish: false`).
|
|
1094
|
+
*/
|
|
1095
|
+
create(data: CreateInput<T>, options?: CreateAssetOptions & RetryableWriteOptions): Promise<AssetEntryResponse<T>>;
|
|
1096
|
+
/** Update an asset entry's metadata fields (and/or slug). */
|
|
1097
|
+
update(id: string, data: UpdateInput<T>, options?: UpdateAssetOptions): Promise<AssetEntryResponse<T>>;
|
|
1098
|
+
/** Delete an asset entry (cascades file-byte cleanup + gateway purge). */
|
|
1099
|
+
delete(id: string, options?: ConditionalWriteOptions): Promise<void>;
|
|
1100
|
+
/** Get the file sub-resource builder for a specific asset entry. */
|
|
1101
|
+
file(entryUid: string): AssetFileBuilder<T>;
|
|
1102
|
+
/** Start a high-level upload (create → presign → PUT → confirm). */
|
|
1103
|
+
upload(file: Blob): AssetUploadBuilder<T>;
|
|
1104
|
+
/** Get the asset type id. */
|
|
1105
|
+
getAssetType(): string;
|
|
1106
|
+
/** Get the current default locale. */
|
|
1107
|
+
getDefaultLocale(): string | undefined;
|
|
1108
|
+
/** Create a new AssetClient for this type with a different default locale. */
|
|
1109
|
+
withLocale(locale: string): AssetClient<T>;
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Narrow an entry (e.g. a populated reference from `include`) to an asset entry.
|
|
1113
|
+
* Relies on the `_metadata.entryType` discriminator the API emits (plan 06).
|
|
1114
|
+
*
|
|
1115
|
+
* @example
|
|
1116
|
+
* ```typescript
|
|
1117
|
+
* const article = await relyio.content('article').fetchOne(id, { include: ['hero'] })
|
|
1118
|
+
* if (isAssetEntry(article?.hero)) {
|
|
1119
|
+
* console.log(article.hero.urls?.original)
|
|
1120
|
+
* }
|
|
1121
|
+
* ```
|
|
1122
|
+
*/
|
|
1123
|
+
declare function isAssetEntry<T extends BaseContent = BaseContent>(entry: unknown): entry is AssetEntryResponse<T>;
|
|
1124
|
+
/**
|
|
1125
|
+
* A reference field populated (via `include`) with a full asset entry. Identical
|
|
1126
|
+
* to {@link AssetEntryResponse}; named for readability at reference call sites.
|
|
1127
|
+
*/
|
|
1128
|
+
type PopulatedAssetReference<T extends BaseContent = BaseContent> = AssetEntryResponse<T>;
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* Singleton fetch options
|
|
1132
|
+
*/
|
|
1133
|
+
interface SingletonFetchOptions {
|
|
1134
|
+
/** Locale for localized content */
|
|
1135
|
+
locale?: string;
|
|
1136
|
+
/** Reference fields to populate */
|
|
1137
|
+
include?: string[];
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Singleton client for managing singleton content operations
|
|
1141
|
+
* Provides a fluent API for singleton operations following the same pattern as ContentClient
|
|
1142
|
+
*
|
|
1143
|
+
* @example
|
|
1144
|
+
* ```typescript
|
|
1145
|
+
* const homepage = await client.singleton('homepage')
|
|
1146
|
+
* .include(['featuredProducts', 'heroImage'])
|
|
1147
|
+
* .locale('en')
|
|
1148
|
+
* .fetch()
|
|
1149
|
+
* ```
|
|
1150
|
+
*/
|
|
1151
|
+
declare class SingletonClient<T = unknown> {
|
|
1152
|
+
private httpClient;
|
|
1153
|
+
private singletonKey;
|
|
1154
|
+
private includeFields?;
|
|
1155
|
+
private localeValue?;
|
|
1156
|
+
constructor(httpClient: HttpClient, singletonKey: string);
|
|
1157
|
+
/**
|
|
1158
|
+
* Include reference fields in the response
|
|
1159
|
+
* @param fields - Reference field names to populate
|
|
1160
|
+
*/
|
|
1161
|
+
include(fields: string[]): this;
|
|
1162
|
+
/**
|
|
1163
|
+
* Set locale for localized content
|
|
1164
|
+
* @param locale - Locale code (e.g., 'en', 'de', 'fr')
|
|
1165
|
+
*/
|
|
1166
|
+
locale(locale: string): this;
|
|
1167
|
+
/**
|
|
1168
|
+
* Fetch the singleton content
|
|
1169
|
+
* @param options - Optional fetch options (alternative to fluent methods)
|
|
1170
|
+
*/
|
|
1171
|
+
fetch(options?: SingletonFetchOptions): Promise<T | null>;
|
|
1172
|
+
/**
|
|
1173
|
+
* Fetch the singleton **and the entity tag that read served**, which is what
|
|
1174
|
+
* `update`'s `ifMatch` takes (`INV-API-CONDITIONAL-WRITE-IS-REACHABLE`).
|
|
1175
|
+
*
|
|
1176
|
+
* `entityTag` is absent on a cache HIT: a cached body cannot know the current
|
|
1177
|
+
* version, and a stale tag would refuse the very next write.
|
|
1178
|
+
*/
|
|
1179
|
+
fetchWithTag(options?: SingletonFetchOptions): Promise<{
|
|
1180
|
+
content: T;
|
|
1181
|
+
entityTag?: string;
|
|
1182
|
+
}>;
|
|
1183
|
+
/**
|
|
1184
|
+
* Update singleton content. The API auto-publishes on PATCH — there is no
|
|
1185
|
+
* separate publish route; calling `update()` writes and publishes.
|
|
1186
|
+
* @param data - The content fields to update
|
|
1187
|
+
* @param locale - Optional locale for localized content (overrides fluent locale)
|
|
1188
|
+
* @param options - `If-Match` / `Idempotency-Key`, both declared on this route
|
|
1189
|
+
*/
|
|
1190
|
+
update(data: Partial<T>, locale?: string, options?: ConditionalWriteOptions): Promise<T>;
|
|
1191
|
+
/**
|
|
1192
|
+
* Check if singleton exists
|
|
1193
|
+
*/
|
|
1194
|
+
exists(): Promise<boolean>;
|
|
1195
|
+
/**
|
|
1196
|
+
* Get version history for one locale of the singleton.
|
|
1197
|
+
*
|
|
1198
|
+
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
1199
|
+
* schema default, no fallback is applied, and a locale with no history returns an empty array
|
|
1200
|
+
* rather than another locale's rows. Every row names the locale it belongs to.
|
|
1201
|
+
*/
|
|
1202
|
+
versions(options?: {
|
|
1203
|
+
limit?: number;
|
|
1204
|
+
locale?: string;
|
|
1205
|
+
}): Promise<Array<T & {
|
|
1206
|
+
versionNumber: number;
|
|
1207
|
+
locale: string;
|
|
1208
|
+
}>>;
|
|
1209
|
+
/**
|
|
1210
|
+
* Get a specific version of the singleton.
|
|
1211
|
+
*
|
|
1212
|
+
* `locale` defaults to the schema default. Version numbers are per locale, so version 2 is
|
|
1213
|
+
* different content in each one.
|
|
1214
|
+
*/
|
|
1215
|
+
version(versionNumber: number, options?: {
|
|
1216
|
+
locale?: string;
|
|
1217
|
+
}): Promise<T | null>;
|
|
1218
|
+
/**
|
|
1219
|
+
* Get the singleton key
|
|
1220
|
+
*/
|
|
1221
|
+
getSingletonKey(): string;
|
|
1222
|
+
/**
|
|
1223
|
+
* Reset fluent options for reuse
|
|
1224
|
+
*/
|
|
1225
|
+
reset(): this;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Settings fetch options
|
|
1230
|
+
*/
|
|
1231
|
+
interface SettingsFetchOptions {
|
|
1232
|
+
/** Locale for localized settings */
|
|
1233
|
+
locale?: string;
|
|
1234
|
+
/** Reference fields to populate */
|
|
1235
|
+
include?: string[];
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Settings client for managing settings group operations
|
|
1239
|
+
* Provides a fluent API for settings operations following the same pattern as ContentClient
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
* ```typescript
|
|
1243
|
+
* const emailConfig = await client.settings('email-config')
|
|
1244
|
+
* .include(['defaultTemplate'])
|
|
1245
|
+
* .locale('en')
|
|
1246
|
+
* .fetch()
|
|
1247
|
+
* ```
|
|
1248
|
+
*/
|
|
1249
|
+
declare class SettingsClient<T = unknown> {
|
|
1250
|
+
private readonly httpClient;
|
|
1251
|
+
private readonly groupId;
|
|
1252
|
+
private includeFields?;
|
|
1253
|
+
private localeValue?;
|
|
1254
|
+
constructor(httpClient: HttpClient, groupId: string);
|
|
1255
|
+
/**
|
|
1256
|
+
* Include reference fields in the response
|
|
1257
|
+
* @param fields - Reference field names to populate
|
|
1258
|
+
*/
|
|
1259
|
+
include(fields: string[]): this;
|
|
1260
|
+
/**
|
|
1261
|
+
* Set locale for localized settings
|
|
1262
|
+
* @param locale - Locale code (e.g., 'en', 'de', 'fr')
|
|
1263
|
+
*/
|
|
1264
|
+
locale(locale: string): this;
|
|
1265
|
+
/**
|
|
1266
|
+
* Fetch the settings group
|
|
1267
|
+
* @param options - Optional fetch options (alternative to fluent methods)
|
|
1268
|
+
*/
|
|
1269
|
+
fetch(options?: SettingsFetchOptions): Promise<T | null>;
|
|
1270
|
+
/**
|
|
1271
|
+
* Update settings group
|
|
1272
|
+
* @param settings - The settings fields to update
|
|
1273
|
+
* @param locale - Optional locale for localized settings (overrides fluent locale)
|
|
1274
|
+
*/
|
|
1275
|
+
update(settings: Partial<T>, locale?: string, options?: ConditionalWriteOptions): Promise<T>;
|
|
1276
|
+
/**
|
|
1277
|
+
* Fetch the group **and the entity tag that read served**, which is what
|
|
1278
|
+
* `update`'s and `reset`'s `ifMatch` take
|
|
1279
|
+
* (`INV-API-CONDITIONAL-WRITE-IS-REACHABLE`).
|
|
1280
|
+
*/
|
|
1281
|
+
fetchWithTag(options?: SettingsFetchOptions): Promise<{
|
|
1282
|
+
settings: T;
|
|
1283
|
+
entityTag?: string;
|
|
1284
|
+
}>;
|
|
1285
|
+
/**
|
|
1286
|
+
* Reset settings to default values
|
|
1287
|
+
* @param locale - Optional locale for localized settings
|
|
1288
|
+
*/
|
|
1289
|
+
reset(locale?: string, options?: ConditionalWriteOptions): Promise<T>;
|
|
1290
|
+
/**
|
|
1291
|
+
* Get default settings for this group
|
|
1292
|
+
*/
|
|
1293
|
+
getDefaults(): Promise<T>;
|
|
1294
|
+
/**
|
|
1295
|
+
* Check if settings group exists
|
|
1296
|
+
*/
|
|
1297
|
+
exists(): Promise<boolean>;
|
|
1298
|
+
/**
|
|
1299
|
+
* Get version history for one locale of the settings group.
|
|
1300
|
+
*
|
|
1301
|
+
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
1302
|
+
* schema default, no fallback is applied, and a locale with no history returns an empty array
|
|
1303
|
+
* rather than another locale's rows. Every row names the locale it belongs to.
|
|
1304
|
+
*/
|
|
1305
|
+
versions(options?: {
|
|
1306
|
+
limit?: number;
|
|
1307
|
+
locale?: string;
|
|
1308
|
+
}): Promise<Array<T & {
|
|
1309
|
+
versionNumber: number;
|
|
1310
|
+
locale: string;
|
|
1311
|
+
}>>;
|
|
1312
|
+
/**
|
|
1313
|
+
* Get a specific version of the settings.
|
|
1314
|
+
*
|
|
1315
|
+
* `locale` defaults to the schema default. Version numbers are per locale, so version 2 is
|
|
1316
|
+
* different content in each one.
|
|
1317
|
+
*/
|
|
1318
|
+
version(versionNumber: number, options?: {
|
|
1319
|
+
locale?: string;
|
|
1320
|
+
}): Promise<T | null>;
|
|
1321
|
+
/**
|
|
1322
|
+
* Get the settings group ID
|
|
1323
|
+
*/
|
|
1324
|
+
getGroupId(): string;
|
|
1325
|
+
/**
|
|
1326
|
+
* Reset fluent options for reuse
|
|
1327
|
+
*/
|
|
1328
|
+
resetOptions(): this;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
/**
|
|
1332
|
+
* Search mode for content queries
|
|
1333
|
+
*/
|
|
1334
|
+
type SearchMode = 'keyword' | 'semantic' | 'hybrid';
|
|
1335
|
+
/**
|
|
1336
|
+
* One search hit as the route emits it: the entry fields at the top level,
|
|
1337
|
+
* plus optional score annotations. There is no per-item `data` wrapper.
|
|
1338
|
+
*/
|
|
1339
|
+
type SearchResultItem<T = unknown> = T & {
|
|
1340
|
+
_score?: number;
|
|
1341
|
+
_scoreBreakdown?: {
|
|
1342
|
+
keyword?: number;
|
|
1343
|
+
semantic?: number;
|
|
1344
|
+
};
|
|
1345
|
+
_highlights?: Record<string, string[]>;
|
|
1346
|
+
};
|
|
1347
|
+
/**
|
|
1348
|
+
* Search response from API
|
|
1349
|
+
*/
|
|
1350
|
+
/**
|
|
1351
|
+
* What `POST /v1/search` serves, **read from the committed document**.
|
|
1352
|
+
*
|
|
1353
|
+
* `{ data, page: { offset, limit, total }, meta }` — search is the offset
|
|
1354
|
+
* dialect precisely because a facet-bearing result wants a total and an offset
|
|
1355
|
+
* (Decision 5), and the facets, the strategy the engine chose and its warnings
|
|
1356
|
+
* ride the declared `meta` sibling because none of them is an item or a page
|
|
1357
|
+
* fact.
|
|
1358
|
+
*
|
|
1359
|
+
* The hand-written `{ items, total?, metadata? }` this replaces named three
|
|
1360
|
+
* keys the route does not send. `SearchBuilder.items()` returned `undefined`
|
|
1361
|
+
* and `.total` was always `undefined` — with nothing able to see either,
|
|
1362
|
+
* because the type asserted them.
|
|
1363
|
+
*/
|
|
1364
|
+
type SearchResponse<T = unknown> = Wire<'/v1/search', 'post', SearchResultItem<T>>;
|
|
1365
|
+
/**
|
|
1366
|
+
* Autocomplete suggestion
|
|
1367
|
+
*/
|
|
1368
|
+
interface AutocompleteSuggestion {
|
|
1369
|
+
/** Suggested text */
|
|
1370
|
+
text: string;
|
|
1371
|
+
/** Highlighted version */
|
|
1372
|
+
highlighted?: string;
|
|
1373
|
+
/** Score */
|
|
1374
|
+
score?: number;
|
|
1375
|
+
/** Source entry ID */
|
|
1376
|
+
entryId?: string;
|
|
1377
|
+
/** Content type */
|
|
1378
|
+
contentType?: string;
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* Autocomplete response
|
|
1382
|
+
*/
|
|
1383
|
+
/**
|
|
1384
|
+
* What `POST /v1/search/autocomplete` serves. The suggestions are the
|
|
1385
|
+
* collection's `data`; the query it completed and the field it matched on ride
|
|
1386
|
+
* `meta`. Autocomplete is unpaginated, so its page reports `offset: 0` and a
|
|
1387
|
+
* `total` equal to what it returned — the dialect is declared rather than
|
|
1388
|
+
* omitted so one collection shape covers every list.
|
|
1389
|
+
*/
|
|
1390
|
+
type AutocompleteResponse = Wire<'/v1/search/autocomplete', 'post', AutocompleteSuggestion>;
|
|
1391
|
+
/**
|
|
1392
|
+
* One similar-content hit as the route emits it — a flat entry, no `data` wrapper.
|
|
1393
|
+
*/
|
|
1394
|
+
type SimilarResult<T = unknown> = T & {
|
|
1395
|
+
_score?: number;
|
|
1396
|
+
};
|
|
1397
|
+
/**
|
|
1398
|
+
* Similar response
|
|
1399
|
+
*/
|
|
1400
|
+
/** What `POST /v1/search/similar` serves. */
|
|
1401
|
+
type SimilarResponse<T = unknown> = Wire<'/v1/search/similar', 'post', SimilarResult<T>>;
|
|
1402
|
+
/**
|
|
1403
|
+
* Filter conditions for search
|
|
1404
|
+
*/
|
|
1405
|
+
type SearchFilter = Record<string, unknown>;
|
|
1406
|
+
/**
|
|
1407
|
+
* Field projection for search results
|
|
1408
|
+
*/
|
|
1409
|
+
type SearchFields<T> = {
|
|
1410
|
+
[K: string]: keyof T | string;
|
|
1411
|
+
};
|
|
1412
|
+
/**
|
|
1413
|
+
* Fluent builder for search queries
|
|
1414
|
+
*
|
|
1415
|
+
* @example
|
|
1416
|
+
* ```typescript
|
|
1417
|
+
* const results = await relyio.search('wireless headphones')
|
|
1418
|
+
* .in('product')
|
|
1419
|
+
* .where({ status: 'active' })
|
|
1420
|
+
* .searchFields(['title', 'description'])
|
|
1421
|
+
* .limit(20)
|
|
1422
|
+
* .includeScore()
|
|
1423
|
+
* .execute()
|
|
1424
|
+
* ```
|
|
1425
|
+
*/
|
|
1426
|
+
declare class SearchBuilder<T extends BaseContent = BaseContent> {
|
|
1427
|
+
private readonly httpClient;
|
|
1428
|
+
private query;
|
|
1429
|
+
private searchOptions;
|
|
1430
|
+
constructor(httpClient: HttpClient, query: string);
|
|
1431
|
+
/**
|
|
1432
|
+
* Search within a single content type
|
|
1433
|
+
* @param contentType - Content type to search in
|
|
1434
|
+
*/
|
|
1435
|
+
in<K extends string>(contentType: K): SearchBuilder<T>;
|
|
1436
|
+
/**
|
|
1437
|
+
* Search across multiple content types
|
|
1438
|
+
* @param contentTypes - Array of content types or '*' for all
|
|
1439
|
+
*/
|
|
1440
|
+
across(contentTypes: string[] | '*'): SearchBuilder<T>;
|
|
1441
|
+
/**
|
|
1442
|
+
* Add filter conditions
|
|
1443
|
+
* @param conditions - Filter conditions
|
|
1444
|
+
*/
|
|
1445
|
+
where(conditions: SearchFilter): this;
|
|
1446
|
+
/**
|
|
1447
|
+
* Specify which fields to search in
|
|
1448
|
+
* @param fields - Field names to search
|
|
1449
|
+
*/
|
|
1450
|
+
searchFields(fields: string[]): this;
|
|
1451
|
+
/**
|
|
1452
|
+
* Project specific fields in results
|
|
1453
|
+
* @param projection - Field mapping
|
|
1454
|
+
*/
|
|
1455
|
+
fields(projection: Record<string, string>): this;
|
|
1456
|
+
/**
|
|
1457
|
+
* Limit number of results
|
|
1458
|
+
* @param count - Maximum results
|
|
1459
|
+
*/
|
|
1460
|
+
limit(count: number): this;
|
|
1461
|
+
/**
|
|
1462
|
+
* Skip results for pagination
|
|
1463
|
+
* @param count - Number to skip
|
|
1464
|
+
*/
|
|
1465
|
+
offset(count: number): this;
|
|
1466
|
+
/**
|
|
1467
|
+
* Include relevance scores in results
|
|
1468
|
+
*/
|
|
1469
|
+
includeScore(): this;
|
|
1470
|
+
/**
|
|
1471
|
+
* Include score breakdown explanation
|
|
1472
|
+
*/
|
|
1473
|
+
explain(): this;
|
|
1474
|
+
/**
|
|
1475
|
+
* Set locale for localized content
|
|
1476
|
+
* @param locale - Locale code
|
|
1477
|
+
*/
|
|
1478
|
+
locale(locale: string): this;
|
|
1479
|
+
/**
|
|
1480
|
+
* Execute the search query
|
|
1481
|
+
*/
|
|
1482
|
+
execute(): Promise<SearchResponse<T>>;
|
|
1483
|
+
/**
|
|
1484
|
+
* Execute and return just the items (convenience method)
|
|
1485
|
+
*/
|
|
1486
|
+
items(): Promise<Array<SearchResultItem<T>>>;
|
|
1487
|
+
/**
|
|
1488
|
+
* Get the first result
|
|
1489
|
+
*/
|
|
1490
|
+
first(): Promise<SearchResultItem<T> | null>;
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* Fluent builder for autocomplete queries
|
|
1494
|
+
*
|
|
1495
|
+
* @example
|
|
1496
|
+
* ```typescript
|
|
1497
|
+
* const suggestions = await relyio.autocomplete('wire')
|
|
1498
|
+
* .in('product')
|
|
1499
|
+
* .field('title')
|
|
1500
|
+
* .fuzzy()
|
|
1501
|
+
* .limit(10)
|
|
1502
|
+
* .execute()
|
|
1503
|
+
* ```
|
|
1504
|
+
*/
|
|
1505
|
+
declare class AutocompleteBuilder {
|
|
1506
|
+
private readonly httpClient;
|
|
1507
|
+
private query;
|
|
1508
|
+
private autocompleteOptions;
|
|
1509
|
+
constructor(httpClient: HttpClient, query: string);
|
|
1510
|
+
/**
|
|
1511
|
+
* Autocomplete within a content type
|
|
1512
|
+
* @param contentType - Content type to search
|
|
1513
|
+
*/
|
|
1514
|
+
in(contentType: string): this;
|
|
1515
|
+
/**
|
|
1516
|
+
* Field to autocomplete on
|
|
1517
|
+
* @param fieldName - Field name (supports nested like 'category.name')
|
|
1518
|
+
*/
|
|
1519
|
+
field(fieldName: string): this;
|
|
1520
|
+
/**
|
|
1521
|
+
* Enable fuzzy matching for typo tolerance
|
|
1522
|
+
*/
|
|
1523
|
+
fuzzy(): this;
|
|
1524
|
+
/**
|
|
1525
|
+
* Add filter conditions
|
|
1526
|
+
* @param conditions - Filter conditions
|
|
1527
|
+
*/
|
|
1528
|
+
where(conditions: SearchFilter): this;
|
|
1529
|
+
/**
|
|
1530
|
+
* Limit number of suggestions
|
|
1531
|
+
* @param count - Maximum suggestions
|
|
1532
|
+
*/
|
|
1533
|
+
limit(count: number): this;
|
|
1534
|
+
/**
|
|
1535
|
+
* Set locale for localized content
|
|
1536
|
+
* @param locale - Locale code
|
|
1537
|
+
*/
|
|
1538
|
+
locale(locale: string): this;
|
|
1539
|
+
/**
|
|
1540
|
+
* Execute the autocomplete query
|
|
1541
|
+
*/
|
|
1542
|
+
execute(): Promise<AutocompleteResponse>;
|
|
1543
|
+
/**
|
|
1544
|
+
* Get just the suggestion texts
|
|
1545
|
+
*/
|
|
1546
|
+
texts(): Promise<string[]>;
|
|
1547
|
+
}
|
|
1548
|
+
/**
|
|
1549
|
+
* Fluent builder for finding similar content
|
|
1550
|
+
*
|
|
1551
|
+
* @example
|
|
1552
|
+
* ```typescript
|
|
1553
|
+
* const similar = await relyio.similar('entry_abc123')
|
|
1554
|
+
* .in('product')
|
|
1555
|
+
* .locale('fr-FR')
|
|
1556
|
+
* .limit(5)
|
|
1557
|
+
* .execute()
|
|
1558
|
+
* ```
|
|
1559
|
+
*/
|
|
1560
|
+
declare class SimilarBuilder<T extends BaseContent = BaseContent> {
|
|
1561
|
+
private readonly httpClient;
|
|
1562
|
+
private sourceId;
|
|
1563
|
+
private similarOptions;
|
|
1564
|
+
constructor(httpClient: HttpClient, sourceId: string);
|
|
1565
|
+
/**
|
|
1566
|
+
* Find similar content within a content type
|
|
1567
|
+
* @param contentType - Content type to search
|
|
1568
|
+
*/
|
|
1569
|
+
in(contentType: string): this;
|
|
1570
|
+
/**
|
|
1571
|
+
* Add filter conditions
|
|
1572
|
+
* @param conditions - Filter conditions
|
|
1573
|
+
*/
|
|
1574
|
+
where(conditions: SearchFilter): this;
|
|
1575
|
+
/**
|
|
1576
|
+
* Limit number of results
|
|
1577
|
+
* @param count - Maximum results
|
|
1578
|
+
*/
|
|
1579
|
+
limit(count: number): this;
|
|
1580
|
+
/**
|
|
1581
|
+
* Set locale for localized content
|
|
1582
|
+
* @param locale - Locale code
|
|
1583
|
+
*/
|
|
1584
|
+
locale(locale: string): this;
|
|
1585
|
+
/**
|
|
1586
|
+
* Execute the similar query
|
|
1587
|
+
*/
|
|
1588
|
+
execute(): Promise<SimilarResponse<T>>;
|
|
1589
|
+
/**
|
|
1590
|
+
* Get just the similar items
|
|
1591
|
+
*/
|
|
1592
|
+
items(): Promise<Array<SimilarResult<T>>>;
|
|
1593
|
+
/**
|
|
1594
|
+
* Get the most similar item
|
|
1595
|
+
*/
|
|
1596
|
+
first(): Promise<SimilarResult<T> | null>;
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Search client providing fluent access to all search capabilities
|
|
1600
|
+
*
|
|
1601
|
+
* @example
|
|
1602
|
+
* ```typescript
|
|
1603
|
+
* const searchClient = new SearchClient(httpClient)
|
|
1604
|
+
*
|
|
1605
|
+
* // Full-text/hybrid search
|
|
1606
|
+
* const products = await searchClient.search('wireless')
|
|
1607
|
+
* .in('product')
|
|
1608
|
+
* .limit(20)
|
|
1609
|
+
* .execute()
|
|
1610
|
+
*
|
|
1611
|
+
* // Autocomplete
|
|
1612
|
+
* const suggestions = await searchClient.autocomplete('wire')
|
|
1613
|
+
* .in('product')
|
|
1614
|
+
* .field('title')
|
|
1615
|
+
* .execute()
|
|
1616
|
+
*
|
|
1617
|
+
* // Find similar
|
|
1618
|
+
* const similar = await searchClient.similar('entry_123')
|
|
1619
|
+
* .in('product')
|
|
1620
|
+
* .execute()
|
|
1621
|
+
* ```
|
|
1622
|
+
*/
|
|
1623
|
+
declare class SearchClient {
|
|
1624
|
+
private readonly httpClient;
|
|
1625
|
+
constructor(httpClient: HttpClient);
|
|
1626
|
+
/**
|
|
1627
|
+
* Start a search query
|
|
1628
|
+
* @param query - Search query string
|
|
1629
|
+
*/
|
|
1630
|
+
search<T extends BaseContent = BaseContent>(query: string): SearchBuilder<T>;
|
|
1631
|
+
/**
|
|
1632
|
+
* Start an autocomplete query
|
|
1633
|
+
* @param query - Partial query to autocomplete
|
|
1634
|
+
*/
|
|
1635
|
+
autocomplete(query: string): AutocompleteBuilder;
|
|
1636
|
+
/**
|
|
1637
|
+
* Find content similar to a given entry
|
|
1638
|
+
* @param sourceId - Entry ID to find similar content for
|
|
1639
|
+
*/
|
|
1640
|
+
similar<T extends BaseContent = BaseContent>(sourceId: string): SimilarBuilder<T>;
|
|
1641
|
+
/**
|
|
1642
|
+
* Quick search helper - searches all content types
|
|
1643
|
+
* @param query - Search query
|
|
1644
|
+
* @param limit - Max results (default 20)
|
|
1645
|
+
*/
|
|
1646
|
+
global<T extends BaseContent = BaseContent>(query: string, limit?: number): Promise<SearchResponse<T>>;
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* HTTP methods supported in batch operations
|
|
1651
|
+
*/
|
|
1652
|
+
type BatchMethod = 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
1653
|
+
/**
|
|
1654
|
+
* A single batch operation
|
|
1655
|
+
*/
|
|
1656
|
+
interface BatchOperation {
|
|
1657
|
+
/** Optional operation ID for tracking */
|
|
1658
|
+
id?: string;
|
|
1659
|
+
/** HTTP method */
|
|
1660
|
+
method: BatchMethod;
|
|
1661
|
+
/** Path to resource (e.g., '/product' or '/product/entry_123') */
|
|
1662
|
+
path: string;
|
|
1663
|
+
/** Request body for create/update operations */
|
|
1664
|
+
body?: Record<string, unknown>;
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Batch execution options
|
|
1668
|
+
*/
|
|
1669
|
+
interface BatchOptions {
|
|
1670
|
+
/**
|
|
1671
|
+
* If true, the batch runs as one transaction: every operation lands or none does.
|
|
1672
|
+
*
|
|
1673
|
+
* Requires that all operations be the same kind of write — one transaction cannot span two
|
|
1674
|
+
* calls — so a batch mixing creates and deletes, or `update` and `replace`, is rejected with
|
|
1675
|
+
* a 400 before anything is attempted.
|
|
1676
|
+
*
|
|
1677
|
+
* @default false
|
|
1678
|
+
*/
|
|
1679
|
+
atomic?: boolean;
|
|
1680
|
+
/**
|
|
1681
|
+
* If true, run the checks and write nothing.
|
|
1682
|
+
*
|
|
1683
|
+
* Every entry is resolved, authorized and validated against its schema, so what passes a dry
|
|
1684
|
+
* run is what a real write accepts.
|
|
1685
|
+
*
|
|
1686
|
+
* @default false
|
|
1687
|
+
*/
|
|
1688
|
+
dryRun?: boolean;
|
|
1689
|
+
/**
|
|
1690
|
+
* If true, include full data in response
|
|
1691
|
+
* @default true
|
|
1692
|
+
*/
|
|
1693
|
+
returnData?: boolean;
|
|
1694
|
+
/**
|
|
1695
|
+
* If true, continue executing after failures (non-atomic mode only)
|
|
1696
|
+
* @default true
|
|
1697
|
+
*/
|
|
1698
|
+
continueOnError?: boolean;
|
|
1699
|
+
}
|
|
1700
|
+
/**
|
|
1701
|
+
* Result of a single operation in the batch
|
|
1702
|
+
*/
|
|
1703
|
+
/**
|
|
1704
|
+
* One batch item, **as the committed document describes the `multi` kind**.
|
|
1705
|
+
*
|
|
1706
|
+
* Read from `api-schema.ts` rather than imported from `@relyio/api-contract`
|
|
1707
|
+
* for the same reason every other response type here is: the document is the
|
|
1708
|
+
* one source, and a type this package publishes must resolve for a customer who
|
|
1709
|
+
* installs `@relyio/sdk` alone. The contract's runtime half is bundled; its
|
|
1710
|
+
* `.d.ts` is not something a consumer can reach.
|
|
1711
|
+
*
|
|
1712
|
+
* The hand-written version carried `success: boolean` and a per-item `status`
|
|
1713
|
+
* number. Both are gone from the wire and neither loss is a gap: the presence
|
|
1714
|
+
* of `error` already says whether the item succeeded (Decision 2, gap 16), and
|
|
1715
|
+
* a sub-response carrying its own HTTP status is exactly the duplication
|
|
1716
|
+
* `INV-API-NO-DUPLICATE-STATUS` removes. What replaced them says more, not
|
|
1717
|
+
* less — `outcome` distinguishes `created` from `updated` from `unchanged`
|
|
1718
|
+
* from `duplicate` from `skipped`, which one boolean never could.
|
|
1719
|
+
*/
|
|
1720
|
+
type BatchOperationResult = components['schemas']['MultiPayload']['results'][number];
|
|
1721
|
+
/** Summary of batch execution, from the contract. */
|
|
1722
|
+
type BatchSummary = components['schemas']['MultiSummary'];
|
|
1723
|
+
/**
|
|
1724
|
+
* The full batch payload: `{ results, summary }`.
|
|
1725
|
+
*
|
|
1726
|
+
* `transactionId`, `executionTimeMs` and `dryRun` were named here and are not
|
|
1727
|
+
* on the wire; nothing produced them and nothing could read them.
|
|
1728
|
+
*/
|
|
1729
|
+
type BatchResponse = components['schemas']['MultiPayload'];
|
|
1730
|
+
/**
|
|
1731
|
+
* Fluent builder for batch operations
|
|
1732
|
+
*
|
|
1733
|
+
* @example
|
|
1734
|
+
* ```typescript
|
|
1735
|
+
* const result = await relyio.batch()
|
|
1736
|
+
* .create('product', { content: { title: 'iPhone', price: 999 } })
|
|
1737
|
+
* .update('product', 'entry_abc', { content: { price: 899 } })
|
|
1738
|
+
* .delete('product', 'entry_xyz')
|
|
1739
|
+
* .upsertSingleton('homepage', { content: { hero: 'Welcome!' } })
|
|
1740
|
+
* .execute({ atomic: true })
|
|
1741
|
+
*
|
|
1742
|
+
* console.log(result.summary.succeeded) // 4
|
|
1743
|
+
* ```
|
|
1744
|
+
*/
|
|
1745
|
+
declare class BatchBuilder<TSchema = unknown> {
|
|
1746
|
+
private readonly httpClient;
|
|
1747
|
+
private operations;
|
|
1748
|
+
private defaultOptions;
|
|
1749
|
+
constructor(httpClient: HttpClient);
|
|
1750
|
+
/**
|
|
1751
|
+
* Add a create operation
|
|
1752
|
+
* @param contentType - Content type to create
|
|
1753
|
+
* @param data - Entry data with content field
|
|
1754
|
+
* @param id - Optional operation ID for tracking
|
|
1755
|
+
*/
|
|
1756
|
+
create<T extends BaseContent = BaseContent>(contentType: string, data: {
|
|
1757
|
+
content: CreateInput<T>;
|
|
1758
|
+
slug?: string;
|
|
1759
|
+
locale?: string;
|
|
1760
|
+
parentId?: string;
|
|
1761
|
+
sortOrder?: number;
|
|
1762
|
+
}, id?: string): this;
|
|
1763
|
+
/**
|
|
1764
|
+
* Add an update operation (partial update).
|
|
1765
|
+
*
|
|
1766
|
+
* The submitted fields are merged into the entry and the rest are left as they are. The merge is
|
|
1767
|
+
* field-level rather than deep: sending an object-typed field replaces that field's whole value.
|
|
1768
|
+
*
|
|
1769
|
+
* @param contentType - Content type
|
|
1770
|
+
* @param entryId - Entry ID to update
|
|
1771
|
+
* @param data - Fields to update
|
|
1772
|
+
* @param id - Optional operation ID for tracking
|
|
1773
|
+
*/
|
|
1774
|
+
update<T extends BaseContent = BaseContent>(contentType: string, entryId: string, data: {
|
|
1775
|
+
content?: UpdateInput<T>;
|
|
1776
|
+
slug?: string;
|
|
1777
|
+
locale?: string;
|
|
1778
|
+
parentId?: string;
|
|
1779
|
+
sortOrder?: number;
|
|
1780
|
+
}, id?: string): this;
|
|
1781
|
+
/**
|
|
1782
|
+
* Add a replace operation (full replacement).
|
|
1783
|
+
*
|
|
1784
|
+
* The payload becomes the entry's content for the addressed locale: fields you do not send are
|
|
1785
|
+
* cleared. Send the whole entry, or use {@link BatchClient.update} to change part of one.
|
|
1786
|
+
*
|
|
1787
|
+
* @param contentType - Content type
|
|
1788
|
+
* @param entryId - Entry ID to replace
|
|
1789
|
+
* @param data - Complete entry data
|
|
1790
|
+
* @param id - Optional operation ID for tracking
|
|
1791
|
+
*/
|
|
1792
|
+
replace<T extends BaseContent = BaseContent>(contentType: string, entryId: string, data: {
|
|
1793
|
+
content: CreateInput<T>;
|
|
1794
|
+
slug?: string;
|
|
1795
|
+
locale?: string;
|
|
1796
|
+
parentId?: string;
|
|
1797
|
+
sortOrder?: number;
|
|
1798
|
+
}, id?: string): this;
|
|
1799
|
+
/**
|
|
1800
|
+
* Add a delete operation
|
|
1801
|
+
* @param contentType - Content type
|
|
1802
|
+
* @param entryId - Entry ID to delete
|
|
1803
|
+
* @param id - Optional operation ID for tracking
|
|
1804
|
+
*/
|
|
1805
|
+
delete(contentType: string, entryId: string, id?: string): this;
|
|
1806
|
+
/**
|
|
1807
|
+
* Add a singleton upsert operation
|
|
1808
|
+
* @param singletonKey - Singleton key
|
|
1809
|
+
* @param data - Singleton content
|
|
1810
|
+
* @param id - Optional operation ID for tracking
|
|
1811
|
+
*/
|
|
1812
|
+
upsertSingleton(singletonKey: string, data: {
|
|
1813
|
+
content: Record<string, unknown>;
|
|
1814
|
+
locale?: string;
|
|
1815
|
+
}, id?: string): this;
|
|
1816
|
+
/**
|
|
1817
|
+
* Add a singleton create operation (alias for upsert with POST)
|
|
1818
|
+
* @param singletonKey - Singleton key
|
|
1819
|
+
* @param data - Singleton content
|
|
1820
|
+
* @param id - Optional operation ID for tracking
|
|
1821
|
+
*/
|
|
1822
|
+
createSingleton(singletonKey: string, data: {
|
|
1823
|
+
content: Record<string, unknown>;
|
|
1824
|
+
locale?: string;
|
|
1825
|
+
}, id?: string): this;
|
|
1826
|
+
/**
|
|
1827
|
+
* Add a raw operation (for advanced use cases)
|
|
1828
|
+
* @param operation - The operation to add
|
|
1829
|
+
*/
|
|
1830
|
+
raw(operation: BatchOperation): this;
|
|
1831
|
+
/**
|
|
1832
|
+
* Add multiple raw operations
|
|
1833
|
+
* @param operations - Operations to add
|
|
1834
|
+
*/
|
|
1835
|
+
rawMany(operations: BatchOperation[]): this;
|
|
1836
|
+
/**
|
|
1837
|
+
* Bulk create multiple entries of the same content type
|
|
1838
|
+
* @param contentType - Content type
|
|
1839
|
+
* @param items - Array of entry data
|
|
1840
|
+
*/
|
|
1841
|
+
bulkCreate<T extends BaseContent = BaseContent>(contentType: string, items: Array<{
|
|
1842
|
+
content: CreateInput<T>;
|
|
1843
|
+
slug?: string;
|
|
1844
|
+
locale?: string;
|
|
1845
|
+
id?: string;
|
|
1846
|
+
}>): this;
|
|
1847
|
+
/**
|
|
1848
|
+
* Bulk update multiple entries
|
|
1849
|
+
* @param contentType - Content type
|
|
1850
|
+
* @param updates - Array of { entryId, data } pairs
|
|
1851
|
+
*/
|
|
1852
|
+
bulkUpdate<T extends BaseContent = BaseContent>(contentType: string, updates: Array<{
|
|
1853
|
+
entryId: string;
|
|
1854
|
+
data: {
|
|
1855
|
+
content?: UpdateInput<T>;
|
|
1856
|
+
};
|
|
1857
|
+
id?: string;
|
|
1858
|
+
}>): this;
|
|
1859
|
+
/**
|
|
1860
|
+
* Bulk delete multiple entries
|
|
1861
|
+
* @param contentType - Content type
|
|
1862
|
+
* @param entryIds - Entry IDs to delete
|
|
1863
|
+
*/
|
|
1864
|
+
bulkDelete(contentType: string, entryIds: string[]): this;
|
|
1865
|
+
/**
|
|
1866
|
+
* Configure default options for execution
|
|
1867
|
+
* @param options - Batch options
|
|
1868
|
+
*/
|
|
1869
|
+
configure(options: BatchOptions): this;
|
|
1870
|
+
/**
|
|
1871
|
+
* Enable atomic mode (all-or-nothing)
|
|
1872
|
+
*/
|
|
1873
|
+
atomic(): this;
|
|
1874
|
+
/**
|
|
1875
|
+
* Enable dry-run mode (validate without executing)
|
|
1876
|
+
*/
|
|
1877
|
+
dryRun(): this;
|
|
1878
|
+
/**
|
|
1879
|
+
* Disable returning full data in response
|
|
1880
|
+
*/
|
|
1881
|
+
noData(): this;
|
|
1882
|
+
/**
|
|
1883
|
+
* Stop on first error (non-atomic mode)
|
|
1884
|
+
*/
|
|
1885
|
+
stopOnError(): this;
|
|
1886
|
+
/**
|
|
1887
|
+
* Get the current list of operations
|
|
1888
|
+
*/
|
|
1889
|
+
getOperations(): BatchOperation[];
|
|
1890
|
+
/**
|
|
1891
|
+
* Get the number of operations
|
|
1892
|
+
*/
|
|
1893
|
+
size(): number;
|
|
1894
|
+
/**
|
|
1895
|
+
* Clear all operations
|
|
1896
|
+
*/
|
|
1897
|
+
clear(): this;
|
|
1898
|
+
/**
|
|
1899
|
+
* Clone the builder
|
|
1900
|
+
*/
|
|
1901
|
+
clone(): BatchBuilder<TSchema>;
|
|
1902
|
+
/**
|
|
1903
|
+
* Execute the batch operations
|
|
1904
|
+
* @param options - Override default options
|
|
1905
|
+
*/
|
|
1906
|
+
execute(options?: BatchOptions): Promise<BatchResponse>;
|
|
1907
|
+
/**
|
|
1908
|
+
* Validate operations without executing (convenience for dry-run)
|
|
1909
|
+
*/
|
|
1910
|
+
validate(): Promise<BatchResponse>;
|
|
1911
|
+
/**
|
|
1912
|
+
* Execute and throw if any operation failed
|
|
1913
|
+
*/
|
|
1914
|
+
executeOrThrow(options?: BatchOptions): Promise<BatchResponse>;
|
|
1915
|
+
}
|
|
1916
|
+
/**
|
|
1917
|
+
* Batch client for bulk operations
|
|
1918
|
+
*
|
|
1919
|
+
* @example
|
|
1920
|
+
* ```typescript
|
|
1921
|
+
* const batchClient = new BatchClient(httpClient)
|
|
1922
|
+
*
|
|
1923
|
+
* // Create a batch with fluent API
|
|
1924
|
+
* const result = await batchClient.create()
|
|
1925
|
+
* .create('product', { content: { title: 'New Product' } })
|
|
1926
|
+
* .update('product', 'entry_123', { content: { price: 99 } })
|
|
1927
|
+
* .execute()
|
|
1928
|
+
*
|
|
1929
|
+
* // Quick bulk create
|
|
1930
|
+
* const products = await batchClient.bulkCreate('product', [
|
|
1931
|
+
* { content: { title: 'Product 1' } },
|
|
1932
|
+
* { content: { title: 'Product 2' } },
|
|
1933
|
+
* ])
|
|
1934
|
+
* ```
|
|
1935
|
+
*/
|
|
1936
|
+
declare class BatchClient<TSchema = unknown> {
|
|
1937
|
+
private readonly httpClient;
|
|
1938
|
+
constructor(httpClient: HttpClient);
|
|
1939
|
+
/**
|
|
1940
|
+
* Create a new batch builder
|
|
1941
|
+
*/
|
|
1942
|
+
create(): BatchBuilder<TSchema>;
|
|
1943
|
+
/**
|
|
1944
|
+
* Quick bulk create entries
|
|
1945
|
+
* @param contentType - Content type
|
|
1946
|
+
* @param items - Array of entry data
|
|
1947
|
+
* @param options - Batch options
|
|
1948
|
+
*/
|
|
1949
|
+
bulkCreate<T extends BaseContent = BaseContent>(contentType: string, items: Array<{
|
|
1950
|
+
content: CreateInput<T>;
|
|
1951
|
+
slug?: string;
|
|
1952
|
+
locale?: string;
|
|
1953
|
+
}>, options?: BatchOptions): Promise<BatchResponse>;
|
|
1954
|
+
/**
|
|
1955
|
+
* Quick bulk update entries
|
|
1956
|
+
* @param contentType - Content type
|
|
1957
|
+
* @param updates - Array of updates
|
|
1958
|
+
* @param options - Batch options
|
|
1959
|
+
*/
|
|
1960
|
+
bulkUpdate<T extends BaseContent = BaseContent>(contentType: string, updates: Array<{
|
|
1961
|
+
entryId: string;
|
|
1962
|
+
data: {
|
|
1963
|
+
content?: UpdateInput<T>;
|
|
1964
|
+
};
|
|
1965
|
+
}>, options?: BatchOptions): Promise<BatchResponse>;
|
|
1966
|
+
/**
|
|
1967
|
+
* Quick bulk delete entries
|
|
1968
|
+
* @param contentType - Content type
|
|
1969
|
+
* @param entryIds - Entry IDs to delete
|
|
1970
|
+
* @param options - Batch options
|
|
1971
|
+
*/
|
|
1972
|
+
bulkDelete(contentType: string, entryIds: string[], options?: BatchOptions): Promise<BatchResponse>;
|
|
1973
|
+
/**
|
|
1974
|
+
* Execute raw batch operations
|
|
1975
|
+
* @param operations - Array of operations
|
|
1976
|
+
* @param options - Batch options
|
|
1977
|
+
*/
|
|
1978
|
+
execute(operations: BatchOperation[], options?: BatchOptions): Promise<BatchResponse>;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
/**
|
|
1982
|
+
* Fetch block for retrieving content
|
|
1983
|
+
*/
|
|
1984
|
+
interface FetchBlock {
|
|
1985
|
+
/** Content type to fetch (mutually exclusive with singleton) */
|
|
1986
|
+
contentType?: string;
|
|
1987
|
+
/** Singleton key to fetch (mutually exclusive with contentType) */
|
|
1988
|
+
singleton?: string;
|
|
1989
|
+
/** Filter conditions */
|
|
1990
|
+
where?: Record<string, unknown>;
|
|
1991
|
+
/** Reference fields to populate */
|
|
1992
|
+
include?: string | string[];
|
|
1993
|
+
/** Sort specification */
|
|
1994
|
+
sort?: Record<string, 'asc' | 'desc'>;
|
|
1995
|
+
/** Maximum entries to return */
|
|
1996
|
+
limit?: number;
|
|
1997
|
+
/** Entries to skip */
|
|
1998
|
+
offset?: number;
|
|
1999
|
+
}
|
|
2000
|
+
/**
|
|
2001
|
+
* Aggregate block for computing metrics
|
|
2002
|
+
*/
|
|
2003
|
+
interface AggregateBlock {
|
|
2004
|
+
/** Source content type or query reference */
|
|
2005
|
+
source: string;
|
|
2006
|
+
/** Field to group by */
|
|
2007
|
+
by?: string | string[];
|
|
2008
|
+
/** Metrics to compute */
|
|
2009
|
+
metrics: Record<string, AggregateMetric>;
|
|
2010
|
+
}
|
|
2011
|
+
/**
|
|
2012
|
+
* Aggregate metric definition
|
|
2013
|
+
*/
|
|
2014
|
+
interface AggregateMetric {
|
|
2015
|
+
/** Aggregation function */
|
|
2016
|
+
fn: 'count' | 'sum' | 'avg' | 'min' | 'max' | 'first' | 'last';
|
|
2017
|
+
/** Field to aggregate (optional for count) */
|
|
2018
|
+
field?: string;
|
|
2019
|
+
}
|
|
2020
|
+
/**
|
|
2021
|
+
* Search block for full-text/semantic search
|
|
2022
|
+
*/
|
|
2023
|
+
interface SearchBlock {
|
|
2024
|
+
/** Content type to search */
|
|
2025
|
+
contentType: string;
|
|
2026
|
+
/** Search query (can use ${param} syntax) */
|
|
2027
|
+
query: string;
|
|
2028
|
+
/** Search mode */
|
|
2029
|
+
mode?: 'keyword' | 'semantic' | 'hybrid';
|
|
2030
|
+
/** Fields to search */
|
|
2031
|
+
searchFields?: string[];
|
|
2032
|
+
/** Additional filters */
|
|
2033
|
+
where?: Record<string, unknown>;
|
|
2034
|
+
/** Maximum results */
|
|
2035
|
+
limit?: number;
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* Similar block for vector similarity search
|
|
2039
|
+
*/
|
|
2040
|
+
interface SimilarBlock {
|
|
2041
|
+
/** Content type */
|
|
2042
|
+
contentType: string;
|
|
2043
|
+
/** Source entry ID */
|
|
2044
|
+
source: string;
|
|
2045
|
+
/** Minimum similarity threshold */
|
|
2046
|
+
threshold?: number;
|
|
2047
|
+
/** Additional filters */
|
|
2048
|
+
where?: Record<string, unknown>;
|
|
2049
|
+
/** Maximum results */
|
|
2050
|
+
limit?: number;
|
|
2051
|
+
}
|
|
2052
|
+
/**
|
|
2053
|
+
* Post-fetch filters with parameter support
|
|
2054
|
+
*/
|
|
2055
|
+
type FilterValue = string | number | boolean | {
|
|
2056
|
+
eq?: unknown;
|
|
2057
|
+
ne?: unknown;
|
|
2058
|
+
gt?: unknown;
|
|
2059
|
+
gte?: unknown;
|
|
2060
|
+
lt?: unknown;
|
|
2061
|
+
lte?: unknown;
|
|
2062
|
+
in?: unknown[];
|
|
2063
|
+
nin?: unknown[];
|
|
2064
|
+
contains?: unknown;
|
|
2065
|
+
startsWith?: string;
|
|
2066
|
+
endsWith?: string;
|
|
2067
|
+
};
|
|
2068
|
+
/**
|
|
2069
|
+
* Full-text search configuration
|
|
2070
|
+
*/
|
|
2071
|
+
interface FullTextConfig {
|
|
2072
|
+
/** Search query (can use ${param} syntax) */
|
|
2073
|
+
query: string;
|
|
2074
|
+
/** Fields to search */
|
|
2075
|
+
fields?: string[];
|
|
2076
|
+
/** Minimum score threshold */
|
|
2077
|
+
minScore?: number;
|
|
2078
|
+
}
|
|
2079
|
+
/**
|
|
2080
|
+
* Ad-hoc query definition
|
|
2081
|
+
*/
|
|
2082
|
+
interface AdhocQueryDefinition {
|
|
2083
|
+
/** Fetch block - retrieve content */
|
|
2084
|
+
fetch?: FetchBlock;
|
|
2085
|
+
/** Aggregate block - compute metrics */
|
|
2086
|
+
aggregate?: AggregateBlock;
|
|
2087
|
+
/** Search block - full-text/semantic search */
|
|
2088
|
+
search?: SearchBlock;
|
|
2089
|
+
/** Similar block - vector similarity */
|
|
2090
|
+
similar?: SimilarBlock;
|
|
2091
|
+
/** Field selection/transformation */
|
|
2092
|
+
select?: Record<string, string>;
|
|
2093
|
+
/** Post-fetch filters with parameter support */
|
|
2094
|
+
filters?: Record<string, FilterValue>;
|
|
2095
|
+
/** Full-text search configuration */
|
|
2096
|
+
fullText?: FullTextConfig;
|
|
2097
|
+
/** Cache policy */
|
|
2098
|
+
cache?: {
|
|
2099
|
+
ttl?: number;
|
|
2100
|
+
strategy?: 'stale-while-revalidate' | 'cache-first' | 'network-first';
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
/**
|
|
2104
|
+
* Ad-hoc query execution options
|
|
2105
|
+
*/
|
|
2106
|
+
interface AdhocQueryOptions {
|
|
2107
|
+
/** Include debug information in response */
|
|
2108
|
+
debug?: boolean;
|
|
2109
|
+
/** Bypass cache for this request */
|
|
2110
|
+
skipCache?: boolean;
|
|
2111
|
+
/** Custom timeout in milliseconds (1000-60000) */
|
|
2112
|
+
timeout?: number;
|
|
2113
|
+
}
|
|
2114
|
+
/**
|
|
2115
|
+
* Query execution metadata
|
|
2116
|
+
*/
|
|
2117
|
+
interface QueryMetadata {
|
|
2118
|
+
/** Query identifier */
|
|
2119
|
+
queryId: string;
|
|
2120
|
+
/** Execution time in milliseconds */
|
|
2121
|
+
executionTimeMs: number;
|
|
2122
|
+
/** Number of results */
|
|
2123
|
+
resultCount: number;
|
|
2124
|
+
/** ISO timestamp */
|
|
2125
|
+
timestamp: string;
|
|
2126
|
+
/** Whether result was from cache */
|
|
2127
|
+
cacheHit?: boolean;
|
|
2128
|
+
/** Generated pipeline (if debug enabled) */
|
|
2129
|
+
pipeline?: unknown[];
|
|
2130
|
+
/** Resolved parameters (if debug enabled) */
|
|
2131
|
+
parameters?: Record<string, unknown>;
|
|
2132
|
+
/** Validation warnings */
|
|
2133
|
+
warnings?: string[];
|
|
2134
|
+
}
|
|
2135
|
+
/**
|
|
2136
|
+
* The payload `POST /v1/query` serves: `{ result, metadata }`.
|
|
2137
|
+
*
|
|
2138
|
+
* The route is an `object` kind, so there is one payload key whether the query
|
|
2139
|
+
* fetched a list or a singleton — `result` is the records either way. Three
|
|
2140
|
+
* members of the hand-written type are gone and each for a stated reason:
|
|
2141
|
+
* `success` because the status line says it, `items` because no contract shape
|
|
2142
|
+
* introduces that key (`INV-API-SUCCESS-HAS-ONE-SHAPE`), and `errors` because a
|
|
2143
|
+
* failed query is a **refusal**, which arrives as `{ error: { code, messages } }`
|
|
2144
|
+
* and is thrown as a typed SDK error rather than returned as a 200 with a flag.
|
|
2145
|
+
*/
|
|
2146
|
+
interface AdhocQueryResult<T = unknown> {
|
|
2147
|
+
/** The records the query produced — an array for a list, one item for a singleton. */
|
|
2148
|
+
result?: T | T[];
|
|
2149
|
+
/** Execution metadata */
|
|
2150
|
+
metadata?: QueryMetadata;
|
|
2151
|
+
}
|
|
2152
|
+
/**
|
|
2153
|
+
* Fluent builder for ad-hoc queries
|
|
2154
|
+
*
|
|
2155
|
+
* @example
|
|
2156
|
+
* ```typescript
|
|
2157
|
+
* const result = await relyio.query.adhoc()
|
|
2158
|
+
* .fetch({
|
|
2159
|
+
* contentType: 'product',
|
|
2160
|
+
* where: { status: 'active' },
|
|
2161
|
+
* include: ['brand', 'categories'],
|
|
2162
|
+
* limit: 20
|
|
2163
|
+
* })
|
|
2164
|
+
* .select({
|
|
2165
|
+
* id: 'id',
|
|
2166
|
+
* title: 'title',
|
|
2167
|
+
* price: 'pricing.basePrice',
|
|
2168
|
+
* brandName: 'brand.name'
|
|
2169
|
+
* })
|
|
2170
|
+
* .filter('pricing.basePrice', { gte: '${minPrice}', lte: '${maxPrice}' })
|
|
2171
|
+
* .params({ minPrice: 100, maxPrice: 500 })
|
|
2172
|
+
* .debug()
|
|
2173
|
+
* .execute()
|
|
2174
|
+
* ```
|
|
2175
|
+
*/
|
|
2176
|
+
declare class AdhocQueryBuilder<T = unknown> {
|
|
2177
|
+
private readonly httpClient;
|
|
2178
|
+
private queryDef;
|
|
2179
|
+
private parameters;
|
|
2180
|
+
private options;
|
|
2181
|
+
constructor(httpClient: HttpClient);
|
|
2182
|
+
/**
|
|
2183
|
+
* Add a fetch block to retrieve content
|
|
2184
|
+
* @param config - Fetch configuration
|
|
2185
|
+
*/
|
|
2186
|
+
fetch(config: FetchBlock): this;
|
|
2187
|
+
/**
|
|
2188
|
+
* Fetch from a content type
|
|
2189
|
+
* @param contentType - Content type to fetch
|
|
2190
|
+
*/
|
|
2191
|
+
from(contentType: string): this;
|
|
2192
|
+
/**
|
|
2193
|
+
* Fetch a singleton
|
|
2194
|
+
* @param singletonKey - Singleton key
|
|
2195
|
+
*/
|
|
2196
|
+
singleton(singletonKey: string): this;
|
|
2197
|
+
/**
|
|
2198
|
+
* Add aggregate block
|
|
2199
|
+
* @param config - Aggregate configuration
|
|
2200
|
+
*/
|
|
2201
|
+
aggregate(config: AggregateBlock): this;
|
|
2202
|
+
/**
|
|
2203
|
+
* Add search block
|
|
2204
|
+
* @param config - Search configuration
|
|
2205
|
+
*/
|
|
2206
|
+
search(config: SearchBlock): this;
|
|
2207
|
+
/**
|
|
2208
|
+
* Add similar block
|
|
2209
|
+
* @param config - Similar configuration
|
|
2210
|
+
*/
|
|
2211
|
+
similar(config: SimilarBlock): this;
|
|
2212
|
+
/**
|
|
2213
|
+
* Add where conditions to fetch
|
|
2214
|
+
* @param conditions - Filter conditions
|
|
2215
|
+
*/
|
|
2216
|
+
where(conditions: Record<string, unknown>): this;
|
|
2217
|
+
/**
|
|
2218
|
+
* Add include for reference population
|
|
2219
|
+
* @param fields - Reference fields to include
|
|
2220
|
+
*/
|
|
2221
|
+
include(fields: string | string[]): this;
|
|
2222
|
+
/**
|
|
2223
|
+
* Add sort specification
|
|
2224
|
+
* @param sort - Sort configuration
|
|
2225
|
+
*/
|
|
2226
|
+
sort(sort: Record<string, 'asc' | 'desc'>): this;
|
|
2227
|
+
/**
|
|
2228
|
+
* Sort by field ascending
|
|
2229
|
+
* @param field - Field to sort by
|
|
2230
|
+
*/
|
|
2231
|
+
sortAsc(field: string): this;
|
|
2232
|
+
/**
|
|
2233
|
+
* Sort by field descending
|
|
2234
|
+
* @param field - Field to sort by
|
|
2235
|
+
*/
|
|
2236
|
+
sortDesc(field: string): this;
|
|
2237
|
+
/**
|
|
2238
|
+
* Limit results
|
|
2239
|
+
* @param count - Maximum results
|
|
2240
|
+
*/
|
|
2241
|
+
limit(count: number): this;
|
|
2242
|
+
/**
|
|
2243
|
+
* Skip results
|
|
2244
|
+
* @param count - Number to skip
|
|
2245
|
+
*/
|
|
2246
|
+
offset(count: number): this;
|
|
2247
|
+
/**
|
|
2248
|
+
* Select and transform fields in output
|
|
2249
|
+
* @param projection - Field mapping (outputField: sourceField)
|
|
2250
|
+
*/
|
|
2251
|
+
select(projection: Record<string, string>): this;
|
|
2252
|
+
/**
|
|
2253
|
+
* Add a post-fetch filter (supports ${param} syntax)
|
|
2254
|
+
* @param field - Field path to filter
|
|
2255
|
+
* @param condition - Filter condition
|
|
2256
|
+
*/
|
|
2257
|
+
filter(field: string, condition: FilterValue): this;
|
|
2258
|
+
/**
|
|
2259
|
+
* Add full-text search
|
|
2260
|
+
* @param config - Full-text configuration
|
|
2261
|
+
*/
|
|
2262
|
+
fullText(config: FullTextConfig): this;
|
|
2263
|
+
/**
|
|
2264
|
+
* Set query parameters
|
|
2265
|
+
* @param params - Parameter values
|
|
2266
|
+
*/
|
|
2267
|
+
params(params: Record<string, unknown>): this;
|
|
2268
|
+
/**
|
|
2269
|
+
* Set a single parameter
|
|
2270
|
+
* @param name - Parameter name
|
|
2271
|
+
* @param value - Parameter value
|
|
2272
|
+
*/
|
|
2273
|
+
param(name: string, value: unknown): this;
|
|
2274
|
+
/**
|
|
2275
|
+
* Enable debug mode
|
|
2276
|
+
*/
|
|
2277
|
+
debug(): this;
|
|
2278
|
+
/**
|
|
2279
|
+
* Skip cache for this request
|
|
2280
|
+
*/
|
|
2281
|
+
skipCache(): this;
|
|
2282
|
+
/**
|
|
2283
|
+
* Set custom timeout
|
|
2284
|
+
* @param ms - Timeout in milliseconds (1000-60000)
|
|
2285
|
+
*/
|
|
2286
|
+
timeout(ms: number): this;
|
|
2287
|
+
/**
|
|
2288
|
+
* Set cache policy
|
|
2289
|
+
* @param ttl - Cache TTL in seconds
|
|
2290
|
+
* @param strategy - Cache strategy
|
|
2291
|
+
*/
|
|
2292
|
+
cache(ttl: number, strategy?: 'stale-while-revalidate' | 'cache-first' | 'network-first'): this;
|
|
2293
|
+
/**
|
|
2294
|
+
* Get the query definition (for debugging)
|
|
2295
|
+
*/
|
|
2296
|
+
getDefinition(): AdhocQueryDefinition;
|
|
2297
|
+
/**
|
|
2298
|
+
* Get the parameters (for debugging)
|
|
2299
|
+
*/
|
|
2300
|
+
getParameters(): Record<string, unknown>;
|
|
2301
|
+
/**
|
|
2302
|
+
* Execute the query
|
|
2303
|
+
*/
|
|
2304
|
+
execute(): Promise<AdhocQueryResult<T>>;
|
|
2305
|
+
/**
|
|
2306
|
+
* Execute and return the records as an array (for list queries).
|
|
2307
|
+
*/
|
|
2308
|
+
items(): Promise<T[]>;
|
|
2309
|
+
/**
|
|
2310
|
+
* Execute and return the single record (for singleton queries).
|
|
2311
|
+
*/
|
|
2312
|
+
data(): Promise<T | undefined>;
|
|
2313
|
+
/**
|
|
2314
|
+
* Clone the builder
|
|
2315
|
+
*/
|
|
2316
|
+
clone(): AdhocQueryBuilder<T>;
|
|
2317
|
+
}
|
|
2318
|
+
/**
|
|
2319
|
+
* Client for executing ad-hoc queries
|
|
2320
|
+
*
|
|
2321
|
+
* @example
|
|
2322
|
+
* ```typescript
|
|
2323
|
+
* const queryClient = new AdhocQueryClient(httpClient)
|
|
2324
|
+
*
|
|
2325
|
+
* // Fluent builder
|
|
2326
|
+
* const products = await queryClient.build()
|
|
2327
|
+
* .from('product')
|
|
2328
|
+
* .where({ status: 'active' })
|
|
2329
|
+
* .limit(20)
|
|
2330
|
+
* .execute()
|
|
2331
|
+
*
|
|
2332
|
+
* // Direct execution
|
|
2333
|
+
* const result = await queryClient.execute({
|
|
2334
|
+
* fetch: { contentType: 'product', limit: 10 }
|
|
2335
|
+
* })
|
|
2336
|
+
* ```
|
|
2337
|
+
*/
|
|
2338
|
+
declare class AdhocQueryClient {
|
|
2339
|
+
private readonly httpClient;
|
|
2340
|
+
constructor(httpClient: HttpClient);
|
|
2341
|
+
/**
|
|
2342
|
+
* Create a new query builder
|
|
2343
|
+
*/
|
|
2344
|
+
build<T = unknown>(): AdhocQueryBuilder<T>;
|
|
2345
|
+
/**
|
|
2346
|
+
* Execute a query definition directly
|
|
2347
|
+
* @param definition - Query definition
|
|
2348
|
+
* @param parameters - Parameter values
|
|
2349
|
+
* @param options - Execution options
|
|
2350
|
+
*/
|
|
2351
|
+
execute<T = unknown>(definition: AdhocQueryDefinition, parameters?: Record<string, unknown>, options?: AdhocQueryOptions): Promise<AdhocQueryResult<T>>;
|
|
2352
|
+
/**
|
|
2353
|
+
* Quick fetch helper
|
|
2354
|
+
* @param contentType - Content type
|
|
2355
|
+
* @param options - Fetch options
|
|
2356
|
+
*/
|
|
2357
|
+
fetch<T = unknown>(contentType: string, options?: Omit<FetchBlock, 'contentType'>): Promise<T[]>;
|
|
2358
|
+
/**
|
|
2359
|
+
* Quick singleton fetch helper
|
|
2360
|
+
* @param singletonKey - Singleton key
|
|
2361
|
+
*/
|
|
2362
|
+
fetchSingleton<T = unknown>(singletonKey: string): Promise<T | undefined>;
|
|
2363
|
+
/**
|
|
2364
|
+
* Quick aggregate helper
|
|
2365
|
+
* @param source - Source content type
|
|
2366
|
+
* @param metrics - Metrics to compute
|
|
2367
|
+
* @param groupBy - Optional grouping field
|
|
2368
|
+
*/
|
|
2369
|
+
aggregate<T = unknown>(source: string, metrics: Record<string, AggregateMetric>, groupBy?: string | string[]): Promise<T[]>;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
/**
|
|
2373
|
+
* Type alias for any schema definition.
|
|
2374
|
+
* Uses `any` intentionally to accept schemas with any content types, components, etc.
|
|
2375
|
+
* This is necessary for the SDK to be flexible with user-defined schemas.
|
|
2376
|
+
*/
|
|
2377
|
+
type AnySchemaDefinition = SchemaDefinition<any, any, any, any, any>;
|
|
2378
|
+
/**
|
|
2379
|
+
* Client configuration with optional schema
|
|
2380
|
+
*/
|
|
2381
|
+
interface TypedClientConfig<TSchema extends AnySchemaDefinition | undefined = undefined> extends RelyIOConfig {
|
|
2382
|
+
/** Schema definition for type inference (optional - omit for dynamic/untyped usage) */
|
|
2383
|
+
schema?: TSchema;
|
|
2384
|
+
}
|
|
2385
|
+
/**
|
|
2386
|
+
* Typed RelyIO client with full schema awareness
|
|
2387
|
+
*
|
|
2388
|
+
* @example
|
|
2389
|
+
* ```typescript
|
|
2390
|
+
* import { createClient } from '@relyio/sdk'
|
|
2391
|
+
* import { schema } from './schema'
|
|
2392
|
+
*
|
|
2393
|
+
* const relyio = createClient({
|
|
2394
|
+
* apiKey: process.env.RELYIO_API_KEY!,
|
|
2395
|
+
* schema,
|
|
2396
|
+
* })
|
|
2397
|
+
*
|
|
2398
|
+
* // Content operations
|
|
2399
|
+
* const products = await relyio.content('product').query().execute()
|
|
2400
|
+
*
|
|
2401
|
+
* // Search
|
|
2402
|
+
* const results = await relyio.search('wireless').in('product').execute()
|
|
2403
|
+
*
|
|
2404
|
+
* // Batch operations
|
|
2405
|
+
* const batch = await relyio.batch()
|
|
2406
|
+
* .create('product', { content: { title: 'New' } })
|
|
2407
|
+
* .execute()
|
|
2408
|
+
* ```
|
|
2409
|
+
*/
|
|
2410
|
+
declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined = undefined> {
|
|
2411
|
+
private httpClient;
|
|
2412
|
+
private config;
|
|
2413
|
+
private _search;
|
|
2414
|
+
private _batch;
|
|
2415
|
+
private _adhocQuery;
|
|
2416
|
+
private _schema;
|
|
2417
|
+
constructor(config: TypedClientConfig<TSchema>);
|
|
2418
|
+
/**
|
|
2419
|
+
* Get the schema definition
|
|
2420
|
+
*/
|
|
2421
|
+
get schema(): TSchema;
|
|
2422
|
+
/**
|
|
2423
|
+
* Get the ad-hoc query client
|
|
2424
|
+
*/
|
|
2425
|
+
get query(): AdhocQueryClient;
|
|
2426
|
+
/**
|
|
2427
|
+
* Get a content client for a specific content type
|
|
2428
|
+
* Type-safe when schema is provided: autocompletes content type names AND field names
|
|
2429
|
+
*
|
|
2430
|
+
* @example
|
|
2431
|
+
* ```typescript
|
|
2432
|
+
* const products = await relyio.content('product')
|
|
2433
|
+
* .query()
|
|
2434
|
+
* .where({ status: 'active' }) // ← Field names autocomplete with schema!
|
|
2435
|
+
* .locale('en-US')
|
|
2436
|
+
* .limit(20)
|
|
2437
|
+
* .execute()
|
|
2438
|
+
* ```
|
|
2439
|
+
*/
|
|
2440
|
+
content<K extends TSchema extends AnySchemaDefinition ? SchemaContentTypeNames<TSchema> : string>(contentType: K): TSchema extends AnySchemaDefinition ? ContentClient<InferContentType<TSchema['contentTypes'][K & keyof TSchema['contentTypes']]>> : ContentClient<BaseContent>;
|
|
2441
|
+
/**
|
|
2442
|
+
* Get an asset client for a specific asset type.
|
|
2443
|
+
*
|
|
2444
|
+
* Mirrors `content()` but targets `entryType: 'asset'` entries on the same
|
|
2445
|
+
* dynamic `/{assetTypeId}` routes, and adds the `file(entryUid)` sub-resource
|
|
2446
|
+
* builder + a high-level `upload()` helper. Type-safe when a schema is
|
|
2447
|
+
* provided: autocompletes asset type names AND metadata field names.
|
|
2448
|
+
*
|
|
2449
|
+
* @example
|
|
2450
|
+
* ```typescript
|
|
2451
|
+
* const photo = await relyio.asset('productPhoto').upload(file)
|
|
2452
|
+
* .filename('shoe.jpg')
|
|
2453
|
+
* .visibility('public')
|
|
2454
|
+
* .execute()
|
|
2455
|
+
*
|
|
2456
|
+
* const heroUrl = await relyio.asset('productPhoto').file(photo._metadata.id).url({ variantId: 'hero' })
|
|
2457
|
+
* ```
|
|
2458
|
+
*/
|
|
2459
|
+
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>;
|
|
2460
|
+
/**
|
|
2461
|
+
* Get a singleton client for a specific singleton key
|
|
2462
|
+
* Type-safe when schema is provided: autocompletes singleton names AND field names
|
|
2463
|
+
*
|
|
2464
|
+
* @example
|
|
2465
|
+
* ```typescript
|
|
2466
|
+
* const homepage = await relyio.singleton('homepage')
|
|
2467
|
+
* .include(['featuredProducts'])
|
|
2468
|
+
* .locale('en')
|
|
2469
|
+
* .fetch()
|
|
2470
|
+
* ```
|
|
2471
|
+
*/
|
|
2472
|
+
singleton<K extends TSchema extends AnySchemaDefinition ? SchemaSingletonNames<TSchema> : string>(key: K): TSchema extends AnySchemaDefinition ? SingletonClient<InferSingleton<TSchema['singletonContentTypes'][K & keyof TSchema['singletonContentTypes']]>> : SingletonClient<unknown>;
|
|
2473
|
+
/**
|
|
2474
|
+
* Get a settings client for a specific settings group
|
|
2475
|
+
* Type-safe when schema is provided: autocompletes settings group names AND field names
|
|
2476
|
+
*
|
|
2477
|
+
* @example
|
|
2478
|
+
* ```typescript
|
|
2479
|
+
* const emailConfig = await relyio.settings('email-config')
|
|
2480
|
+
* .include(['defaultTemplate'])
|
|
2481
|
+
* .fetch()
|
|
2482
|
+
* ```
|
|
2483
|
+
*/
|
|
2484
|
+
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>;
|
|
2485
|
+
/**
|
|
2486
|
+
* Start a search query with full-text, semantic, or hybrid search
|
|
2487
|
+
*
|
|
2488
|
+
* @example
|
|
2489
|
+
* ```typescript
|
|
2490
|
+
* const results = await relyio.search('wireless headphones')
|
|
2491
|
+
* .in('product')
|
|
2492
|
+
* .where({ status: 'active' })
|
|
2493
|
+
* .limit(20)
|
|
2494
|
+
* .includeScore()
|
|
2495
|
+
* .execute()
|
|
2496
|
+
* ```
|
|
2497
|
+
*/
|
|
2498
|
+
search<T extends BaseContent = BaseContent>(query: string): SearchBuilder<T>;
|
|
2499
|
+
/**
|
|
2500
|
+
* Start an autocomplete query for search suggestions
|
|
2501
|
+
*
|
|
2502
|
+
* @example
|
|
2503
|
+
* ```typescript
|
|
2504
|
+
* const suggestions = await relyio.autocomplete('wire')
|
|
2505
|
+
* .in('product')
|
|
2506
|
+
* .field('title')
|
|
2507
|
+
* .fuzzy()
|
|
2508
|
+
* .limit(10)
|
|
2509
|
+
* .execute()
|
|
2510
|
+
* ```
|
|
2511
|
+
*/
|
|
2512
|
+
autocomplete(query: string): AutocompleteBuilder;
|
|
2513
|
+
/**
|
|
2514
|
+
* Find content similar to a given entry using vector search
|
|
2515
|
+
*
|
|
2516
|
+
* @example
|
|
2517
|
+
* ```typescript
|
|
2518
|
+
* const similar = await relyio.similar('entry_abc123')
|
|
2519
|
+
* .in('product')
|
|
2520
|
+
* .locale('fr-FR')
|
|
2521
|
+
* .limit(5)
|
|
2522
|
+
* .execute()
|
|
2523
|
+
* ```
|
|
2524
|
+
*/
|
|
2525
|
+
similar<T extends BaseContent = BaseContent>(sourceId: string): SimilarBuilder<T>;
|
|
2526
|
+
/**
|
|
2527
|
+
* Start a batch operation for bulk create/update/delete
|
|
2528
|
+
*
|
|
2529
|
+
* @example
|
|
2530
|
+
* ```typescript
|
|
2531
|
+
* const result = await relyio.batch()
|
|
2532
|
+
* .create('product', { content: { title: 'iPhone', price: 999 } })
|
|
2533
|
+
* .update('product', 'entry_abc', { content: { price: 899 } })
|
|
2534
|
+
* .delete('product', 'entry_xyz')
|
|
2535
|
+
* .upsertSingleton('homepage', { content: { hero: 'Welcome!' } })
|
|
2536
|
+
* .execute({ atomic: true })
|
|
2537
|
+
*
|
|
2538
|
+
* console.log(result.summary.succeeded)
|
|
2539
|
+
* ```
|
|
2540
|
+
*/
|
|
2541
|
+
batch(): BatchBuilder<NonNullable<TSchema>>;
|
|
2542
|
+
/**
|
|
2543
|
+
* Build and execute an ad-hoc query dynamically
|
|
2544
|
+
*
|
|
2545
|
+
* @example
|
|
2546
|
+
* ```typescript
|
|
2547
|
+
* const result = await relyio.adhoc()
|
|
2548
|
+
* .from('product')
|
|
2549
|
+
* .where({ status: 'active' })
|
|
2550
|
+
* .include(['brand', 'categories'])
|
|
2551
|
+
* .select({
|
|
2552
|
+
* id: 'id',
|
|
2553
|
+
* title: 'title',
|
|
2554
|
+
* price: 'pricing.basePrice'
|
|
2555
|
+
* })
|
|
2556
|
+
* .limit(20)
|
|
2557
|
+
* .execute()
|
|
2558
|
+
* ```
|
|
2559
|
+
*/
|
|
2560
|
+
adhoc<T = unknown>(): AdhocQueryBuilder<T>;
|
|
2561
|
+
/**
|
|
2562
|
+
* Execute a predefined query by name (from schema)
|
|
2563
|
+
* Type-safe when schema is provided: autocompletes query names
|
|
2564
|
+
*
|
|
2565
|
+
* @example
|
|
2566
|
+
* ```typescript
|
|
2567
|
+
* const featured = await relyio.executeQuery('featured-products', {
|
|
2568
|
+
* limit: 10,
|
|
2569
|
+
* category: 'electronics'
|
|
2570
|
+
* })
|
|
2571
|
+
* ```
|
|
2572
|
+
*/
|
|
2573
|
+
executeQuery<K extends TSchema extends AnySchemaDefinition ? SchemaQueryNames<TSchema> : string>(queryName: K, params?: Record<string, unknown>): Promise<unknown[]>;
|
|
2574
|
+
/**
|
|
2575
|
+
* Get schema information from the API
|
|
2576
|
+
*/
|
|
2577
|
+
getSchemaInfo(contentType?: string): Promise<unknown>;
|
|
2578
|
+
/**
|
|
2579
|
+
* List all content types from the API
|
|
2580
|
+
*/
|
|
2581
|
+
listContentTypes(): Promise<Array<{
|
|
2582
|
+
id: string;
|
|
2583
|
+
name: string;
|
|
2584
|
+
type: 'content' | 'singleton';
|
|
2585
|
+
}>>;
|
|
2586
|
+
/**
|
|
2587
|
+
* Get API health status
|
|
2588
|
+
*/
|
|
2589
|
+
health(): Promise<{
|
|
2590
|
+
status: 'ok' | 'degraded' | 'down';
|
|
2591
|
+
timestamp: string;
|
|
2592
|
+
}>;
|
|
2593
|
+
/**
|
|
2594
|
+
* Check if the API is ready
|
|
2595
|
+
*/
|
|
2596
|
+
ready(): Promise<boolean>;
|
|
2597
|
+
/**
|
|
2598
|
+
* Test the connection to the API
|
|
2599
|
+
*/
|
|
2600
|
+
testConnection(): Promise<boolean>;
|
|
2601
|
+
/**
|
|
2602
|
+
* Update the configuration and reinitialize all clients
|
|
2603
|
+
*/
|
|
2604
|
+
updateConfig(newConfig: Partial<RelyIOConfig>): void;
|
|
2605
|
+
/**
|
|
2606
|
+
* Get the current configuration
|
|
2607
|
+
*/
|
|
2608
|
+
getConfig(): Readonly<MergedRelyIOConfig>;
|
|
2609
|
+
/**
|
|
2610
|
+
* Set the API key
|
|
2611
|
+
*/
|
|
2612
|
+
setApiKey(apiKey: string): void;
|
|
2613
|
+
/**
|
|
2614
|
+
* Get the HTTP client instance (for advanced usage)
|
|
2615
|
+
*/
|
|
2616
|
+
getHttpClient(): HttpClient;
|
|
2617
|
+
/**
|
|
2618
|
+
* Create a locale-scoped client
|
|
2619
|
+
* All content operations on the returned client will use the specified locale
|
|
2620
|
+
*
|
|
2621
|
+
* Type-safe when schema is provided: autocompletes valid locale codes!
|
|
2622
|
+
*
|
|
2623
|
+
* @example
|
|
2624
|
+
* ```typescript
|
|
2625
|
+
* const spanish = relyio.withLocale('es-ES') // ← Autocompletes with schema!
|
|
2626
|
+
*
|
|
2627
|
+
* // All operations use Spanish
|
|
2628
|
+
* const products = await spanish.content('product').query().execute()
|
|
2629
|
+
* const homepage = await spanish.singleton('homepage').fetch()
|
|
2630
|
+
*
|
|
2631
|
+
* // Original client unchanged
|
|
2632
|
+
* const englishProducts = await relyio.content('product').query().execute()
|
|
2633
|
+
* ```
|
|
2634
|
+
*/
|
|
2635
|
+
withLocale<L extends TSchema extends AnySchemaDefinition ? SchemaLocaleCodes<TSchema> : string>(locale: L): TypedRelyIOClient<TSchema>;
|
|
2636
|
+
/**
|
|
2637
|
+
* Get the current default locale
|
|
2638
|
+
*/
|
|
2639
|
+
getLocale(): string | undefined;
|
|
2640
|
+
/**
|
|
2641
|
+
* Get available locales from the API
|
|
2642
|
+
*
|
|
2643
|
+
* @example
|
|
2644
|
+
* ```typescript
|
|
2645
|
+
* const { locales, defaultLocale } = await relyio.getLocales()
|
|
2646
|
+
*
|
|
2647
|
+
* // Build language switcher
|
|
2648
|
+
* const options = locales.map(l => ({
|
|
2649
|
+
* code: l.code,
|
|
2650
|
+
* label: l.displayName,
|
|
2651
|
+
* isDefault: l.default,
|
|
2652
|
+
* }))
|
|
2653
|
+
* ```
|
|
2654
|
+
*/
|
|
2655
|
+
getLocales(search?: string): Promise<{
|
|
2656
|
+
locales: Array<{
|
|
2657
|
+
code: string;
|
|
2658
|
+
displayName?: string;
|
|
2659
|
+
default?: boolean;
|
|
2660
|
+
fallback?: string[];
|
|
2661
|
+
direction?: 'ltr' | 'rtl';
|
|
2662
|
+
active?: boolean;
|
|
2663
|
+
}>;
|
|
2664
|
+
defaultLocale: string | null;
|
|
2665
|
+
total: number;
|
|
2666
|
+
}>;
|
|
2667
|
+
/**
|
|
2668
|
+
* Get the default locale from the API
|
|
2669
|
+
*/
|
|
2670
|
+
getDefaultLocale(): Promise<string | null>;
|
|
2671
|
+
}
|
|
2672
|
+
/**
|
|
2673
|
+
* Create a RelyIO client
|
|
2674
|
+
*
|
|
2675
|
+
* @example Without schema (dynamic usage)
|
|
2676
|
+
* ```typescript
|
|
2677
|
+
* import { createClient } from '@relyio/sdk'
|
|
2678
|
+
*
|
|
2679
|
+
* const relyio = createClient({
|
|
2680
|
+
* apiKey: process.env.RELYIO_API_KEY!,
|
|
2681
|
+
* })
|
|
2682
|
+
*
|
|
2683
|
+
* // Works but no autocomplete for content types
|
|
2684
|
+
* const products = await relyio.content('product').fetchAll()
|
|
2685
|
+
* ```
|
|
2686
|
+
*
|
|
2687
|
+
* @example With schema (fully typed)
|
|
2688
|
+
* ```typescript
|
|
2689
|
+
* import { createClient } from '@relyio/sdk'
|
|
2690
|
+
* import { schema } from './schema'
|
|
2691
|
+
*
|
|
2692
|
+
* const relyio = createClient({
|
|
2693
|
+
* apiKey: process.env.RELYIO_API_KEY!,
|
|
2694
|
+
* schema,
|
|
2695
|
+
* })
|
|
2696
|
+
*
|
|
2697
|
+
* // Content type names autocomplete!
|
|
2698
|
+
* const products = await relyio.content('product').fetchAll()
|
|
2699
|
+
* ```
|
|
2700
|
+
*/
|
|
2701
|
+
declare function createClient<TSchema extends AnySchemaDefinition>(config: TypedClientConfig<TSchema>): TypedRelyIOClient<TSchema>;
|
|
2702
|
+
declare function createClient(config: RelyIOConfig): TypedRelyIOClient<undefined>;
|
|
2703
|
+
/**
|
|
2704
|
+
* Helper type to extract schema from client
|
|
2705
|
+
*/
|
|
2706
|
+
type ClientSchema<T extends TypedRelyIOClient<AnySchemaDefinition>> = T extends TypedRelyIOClient<infer TSchema> ? TSchema : never;
|
|
2707
|
+
|
|
2708
|
+
export { AssetFileBuilder as $, AutocompleteBuilder as A, BatchClient as B, type ClientSchema as C, type BatchOperation as D, type ExtendedQueryResult as E, type BatchOptions as F, type BatchOperationResult as G, HttpClient as H, type BatchSummary as I, type BatchResponse as J, AdhocQueryClient as K, AdhocQueryBuilder as L, type FetchBlock as M, type AggregateBlock as N, type AggregateMetric as O, type SearchBlock as P, type SimilarBlock as Q, type RetryableWriteOptions as R, type SendOptions as S, TypedRelyIOClient as T, type FilterValue as U, type FullTextConfig as V, type AdhocQueryDefinition as W, type AdhocQueryOptions as X, type QueryMetadata as Y, type AdhocQueryResult as Z, AssetClient as _, type TypedClientConfig as a, AssetUploadBuilder as a0, isAssetEntry as a1, type AssetVisibility as a2, type FileStatus as a3, type FileBackend as a4, type AssetFileBlock as a5, type AssetFileExtracted as a6, type AssetUrls as a7, type AssetEntryResponse as a8, type PopulatedAssetReference as a9, type PresignInput as aa, type PresignResult as ab, type ConfirmInput as ac, type ConfirmResult as ad, type ResolveUrlInput as ae, type ResolveUrlResult as af, type CreateAssetOptions as ag, type WaitUntilReadyOptions as ah, type MultipartCreateResult as ai, type MultipartPart as aj, type MultipartTarget as ak, type UploadProgress as al, type FileErrorCode as am, FileUploadError as an, FileValidationError as ao, type FileValidationConstraints as ap, validateFile as aq, type ConditionalWriteOptions as b, createClient as c, ContentClient as d, entityTagOf as e, SingletonClient as f, SettingsClient as g, ContentQueryBuilder as h, ContentByIdBuilder as i, type ChildrenOptions as j, type SingletonFetchOptions as k, type SettingsFetchOptions as l, SearchClient as m, SearchBuilder as n, SimilarBuilder as o, type SearchMode as p, type SearchResultItem as q, type SearchResponse as r, type AutocompleteSuggestion as s, type AutocompleteResponse as t, type SimilarResult as u, type SimilarResponse as v, type SearchFilter as w, type SearchFields as x, BatchBuilder as y, type BatchMethod as z };
|