@relyio/sdk 0.15.0 → 0.17.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 +61 -0
- package/dist/{chunk-3BHDGUNS.cjs → chunk-6E22GYPB.cjs} +434 -593
- package/dist/chunk-6PTRZP5U.cjs +433 -0
- package/dist/{chunk-PCFTJLEP.js → chunk-DIZY6CKM.js} +2 -2
- package/dist/{chunk-X4KSS7PP.cjs → chunk-GHYB6IZK.cjs} +2 -2
- package/dist/chunk-OVMIHAYK.js +411 -0
- package/dist/{chunk-PXA5ONIU.js → chunk-VS2DEUTN.js} +397 -560
- package/dist/client/index.cjs +4 -3
- package/dist/client/index.d.cts +3 -4
- package/dist/client/index.d.ts +3 -4
- package/dist/client/index.js +2 -1
- package/dist/{define-content-type-B2gQZkTy.d.cts → define-content-type-AuL9-oz6.d.cts} +668 -85
- package/dist/{define-content-type-Ds5rCAYl.d.ts → define-content-type-BGoQxqLf.d.ts} +668 -85
- package/dist/{define-schema-CxpIYFFR.d.ts → define-schema-DgCX9YB7.d.ts} +1 -1
- package/dist/{define-schema-Cm_5y3ei.d.cts → define-schema-DkXwpp0I.d.cts} +1 -1
- package/dist/{index-DQ7eTUPQ.d.ts → index-BBp8_tn9.d.ts} +467 -193
- package/dist/{index-DY64WjZM.d.cts → index-Bp4AiNT3.d.cts} +1 -1
- package/dist/{index-Db3_tmYf.d.ts → index-DaMZ4FQ_.d.ts} +1 -1
- package/dist/{index-F0UuHpRj.d.cts → index-DxRmKPrR.d.cts} +467 -193
- package/dist/index.cjs +96 -71
- package/dist/index.d.cts +26 -16
- package/dist/index.d.ts +26 -16
- package/dist/index.js +4 -3
- package/dist/markdown/index.cjs +10 -2
- package/dist/markdown/index.d.cts +12 -3
- package/dist/markdown/index.d.ts +12 -3
- package/dist/markdown/index.js +10 -2
- package/dist/preview/index.cjs +29 -0
- package/dist/preview/index.d.cts +117 -0
- package/dist/preview/index.d.ts +117 -0
- package/dist/preview/index.js +4 -0
- package/dist/rich-text/index.d.cts +2 -2
- package/dist/rich-text/index.d.ts +2 -2
- package/dist/schema/index.cjs +33 -33
- package/dist/schema/index.d.cts +3 -3
- package/dist/schema/index.d.ts +3 -3
- package/dist/schema/index.js +1 -1
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +10 -4
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as SchemaDefinition, b as SchemaContentTypeNames, j as SchemaEntryOf, f as SchemaLocaleCodes, c as SchemaSingletonNames, A as AggregateBlock, K as QueryParameterValue, F as FullTextSearch, e as SchemaQueryNames, J as InferQueryParams, L as AnyQueryParameters, h as SchemaAssetTypeNames, g as SchemaSettingsGroupNames } from './define-schema-
|
|
3
|
-
import { VisitorResyncReason } from './live-visitor.js';
|
|
1
|
+
import { d2 as paths, cW as RetryConfig, d3 as MergedRelyIOConfig, cV as ApiResponse, aM as EntryMetadata, ap as Reading, cs as BaseContent, al as CheckedIncludes, d4 as ReadWhere, cx as WhereClause, d5 as components, aq as ReadWith, cI as UpdateInput, at as UntypedReading, cC as RevisedContent, cA as CreateInput, cB as CreatedContent, cH as ContentVersionRow, cG as ContentVersion, cF as RestoredContent, cl as SDKError, c$ as BaseValidationError, c_ as ValidationViolation, b2 as AssetServedBlocks, d6 as CheckedInclude, cw as WhereFieldCondition, cq as AssetFileBlock, ct as BaseSingleton, cD as WrittenSingleton, cu as BaseSettingsGroup, cE as WrittenSettingsGroup, aN as InferContentType, an as ContentReading, aT as InferSingleton, cm as RelyIOConfig, b0 as InferAssetType, ak as AssetReading, as as SingletonReading, aY as InferSettingsGroup, ar as SettingsReading, cn as RelyIOConfigUpdate } from './define-content-type-AuL9-oz6.cjs';
|
|
2
|
+
import { a as SchemaDefinition, b as SchemaContentTypeNames, j as SchemaEntryOf, f as SchemaLocaleCodes, c as SchemaSingletonNames, A as AggregateBlock, K as QueryParameterValue, F as FullTextSearch, e as SchemaQueryNames, J as InferQueryParams, L as AnyQueryParameters, h as SchemaAssetTypeNames, g as SchemaSettingsGroupNames } from './define-schema-DkXwpp0I.cjs';
|
|
4
3
|
import { DevUnreadableReason } from './dev-handshake/index.cjs';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -201,6 +200,81 @@ type ActiveSandbox = Extract<SandboxState, {
|
|
|
201
200
|
state: 'active';
|
|
202
201
|
}>;
|
|
203
202
|
|
|
203
|
+
/**
|
|
204
|
+
* The part of a request a retry decision is allowed to look at.
|
|
205
|
+
*
|
|
206
|
+
* `method` is typed as a plain `string` rather than as `RequestConfig['method']`
|
|
207
|
+
* on purpose. The five verbs that union names are the five the typed transport
|
|
208
|
+
* can express today; the question "may this be sent twice?" is a fact about
|
|
209
|
+
* HTTP, and an unrecognised verb has to reach the conservative arm rather than
|
|
210
|
+
* be unrepresentable.
|
|
211
|
+
*/
|
|
212
|
+
interface RetryableRequest {
|
|
213
|
+
method: string;
|
|
214
|
+
headers?: Record<string, string>;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Whether a failed request may be sent again, and after how long.
|
|
218
|
+
*
|
|
219
|
+
* The two halves are separate because they fail separately. The incumbent loop
|
|
220
|
+
* had neither: it asked `error.retryable` and nothing else, so a `POST` that met
|
|
221
|
+
* a 500 was sent again twice — and `SERVICE_INDETERMINATE`, whose whole meaning
|
|
222
|
+
* is "the service could not decide", is marked retryable, which means the write
|
|
223
|
+
* may already have landed. Meanwhile the `Retry-After` the service sent was
|
|
224
|
+
* collected by the transport and read by nobody, so a 429 whose window is
|
|
225
|
+
* measured in minutes was retried after an exponential guess capped at ten
|
|
226
|
+
* seconds.
|
|
227
|
+
*
|
|
228
|
+
* `error` is `Error`, not `SDKError`, because that is what the loop actually
|
|
229
|
+
* holds: a `TypeError: fetch failed` is only mapped to an `SDKError` **after**
|
|
230
|
+
* the loop gives up, so a policy typed to `SDKError` could not see the transport
|
|
231
|
+
* failures it most needs to retry.
|
|
232
|
+
*/
|
|
233
|
+
interface RetryPolicy {
|
|
234
|
+
/**
|
|
235
|
+
* Never replays a request that could apply twice: a write is retried only
|
|
236
|
+
* when it carries `Idempotency-Key`, or the verb is idempotent.
|
|
237
|
+
*
|
|
238
|
+
* @param attempt - How many attempts have been made, 1 for the first.
|
|
239
|
+
*/
|
|
240
|
+
shouldRetry(attempt: number, error: Error, request: RetryableRequest): boolean;
|
|
241
|
+
/** Honours `Retry-After` / `RateLimitError.resetAt` over exponential backoff. */
|
|
242
|
+
delayFor(attempt: number, error: Error): number;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Whether sending this request a second time can apply it a second time.
|
|
246
|
+
*
|
|
247
|
+
* Two ways to be safe, and they are genuinely different questions: the verb may
|
|
248
|
+
* be idempotent by definition, or the request may carry an `Idempotency-Key`
|
|
249
|
+
* that makes the service answer a replay from the original outcome rather than
|
|
250
|
+
* applying it again.
|
|
251
|
+
*/
|
|
252
|
+
declare function isReplaySafe(request: RetryableRequest): boolean;
|
|
253
|
+
/**
|
|
254
|
+
* The policy the SDK ships with.
|
|
255
|
+
*
|
|
256
|
+
* Construction takes the same `RetryConfig` the SDK has always exported; what
|
|
257
|
+
* it no longer takes is a `retryCondition`, because a caller-supplied predicate
|
|
258
|
+
* over `(error, attempt)` structurally **cannot** see the request and so cannot
|
|
259
|
+
* express the rule this class exists for.
|
|
260
|
+
*/
|
|
261
|
+
declare class DefaultRetryPolicy implements RetryPolicy {
|
|
262
|
+
private readonly config;
|
|
263
|
+
constructor(config: RetryConfig);
|
|
264
|
+
shouldRetry(attempt: number, error: Error, request: RetryableRequest): boolean;
|
|
265
|
+
delayFor(attempt: number, error: Error): number;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The retry policy a client sends with, at `maxAttempts` attempts (the first included): the SDK's
|
|
269
|
+
* own, from `retryAttempts`, and the CLI's (REL-721).
|
|
270
|
+
*
|
|
271
|
+
* The backoff numbers are stated here once. The CLI ran a second policy beside this one —
|
|
272
|
+
* `axios-retry` with its own delays and its own reading of a refusal, which retried by numeric
|
|
273
|
+
* status — so a refusal one client gave up on, the other sent again. Now both ask this function, and
|
|
274
|
+
* a change to when a request is replayed reaches both.
|
|
275
|
+
*/
|
|
276
|
+
declare function retryPolicyFor(maxAttempts: number): RetryPolicy;
|
|
277
|
+
|
|
204
278
|
/**
|
|
205
279
|
* What a call site supplies beside the route it named.
|
|
206
280
|
*
|
|
@@ -234,39 +308,35 @@ type SendOptions<P extends ApiPath, M extends ApiMethod<P>> = {
|
|
|
234
308
|
* then the one unwrap — there is no second spelling and no runtime test of
|
|
235
309
|
* which envelope arrived (`INV-API-CLIENT-IS-DERIVED`).
|
|
236
310
|
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
311
|
+
* What the class makes public is what something outside it calls: `send` and `fetchPayload` are
|
|
312
|
+
* the requests; `configure`, `withHeaders` and `setApiKey` are the owning client's (`updateConfig()`,
|
|
313
|
+
* `with()`, `setApiKey()`). There are no verb helpers, no header or base-URL accessors and no
|
|
314
|
+
* untyped `request` (REL-717): a route is named by its document path, or it is not called.
|
|
239
315
|
*/
|
|
240
316
|
declare class HttpClient {
|
|
241
317
|
/** What every request reads off the configuration, derived by {@link configure} and nowhere else. */
|
|
242
|
-
|
|
318
|
+
protected connection: Connection;
|
|
243
319
|
/**
|
|
244
320
|
* Set on a view {@link withHeaders} made: the client every request is sent through, and the
|
|
245
321
|
* headers laid beneath each request's own. A view keeps no connection of its own that matters —
|
|
246
322
|
* everything it is asked to change, it changes on that client.
|
|
247
323
|
*/
|
|
248
|
-
|
|
324
|
+
protected view?: {
|
|
325
|
+
readonly client: ControlledHttpClient;
|
|
326
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
327
|
+
};
|
|
249
328
|
constructor(config: MergedRelyIOConfig);
|
|
329
|
+
protected announce(): void;
|
|
250
330
|
/**
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
* this client. `client.with({ dataset })` is one (REL-2417).
|
|
256
|
-
*/
|
|
257
|
-
withHeaders(headers: Readonly<Record<string, string>>): HttpClient;
|
|
258
|
-
/**
|
|
259
|
-
* Run on `config` from now on: every later request — whoever holds this client — is sent to its
|
|
260
|
-
* `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
|
|
261
|
-
* logged by its `debug` options.
|
|
331
|
+
* Send bytes to an address that is not a RelyIO route — an asset upload's presigned `PUT` and its
|
|
332
|
+
* multipart parts — through the client's configured `fetch`, so a wrapper that records, proxies or
|
|
333
|
+
* forbids network access sees every request this client makes (REL-2671). Nothing else is added: no
|
|
334
|
+
* key, no retry, no timeout, because the address belongs to the storage service, not to RelyIO.
|
|
262
335
|
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* set on this client since it was last configured — `setDefaultHeaders()`, `setBaseUrl()` — is
|
|
266
|
-
* replaced by what `config` says.
|
|
336
|
+
* Static so the instances a customer holds stay `send` and `fetchPayload` (REL-3107). The `fetch`
|
|
337
|
+
* is read per call, from the client a view sends through, like the requests are.
|
|
267
338
|
*/
|
|
268
|
-
|
|
269
|
-
private announce;
|
|
339
|
+
static transfer(client: HttpClient, url: string, init: RequestInit): Promise<Response>;
|
|
270
340
|
/**
|
|
271
341
|
* Call a route the committed document declares, and get back the body that
|
|
272
342
|
* document says it serves.
|
|
@@ -301,62 +371,7 @@ declare class HttpClient {
|
|
|
301
371
|
* build that holds no key (REL-1120) — and so does one whose `setApiKey` was
|
|
302
372
|
* given none.
|
|
303
373
|
*/
|
|
304
|
-
request
|
|
305
|
-
/**
|
|
306
|
-
* Make a GET request
|
|
307
|
-
*/
|
|
308
|
-
get<T = unknown>(url: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
309
|
-
/**
|
|
310
|
-
* Make a POST request
|
|
311
|
-
*/
|
|
312
|
-
post<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
313
|
-
/**
|
|
314
|
-
* Make a PUT request
|
|
315
|
-
*/
|
|
316
|
-
put<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
317
|
-
/**
|
|
318
|
-
* Make a DELETE request
|
|
319
|
-
*/
|
|
320
|
-
delete<T = unknown>(url: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
321
|
-
/**
|
|
322
|
-
* Make a PATCH request
|
|
323
|
-
*/
|
|
324
|
-
patch<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
325
|
-
/**
|
|
326
|
-
* Add headers to every later request, each replacing any header of the same name — the name
|
|
327
|
-
* matched without regard to case — until the client is next configured.
|
|
328
|
-
*/
|
|
329
|
-
setDefaultHeaders(headers: Record<string, string>): void;
|
|
330
|
-
/**
|
|
331
|
-
* Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
|
|
332
|
-
* reports.
|
|
333
|
-
*
|
|
334
|
-
* The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
|
|
335
|
-
* no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
|
|
336
|
-
* before anything is sent. A key header of any other spelling — one given in `headers` — goes
|
|
337
|
-
* too, from the headers sent and from the headers the configuration reports, so the old key is
|
|
338
|
-
* never sent beside the new one.
|
|
339
|
-
*
|
|
340
|
-
* The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
|
|
341
|
-
* constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
|
|
342
|
-
* key sent from here on.
|
|
343
|
-
*
|
|
344
|
-
* This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
|
|
345
|
-
* never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
|
|
346
|
-
*/
|
|
347
|
-
setApiKey(apiKey: string): void;
|
|
348
|
-
/**
|
|
349
|
-
* Get current default headers
|
|
350
|
-
*/
|
|
351
|
-
getDefaultHeaders(): Record<string, string>;
|
|
352
|
-
/**
|
|
353
|
-
* Update base URL
|
|
354
|
-
*/
|
|
355
|
-
setBaseUrl(baseUrl: string): void;
|
|
356
|
-
/**
|
|
357
|
-
* Get current base URL
|
|
358
|
-
*/
|
|
359
|
-
getBaseUrl(): string;
|
|
374
|
+
private request;
|
|
360
375
|
/**
|
|
361
376
|
* One attempt.
|
|
362
377
|
*
|
|
@@ -388,6 +403,63 @@ declare class HttpClient {
|
|
|
388
403
|
private headersToObject;
|
|
389
404
|
private log;
|
|
390
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* The client the SDK's own factory holds: {@link HttpClient} plus the three things only the owning
|
|
408
|
+
* client does to it — `configure` (`updateConfig()`), `withHeaders` (`with()`) and `setApiKey`
|
|
409
|
+
* (`setApiKey()`). It is not exported from the package, so a customer holding the client from
|
|
410
|
+
* `getHttpClient()` sees `send` and `fetchPayload` and nothing else (REL-3107).
|
|
411
|
+
*/
|
|
412
|
+
declare class ControlledHttpClient extends HttpClient {
|
|
413
|
+
/**
|
|
414
|
+
* A view of this client that sends every request through it with `headers` added — beneath the
|
|
415
|
+
* request's own, over this client's — and changes nothing else: its key, base URL, timeout,
|
|
416
|
+
* retries and `fetch` are this client's as they are when each request is sent, so a later
|
|
417
|
+
* `configure()` or `setApiKey()` on this client reaches the view, and one on the view reaches
|
|
418
|
+
* this client. `client.with({ dataset })` is one (REL-2417).
|
|
419
|
+
*/
|
|
420
|
+
withHeaders(headers: Readonly<Record<string, string>>): ControlledHttpClient;
|
|
421
|
+
/**
|
|
422
|
+
* Run on `config` from now on: every later request — whoever holds this client — is sent to its
|
|
423
|
+
* `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
|
|
424
|
+
* logged by its `debug` options.
|
|
425
|
+
*
|
|
426
|
+
* The client's own `updateConfig()` calls this rather than building a second client, so a
|
|
427
|
+
* `content()` or other sub-client taken before the update sends through the update too. Anything
|
|
428
|
+
* set on this client since it was last configured — `setApiKey()` — is replaced by what `config`
|
|
429
|
+
* says.
|
|
430
|
+
*/
|
|
431
|
+
configure(config: MergedRelyIOConfig): void;
|
|
432
|
+
/**
|
|
433
|
+
* Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
|
|
434
|
+
* reports.
|
|
435
|
+
*
|
|
436
|
+
* The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
|
|
437
|
+
* no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
|
|
438
|
+
* before anything is sent. A key header of any other spelling — one given in `headers` — goes
|
|
439
|
+
* too, from the headers sent and from the headers the configuration reports, so the old key is
|
|
440
|
+
* never sent beside the new one.
|
|
441
|
+
*
|
|
442
|
+
* The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
|
|
443
|
+
* constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
|
|
444
|
+
* key sent from here on.
|
|
445
|
+
*
|
|
446
|
+
* This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
|
|
447
|
+
* never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
|
|
448
|
+
*/
|
|
449
|
+
setApiKey(apiKey: string): void;
|
|
450
|
+
}
|
|
451
|
+
/** Everything a request reads off the configuration, replaced whole whenever it changes. */
|
|
452
|
+
interface Connection {
|
|
453
|
+
/**
|
|
454
|
+
* The configuration itself, for what is read per request — `fetch`, the `browser` options,
|
|
455
|
+
* `debug` — and the object `setApiKey` writes the key into, which the owning client reports.
|
|
456
|
+
*/
|
|
457
|
+
readonly config: MergedRelyIOConfig;
|
|
458
|
+
readonly baseUrl: string;
|
|
459
|
+
readonly defaultHeaders: Readonly<Record<string, string>>;
|
|
460
|
+
readonly timeout: number;
|
|
461
|
+
readonly retryPolicy: RetryPolicy;
|
|
462
|
+
}
|
|
391
463
|
|
|
392
464
|
/**
|
|
393
465
|
* API4's two request headers, as the SDK's writes send them.
|
|
@@ -453,6 +525,106 @@ declare function versionCheckOf(entry: ReadEntry): {
|
|
|
453
525
|
*/
|
|
454
526
|
type ClientLocale = string | (() => string | undefined);
|
|
455
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Site-visitor live, declared once for everyone who speaks it (`live-layer-spec.md` decisions 15, 19
|
|
530
|
+
* and 20; phase LV5): the wire a visitor's browser meets at `live.relyio.com`, and the two internal
|
|
531
|
+
* routes the live Worker calls on `apps/services/api` to serve it.
|
|
532
|
+
*
|
|
533
|
+
* It sits in this package's root because three runtimes read it and this is the one package all
|
|
534
|
+
* three may import: `@relyio/sdk` through the customer-layer chokepoint (`INV-SS-CUSTOMER-FENCE`,
|
|
535
|
+
* which allows this root), the live Worker, and `apps/services/api`. Pure, like the rest of the root:
|
|
536
|
+
* no `node:` import, so it runs in workerd and a browser.
|
|
537
|
+
*
|
|
538
|
+
* ## The visitor front door — `wss://live.relyio.com/visitor/changes` and `GET` on the same path
|
|
539
|
+
*
|
|
540
|
+
* A visitor presents a **publishable** key (`rly_pub_…`, `sdk-surfaces-spec.md` decision 29) in the
|
|
541
|
+
* `key` query parameter — a browser cannot set a socket's headers, and a query parameter keeps the
|
|
542
|
+
* poll a simple request with no preflight. The door resolves the key's scope, checks the page's
|
|
543
|
+
* `Origin` against the key's allowed origins, and refuses a key it cannot use, an unlisted origin or
|
|
544
|
+
* a malformed request **before any object is addressed**. A secret or preview key is refused here:
|
|
545
|
+
* a preview key's live connection stays on the Content API's `/v1/changes`.
|
|
546
|
+
*
|
|
547
|
+
* Only the published lens exists at this door (`INV-SS-FEED-LENS-IS-THE-KEY`); no parameter names a
|
|
548
|
+
* lens. The dataset is `dataset` — an id or a name, as `X-RelyIO-Dataset` takes it — or the key's
|
|
549
|
+
* default. `types` and `ids` narrow what reaches this client, comma-separated, and the socket keeps
|
|
550
|
+
* them as its own filter (`INV-LV-VISITOR-AT-THE-EDGE`).
|
|
551
|
+
*
|
|
552
|
+
* ### The socket
|
|
553
|
+
*
|
|
554
|
+
* Every frame is text. From the client, only the keepalive {@link VISITOR_KEEPALIVE}, which the
|
|
555
|
+
* runtime answers without waking the feed; anything else is ignored. From the feed,
|
|
556
|
+
* {@link VisitorFrame}s:
|
|
557
|
+
*
|
|
558
|
+
* 1. Zero or more `feed.changes` / at most one `feed.resync`: the changes after the connect's
|
|
559
|
+
* `since` (`INV-SS-CURSOR-REPLAYS`), or the named reason none can be listed.
|
|
560
|
+
* 2. `feed.opened` exactly once, with the cursor the socket is caught up to: every change after it
|
|
561
|
+
* reaches this socket. A connect **without** `since` gets this first, and the client fetches what
|
|
562
|
+
* it shows after receiving it — fetching after the feed holds the cursor is what makes the view
|
|
563
|
+
* gap-free.
|
|
564
|
+
* 3. `feed.changes` as the dataset changes, each carrying ids only (`INV-SS-CHANGE-IS-IDS`) and the
|
|
565
|
+
* cursor after it. The client keeps the last cursor it received and reconnects with it as
|
|
566
|
+
* `since` — after a deploy or a dropped network alike — and is replayed what it missed.
|
|
567
|
+
*
|
|
568
|
+
* A change is at-least-once: a replay and the live frames that follow it may name one change twice.
|
|
569
|
+
* A client refetches what a change names, so a repeat costs a read and never a wrong view.
|
|
570
|
+
*
|
|
571
|
+
* A refusal is a socket closed at once with one of {@link VISITOR_CLOSE_CODES} and a reason string,
|
|
572
|
+
* because a browser cannot read the status of a refused WebSocket handshake; what a client does next
|
|
573
|
+
* is {@link VISITOR_CLOSE_RETRY}'s, per code.
|
|
574
|
+
*
|
|
575
|
+
* ### Admission (`INV-LV-LIVE-CEILINGS`)
|
|
576
|
+
*
|
|
577
|
+
* After the key, origin and dataset, the door asks the project's counter whether one more connection
|
|
578
|
+
* may open — against the project's plan allowance (Starter's 100), its safety ceiling (Pro's 50,000)
|
|
579
|
+
* and a per-address limit the Worker holds — and refuses before any feed is addressed. The counts are approximate
|
|
580
|
+
* by design: a feed reports its count within about a second of a change and at least every minute, so
|
|
581
|
+
* a refusal is decided on counts at most one reporting interval old.
|
|
582
|
+
*
|
|
583
|
+
* ### The poll
|
|
584
|
+
*
|
|
585
|
+
* `GET` on the same path with the same parameters and a `client` id (a random id the client keeps for
|
|
586
|
+
* the page's life, so one visitor polling counts once), answered **at once** — never held — with
|
|
587
|
+
* `{ data: VisitorPollAnswer }`. Where a WebSocket cannot open, a client polls about every
|
|
588
|
+
* {@link VISITOR_POLL_INTERVAL_MS}. A refusal is the one error envelope, `{ error: { code, messages } }`,
|
|
589
|
+
* at the code's status.
|
|
590
|
+
*
|
|
591
|
+
* ## The two internal routes (`apps/services/api`, `x-internal-secret`)
|
|
592
|
+
*
|
|
593
|
+
* - `POST /internal/live/visitor-key` — {@link VisitorKeyResolve} → {@link VisitorKeyResolution}:
|
|
594
|
+
* what a presented key may reach, in the binding shape `./edge.ts` already declares for the Content
|
|
595
|
+
* API's edge, plus the project's live regions the feed is placed by. The Worker keeps the answer
|
|
596
|
+
* under the key's SHA-256, with the tag origin minted for it, as `apps/edge/api` keeps a binding, so
|
|
597
|
+
* a revocation's purge evicts both.
|
|
598
|
+
* - `POST /internal/live/visitor-feed/{projectId}/{datasetId}/changes` — {@link VisitorLedgerRead} →
|
|
599
|
+
* {@link VisitorLedgerPage}: the ledger page after a cursor in the `public` lens, the same read and
|
|
600
|
+
* the same page shape the Studio service answers a dataset room with in the `preview` lens
|
|
601
|
+
* (`@relyio/live-contracts`' `rest/live-room.ts`), plus one resync reason a room never meets —
|
|
602
|
+
* a cursor a visitor's client supplied that this dataset's feed never issued.
|
|
603
|
+
*/
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Why a ledger read cannot list the changes from a cursor to now:
|
|
607
|
+
*
|
|
608
|
+
* - `retention` — rows after the cursor may have been reaped (`@relyio/entry-changes`' retention).
|
|
609
|
+
* - `dataset-replaced` — the dataset was purged or populated wholesale.
|
|
610
|
+
* - `ahead-of-head` — the cursor is past the ledger's head: the ledger was reset under it.
|
|
611
|
+
* - `foreign-cursor` — the cursor is not one this dataset's feed issued (malformed, or another
|
|
612
|
+
* dataset's). A room never meets it; a visitor's client supplies its own cursor.
|
|
613
|
+
*/
|
|
614
|
+
type VisitorLedgerResyncReason = 'retention' | 'dataset-replaced' | 'ahead-of-head' | 'foreign-cursor';
|
|
615
|
+
/**
|
|
616
|
+
* Why a client is told to refetch everything: any reason the ledger gave, or `too-far-behind` — the
|
|
617
|
+
* client's cursor is further back than one replay lists (`VisitorFeed`'s `MAX_REPLAY_PAGES`), and a
|
|
618
|
+
* refetch is less than the replay would be.
|
|
619
|
+
*/
|
|
620
|
+
type VisitorResyncReason = VisitorLedgerResyncReason | 'too-far-behind';
|
|
621
|
+
/**
|
|
622
|
+
* What a client does after a refusal: `stop` (the same request meets the same answer), `retry`
|
|
623
|
+
* (backoff and jitter from about a second) or `back-off` (full now: wait at least
|
|
624
|
+
* {@link VISITOR_ADMISSION_RETRY_AFTER_SECONDS}, with jitter, doubling while it repeats).
|
|
625
|
+
*/
|
|
626
|
+
type VisitorRetry = 'stop' | 'retry' | 'back-off';
|
|
627
|
+
|
|
456
628
|
/**
|
|
457
629
|
* Two read terms every read that takes them writes the same way: the children an entry embeds,
|
|
458
630
|
* and the refusal of a condition on `_metadata`. Here once, for the list and entry reads
|
|
@@ -551,7 +723,7 @@ type FreshOption = true | NonNullable<Term<'/v1/{contentType}', 'get', '_fresh'>
|
|
|
551
723
|
* - `children` — each entry's children, of every content type, under `_children`: `true` for one
|
|
552
724
|
* level, or a depth of 1 to 3 and at most `limit` per parent (REL-1118).
|
|
553
725
|
*/
|
|
554
|
-
interface EntryReadOptions<R extends Reading, P extends readonly string[], L extends LocaleOption<ReadLocale<R>> | undefined = undefined> {
|
|
726
|
+
interface EntryReadOptions<R extends Reading, P extends readonly string[], L extends LocaleOption<ReadLocale<R>> | undefined = undefined, C extends ChildrenRead | undefined = ChildrenRead | undefined> {
|
|
555
727
|
/** Include paths: the references to expand into the entries they point at (REL-1801). */
|
|
556
728
|
readonly include?: CheckedIncludes<R, P>;
|
|
557
729
|
/** The locale, locales or `'*'` to read, over the client's locale (Q16). */
|
|
@@ -561,10 +733,16 @@ interface EntryReadOptions<R extends Reading, P extends readonly string[], L ext
|
|
|
561
733
|
/** How fresh the answer must be: a feed position, or `true` for past every cache. */
|
|
562
734
|
readonly fresh?: FreshOption;
|
|
563
735
|
/** Embed each entry's children: `true`, or a depth and a per-parent limit (REL-1118). */
|
|
564
|
-
readonly children?:
|
|
736
|
+
readonly children?: C;
|
|
737
|
+
/**
|
|
738
|
+
* Cancels the request when it aborts. The call then rejects with the platform's `AbortError` —
|
|
739
|
+
* not a `TimeoutError` — and a request already cancelled sends nothing. The client's timeout
|
|
740
|
+
* still applies.
|
|
741
|
+
*/
|
|
742
|
+
readonly signal?: AbortSignal;
|
|
565
743
|
}
|
|
566
744
|
/** The options a list read takes beside how it pages: what it keeps, how, and how many a page holds. */
|
|
567
|
-
interface ListReadOptions<T extends BaseContent, R extends Reading, P extends readonly string[], S extends readonly FieldKey<T>[] | undefined = undefined, L extends LocaleOption<ReadLocale<R>> | undefined = undefined> extends EntryReadOptions<R, P, L> {
|
|
745
|
+
interface ListReadOptions<T extends BaseContent, R extends Reading, P extends readonly string[], S extends readonly FieldKey<T>[] | undefined = undefined, L extends LocaleOption<ReadLocale<R>> | undefined = undefined, C extends ChildrenRead | undefined = ChildrenRead | undefined> extends EntryReadOptions<R, P, L, C> {
|
|
568
746
|
/**
|
|
569
747
|
* The conditions an entry must meet, by the paths the API filters on (REL-2136). A condition on
|
|
570
748
|
* `_metadata` is refused before anything is sent.
|
|
@@ -593,20 +771,20 @@ type Paging = {
|
|
|
593
771
|
readonly cursor?: never;
|
|
594
772
|
};
|
|
595
773
|
/** What `list(options)` takes. */
|
|
596
|
-
type ListOptions<T extends BaseContent, R extends Reading, P extends readonly string[], S extends readonly FieldKey<T>[] | undefined = undefined, L extends LocaleOption<ReadLocale<R>> | undefined = undefined> = ListReadOptions<T, R, P, S, L> & Paging;
|
|
774
|
+
type ListOptions<T extends BaseContent, R extends Reading, P extends readonly string[], S extends readonly FieldKey<T>[] | undefined = undefined, L extends LocaleOption<ReadLocale<R>> | undefined = undefined, C extends ChildrenRead | undefined = ChildrenRead | undefined> = ListReadOptions<T, R, P, S, L, C> & Paging;
|
|
597
775
|
/**
|
|
598
776
|
* What `children(id, options)` takes (REL-1864): an entry read's options and the page of the list
|
|
599
777
|
* — `limit` the page size, and the `cursor` a page handed back or a page number to choose which.
|
|
600
778
|
* No `where`, `select` or `sort`: the route declares none, and the order is the hierarchy's.
|
|
601
779
|
*/
|
|
602
|
-
type ChildrenListOptions<R extends Reading, P extends readonly string[], L extends LocaleOption<ReadLocale<R>> | undefined = undefined> = EntryReadOptions<R, P, L> & {
|
|
780
|
+
type ChildrenListOptions<R extends Reading, P extends readonly string[], L extends LocaleOption<ReadLocale<R>> | undefined = undefined, C extends ChildrenRead | undefined = ChildrenRead | undefined> = EntryReadOptions<R, P, L, C> & {
|
|
603
781
|
/** How many children a page holds, whether it is read by cursor or by number. */
|
|
604
782
|
readonly limit?: Term<'/v1/{contentType}/{id}/children', 'get', 'limit'>;
|
|
605
783
|
} & Paging;
|
|
606
784
|
/** What `listAll(options)` takes: a list's options, paged by the walk itself. */
|
|
607
|
-
type ListAllOptions<T extends BaseContent, R extends Reading, P extends readonly string[], S extends readonly FieldKey<T>[] | undefined = undefined, L extends LocaleOption<ReadLocale<R>> | undefined = undefined> = ListReadOptions<T, R, P, S, L>;
|
|
785
|
+
type ListAllOptions<T extends BaseContent, R extends Reading, P extends readonly string[], S extends readonly FieldKey<T>[] | undefined = undefined, L extends LocaleOption<ReadLocale<R>> | undefined = undefined, C extends ChildrenRead | undefined = ChildrenRead | undefined> = ListReadOptions<T, R, P, S, L, C>;
|
|
608
786
|
/** What `get(idOrSlug, options)` takes. */
|
|
609
|
-
type GetOptions<R extends Reading, P extends readonly string[], L extends LocaleOption<ReadLocale<R>> | undefined = undefined> = EntryReadOptions<R, P, L>;
|
|
787
|
+
type GetOptions<R extends Reading, P extends readonly string[], L extends LocaleOption<ReadLocale<R>> | undefined = undefined, C extends ChildrenRead | undefined = ChildrenRead | undefined> = EntryReadOptions<R, P, L, C>;
|
|
610
788
|
/**
|
|
611
789
|
* What a one-document read takes — `singleton(key).get(options)` and `settings(group).get(options)`
|
|
612
790
|
* (REL-2419, REL-2409 decision Q18): a content read's options where their routes declare them.
|
|
@@ -627,6 +805,12 @@ interface DocumentReadOptions<R extends Reading, P extends readonly string[]> {
|
|
|
627
805
|
readonly dataset?: string;
|
|
628
806
|
/** How fresh the answer must be: a feed position, or `true` for past every cache. */
|
|
629
807
|
readonly fresh?: FreshOption;
|
|
808
|
+
/**
|
|
809
|
+
* Cancels the request when it aborts. The call then rejects with the platform's `AbortError` —
|
|
810
|
+
* not a `TimeoutError` — and a request already cancelled sends nothing. The client's timeout
|
|
811
|
+
* still applies.
|
|
812
|
+
*/
|
|
813
|
+
readonly signal?: AbortSignal;
|
|
630
814
|
}
|
|
631
815
|
/**
|
|
632
816
|
* What `version()` takes on every handle (REL-2427): the version to read, and the locale whose
|
|
@@ -664,8 +848,27 @@ type Localized<E, L, C extends string> = L extends '*' | readonly string[] ? E e
|
|
|
664
848
|
localizations: Localizations<E, L extends readonly string[] ? L[number] : C>;
|
|
665
849
|
};
|
|
666
850
|
} : E : E;
|
|
667
|
-
/** What a read
|
|
668
|
-
type
|
|
851
|
+
/** What a read's `children` takes: `true`, or a depth and a per-parent limit. */
|
|
852
|
+
type ChildrenRead = true | ChildrenOptions;
|
|
853
|
+
/**
|
|
854
|
+
* One child as the API serves it: an entry of any content type, the document's `Entry`. The
|
|
855
|
+
* children of an entry are of every content type (there is no filter by type), so no one schema
|
|
856
|
+
* types them.
|
|
857
|
+
*/
|
|
858
|
+
type ChildEntry = components['schemas']['Entry'];
|
|
859
|
+
/**
|
|
860
|
+
* What `children` adds to a read (REL-2456): `_children`, the document's own shape
|
|
861
|
+
* (`components['schemas']['Entry']['_children']`, which the API serves beside the fields), on a read
|
|
862
|
+
* that asked for them — and nothing on one that did not, since the API serves none then.
|
|
863
|
+
*/
|
|
864
|
+
type WithChildren<E, C> = [C] extends [undefined] ? E : [C] extends [ChildrenRead] ? E & {
|
|
865
|
+
readonly _children: NonNullable<ChildEntry['_children']>;
|
|
866
|
+
} : E;
|
|
867
|
+
/**
|
|
868
|
+
* What a read of `R` returns under its include paths `P`, selection `S`, locale `L` and children
|
|
869
|
+
* `C` (what its `children` option was).
|
|
870
|
+
*/
|
|
871
|
+
type ReadAs<R extends Reading, P extends readonly string[], S = undefined, L = undefined, C = undefined> = WithChildren<Localized<SelectedFields<ReadWith<R, P[number]>, S, P[number]>, L, ReadLocale<R>>, C>;
|
|
669
872
|
/**
|
|
670
873
|
* Where a read reads and how fresh it must be, as an implementation reads them whatever the type
|
|
671
874
|
* parameters checked: the clump every read takes — an entry read, a list, a one-document read, a
|
|
@@ -677,6 +880,12 @@ interface WrittenReadScope {
|
|
|
677
880
|
readonly locale?: string | readonly string[];
|
|
678
881
|
readonly dataset?: string;
|
|
679
882
|
readonly fresh?: FreshOption;
|
|
883
|
+
/**
|
|
884
|
+
* Cancels the request when it aborts. The call then rejects with the platform's `AbortError` —
|
|
885
|
+
* not a `TimeoutError` — and a request already cancelled sends nothing. The client's timeout
|
|
886
|
+
* still applies.
|
|
887
|
+
*/
|
|
888
|
+
readonly signal?: AbortSignal;
|
|
680
889
|
}
|
|
681
890
|
/**
|
|
682
891
|
* A `sort` as an implementation reads it, whatever keys the type checked ({@link SortOption}): a
|
|
@@ -733,7 +942,7 @@ declare abstract class EntryHandle<T extends BaseContent, R extends Reading, Rev
|
|
|
733
942
|
* })
|
|
734
943
|
* ```
|
|
735
944
|
*/
|
|
736
|
-
list<const P extends readonly string[] = [], const S extends readonly FieldKey<T>[] | undefined = undefined, const L extends LocaleOption<ReadLocale<R>> | undefined = undefined>(options?: ListOptions<T, R, P, S, L>): Promise<EntryList<ReadAs<R, P, S, L>>>;
|
|
945
|
+
list<const P extends readonly string[] = [], const S extends readonly FieldKey<T>[] | undefined = undefined, const L extends LocaleOption<ReadLocale<R>> | undefined = undefined, const C extends ChildrenRead | undefined = undefined>(options?: ListOptions<T, R, P, S, L, C>): Promise<EntryList<ReadAs<R, P, S, L, C>>>;
|
|
737
946
|
/**
|
|
738
947
|
* Every entry of this type that `where` keeps, page after page, as an async iterable: the walk
|
|
739
948
|
* follows each page's cursor and stops where the API says there is no more (REL-2415).
|
|
@@ -743,7 +952,7 @@ declare abstract class EntryHandle<T extends BaseContent, R extends Reading, Rev
|
|
|
743
952
|
* Iterating throws when a page says there is more and hands back no cursor to read it by, rather
|
|
744
953
|
* than ending the walk short.
|
|
745
954
|
*/
|
|
746
|
-
listAll<const P extends readonly string[] = [], const S extends readonly FieldKey<T>[] | undefined = undefined, const L extends LocaleOption<ReadLocale<R>> | undefined = undefined>(options?: ListAllOptions<T, R, P, S, L>): AsyncIterable<ReadAs<R, P, S, L>>;
|
|
955
|
+
listAll<const P extends readonly string[] = [], const S extends readonly FieldKey<T>[] | undefined = undefined, const L extends LocaleOption<ReadLocale<R>> | undefined = undefined, const C extends ChildrenRead | undefined = undefined>(options?: ListAllOptions<T, R, P, S, L, C>): AsyncIterable<ReadAs<R, P, S, L, C>>;
|
|
747
956
|
private walk;
|
|
748
957
|
/**
|
|
749
958
|
* One entry by its id or slug, or `null` when there is no such entry (REL-2415).
|
|
@@ -762,7 +971,7 @@ declare abstract class EntryHandle<T extends BaseContent, R extends Reading, Rev
|
|
|
762
971
|
* if (post === null) return notFound()
|
|
763
972
|
* ```
|
|
764
973
|
*/
|
|
765
|
-
get<const P extends readonly string[] = [], const L extends LocaleOption<ReadLocale<R>> | undefined = undefined>(idOrSlug: string, options?: GetOptions<R, P, L>): Promise<ReadAs<R, P, undefined, L> | null>;
|
|
974
|
+
get<const P extends readonly string[] = [], const L extends LocaleOption<ReadLocale<R>> | undefined = undefined, const C extends ChildrenRead | undefined = undefined>(idOrSlug: string, options?: GetOptions<R, P, L, C>): Promise<ReadAs<R, P, undefined, L, C> | null>;
|
|
766
975
|
/**
|
|
767
976
|
* Update an entry you read, checked against the version it was read at (REL-2418).
|
|
768
977
|
*
|
|
@@ -840,7 +1049,10 @@ interface CreateEntryOptions extends EntryPlacement, RetryableWriteOptions {
|
|
|
840
1049
|
*/
|
|
841
1050
|
declare class ContentClient<T extends BaseContent = BaseContent, R extends Reading = UntypedReading<T>> extends EntryHandle<T, R, RevisedContent<T>, EntryPlacement> {
|
|
842
1051
|
/**
|
|
843
|
-
* Create a new content entry.
|
|
1052
|
+
* Create a new content entry, published. The answer's `_metadata.warnings` lists each reference
|
|
1053
|
+
* the content type declares `weak` that the create made live while the entry it points at is
|
|
1054
|
+
* unpublished (`REFERENCE_NOT_PUBLISHED`) — `[]` when there are none; the create is never refused
|
|
1055
|
+
* for them.
|
|
844
1056
|
*
|
|
845
1057
|
* `locale` defaults to the client's own, and `dataset` to the client's (`client.with({ dataset })`
|
|
846
1058
|
* sets it for every call).
|
|
@@ -850,22 +1062,19 @@ declare class ContentClient<T extends BaseContent = BaseContent, R extends Readi
|
|
|
850
1062
|
* const post = await relyio.content('post').create({ title: 'Hello' }, { slug: 'hello' })
|
|
851
1063
|
* ```
|
|
852
1064
|
*/
|
|
853
|
-
create(data: CreateInput<T>, options?: CreateEntryOptions): Promise<T
|
|
1065
|
+
create(data: CreateInput<T>, options?: CreateEntryOptions): Promise<CreatedContent<T>>;
|
|
854
1066
|
/**
|
|
855
1067
|
* Get version history for one locale of an entry.
|
|
856
1068
|
*
|
|
857
1069
|
* Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
|
|
858
1070
|
* client's own, else the schema default; no fallback is applied, and a locale
|
|
859
1071
|
* with no history returns an empty array rather than another locale's rows. Every row names the
|
|
860
|
-
* locale it belongs to
|
|
1072
|
+
* locale it belongs to, and holds that locale's fields under `fields`.
|
|
861
1073
|
*/
|
|
862
1074
|
versions(id: string, options?: {
|
|
863
1075
|
limit?: number;
|
|
864
1076
|
locale?: string;
|
|
865
|
-
}): Promise<Array<T
|
|
866
|
-
versionNumber: number;
|
|
867
|
-
locale: string;
|
|
868
|
-
}>>;
|
|
1077
|
+
}): Promise<Array<ContentVersionRow<T>>>;
|
|
869
1078
|
/**
|
|
870
1079
|
* One version of an entry: `version(id, { version, locale })`.
|
|
871
1080
|
*
|
|
@@ -875,8 +1084,11 @@ declare class ContentClient<T extends BaseContent = BaseContent, R extends Readi
|
|
|
875
1084
|
* There is no `null`: a version the locale does not have, an entry that is not there, a type the
|
|
876
1085
|
* schema does not declare and a dataset with no schema all throw `ResourceNotFoundError`, its
|
|
877
1086
|
* `context.resourceType` naming which (REL-2409 Q12).
|
|
1087
|
+
*
|
|
1088
|
+
* It answers the version, not the entry: that locale's own fields as the version stored them, and
|
|
1089
|
+
* `_metadata` with `status: 'version'` ({@link ContentVersion}).
|
|
878
1090
|
*/
|
|
879
|
-
version(id: string, options: VersionOptions): Promise<T
|
|
1091
|
+
version(id: string, options: VersionOptions): Promise<ContentVersion<T>>;
|
|
880
1092
|
/**
|
|
881
1093
|
* Revert one locale of an entry you read to a previous version: `restore(entry, { version })`,
|
|
882
1094
|
* checked against the version the entry carries, in the locale it was read in — as
|
|
@@ -930,7 +1142,7 @@ declare class ContentClient<T extends BaseContent = BaseContent, R extends Readi
|
|
|
930
1142
|
* }
|
|
931
1143
|
* ```
|
|
932
1144
|
*/
|
|
933
|
-
children<const P extends readonly string[] = [], const L extends LocaleOption<ReadLocale<R>> | undefined = undefined>(id: string, options?: ChildrenListOptions<R, P, L>): Promise<EntryList<ReadAs<R, P, undefined, L>>>;
|
|
1145
|
+
children<const P extends readonly string[] = [], const L extends LocaleOption<ReadLocale<R>> | undefined = undefined, const C extends ChildrenRead | undefined = undefined>(id: string, options?: ChildrenListOptions<R, P, L, C>): Promise<EntryList<ReadAs<R, P, undefined, L, C>>>;
|
|
934
1146
|
}
|
|
935
1147
|
|
|
936
1148
|
/**
|
|
@@ -1343,6 +1555,23 @@ declare class AssetUploadBuilder<T extends BaseContent = BaseContent> {
|
|
|
1343
1555
|
private putPartWithRetry;
|
|
1344
1556
|
private emitProgress;
|
|
1345
1557
|
}
|
|
1558
|
+
/**
|
|
1559
|
+
* The `file.*` paths an asset list filters by (REL-2456): the facets of the binding the route admits
|
|
1560
|
+
* on a public read (`QUERY_FILE_MEMBERS` in `@relyio/schema`), each taking the condition its value
|
|
1561
|
+
* does. The binding's server-only members — `objectKey`, `streamVideoId`, `storageVersion`,
|
|
1562
|
+
* `scan.*`, `extracted.text` — are refused by the API by name (REL-1501, REL-933), so they are no
|
|
1563
|
+
* key here; nor is `urls`, which is computed and never stored.
|
|
1564
|
+
*/
|
|
1565
|
+
interface AssetFileWhere {
|
|
1566
|
+
readonly 'file.status'?: WhereFieldCondition<AssetFileBlock['status']>;
|
|
1567
|
+
readonly 'file.backend'?: WhereFieldCondition<AssetFileBlock['backend']>;
|
|
1568
|
+
readonly 'file.mimeType'?: WhereFieldCondition<string>;
|
|
1569
|
+
readonly 'file.fileName'?: WhereFieldCondition<string>;
|
|
1570
|
+
readonly 'file.size'?: WhereFieldCondition<number>;
|
|
1571
|
+
readonly 'file.extracted.width'?: WhereFieldCondition<number>;
|
|
1572
|
+
readonly 'file.extracted.height'?: WhereFieldCondition<number>;
|
|
1573
|
+
readonly 'file.extracted.duration'?: WhereFieldCondition<number>;
|
|
1574
|
+
}
|
|
1346
1575
|
/**
|
|
1347
1576
|
* An asset read typed by the asset type's reading `R`: what the type's include paths make of its
|
|
1348
1577
|
* fields, beside the `file` and `urls` blocks every asset read carries (REL-1801).
|
|
@@ -1351,10 +1580,11 @@ interface AssetResponseReading<R extends Reading, T extends BaseContent = BaseCo
|
|
|
1351
1580
|
readonly read: AssetEntryResponse<Extract<ReadWith<R, this['include']>, BaseContent>>;
|
|
1352
1581
|
readonly checked: CheckedInclude<R, this['path']>;
|
|
1353
1582
|
/**
|
|
1354
|
-
* The asset type's own `where` — every path the API filters its fields by
|
|
1355
|
-
*
|
|
1583
|
+
* The asset type's own `where` — every path the API filters its fields by — and the `file.*`
|
|
1584
|
+
* facets the list admits ({@link AssetFileWhere}, REL-2456), or, where no schema types it, the
|
|
1585
|
+
* conditions `T`'s keys take (REL-2195).
|
|
1356
1586
|
*/
|
|
1357
|
-
readonly where: ReadWhere<WhereClause<T>, R
|
|
1587
|
+
readonly where: ReadWhere<WhereClause<T>, R> & AssetFileWhere;
|
|
1358
1588
|
/** The locale codes its `locale` may name: the asset type's reading's. */
|
|
1359
1589
|
readonly locale: ReadLocale<R>;
|
|
1360
1590
|
}
|
|
@@ -1423,11 +1653,21 @@ interface DocumentVersionsOptions {
|
|
|
1423
1653
|
/** The locale whose timeline it is; the client's own, then the schema default, when left out. */
|
|
1424
1654
|
readonly locale?: string;
|
|
1425
1655
|
}
|
|
1426
|
-
/**
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1656
|
+
/**
|
|
1657
|
+
* One version of a singleton or a settings group, as `version({ version })` reads it — the
|
|
1658
|
+
* document's `DocumentVersion` (REL-3181): which version of which locale, who wrote it and when, and
|
|
1659
|
+
* the fields that locale stored, nested under `fields`. Every field is optional: a locale's row
|
|
1660
|
+
* holds that locale's own fields, never the shared ones.
|
|
1661
|
+
*/
|
|
1662
|
+
type DocumentVersion<T> = Omit<components['schemas']['DocumentVersion'], 'fields'> & {
|
|
1663
|
+
fields: Partial<Omit<T, '_metadata'>>;
|
|
1430
1664
|
};
|
|
1665
|
+
/**
|
|
1666
|
+
* One row of a one-document handle's history, as `versions()` lists it — the document's
|
|
1667
|
+
* `DocumentVersionRow` (REL-3269): a version's number, locale, author and time, without its fields,
|
|
1668
|
+
* which the list does not send. Read one with `version({ version })` for what it stored.
|
|
1669
|
+
*/
|
|
1670
|
+
type DocumentVersionRow = components['schemas']['DocumentVersionRow'];
|
|
1431
1671
|
/**
|
|
1432
1672
|
* The verbs a singleton's and a settings group's handle share (REL-2419, REL-2409 decision Q18):
|
|
1433
1673
|
* `update`, `versions` and `version`, written once, as {@link EntryHandle} writes the entry routes'
|
|
@@ -1441,7 +1681,7 @@ type DocumentVersion<T> = T & {
|
|
|
1441
1681
|
* Every call is in the locale it names, and otherwise in the client's own as it is when the call is
|
|
1442
1682
|
* made; a write of a document you read writes the locale it was read in.
|
|
1443
1683
|
*/
|
|
1444
|
-
declare abstract class DocumentHandle<T> {
|
|
1684
|
+
declare abstract class DocumentHandle<T, W = T> {
|
|
1445
1685
|
protected readonly httpClient: HttpClient;
|
|
1446
1686
|
protected readonly name: string;
|
|
1447
1687
|
/** The client's locale, asked on every call rather than copied when this handle was taken. */
|
|
@@ -1458,12 +1698,12 @@ declare abstract class DocumentHandle<T> {
|
|
|
1458
1698
|
* read, the write is refused with `ResourceConflictError` naming both versions: re-read it with
|
|
1459
1699
|
* `fresh: true` and retry.
|
|
1460
1700
|
*/
|
|
1461
|
-
update(read: ReadEntry, data: DocumentFields<T>, options?: RetryableWriteOptions): Promise<
|
|
1701
|
+
update(read: ReadEntry, data: DocumentFields<T>, options?: RetryableWriteOptions): Promise<W>;
|
|
1462
1702
|
/**
|
|
1463
1703
|
* Write the document with no version check, on purpose, in `options.locale` or the client's own —
|
|
1464
1704
|
* creating it, when nobody has yet.
|
|
1465
1705
|
*/
|
|
1466
|
-
update(data: DocumentFields<T>, options?: DocumentWriteOptions): Promise<
|
|
1706
|
+
update(data: DocumentFields<T>, options?: DocumentWriteOptions): Promise<W>;
|
|
1467
1707
|
/**
|
|
1468
1708
|
* Version history for one locale of the document.
|
|
1469
1709
|
*
|
|
@@ -1472,7 +1712,7 @@ declare abstract class DocumentHandle<T> {
|
|
|
1472
1712
|
* returns an empty array rather than another locale's rows. Every row names the locale it belongs
|
|
1473
1713
|
* to.
|
|
1474
1714
|
*/
|
|
1475
|
-
versions(options?: DocumentVersionsOptions): Promise<
|
|
1715
|
+
versions(options?: DocumentVersionsOptions): Promise<DocumentVersionRow[]>;
|
|
1476
1716
|
/**
|
|
1477
1717
|
* One version of the document: `version({ version, locale })`. `locale` defaults to the client's
|
|
1478
1718
|
* own, then the schema default; version numbers are per locale, so version 2 is different content
|
|
@@ -1482,20 +1722,20 @@ declare abstract class DocumentHandle<T> {
|
|
|
1482
1722
|
* schema does not declare and a dataset with no schema all throw `ResourceNotFoundError`, its
|
|
1483
1723
|
* `context.resourceType` naming which (REL-2409 Q12).
|
|
1484
1724
|
*/
|
|
1485
|
-
version(options: VersionOptions): Promise<T
|
|
1486
|
-
/** `PATCH` the document's route with this write. */
|
|
1487
|
-
protected abstract patch(write: DocumentWrite<T>, options?: RetryableWriteOptions): Promise<
|
|
1725
|
+
version(options: VersionOptions): Promise<DocumentVersion<T>>;
|
|
1726
|
+
/** `PATCH` the document's route with this write, answering what the route answers a write. */
|
|
1727
|
+
protected abstract patch(write: DocumentWrite<T>, options?: RetryableWriteOptions): Promise<W>;
|
|
1488
1728
|
/** `GET` the document's version history route. */
|
|
1489
1729
|
protected abstract readVersions(query: {
|
|
1490
1730
|
limit: number;
|
|
1491
1731
|
locale?: string;
|
|
1492
1732
|
}): Promise<{
|
|
1493
|
-
versions:
|
|
1733
|
+
versions: DocumentVersionRow[];
|
|
1494
1734
|
}>;
|
|
1495
1735
|
/** `GET` one version of the document. */
|
|
1496
1736
|
protected abstract readVersion(versionNumber: string, query: {
|
|
1497
1737
|
locale?: string;
|
|
1498
|
-
}): Promise<T
|
|
1738
|
+
}): Promise<DocumentVersion<T>>;
|
|
1499
1739
|
/** The locale a write or a history read sends: the call's, else the client's. */
|
|
1500
1740
|
protected localeOf(named: string | undefined): string | undefined;
|
|
1501
1741
|
/** The write's body: its data, and the locale it names when it names one. */
|
|
@@ -1526,7 +1766,7 @@ declare abstract class DocumentHandle<T> {
|
|
|
1526
1766
|
* if (homepage) await client.singleton('homepage').update(homepage, { title: 'Welcome' })
|
|
1527
1767
|
* ```
|
|
1528
1768
|
*/
|
|
1529
|
-
declare class SingletonClient<T = BaseSingleton, R extends Reading = UntypedReading<T>> extends DocumentHandle<T
|
|
1769
|
+
declare class SingletonClient<T = BaseSingleton, R extends Reading = UntypedReading<T>> extends DocumentHandle<T, WrittenSingleton<T>> {
|
|
1530
1770
|
/**
|
|
1531
1771
|
* The singleton, or `null` when nobody has written it yet (REL-2419, REL-2409 Q18).
|
|
1532
1772
|
*
|
|
@@ -1544,17 +1784,20 @@ declare class SingletonClient<T = BaseSingleton, R extends Reading = UntypedRead
|
|
|
1544
1784
|
* ```
|
|
1545
1785
|
*/
|
|
1546
1786
|
get<const P extends readonly string[] = []>(options?: DocumentReadOptions<R, P>): Promise<ReadWith<R, P[number]> | null>;
|
|
1547
|
-
/**
|
|
1548
|
-
|
|
1787
|
+
/**
|
|
1788
|
+
* The API publishes on PATCH: there is no separate publish route. The answer's `_metadata` also
|
|
1789
|
+
* lists the links the write left pointing nowhere and its `warnings` (REL-3097).
|
|
1790
|
+
*/
|
|
1791
|
+
protected patch(write: DocumentWrite<T>, options?: RetryableWriteOptions): Promise<WrittenSingleton<T>>;
|
|
1549
1792
|
protected readVersions(query: {
|
|
1550
1793
|
limit: number;
|
|
1551
1794
|
locale?: string;
|
|
1552
1795
|
}): Promise<{
|
|
1553
|
-
versions:
|
|
1796
|
+
versions: DocumentVersionRow[];
|
|
1554
1797
|
}>;
|
|
1555
1798
|
protected readVersion(versionNumber: string, query: {
|
|
1556
1799
|
locale?: string;
|
|
1557
|
-
}): Promise<T
|
|
1800
|
+
}): Promise<DocumentVersion<T>>;
|
|
1558
1801
|
}
|
|
1559
1802
|
|
|
1560
1803
|
/**
|
|
@@ -1581,7 +1824,7 @@ declare class SingletonClient<T = BaseSingleton, R extends Reading = UntypedRead
|
|
|
1581
1824
|
* await client.settings('email-config').update(emailConfig, { fromName: 'RelyIO' })
|
|
1582
1825
|
* ```
|
|
1583
1826
|
*/
|
|
1584
|
-
declare class SettingsClient<T = BaseSettingsGroup, R extends Reading = UntypedReading<T>> extends DocumentHandle<T
|
|
1827
|
+
declare class SettingsClient<T = BaseSettingsGroup, R extends Reading = UntypedReading<T>> extends DocumentHandle<T, WrittenSettingsGroup<T>> {
|
|
1585
1828
|
/**
|
|
1586
1829
|
* The settings group (REL-2419, REL-2409 Q18).
|
|
1587
1830
|
*
|
|
@@ -1606,25 +1849,25 @@ declare class SettingsClient<T = BaseSettingsGroup, R extends Reading = UntypedR
|
|
|
1606
1849
|
* in the locale it was read in (REL-2419) — refused with `ResourceConflictError` if it changed
|
|
1607
1850
|
* since the read.
|
|
1608
1851
|
*/
|
|
1609
|
-
reset(read: ReadEntry, options?: RetryableWriteOptions): Promise<T
|
|
1852
|
+
reset(read: ReadEntry, options?: RetryableWriteOptions): Promise<WrittenSettingsGroup<T>>;
|
|
1610
1853
|
/**
|
|
1611
1854
|
* Reset the group to its default values with no version check, in `options.locale` or the
|
|
1612
1855
|
* client's own. The route reads its locale from `?locale=` and takes no body, so that is where it
|
|
1613
1856
|
* is sent.
|
|
1614
1857
|
*/
|
|
1615
|
-
reset(options?: DocumentWriteOptions): Promise<T
|
|
1858
|
+
reset(options?: DocumentWriteOptions): Promise<WrittenSettingsGroup<T>>;
|
|
1616
1859
|
/** The group's default values, as the schema declares them. */
|
|
1617
1860
|
getDefaults(): Promise<T>;
|
|
1618
|
-
protected patch(write: DocumentWrite<T>, options?: RetryableWriteOptions): Promise<T
|
|
1861
|
+
protected patch(write: DocumentWrite<T>, options?: RetryableWriteOptions): Promise<WrittenSettingsGroup<T>>;
|
|
1619
1862
|
protected readVersions(query: {
|
|
1620
1863
|
limit: number;
|
|
1621
1864
|
locale?: string;
|
|
1622
1865
|
}): Promise<{
|
|
1623
|
-
versions:
|
|
1866
|
+
versions: DocumentVersionRow[];
|
|
1624
1867
|
}>;
|
|
1625
1868
|
protected readVersion(versionNumber: string, query: {
|
|
1626
1869
|
locale?: string;
|
|
1627
|
-
}): Promise<T
|
|
1870
|
+
}): Promise<DocumentVersion<T>>;
|
|
1628
1871
|
}
|
|
1629
1872
|
|
|
1630
1873
|
/**
|
|
@@ -1804,6 +2047,12 @@ interface SearchReadOptions<C extends string> {
|
|
|
1804
2047
|
readonly dataset?: string;
|
|
1805
2048
|
/** How fresh the answer must be: a feed position, or `true` for past every cache. */
|
|
1806
2049
|
readonly fresh?: FreshOption;
|
|
2050
|
+
/**
|
|
2051
|
+
* Cancels the request when it aborts. The call then rejects with the platform's `AbortError` —
|
|
2052
|
+
* not a `TimeoutError` — and a request already cancelled sends nothing. The client's timeout
|
|
2053
|
+
* still applies.
|
|
2054
|
+
*/
|
|
2055
|
+
readonly signal?: AbortSignal;
|
|
1807
2056
|
}
|
|
1808
2057
|
/**
|
|
1809
2058
|
* What `search(q, options)` takes.
|
|
@@ -1993,6 +2242,12 @@ interface BatchWriteOptions {
|
|
|
1993
2242
|
readonly returnData?: boolean;
|
|
1994
2243
|
/** The dataset to write, by id or name, over the client's. */
|
|
1995
2244
|
readonly dataset?: string;
|
|
2245
|
+
/**
|
|
2246
|
+
* Cancels the request when it aborts. The call then rejects with the platform's `AbortError` —
|
|
2247
|
+
* not a `TimeoutError` — and a request already cancelled sends nothing. The client's timeout
|
|
2248
|
+
* still applies.
|
|
2249
|
+
*/
|
|
2250
|
+
readonly signal?: AbortSignal;
|
|
1996
2251
|
}
|
|
1997
2252
|
/**
|
|
1998
2253
|
* One batch item, as the committed document describes the `multi` kind: an `outcome` —
|
|
@@ -2009,21 +2264,26 @@ type BatchBody = Wire<'/v1/batch', 'post', BatchResponse>;
|
|
|
2009
2264
|
/**
|
|
2010
2265
|
* Ad-hoc and named queries as single calls: `client.query(…)` (REL-2421; REL-2409 decision Q22).
|
|
2011
2266
|
*
|
|
2012
|
-
* - `client.query({ from, … })` runs a query inline. It takes `list`'s
|
|
2013
|
-
*
|
|
2014
|
-
* plus its own: `aggregate`, `params` and `fullText`. `where` is `list`'s,
|
|
2015
|
-
* it (`{ views: { $gte: 10 } }`): the query route reads the `where` a list
|
|
2016
|
-
* REL-2409 decision D11), and refuses the bare form a saved query used to
|
|
2267
|
+
* - `client.query({ from, … })` runs a query inline. It takes `list`'s options, typed from the same
|
|
2268
|
+
* option types — `where`, `include`, `select`, `sort`, `limit`, `cursor`, `page`, `locale`,
|
|
2269
|
+
* `dataset`, `fresh` — plus its own: `aggregate`, `params` and `fullText`. `where` is `list`'s,
|
|
2270
|
+
* typed as `list` types it (`{ views: { $gte: 10 } }`): the query route reads the `where` a list
|
|
2271
|
+
* takes (REL-2439, REL-2409 decision D11), and refuses the bare form a saved query used to
|
|
2272
|
+
* declare. `locale` is a code, a list of codes or `'*'`, and `select` sits beside `include`, as
|
|
2273
|
+
* they do on `list` (REL-2460).
|
|
2017
2274
|
* - `client.query(name, { params, … })` runs the saved query the schema declares under `name`, by
|
|
2018
2275
|
* that name alone (`POST /v1/queries/{name}`, D9). Its parameters are typed from the declaration
|
|
2019
2276
|
* ({@link InferQueryParams}): a name it does not declare does not compile, and the API refuses it
|
|
2020
2277
|
* too, naming it.
|
|
2021
2278
|
*
|
|
2022
|
-
*
|
|
2023
|
-
*
|
|
2024
|
-
*
|
|
2025
|
-
* `
|
|
2279
|
+
* An ad-hoc query answers a list's envelope, `{ data, page, meta }` — its records the entries
|
|
2280
|
+
* `list` answers, an aggregate's rows or a singleton as a list of one, `page` the cursor page
|
|
2281
|
+
* `{ nextCursor, hasMore }` and `meta` how the query ran. A named query answers the API's body,
|
|
2282
|
+
* `{ data: { result, metadata } }`.
|
|
2026
2283
|
*
|
|
2284
|
+
* The cursor and the locale ride the POST's query string as they ride a list's (`?cursor=`,
|
|
2285
|
+
* `?locale=`, `?locales=`); a `page` number is sent as the offset that page starts at, so it needs the
|
|
2286
|
+
* `limit` that sizes it — the route has no default page size.
|
|
2027
2287
|
*/
|
|
2028
2288
|
|
|
2029
2289
|
/** The content types a query reads: the schema's, or any where no schema types the client. */
|
|
@@ -2043,45 +2303,35 @@ type NamedQueryParams<S, N> = S extends AnySchemaDefinition ? InferQueryParams<S
|
|
|
2043
2303
|
* route's `aggregate` block. Its source is `from`.
|
|
2044
2304
|
*/
|
|
2045
2305
|
type QueryAggregate = Omit<AggregateBlock, 'source'>;
|
|
2046
|
-
/**
|
|
2306
|
+
/**
|
|
2307
|
+
* Which page of a query: the `cursor` a previous answer's `page` handed back, or a page number, one
|
|
2308
|
+
* or the other as on `list`. A number is sent as the offset it starts at, `(page - 1) * limit`, so it
|
|
2309
|
+
* needs the `limit` that sizes it: the route has no default page size to count from.
|
|
2310
|
+
*/
|
|
2047
2311
|
type QueryPaging<T extends BaseContent, R extends Reading> = {
|
|
2312
|
+
/** The page after the one a previous answer ended on: its `page.nextCursor`. */
|
|
2313
|
+
readonly cursor?: string;
|
|
2048
2314
|
readonly page?: never;
|
|
2049
2315
|
} | {
|
|
2050
2316
|
/** Which page, from 1: sent as the offset it starts at, `(page - 1) * limit`. */
|
|
2051
2317
|
readonly page: number;
|
|
2052
2318
|
readonly limit: NonNullable<ListReadOptions<T, R, []>['limit']>;
|
|
2319
|
+
readonly cursor?: never;
|
|
2053
2320
|
};
|
|
2054
|
-
/**
|
|
2055
|
-
type
|
|
2056
|
-
readonly select?: Sel;
|
|
2057
|
-
readonly include?: undefined;
|
|
2058
|
-
} | {
|
|
2059
|
-
readonly select?: undefined;
|
|
2060
|
-
readonly include?: CheckedIncludes<R, P>;
|
|
2061
|
-
};
|
|
2321
|
+
/** The options a query takes exactly as `list` takes them, typed by `list`'s own types. */
|
|
2322
|
+
type ListedOptions = 'where' | 'include' | 'select' | 'sort' | 'limit' | 'locale' | 'dataset' | 'fresh' | 'signal';
|
|
2062
2323
|
/**
|
|
2063
|
-
* What `client.query({ from, … })` takes: `list`'s options
|
|
2064
|
-
* query's own.
|
|
2324
|
+
* What `client.query({ from, … })` takes: `list`'s options — the very types, so a change to one is a
|
|
2325
|
+
* change to both — and the query's own (REL-2460).
|
|
2326
|
+
*
|
|
2327
|
+
* `where` is `list`'s, a value, a list or `$`-prefixed operators (`{ views: { $gte: 10 } }`), and a
|
|
2328
|
+
* condition on `_metadata` is refused before anything is sent. `locale` is a code, a list of codes or
|
|
2329
|
+
* `'*'`. `select` sits beside `include`: the selected Fields, the expanded references and
|
|
2330
|
+
* `_metadata`.
|
|
2065
2331
|
*/
|
|
2066
|
-
type AdhocQuery<K extends string, T extends BaseContent, R extends Reading, P extends readonly string[], Sel extends readonly FieldKey<T>[] | undefined, A extends QueryAggregate | undefined> = {
|
|
2332
|
+
type AdhocQuery<K extends string, T extends BaseContent, R extends Reading, P extends readonly string[], Sel extends readonly FieldKey<T>[] | undefined, L extends LocaleOption<ReadLocale<R>> | undefined, A extends QueryAggregate | undefined> = {
|
|
2067
2333
|
/** The content type the query reads. */
|
|
2068
2334
|
readonly from: K;
|
|
2069
|
-
/**
|
|
2070
|
-
* The conditions an entry must meet: the `where` `list` takes, typed as `list` types it — a value,
|
|
2071
|
-
* a list, or `$`-prefixed operators (`{ views: { $gte: 10 } }`). A condition on `_metadata` is
|
|
2072
|
-
* refused before anything is sent.
|
|
2073
|
-
*/
|
|
2074
|
-
readonly where?: ListReadOptions<T, R, P>['where'];
|
|
2075
|
-
/** The order, by Field or system date, the key order the priority. */
|
|
2076
|
-
readonly sort?: SortOption<T>;
|
|
2077
|
-
/** How many entries the query answers — a page's size where `page` names one. */
|
|
2078
|
-
readonly limit?: ListReadOptions<T, R, P>['limit'];
|
|
2079
|
-
/** The one locale the entries are composed in, over the client's. */
|
|
2080
|
-
readonly locale?: ReadLocale<R>;
|
|
2081
|
-
/** The dataset to read, by id or name, over the client's. */
|
|
2082
|
-
readonly dataset?: string;
|
|
2083
|
-
/** How fresh the answer must be: a feed position, or `true` for past every cache. */
|
|
2084
|
-
readonly fresh?: FreshOption;
|
|
2085
2335
|
/** Groups and metrics computed over the entries fetched; the answer is then their rows. */
|
|
2086
2336
|
readonly aggregate?: A;
|
|
2087
2337
|
/** Values for the `${param}` expressions the query writes. */
|
|
@@ -2090,7 +2340,7 @@ type AdhocQuery<K extends string, T extends BaseContent, R extends Reading, P ex
|
|
|
2090
2340
|
};
|
|
2091
2341
|
/** A text search over the Fields it names, beside the fetch. */
|
|
2092
2342
|
readonly fullText?: FullTextSearch;
|
|
2093
|
-
} &
|
|
2343
|
+
} & Pick<ListReadOptions<T, R, P, Sel, L, undefined>, ListedOptions> & QueryPaging<T, R>;
|
|
2094
2344
|
/** What `client.query(name, options)` takes beside the parameters. */
|
|
2095
2345
|
interface NamedQueryReadOptions<L extends string> {
|
|
2096
2346
|
/** The one locale the query composes in, over the client's. */
|
|
@@ -2098,10 +2348,17 @@ interface NamedQueryReadOptions<L extends string> {
|
|
|
2098
2348
|
/** The dataset to read, by id or name, over the client's. */
|
|
2099
2349
|
readonly dataset?: string;
|
|
2100
2350
|
/**
|
|
2101
|
-
*
|
|
2102
|
-
*
|
|
2351
|
+
* How fresh the answer must be: a feed position (a change's `fresh`), or `true` for past every
|
|
2352
|
+
* cache. The route is kept at the edge for as long as the query's own `cache` policy allows
|
|
2353
|
+
* (REL-2451), so a position names a key no copy from before that change is under.
|
|
2103
2354
|
*/
|
|
2104
|
-
readonly fresh?:
|
|
2355
|
+
readonly fresh?: FreshOption;
|
|
2356
|
+
/**
|
|
2357
|
+
* Cancels the request when it aborts. The call then rejects with the platform's `AbortError` —
|
|
2358
|
+
* not a `TimeoutError` — and a request already cancelled sends nothing. The client's timeout
|
|
2359
|
+
* still applies.
|
|
2360
|
+
*/
|
|
2361
|
+
readonly signal?: AbortSignal;
|
|
2105
2362
|
}
|
|
2106
2363
|
/** What `client.query(name, options)` takes: `params` required where the query requires one. */
|
|
2107
2364
|
type NamedQueryOptions<Params, L extends string> = NamedQueryReadOptions<L> & (Record<never, never> extends Params ? {
|
|
@@ -2137,7 +2394,7 @@ interface QueryMetadata {
|
|
|
2137
2394
|
/** Validation warnings */
|
|
2138
2395
|
warnings?: string[];
|
|
2139
2396
|
}
|
|
2140
|
-
/** The API's body for a query: the records it produced and how it ran. */
|
|
2397
|
+
/** The API's body for a saved query: the records it produced and how it ran. */
|
|
2141
2398
|
interface QueryAnswer<T> {
|
|
2142
2399
|
readonly data: {
|
|
2143
2400
|
/** The records the query produced. */
|
|
@@ -2146,10 +2403,17 @@ interface QueryAnswer<T> {
|
|
|
2146
2403
|
};
|
|
2147
2404
|
}
|
|
2148
2405
|
/**
|
|
2149
|
-
*
|
|
2150
|
-
*
|
|
2406
|
+
* The API's body for an ad-hoc query: a list's envelope (REL-2460), as `list` answers it —
|
|
2407
|
+
* `data` the records, `page` the cursor dialect's `{ nextCursor, hasMore }` and no total, and
|
|
2408
|
+
* `meta` how the query ran ({@link QueryMetadata}).
|
|
2409
|
+
*/
|
|
2410
|
+
type AdhocAnswer<T> = Wire<'/v1/query', 'post', T>;
|
|
2411
|
+
/**
|
|
2412
|
+
* One record of an ad-hoc query: an aggregate's row, or the entry as `list` answers it — the
|
|
2413
|
+
* selected Fields beside `_metadata`, the expanded references of its include paths, and the other
|
|
2414
|
+
* locales under `_metadata.localizations` for a list of locales or `'*'`.
|
|
2151
2415
|
*/
|
|
2152
|
-
type AdhocRecord<R extends Reading, P extends readonly string[], Sel, A> = A extends QueryAggregate ? Readonly<Record<string, unknown>> :
|
|
2416
|
+
type AdhocRecord<R extends Reading, P extends readonly string[], Sel, L, A> = A extends QueryAggregate ? Readonly<Record<string, unknown>> : ReadAs<R, P, Sel, L>;
|
|
2153
2417
|
/**
|
|
2154
2418
|
* `client.query`: callable two ways, beside the chained client it was before.
|
|
2155
2419
|
*
|
|
@@ -2160,22 +2424,27 @@ type QueryCall<S extends AnySchemaDefinition | undefined> = AdhocQueryCall<S> &
|
|
|
2160
2424
|
/** `client.query({ from, … })`. */
|
|
2161
2425
|
type AdhocQueryCall<S extends AnySchemaDefinition | undefined> = {
|
|
2162
2426
|
/**
|
|
2163
|
-
* Run a query inline: `list`'s options plus `aggregate`, `params` and `fullText`. Answers
|
|
2164
|
-
*
|
|
2427
|
+
* Run a query inline: `list`'s options plus `aggregate`, `params` and `fullText`. Answers a
|
|
2428
|
+
* list's envelope, `{ data, page, meta }` — `data` the entries as `list` answers them, or the
|
|
2429
|
+
* aggregate's rows, `page` the cursor page and `meta` how the query ran.
|
|
2430
|
+
*
|
|
2431
|
+
* Page it by the `cursor` an answer's `page.nextCursor` hands back, as a list is paged; `locale`
|
|
2432
|
+
* is a code, a list of codes or `'*'`, and `select` sits beside `include`.
|
|
2165
2433
|
*
|
|
2166
2434
|
* @example
|
|
2167
2435
|
* ```typescript
|
|
2168
|
-
* const { data } = await relyio.query({
|
|
2436
|
+
* const { data, page } = await relyio.query({
|
|
2169
2437
|
* from: 'post',
|
|
2170
2438
|
* where: { views: { $gte: 100 } },
|
|
2171
2439
|
* select: ['title', 'views'],
|
|
2440
|
+
* include: ['author(name)'],
|
|
2172
2441
|
* sort: { views: 'desc' },
|
|
2173
2442
|
* limit: 10,
|
|
2174
|
-
* page: 2,
|
|
2175
2443
|
* })
|
|
2444
|
+
* const next = page.nextCursor && (await relyio.query({ from: 'post', limit: 10, cursor: page.nextCursor }))
|
|
2176
2445
|
* ```
|
|
2177
2446
|
*/
|
|
2178
|
-
run<K extends QueryTypeName<S>, const P extends readonly string[] = [], const Sel extends readonly FieldKey<EntryOf<S, K>>[] | undefined = undefined, const A extends QueryAggregate | undefined = undefined>(query: AdhocQuery<K, EntryOf<S, K>, ReadingOf<S, K>, P, Sel, A>): Promise<
|
|
2447
|
+
run<K extends QueryTypeName<S>, const P extends readonly string[] = [], const Sel extends readonly FieldKey<EntryOf<S, K>>[] | undefined = undefined, const L extends LocaleOption<ReadLocale<ReadingOf<S, K>>> | undefined = undefined, const A extends QueryAggregate | undefined = undefined>(query: AdhocQuery<K, EntryOf<S, K>, ReadingOf<S, K>, P, Sel, L, A>): Promise<AdhocAnswer<AdhocRecord<ReadingOf<S, K>, P, Sel, L, A>>>;
|
|
2179
2448
|
}['run'];
|
|
2180
2449
|
/** `client.query(name, { params, … })`. */
|
|
2181
2450
|
type NamedQueryCall<S extends AnySchemaDefinition | undefined> = {
|
|
@@ -2299,9 +2568,10 @@ type FeedChange = Change & {
|
|
|
2299
2568
|
};
|
|
2300
2569
|
/**
|
|
2301
2570
|
* Why a cursor could no longer be replayed, or why everything must be refetched. `/v1/changes`
|
|
2302
|
-
* names `retention` and `dataset-replaced
|
|
2303
|
-
* wire declares (`VisitorResyncReason` in
|
|
2304
|
-
* restated). `unknown` when the
|
|
2571
|
+
* names `retention` and `dataset-replaced` as its refusal's `details.reason`; the live edge's
|
|
2572
|
+
* `feed.resync` may name any reason its wire declares (`VisitorResyncReason` in
|
|
2573
|
+
* `@relyio/api-contract`, read from there rather than restated). `unknown` when the error named
|
|
2574
|
+
* none of them.
|
|
2305
2575
|
*/
|
|
2306
2576
|
type ChangesExpiredReason = VisitorResyncReason | 'unknown';
|
|
2307
2577
|
/**
|
|
@@ -2309,9 +2579,11 @@ type ChangesExpiredReason = VisitorResyncReason | 'unknown';
|
|
|
2309
2579
|
* ledger can no longer replay from (`INV-SS-CURSOR-REPLAYS`). The consumer
|
|
2310
2580
|
* resyncs from the read path and starts again without a cursor.
|
|
2311
2581
|
*
|
|
2312
|
-
* A `ResourceExpiredError`, so code that already catches that still does.
|
|
2313
|
-
*
|
|
2314
|
-
*
|
|
2582
|
+
* A `ResourceExpiredError`, so code that already catches that still does.
|
|
2583
|
+
* `reason` is the refusal's `details.reason`, which the error mapper puts on
|
|
2584
|
+
* `context.reason` (REL-3178) — never read from the message, which is English
|
|
2585
|
+
* for a developer and names no reason. An error built by hand names its reason
|
|
2586
|
+
* the same way, as `context.reason`.
|
|
2315
2587
|
*
|
|
2316
2588
|
* The live edge's `feed.resync` — a socket's frame or a poll's answer — is the
|
|
2317
2589
|
* same instruction and arrives as the same error ({@link ChangesExpiredError.resync}),
|
|
@@ -2638,14 +2910,16 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
|
|
|
2638
2910
|
/**
|
|
2639
2911
|
* Run a query in one call (REL-2421, REL-2409 Q22):
|
|
2640
2912
|
*
|
|
2641
|
-
* - `query({ from, … })` runs one inline, with `list`'s
|
|
2642
|
-
*
|
|
2643
|
-
* plus `aggregate`, `params` and `fullText
|
|
2913
|
+
* - `query({ from, … })` runs one inline, with `list`'s options — `where`, `include`, `select`
|
|
2914
|
+
* (beside `include`), `sort`, `limit`, `cursor`, `page`, `locale` (a code, a list or `'*'`),
|
|
2915
|
+
* `dataset`, `fresh` — plus `aggregate`, `params` and `fullText`. It answers a list's envelope,
|
|
2916
|
+
* `{ data, page, meta }` (REL-2460);
|
|
2644
2917
|
* - `query(name, { params, … })` runs the saved query the schema declares under `name`, its
|
|
2645
|
-
* `params` typed from that declaration.
|
|
2918
|
+
* `params` typed from that declaration. It answers the API's body,
|
|
2919
|
+
* `{ data: { result, metadata } }`.
|
|
2646
2920
|
*
|
|
2647
|
-
*
|
|
2648
|
-
*
|
|
2921
|
+
* See {@link QueryCall}. Every query is sent in the client's locale as it is then, unless it names
|
|
2922
|
+
* its own.
|
|
2649
2923
|
*/
|
|
2650
2924
|
get query(): QueryCall<TSchema>;
|
|
2651
2925
|
/**
|
|
@@ -2921,9 +3195,9 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
|
|
|
2921
3195
|
* - an option you name replaces the value the client holds;
|
|
2922
3196
|
* - an option left out, or given as `undefined`, keeps the value the client holds;
|
|
2923
3197
|
* - an option with no default given as `null` is cleared — `locale`, `dataset`, `apiKey`, `dev`,
|
|
2924
|
-
* `fetch`, `browser.onCorsError`, `
|
|
3198
|
+
* `fetch`, `browser.onCorsError`, `debug.logger` — so the client runs as though
|
|
2925
3199
|
* it had never been given one. An option with a default takes no `null`;
|
|
2926
|
-
* - a bag of options you name — `browser`, `cache`, `
|
|
3200
|
+
* - a bag of options you name — `browser`, `cache`, `debug` — keeps every field of it
|
|
2927
3201
|
* you do not name, so `updateConfig({ browser: { includeCredentials: true } })` keeps a
|
|
2928
3202
|
* configured `onCorsError`;
|
|
2929
3203
|
* - `headers` is laid over the headers the client sends, a name matched without regard to case: a
|
|
@@ -3087,4 +3361,4 @@ declare function createClient<TSchema extends AnySchemaDefinition>(config: Typed
|
|
|
3087
3361
|
*/
|
|
3088
3362
|
type ClientSchema<T extends TypedRelyIOClient<AnySchemaDefinition>> = T extends TypedRelyIOClient<infer TSchema> ? TSchema : never;
|
|
3089
3363
|
|
|
3090
|
-
export { type
|
|
3364
|
+
export { type ChildrenOptions as $, type AnySchemaDefinition as A, LIVE_KEEPALIVE_INTERVAL_MS as B, type Change as C, type DeployedLocale as D, LIVE_SOCKET_OPEN_TIMEOUT_MS as E, type FeedChange as F, type LiveChangesOptions as G, type Health as H, ContentClient as I, type CreateEntryOptions as J, type EntryPlacement as K, type LocaleCodeOf as L, type MatchRouteOptions as M, type EntryWriteOptions as N, SingletonClient as O, type Project as P, SettingsClient as Q, type Register as R, type SandboxState as S, TypedRelyIOClient as T, type DocumentFields as U, type VisitorRetry as V, type Wire as W, type DocumentVersion as X, type DocumentVersionRow as Y, type DocumentVersionsOptions as Z, type DocumentWriteOptions as _, ChangesExpiredError as a, AssetClient as a$, type ChildrenListOptions as a0, type DocumentReadOptions as a1, type EntryList as a2, type FieldKey as a3, type FreshOption as a4, type GetOptions as a5, type ListAllOptions as a6, type ListOptions as a7, type LocaleOption as a8, type Paging as a9, type SearchSortOption as aA, type SearchWhere as aB, type SimilarOptions as aC, type BatchOperationResult as aD, type BatchSummary as aE, type BatchResponse as aF, type BatchWrite as aG, type BatchWriteOptions as aH, type BatchBody as aI, type BatchCreate as aJ, type BatchUpdate as aK, type BatchReplace as aL, type BatchDelete as aM, type BatchSingletonWrite as aN, type BatchTarget as aO, type BatchDeleteTarget as aP, type AggregateMetric as aQ, type QueryMetadata as aR, type AdhocQuery as aS, type AdhocRecord as aT, type NamedQueryOptions as aU, type NamedQueryParams as aV, type QueryAggregate as aW, type QueryAnswer as aX, type QueryCall as aY, type QueryName as aZ, type QueryTypeName as a_, type ChildEntry as aa, type ChildrenRead as ab, type ReadAs as ac, type WithChildren as ad, type ReadLocale as ae, type SortOption as af, type VersionOptions as ag, type WrittenReadScope as ah, type WrittenSort as ai, type SearchResultItem as aj, type SearchHitMetadata as ak, type SearchResponse as al, type AutocompleteSuggestion as am, type AutocompleteResponse as an, type SimilarResult as ao, type SimilarResponse as ap, type SearchTypeName as aq, type SearchEntry as ar, type AutocompleteOptions as as, type SearchFacet as at, type SearchFieldKey as au, type SearchHighlight as av, type SearchOptions as aw, type SearchPage as ax, type SearchScope as ay, type SearchSelected as az, type ChangesExpiredReason as b, AssetFileBuilder as b0, AssetUploadBuilder as b1, isAssetEntry as b2, type AssetVisibility as b3, type FileStatus as b4, type FileBackend as b5, type AssetFileExtracted as b6, type FileStatusResult as b7, type AssetEntryResponse as b8, type AssetFileWhere as b9, type PopulatedAssetReference as ba, type PresignInput as bb, type PresignResult as bc, type ConfirmInput as bd, type ConfirmResult as be, type ResolveUrlInput as bf, type ResolveUrlResult as bg, type CreateAssetOptions as bh, type AssetPlacement as bi, type UpdateAssetOptions as bj, type WaitUntilReadyOptions as bk, type MultipartCreateResult as bl, type MultipartPart as bm, type MultipartTarget as bn, type UploadProgress as bo, ResourceNotFoundError as bp, ResourceConflictError as bq, ResourceExpiredError as br, isResourceNotFound as bs, isMissingEntry as bt, type FileErrorCode as bu, type FileUploadErrorCode as bv, FileUploadError as bw, FileValidationError as bx, type FileValidationConstraints as by, validateFile as bz, createClient as c, type TypedClientConfig as d, type ClientDefaults as e, type ClientSchema as f, type DeployedContentType as g, type RegisteredSchema as h, type ActiveSandbox as i, HttpClient as j, type SendOptions as k, type ApiPath as l, type ApiMethod as m, type ApiSuccessBody as n, matchRoute as o, type RouteMatch as p, type ReadEntry as q, type RetryableWriteOptions as r, DefaultRetryPolicy as s, isReplaySafe as t, retryPolicyFor as u, versionCheckOf as v, type RetryPolicy as w, type RetryableRequest as x, type ChangesHeadOptions as y, type ChangesOptions as z };
|