@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.
Files changed (40) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/{chunk-3BHDGUNS.cjs → chunk-6E22GYPB.cjs} +434 -593
  3. package/dist/chunk-6PTRZP5U.cjs +433 -0
  4. package/dist/{chunk-PCFTJLEP.js → chunk-DIZY6CKM.js} +2 -2
  5. package/dist/{chunk-X4KSS7PP.cjs → chunk-GHYB6IZK.cjs} +2 -2
  6. package/dist/chunk-OVMIHAYK.js +411 -0
  7. package/dist/{chunk-PXA5ONIU.js → chunk-VS2DEUTN.js} +397 -560
  8. package/dist/client/index.cjs +4 -3
  9. package/dist/client/index.d.cts +3 -4
  10. package/dist/client/index.d.ts +3 -4
  11. package/dist/client/index.js +2 -1
  12. package/dist/{define-content-type-B2gQZkTy.d.cts → define-content-type-AuL9-oz6.d.cts} +668 -85
  13. package/dist/{define-content-type-Ds5rCAYl.d.ts → define-content-type-BGoQxqLf.d.ts} +668 -85
  14. package/dist/{define-schema-CxpIYFFR.d.ts → define-schema-DgCX9YB7.d.ts} +1 -1
  15. package/dist/{define-schema-Cm_5y3ei.d.cts → define-schema-DkXwpp0I.d.cts} +1 -1
  16. package/dist/{index-DQ7eTUPQ.d.ts → index-BBp8_tn9.d.ts} +467 -193
  17. package/dist/{index-DY64WjZM.d.cts → index-Bp4AiNT3.d.cts} +1 -1
  18. package/dist/{index-Db3_tmYf.d.ts → index-DaMZ4FQ_.d.ts} +1 -1
  19. package/dist/{index-F0UuHpRj.d.cts → index-DxRmKPrR.d.cts} +467 -193
  20. package/dist/index.cjs +96 -71
  21. package/dist/index.d.cts +26 -16
  22. package/dist/index.d.ts +26 -16
  23. package/dist/index.js +4 -3
  24. package/dist/markdown/index.cjs +10 -2
  25. package/dist/markdown/index.d.cts +12 -3
  26. package/dist/markdown/index.d.ts +12 -3
  27. package/dist/markdown/index.js +10 -2
  28. package/dist/preview/index.cjs +29 -0
  29. package/dist/preview/index.d.cts +117 -0
  30. package/dist/preview/index.d.ts +117 -0
  31. package/dist/preview/index.js +4 -0
  32. package/dist/rich-text/index.d.cts +2 -2
  33. package/dist/rich-text/index.d.ts +2 -2
  34. package/dist/schema/index.cjs +33 -33
  35. package/dist/schema/index.d.cts +3 -3
  36. package/dist/schema/index.d.ts +3 -3
  37. package/dist/schema/index.js +1 -1
  38. package/dist/types/index.d.cts +1 -1
  39. package/dist/types/index.d.ts +1 -1
  40. package/package.json +10 -4
@@ -1,11 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkLSRPMNPT_cjs = require('./chunk-LSRPMNPT.cjs');
4
+ var chunk6PTRZP5U_cjs = require('./chunk-6PTRZP5U.cjs');
4
5
  var chunkTZL374LS_cjs = require('./chunk-TZL374LS.cjs');
5
6
  var chunkMWMSFIWN_cjs = require('./chunk-MWMSFIWN.cjs');
6
7
 
7
8
  /* RelyIO SDK - Built with ❤️ by the RelyIO Team */
8
9
 
10
+ // src/config/key-kind.ts
11
+ var PUBLISHABLE_KEY_PREFIX = "rly_pub_";
12
+ var isPublishableKey = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name((apiKey) => apiKey?.startsWith(PUBLISHABLE_KEY_PREFIX) === true, "isPublishableKey");
13
+ var PREVIEW_KEY_PREFIX = "rly_prev_";
14
+ var isPreviewKey = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name((apiKey) => apiKey?.startsWith(PREVIEW_KEY_PREFIX) === true, "isPreviewKey");
15
+
9
16
  // src/errors/sdk-error.ts
10
17
  var _SDKError = class _SDKError extends Error {
11
18
  constructor(message, statusCode, cause, context) {
@@ -59,19 +66,84 @@ var _SDKError = class _SDKError extends Error {
59
66
  return this.code === errorType;
60
67
  }
61
68
  /**
62
- * Create a new error with additional context
69
+ * Create a copy of this error with additional context.
70
+ *
71
+ * The copy is made from this error's own properties, not by calling a constructor: subclasses
72
+ * declare constructors of their own (violations, a timeout, a feature, a failed index second),
73
+ * and no single argument order fits them all. Rebuilding through the base order put the status
74
+ * code in the subclass's second slot. Copying keeps every field, the subclass's own included, and
75
+ * the original `timestamp` and `stack`, since it is the same failure.
76
+ *
77
+ * `Object.create` runs no constructor, so a `#private` field would not survive the copy; none
78
+ * exist in this directory. `stack` is not an own property on V8 and is copied by hand below.
63
79
  */
64
80
  withContext(context) {
65
- const Constructor = this.constructor;
66
- return new Constructor(this.message, this.statusCode, this.cause, {
67
- ...this.context,
68
- ...context
81
+ return Object.create(Object.getPrototypeOf(this), {
82
+ ...Object.getOwnPropertyDescriptors(this),
83
+ stack: { value: this.stack, writable: true, enumerable: false, configurable: true },
84
+ context: {
85
+ value: { ...this.context, ...context },
86
+ writable: true,
87
+ enumerable: true,
88
+ configurable: true
89
+ }
69
90
  });
70
91
  }
71
92
  };
72
93
  chunkMWMSFIWN_cjs.__name(_SDKError, "SDKError");
73
94
  var SDKError = _SDKError;
74
95
 
96
+ // src/errors/content-errors.ts
97
+ var _ResourceNotFoundError = class _ResourceNotFoundError extends SDKError {
98
+ constructor(message = "Resource not found", statusCode = 404, cause, context) {
99
+ super(message, statusCode, cause, context);
100
+ chunkMWMSFIWN_cjs.__publicField(this, "code", "RESOURCE_NOT_FOUND");
101
+ chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
102
+ }
103
+ getUserMessage() {
104
+ const resourceType = this.context?.resourceType;
105
+ const resourceId = this.context?.resourceId;
106
+ if (resourceType != null && resourceId != null) {
107
+ return `${resourceType} with ID "${resourceId}" was not found.`;
108
+ }
109
+ return "The requested resource was not found.";
110
+ }
111
+ };
112
+ chunkMWMSFIWN_cjs.__name(_ResourceNotFoundError, "ResourceNotFoundError");
113
+ var ResourceNotFoundError = _ResourceNotFoundError;
114
+ var _ResourceConflictError = class _ResourceConflictError extends SDKError {
115
+ constructor(message = "Resource conflict", statusCode = 409, cause, context) {
116
+ super(message, statusCode, cause, context);
117
+ chunkMWMSFIWN_cjs.__publicField(this, "code", "RESOURCE_CONFLICT");
118
+ chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
119
+ }
120
+ getUserMessage() {
121
+ return "The resource could not be created or updated due to a conflict.";
122
+ }
123
+ };
124
+ chunkMWMSFIWN_cjs.__name(_ResourceConflictError, "ResourceConflictError");
125
+ var ResourceConflictError = _ResourceConflictError;
126
+ var _ResourceExpiredError = class _ResourceExpiredError extends SDKError {
127
+ constructor(message = "Resource has expired", statusCode = 410, cause, context) {
128
+ super(message, statusCode, cause, context);
129
+ chunkMWMSFIWN_cjs.__publicField(this, "code", "RESOURCE_EXPIRED");
130
+ chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
131
+ }
132
+ getUserMessage() {
133
+ return "The resource is no longer available.";
134
+ }
135
+ };
136
+ chunkMWMSFIWN_cjs.__name(_ResourceExpiredError, "ResourceExpiredError");
137
+ var ResourceExpiredError = _ResourceExpiredError;
138
+ function isResourceNotFound(error) {
139
+ return error instanceof ResourceNotFoundError;
140
+ }
141
+ chunkMWMSFIWN_cjs.__name(isResourceNotFound, "isResourceNotFound");
142
+ function isMissingEntry(error) {
143
+ return error instanceof ResourceNotFoundError && error.context?.resourceType === "entry";
144
+ }
145
+ chunkMWMSFIWN_cjs.__name(isMissingEntry, "isMissingEntry");
146
+
75
147
  // src/errors/contract-errors.ts
76
148
  var _MissingApiKeyError = class _MissingApiKeyError extends SDKError {
77
149
  constructor(message = "No API key was sent", context) {
@@ -184,7 +256,7 @@ var _TransactionRolledBackError = class _TransactionRolledBackError extends SDKE
184
256
  this.failedIndex = failedIndex;
185
257
  }
186
258
  getUserMessage() {
187
- return this.failedIndex === void 0 ? "The batch was rolled back; nothing was written." : `The batch was rolled back at operation ${this.failedIndex}; nothing was written.`;
259
+ return this.failedIndex === void 0 ? "The batch was rolled back; nothing was written." : `The batch was rolled back; nothing was written. This refusal is for operation ${this.failedIndex} of the batch, which is not necessarily the one that failed.`;
188
260
  }
189
261
  };
190
262
  chunkMWMSFIWN_cjs.__name(_TransactionRolledBackError, "TransactionRolledBackError");
@@ -258,57 +330,6 @@ var _InvalidApiKeyError = class _InvalidApiKeyError extends SDKError {
258
330
  chunkMWMSFIWN_cjs.__name(_InvalidApiKeyError, "InvalidApiKeyError");
259
331
  var InvalidApiKeyError = _InvalidApiKeyError;
260
332
 
261
- // src/errors/content-errors.ts
262
- var _ResourceNotFoundError = class _ResourceNotFoundError extends SDKError {
263
- constructor(message = "Resource not found", statusCode = 404, cause, context) {
264
- super(message, statusCode, cause, context);
265
- chunkMWMSFIWN_cjs.__publicField(this, "code", "RESOURCE_NOT_FOUND");
266
- chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
267
- }
268
- getUserMessage() {
269
- const resourceType = this.context?.resourceType;
270
- const resourceId = this.context?.resourceId;
271
- if (resourceType != null && resourceId != null) {
272
- return `${resourceType} with ID "${resourceId}" was not found.`;
273
- }
274
- return "The requested resource was not found.";
275
- }
276
- };
277
- chunkMWMSFIWN_cjs.__name(_ResourceNotFoundError, "ResourceNotFoundError");
278
- var ResourceNotFoundError = _ResourceNotFoundError;
279
- var _ResourceConflictError = class _ResourceConflictError extends SDKError {
280
- constructor(message = "Resource conflict", statusCode = 409, cause, context) {
281
- super(message, statusCode, cause, context);
282
- chunkMWMSFIWN_cjs.__publicField(this, "code", "RESOURCE_CONFLICT");
283
- chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
284
- }
285
- getUserMessage() {
286
- return "The resource could not be created or updated due to a conflict.";
287
- }
288
- };
289
- chunkMWMSFIWN_cjs.__name(_ResourceConflictError, "ResourceConflictError");
290
- var ResourceConflictError = _ResourceConflictError;
291
- var _ResourceExpiredError = class _ResourceExpiredError extends SDKError {
292
- constructor(message = "Resource has expired", statusCode = 410, cause, context) {
293
- super(message, statusCode, cause, context);
294
- chunkMWMSFIWN_cjs.__publicField(this, "code", "RESOURCE_EXPIRED");
295
- chunkMWMSFIWN_cjs.__publicField(this, "retryable", false);
296
- }
297
- getUserMessage() {
298
- return "The resource is no longer available.";
299
- }
300
- };
301
- chunkMWMSFIWN_cjs.__name(_ResourceExpiredError, "ResourceExpiredError");
302
- var ResourceExpiredError = _ResourceExpiredError;
303
- function isResourceNotFound(error) {
304
- return error instanceof ResourceNotFoundError;
305
- }
306
- chunkMWMSFIWN_cjs.__name(isResourceNotFound, "isResourceNotFound");
307
- function isMissingEntry(error) {
308
- return error instanceof ResourceNotFoundError && error.context?.resourceType === "entry";
309
- }
310
- chunkMWMSFIWN_cjs.__name(isMissingEntry, "isMissingEntry");
311
-
312
333
  // src/errors/network-errors.ts
313
334
  var _NetworkError = class _NetworkError extends SDKError {
314
335
  constructor(message = "Network request failed", statusCode, cause, context) {
@@ -416,229 +437,6 @@ var _InvalidPayloadError = class _InvalidPayloadError extends BaseValidationErro
416
437
  chunkMWMSFIWN_cjs.__name(_InvalidPayloadError, "InvalidPayloadError");
417
438
  var InvalidPayloadError = _InvalidPayloadError;
418
439
 
419
- // ../../platform/api-contract/dist/chunk-46347LG2.js
420
- function defineRoute(route) {
421
- if (route.kind === "raw" && route.standardShape === void 0) {
422
- throw new Error("kind 'raw' requires a named StandardShape");
423
- }
424
- if (route.kind === "raw" && route.success === 302 && !route.headers.some((header) => header.name === "Location")) {
425
- throw new Error("a raw route declaring success 302 must declare its 'Location' header");
426
- }
427
- if (route.kind === "stream" && route.stream === void 0) {
428
- throw new Error("kind 'stream' requires a StreamDeclaration");
429
- }
430
- if (route.kind === "collection" && route.page === void 0) {
431
- throw new Error("kind 'collection' requires a page dialect");
432
- }
433
- if (route.queues === true) {
434
- if (route.kind !== "object" && route.kind !== "empty") {
435
- throw new Error(
436
- `kind '${route.kind}' cannot declare \`queues\`: only an object or empty route answers 202 beside its own status`
437
- );
438
- }
439
- if (route.kind === "object" && route.success === 202) {
440
- throw new Error("a route whose own status is 202 cannot also declare `queues`");
441
- }
442
- }
443
- if ((route.kind === "object" || route.kind === "collection") && route.negotiated !== void 0) {
444
- refuseMismatchedAlternate(route, route.negotiated["text/event-stream"]);
445
- }
446
- return route;
447
- }
448
- chunkMWMSFIWN_cjs.__name(defineRoute, "defineRoute");
449
- function refuseMismatchedAlternate(route, stream) {
450
- if (stream.kind !== "stream") {
451
- throw new Error("a negotiated 'text/event-stream' alternate must be kind 'stream'");
452
- }
453
- if (stream.stream.mediaType !== "text/event-stream") {
454
- throw new Error(
455
- `a negotiated 'text/event-stream' alternate declares media type "${stream.stream.mediaType}"`
456
- );
457
- }
458
- const own = [...new Set(route.codes)].sort();
459
- const alternate = [...new Set(stream.codes)].sort();
460
- if (own.length !== alternate.length || own.some((code, index) => code !== alternate[index])) {
461
- throw new Error(
462
- `a negotiated alternate refuses with [${alternate.join(", ")}] while its route refuses with [${own.join(", ")}]; one route refuses with one set of codes on every transport`
463
- );
464
- }
465
- }
466
- chunkMWMSFIWN_cjs.__name(refuseMismatchedAlternate, "refuseMismatchedAlternate");
467
-
468
- // ../../platform/api-contract/dist/index.js
469
- var HEADER_RETRY_AFTER = { name: "Retry-After" };
470
- var HEADER_IF_MATCH = {
471
- name: "If-Match"};
472
- function entityTag(parts) {
473
- return `"${parts.entryUid}:${parts.locale}:${parts.version}:${parts.sharedVersion}"`;
474
- }
475
- chunkMWMSFIWN_cjs.__name(entityTag, "entityTag");
476
- var HEADER_IDEMPOTENCY_KEY = {
477
- name: "Idempotency-Key"};
478
- var FRESH_PARAMETER = "_fresh";
479
- var VISITOR_LIVE_PATH = "/visitor/changes";
480
- var VISITOR_QUERY = {
481
- /** The publishable key. */
482
- key: "key",
483
- /** A dataset id or name the key reaches; absent, the key's default dataset. */
484
- dataset: "dataset",
485
- /** The cursor to continue from; absent, the socket starts now. */
486
- since: "since",
487
- /** Comma-separated content types to keep; absent keeps every type. */
488
- types: "types",
489
- /** Comma-separated entry ids to keep; absent keeps every entry. */
490
- ids: "ids",
491
- /** The poll's client id. Required on a poll, and not read on a socket. */
492
- client: "client"
493
- };
494
- var VISITOR_CURSOR = /^[\w.~-]{1,256}$/;
495
- var VISITOR_POLL_INTERVAL_MS = 15e3;
496
- var VISITOR_KEEPALIVE = { request: "ping", response: "pong" };
497
- var VISITOR_FRAMES = {
498
- opened: "feed.opened",
499
- changes: "feed.changes",
500
- resync: "feed.resync"
501
- };
502
- defineRoute({
503
- kind: "object",
504
- headers: [HEADER_RETRY_AFTER],
505
- codes: [
506
- "REQUEST_INVALID",
507
- "MISSING_API_KEY",
508
- "INVALID_API_KEY",
509
- "ACCESS_DENIED",
510
- "METHOD_NOT_ALLOWED",
511
- "SERVICE_INDETERMINATE",
512
- "USAGE_QUOTA_EXCEEDED",
513
- "RATE_LIMIT_EXCEEDED"
514
- ]
515
- });
516
- var VISITOR_CLOSE_CODES = {
517
- /** A query the door cannot read: a malformed `since`, filter, `dataset` or `client`. */
518
- requestInvalid: 4400,
519
- /** No publishable key, or one that is unknown, revoked, expired, a secret key or a preview key. */
520
- keyRefused: 4401,
521
- /** The page's `Origin` is absent, or not on the key's allowed origins. */
522
- originRefused: 4403,
523
- /** `dataset` names nothing the key reaches. */
524
- datasetRefused: 4404,
525
- /** The key's scope, the project's counter or the feed could not be reached just now. */
526
- unavailable: 1013,
527
- /**
528
- * The project holds as many visitor connections as its plan allows — Starter's 100 — or its
529
- * Organization is suspended. As HTTP's 402: more needs a bigger plan, or visitors leaving.
530
- */
531
- allowanceReached: 4402,
532
- /** This client's address holds as many connections to the project as one address may. */
533
- addressLimitReached: 4429,
534
- /** The project is at its per-project safety ceiling — Pro's 50,000 — whatever it would pay for. */
535
- ceilingReached: 4503
536
- };
537
- var VISITOR_CLOSE_RETRY = {
538
- 4400: "stop",
539
- 4401: "stop",
540
- 4403: "stop",
541
- 4404: "stop",
542
- 1013: "retry",
543
- 4402: "back-off",
544
- 4429: "back-off",
545
- 4503: "back-off"
546
- };
547
- var VISITOR_POLL_RETRY = {
548
- REQUEST_INVALID: "stop",
549
- MISSING_API_KEY: "stop",
550
- INVALID_API_KEY: "stop",
551
- ACCESS_DENIED: "stop",
552
- METHOD_NOT_ALLOWED: "stop",
553
- SERVICE_INDETERMINATE: "retry",
554
- USAGE_QUOTA_EXCEEDED: "back-off",
555
- RATE_LIMIT_EXCEEDED: "back-off"
556
- };
557
- var VISITOR_ADMISSION_RETRY_AFTER_SECONDS = 60;
558
- function parseVisitorFrame(text) {
559
- let value;
560
- try {
561
- value = JSON.parse(text);
562
- } catch {
563
- return null;
564
- }
565
- if (!isRecord2(value) || !isCursor(value.cursor)) return null;
566
- switch (value.type) {
567
- case VISITOR_FRAMES.opened: {
568
- return hasOnly(value, ["type", "cursor"]) ? { type: VISITOR_FRAMES.opened, cursor: value.cursor } : null;
569
- }
570
- case VISITOR_FRAMES.changes: {
571
- const changes = hasOnly(value, ["type", "changes", "cursor"]) ? readVisitorChanges(value.changes) : null;
572
- return changes === null ? null : { type: VISITOR_FRAMES.changes, changes, cursor: value.cursor };
573
- }
574
- case VISITOR_FRAMES.resync: {
575
- return hasOnly(value, ["type", "reason", "cursor"]) && isResyncReason(value.reason) ? { type: VISITOR_FRAMES.resync, reason: value.reason, cursor: value.cursor } : null;
576
- }
577
- default: {
578
- return null;
579
- }
580
- }
581
- }
582
- chunkMWMSFIWN_cjs.__name(parseVisitorFrame, "parseVisitorFrame");
583
- function readVisitorPollAnswer(value) {
584
- if (!isRecord2(value) || !isCursor(value.cursor)) return null;
585
- if (value.kind === "resync") {
586
- return hasOnly(value, ["kind", "reason", "cursor"]) && isResyncReason(value.reason) ? { kind: "resync", reason: value.reason, cursor: value.cursor } : null;
587
- }
588
- if (value.kind !== "changes" || !hasOnly(value, ["kind", "changes", "cursor"])) return null;
589
- const changes = readVisitorChanges(value.changes);
590
- return changes === null ? null : { kind: "changes", changes, cursor: value.cursor };
591
- }
592
- chunkMWMSFIWN_cjs.__name(readVisitorPollAnswer, "readVisitorPollAnswer");
593
- var CHANGE_KINDS = /* @__PURE__ */ new Set([
594
- "published",
595
- "updated",
596
- "unpublished",
597
- "deleted"
598
- ]);
599
- var RESYNC_REASONS = /* @__PURE__ */ new Set([
600
- "retention",
601
- "dataset-replaced",
602
- "ahead-of-head",
603
- "foreign-cursor",
604
- "too-far-behind"
605
- ]);
606
- function isResyncReason(value) {
607
- return typeof value === "string" && RESYNC_REASONS.has(value);
608
- }
609
- chunkMWMSFIWN_cjs.__name(isResyncReason, "isResyncReason");
610
- function readVisitorChanges(value) {
611
- if (!Array.isArray(value)) return null;
612
- const changes = [];
613
- for (const item of value) {
614
- if (!isRecord2(item) || !hasOnly(item, ["entryId", "contentType", "locale", "kind"])) return null;
615
- const { entryId, contentType, locale, kind } = item;
616
- if (!isNonEmptyString2(entryId) || !isNonEmptyString2(contentType)) return null;
617
- if (locale !== null && typeof locale !== "string") return null;
618
- if (typeof kind !== "string" || !CHANGE_KINDS.has(kind)) return null;
619
- changes.push({ entryId, contentType, locale, kind });
620
- }
621
- return changes;
622
- }
623
- chunkMWMSFIWN_cjs.__name(readVisitorChanges, "readVisitorChanges");
624
- function isCursor(value) {
625
- return typeof value === "string" && VISITOR_CURSOR.test(value);
626
- }
627
- chunkMWMSFIWN_cjs.__name(isCursor, "isCursor");
628
- function isRecord2(value) {
629
- return typeof value === "object" && value !== null && !Array.isArray(value);
630
- }
631
- chunkMWMSFIWN_cjs.__name(isRecord2, "isRecord2");
632
- function isNonEmptyString2(value) {
633
- return typeof value === "string" && value.length > 0;
634
- }
635
- chunkMWMSFIWN_cjs.__name(isNonEmptyString2, "isNonEmptyString2");
636
- function hasOnly(value, keys) {
637
- const present = Object.keys(value);
638
- return present.length === keys.length && present.every((key) => keys.includes(key));
639
- }
640
- chunkMWMSFIWN_cjs.__name(hasOnly, "hasOnly");
641
-
642
440
  // ../../platform/api-contract/dist/client/index.js
643
441
  var _a;
644
442
  var ContractBodyError = (_a = class extends Error {
@@ -718,7 +516,7 @@ var _ErrorMapper = class _ErrorMapper {
718
516
  return new NetworkError(`HTTP ${status}: ${statusText}`.trim(), status, void 0, context);
719
517
  }
720
518
  const retryAfterMs = parseRetryAfterMs(
721
- headerValue(headers, HEADER_RETRY_AFTER.name),
519
+ headerValue(headers, chunk6PTRZP5U_cjs.HEADER_RETRY_AFTER.name),
722
520
  Date.now()
723
521
  );
724
522
  return this.fromContractCode(refusal, status, context, retryAfterMs);
@@ -776,9 +574,13 @@ var _ErrorMapper = class _ErrorMapper {
776
574
  }
777
575
  case "RESOURCE_CONFLICT": {
778
576
  const expectedVersion = detailNumber(refusal, "expectedVersion");
779
- const guidance = expectedVersion === void 0 ? message : `${message.endsWith(".") ? message : `${message}.`} ${STALE_VERSION_GUIDANCE}`;
577
+ const blockage = blockageOf(refusal);
578
+ const guidance = blockage !== void 0 || expectedVersion === void 0 ? message : `${message.endsWith(".") ? message : `${message}.`} ${STALE_VERSION_GUIDANCE}`;
780
579
  return new ResourceConflictError(guidance, 409, void 0, {
781
580
  ...context,
581
+ // What stands in the way, as a declared kind a program switches on: `draft-exists`,
582
+ // `release-locked` or `slug-taken` from the Content API (REL-2446).
583
+ blockage,
782
584
  expectedVersion,
783
585
  actualVersion: detailNumber(refusal, "actualVersion"),
784
586
  // The shared fields' counter, which the `If-Match` tag carries beside the locale's and a
@@ -788,7 +590,10 @@ var _ErrorMapper = class _ErrorMapper {
788
590
  });
789
591
  }
790
592
  case "RESOURCE_EXPIRED": {
791
- return new ResourceExpiredError(message, 410, void 0, context);
593
+ return new ResourceExpiredError(message, 410, void 0, {
594
+ ...context,
595
+ reason: detailString(refusal, "reason")
596
+ });
792
597
  }
793
598
  case "REQUEST_TIMEOUT": {
794
599
  return new TimeoutError(message, void 0, status, void 0, context);
@@ -875,6 +680,15 @@ function detailNumber(refusal, key) {
875
680
  return typeof value === "number" ? value : void 0;
876
681
  }
877
682
  chunkMWMSFIWN_cjs.__name(detailNumber, "detailNumber");
683
+ function blockageOf(refusal) {
684
+ const blockage = detailBag(refusal)?.blockage;
685
+ if (typeof blockage !== "object" || blockage === null) return void 0;
686
+ const { kind, facts } = blockage;
687
+ if (typeof kind !== "string") return void 0;
688
+ const named = typeof facts === "object" && facts !== null && !Array.isArray(facts) ? facts : {};
689
+ return { kind, facts: named };
690
+ }
691
+ chunkMWMSFIWN_cjs.__name(blockageOf, "blockageOf");
878
692
  function violationsOf(refusal) {
879
693
  const issues = detailBag(refusal)?.issues;
880
694
  if (!Array.isArray(issues)) return [];
@@ -934,6 +748,7 @@ var DECLARED_PATHS = {
934
748
  "/v1/{contentType}/{id}/file/multipart/sign-part": true,
935
749
  "/v1/{contentType}/{id}/file/presign": true,
936
750
  "/v1/{contentType}/{id}/file/url": true,
751
+ "/v1/{contentType}/{id}/shared-versions/{versionNumber}/restore": true,
937
752
  "/v1/{contentType}/{id}/versions": true,
938
753
  "/v1/{contentType}/{id}/versions/{versionNumber}": true,
939
754
  "/v1/{contentType}/{id}/versions/{versionNumber}/restore": true,
@@ -1018,42 +833,6 @@ function readQuery(searchParams) {
1018
833
  }
1019
834
  chunkMWMSFIWN_cjs.__name(readQuery, "readQuery");
1020
835
 
1021
- // src/http/abortable-sleep.ts
1022
- function sleep(ms, signal) {
1023
- return new Promise((resolve) => {
1024
- if (isAborted(signal)) {
1025
- resolve();
1026
- return;
1027
- }
1028
- const done = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => {
1029
- clearTimeout(timer);
1030
- signal?.removeEventListener("abort", done);
1031
- resolve();
1032
- }, "done");
1033
- const timer = setTimeout(done, ms);
1034
- signal?.addEventListener("abort", done, { once: true });
1035
- });
1036
- }
1037
- chunkMWMSFIWN_cjs.__name(sleep, "sleep");
1038
- function isAborted(signal) {
1039
- return signal?.aborted === true;
1040
- }
1041
- chunkMWMSFIWN_cjs.__name(isAborted, "isAborted");
1042
-
1043
- // src/http/request-timeout.ts
1044
- var MAX_TIMER_DELAY_MS = 2147483647;
1045
- function isTimerDelay(value) {
1046
- return typeof value === "number" && value >= 1 && value <= MAX_TIMER_DELAY_MS;
1047
- }
1048
- chunkMWMSFIWN_cjs.__name(isTimerDelay, "isTimerDelay");
1049
- function assertRequestTimeout(timeout) {
1050
- if (isTimerDelay(timeout)) return;
1051
- throw new Error(
1052
- `timeout must be a number of milliseconds from 1 to ${MAX_TIMER_DELAY_MS} \u2014 a timer given 0, NaN, Infinity or more fires at once and ends every request \u2014 and got ${String(timeout)}`
1053
- );
1054
- }
1055
- chunkMWMSFIWN_cjs.__name(assertRequestTimeout, "assertRequestTimeout");
1056
-
1057
836
  // src/errors/instructed-delay.ts
1058
837
  function serviceInstructedDelayMs(error, nowMs) {
1059
838
  if (error instanceof ServiceIndeterminateError) {
@@ -1080,9 +859,20 @@ var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
1080
859
  ]);
1081
860
  function isReplaySafe(request) {
1082
861
  if (IDEMPOTENT_METHODS.has(request.method.toUpperCase())) return true;
1083
- return headerValue(request.headers, HEADER_IDEMPOTENCY_KEY.name) !== void 0;
862
+ return headerValue(request.headers, chunk6PTRZP5U_cjs.HEADER_IDEMPOTENCY_KEY.name) !== void 0;
1084
863
  }
1085
864
  chunkMWMSFIWN_cjs.__name(isReplaySafe, "isReplaySafe");
865
+ var UNREACHABLE_CODES = /* @__PURE__ */ new Set(["ECONNREFUSED", "ENOTFOUND"]);
866
+ function isUnreachableHost(error, depth = 0) {
867
+ if (depth > 4 || typeof error !== "object" || error === null) return false;
868
+ const { code, cause, errors } = error;
869
+ if (typeof code === "string" && UNREACHABLE_CODES.has(code)) return true;
870
+ if (Array.isArray(errors) && errors.length > 0) {
871
+ if (errors.every((one) => isUnreachableHost(one, depth + 1))) return true;
872
+ }
873
+ return isUnreachableHost(cause, depth + 1);
874
+ }
875
+ chunkMWMSFIWN_cjs.__name(isUnreachableHost, "isUnreachableHost");
1086
876
  var _DefaultRetryPolicy = class _DefaultRetryPolicy {
1087
877
  constructor(config) {
1088
878
  chunkMWMSFIWN_cjs.__publicField(this, "config");
@@ -1091,6 +881,7 @@ var _DefaultRetryPolicy = class _DefaultRetryPolicy {
1091
881
  shouldRetry(attempt, error, request) {
1092
882
  if (attempt >= this.config.maxAttempts) return false;
1093
883
  if (!ErrorMapper.isRetryable(error)) return false;
884
+ if (isUnreachableHost(error)) return false;
1094
885
  return isReplaySafe(request);
1095
886
  }
1096
887
  delayFor(attempt, error) {
@@ -1103,6 +894,86 @@ var _DefaultRetryPolicy = class _DefaultRetryPolicy {
1103
894
  };
1104
895
  chunkMWMSFIWN_cjs.__name(_DefaultRetryPolicy, "DefaultRetryPolicy");
1105
896
  var DefaultRetryPolicy = _DefaultRetryPolicy;
897
+ function retryPolicyFor(maxAttempts) {
898
+ return new DefaultRetryPolicy({
899
+ maxAttempts,
900
+ baseDelay: 1e3,
901
+ maxDelay: 1e4,
902
+ backoffFactor: 2,
903
+ jitter: true
904
+ });
905
+ }
906
+ chunkMWMSFIWN_cjs.__name(retryPolicyFor, "retryPolicyFor");
907
+
908
+ // src/config/preview-read.ts
909
+ var derived = /* @__PURE__ */ new Set();
910
+ var unknown = /* @__PURE__ */ new Map();
911
+ var announced = /* @__PURE__ */ new Set();
912
+ function noteDerivedPreview(dataset) {
913
+ derived.add(dataset);
914
+ }
915
+ chunkMWMSFIWN_cjs.__name(noteDerivedPreview, "noteDerivedPreview");
916
+ function isDerivedPreview(dataset) {
917
+ return derived.has(dataset);
918
+ }
919
+ chunkMWMSFIWN_cjs.__name(isDerivedPreview, "isDerivedPreview");
920
+ function isUnknownPreview(dataset) {
921
+ const since = unknown.get(dataset);
922
+ if (since === void 0) return false;
923
+ if (Date.now() - since < chunk6PTRZP5U_cjs.UNKNOWN_PREVIEW_RECHECK_MS) return true;
924
+ unknown.delete(dataset);
925
+ return false;
926
+ }
927
+ chunkMWMSFIWN_cjs.__name(isUnknownPreview, "isUnknownPreview");
928
+ function rememberUnknownPreview(dataset) {
929
+ unknown.set(dataset, Date.now());
930
+ if (announced.has(dataset)) return;
931
+ announced.add(dataset);
932
+ console.info(
933
+ `[RelyIO] No preview dataset "${dataset}" exists for this deployment's branch \u2014 reading the key's default dataset instead, and asking again in a minute.`
934
+ );
935
+ }
936
+ chunkMWMSFIWN_cjs.__name(rememberUnknownPreview, "rememberUnknownPreview");
937
+ function answersUnknownDataset(error, dataset) {
938
+ return error instanceof ResourceNotFoundError && error.context?.resourceType === "dataset" && error.context.resourceId === dataset;
939
+ }
940
+ chunkMWMSFIWN_cjs.__name(answersUnknownDataset, "answersUnknownDataset");
941
+
942
+ // src/http/abortable-sleep.ts
943
+ function sleep(ms, signal) {
944
+ return new Promise((resolve) => {
945
+ if (isAborted(signal)) {
946
+ resolve();
947
+ return;
948
+ }
949
+ const done = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => {
950
+ clearTimeout(timer);
951
+ signal?.removeEventListener("abort", done);
952
+ resolve();
953
+ }, "done");
954
+ const timer = setTimeout(done, ms);
955
+ signal?.addEventListener("abort", done, { once: true });
956
+ });
957
+ }
958
+ chunkMWMSFIWN_cjs.__name(sleep, "sleep");
959
+ function isAborted(signal) {
960
+ return signal?.aborted === true;
961
+ }
962
+ chunkMWMSFIWN_cjs.__name(isAborted, "isAborted");
963
+
964
+ // src/http/request-timeout.ts
965
+ var MAX_TIMER_DELAY_MS = 2147483647;
966
+ function isTimerDelay(value) {
967
+ return typeof value === "number" && value >= 1 && value <= MAX_TIMER_DELAY_MS;
968
+ }
969
+ chunkMWMSFIWN_cjs.__name(isTimerDelay, "isTimerDelay");
970
+ function assertRequestTimeout(timeout) {
971
+ if (isTimerDelay(timeout)) return;
972
+ throw new Error(
973
+ `timeout must be a number of milliseconds from 1 to ${MAX_TIMER_DELAY_MS} \u2014 a timer given 0, NaN, Infinity or more fires at once and ends every request \u2014 and got ${String(timeout)}`
974
+ );
975
+ }
976
+ chunkMWMSFIWN_cjs.__name(assertRequestTimeout, "assertRequestTimeout");
1106
977
 
1107
978
  // src/http/http-client.ts
1108
979
  var _HttpClient = class _HttpClient {
@@ -1118,33 +989,6 @@ var _HttpClient = class _HttpClient {
1118
989
  this.connection = connectionFor(config);
1119
990
  this.announce();
1120
991
  }
1121
- /**
1122
- * A view of this client that sends every request through it with `headers` added — beneath the
1123
- * request's own, over this client's — and changes nothing else: its key, base URL, timeout,
1124
- * retries and `fetch` are this client's as they are when each request is sent, so a later
1125
- * `configure()` or `setApiKey()` on this client reaches the view, and one on the view reaches
1126
- * this client. `client.with({ dataset })` is one (REL-2417).
1127
- */
1128
- withHeaders(headers) {
1129
- const view = new _HttpClient(this.connection.config);
1130
- view.view = { client: this, headers: { ...headers } };
1131
- return view;
1132
- }
1133
- /**
1134
- * Run on `config` from now on: every later request — whoever holds this client — is sent to its
1135
- * `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
1136
- * logged by its `debug` options.
1137
- *
1138
- * The client's own `updateConfig()` calls this rather than building a second client, so a
1139
- * `content()` or other sub-client taken before the update sends through the update too. Anything
1140
- * set on this client since it was last configured — `setDefaultHeaders()`, `setBaseUrl()` — is
1141
- * replaced by what `config` says.
1142
- */
1143
- configure(config) {
1144
- if (this.view !== void 0) return this.view.client.configure(config);
1145
- this.connection = connectionFor(config);
1146
- this.announce();
1147
- }
1148
992
  announce() {
1149
993
  this.log("debug", "HttpClient initialized", {
1150
994
  baseUrl: this.connection.baseUrl,
@@ -1153,6 +997,20 @@ var _HttpClient = class _HttpClient {
1153
997
  environment: chunkTZL374LS_cjs.isBrowser() ? "browser" : "node"
1154
998
  });
1155
999
  }
1000
+ /**
1001
+ * Send bytes to an address that is not a RelyIO route — an asset upload's presigned `PUT` and its
1002
+ * multipart parts — through the client's configured `fetch`, so a wrapper that records, proxies or
1003
+ * forbids network access sees every request this client makes (REL-2671). Nothing else is added: no
1004
+ * key, no retry, no timeout, because the address belongs to the storage service, not to RelyIO.
1005
+ *
1006
+ * Static so the instances a customer holds stay `send` and `fetchPayload` (REL-3107). The `fetch`
1007
+ * is read per call, from the client a view sends through, like the requests are.
1008
+ */
1009
+ static transfer(client, url, init) {
1010
+ const owner = client.view?.client ?? client;
1011
+ const send = owner.connection.config.fetch ?? globalThis.fetch;
1012
+ return send(url, init);
1013
+ }
1156
1014
  /**
1157
1015
  * Call a route the committed document declares, and get back the body that
1158
1016
  * document says it serves.
@@ -1222,6 +1080,11 @@ var _HttpClient = class _HttpClient {
1222
1080
  if (config.method === "DELETE" && mergedConfig.headers) {
1223
1081
  mergedConfig.headers = layerHeaders(mergedConfig.headers, { "Content-Type": null });
1224
1082
  }
1083
+ let preview = derivedPreviewIn(mergedConfig.headers);
1084
+ if (preview !== void 0 && (isUnknownPreview(preview) || !isPreviewKey(headerValue(mergedConfig.headers, API_KEY_HEADER)))) {
1085
+ mergedConfig.headers = layerHeaders(mergedConfig.headers ?? {}, { [DATASET_HEADER]: null });
1086
+ preview = void 0;
1087
+ }
1225
1088
  for (let attempt = 1; ; attempt++) {
1226
1089
  try {
1227
1090
  const response = await this.makeRequest(mergedConfig.url, mergedConfig);
@@ -1250,6 +1113,10 @@ var _HttpClient = class _HttpClient {
1250
1113
  method: mergedConfig.method,
1251
1114
  attempt
1252
1115
  });
1116
+ if (preview !== void 0 && answersUnknownDataset(sdkError, preview)) {
1117
+ rememberUnknownPreview(preview);
1118
+ return this.request(config);
1119
+ }
1253
1120
  this.log("error", "Request failed after all retries", {
1254
1121
  error: sdkError.toJSON(),
1255
1122
  url: mergedConfig.url
@@ -1258,122 +1125,6 @@ var _HttpClient = class _HttpClient {
1258
1125
  }
1259
1126
  }
1260
1127
  }
1261
- /**
1262
- * Make a GET request
1263
- */
1264
- async get(url, params) {
1265
- return this.request({
1266
- method: "GET",
1267
- url,
1268
- params
1269
- });
1270
- }
1271
- /**
1272
- * Make a POST request
1273
- */
1274
- async post(url, data, params) {
1275
- return this.request({
1276
- method: "POST",
1277
- url,
1278
- body: data,
1279
- params
1280
- });
1281
- }
1282
- /**
1283
- * Make a PUT request
1284
- */
1285
- async put(url, data, params) {
1286
- return this.request({
1287
- method: "PUT",
1288
- url,
1289
- body: data,
1290
- params
1291
- });
1292
- }
1293
- /**
1294
- * Make a DELETE request
1295
- */
1296
- async delete(url, params) {
1297
- return this.request({
1298
- method: "DELETE",
1299
- url,
1300
- params
1301
- });
1302
- }
1303
- /**
1304
- * Make a PATCH request
1305
- */
1306
- async patch(url, data, params) {
1307
- return this.request({
1308
- method: "PATCH",
1309
- url,
1310
- body: data,
1311
- params
1312
- });
1313
- }
1314
- /**
1315
- * Add headers to every later request, each replacing any header of the same name — the name
1316
- * matched without regard to case — until the client is next configured.
1317
- */
1318
- setDefaultHeaders(headers) {
1319
- if (this.view !== void 0) return this.view.client.setDefaultHeaders(headers);
1320
- this.connection = {
1321
- ...this.connection,
1322
- defaultHeaders: layerHeaders(this.connection.defaultHeaders, headers)
1323
- };
1324
- }
1325
- /**
1326
- * Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
1327
- * reports.
1328
- *
1329
- * The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
1330
- * no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
1331
- * before anything is sent. A key header of any other spelling — one given in `headers` — goes
1332
- * too, from the headers sent and from the headers the configuration reports, so the old key is
1333
- * never sent beside the new one.
1334
- *
1335
- * The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
1336
- * constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
1337
- * key sent from here on.
1338
- *
1339
- * This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
1340
- * never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
1341
- */
1342
- setApiKey(apiKey) {
1343
- if (this.view !== void 0) return this.view.client.setApiKey(apiKey);
1344
- const { config } = this.connection;
1345
- config.apiKey = apiKey;
1346
- config.headers = layerHeaders(config.headers, { [API_KEY_HEADER]: null });
1347
- this.connection = {
1348
- ...this.connection,
1349
- defaultHeaders: layerHeaders(this.connection.defaultHeaders, {
1350
- [API_KEY_HEADER]: presentKey(apiKey) ?? null
1351
- })
1352
- };
1353
- }
1354
- /**
1355
- * Get current default headers
1356
- */
1357
- getDefaultHeaders() {
1358
- if (this.view !== void 0) {
1359
- return layerHeaders(this.view.client.getDefaultHeaders(), this.view.headers);
1360
- }
1361
- return { ...this.connection.defaultHeaders };
1362
- }
1363
- /**
1364
- * Update base URL
1365
- */
1366
- setBaseUrl(baseUrl) {
1367
- if (this.view !== void 0) return this.view.client.setBaseUrl(baseUrl);
1368
- this.connection = { ...this.connection, baseUrl };
1369
- }
1370
- /**
1371
- * Get current base URL
1372
- */
1373
- getBaseUrl() {
1374
- if (this.view !== void 0) return this.view.client.getBaseUrl();
1375
- return this.connection.baseUrl;
1376
- }
1377
1128
  /**
1378
1129
  * One attempt.
1379
1130
  *
@@ -1519,10 +1270,11 @@ var _HttpClient = class _HttpClient {
1519
1270
  if (contentType.includes("text/")) {
1520
1271
  return await response.text();
1521
1272
  }
1273
+ const text = await response.text();
1522
1274
  try {
1523
- return await response.json();
1275
+ return JSON.parse(text);
1524
1276
  } catch {
1525
- return await response.text();
1277
+ return text;
1526
1278
  }
1527
1279
  }
1528
1280
  resolveUrl(url) {
@@ -1577,8 +1329,73 @@ var _HttpClient = class _HttpClient {
1577
1329
  };
1578
1330
  chunkMWMSFIWN_cjs.__name(_HttpClient, "HttpClient");
1579
1331
  var HttpClient = _HttpClient;
1332
+ var _ControlledHttpClient = class _ControlledHttpClient extends HttpClient {
1333
+ /**
1334
+ * A view of this client that sends every request through it with `headers` added — beneath the
1335
+ * request's own, over this client's — and changes nothing else: its key, base URL, timeout,
1336
+ * retries and `fetch` are this client's as they are when each request is sent, so a later
1337
+ * `configure()` or `setApiKey()` on this client reaches the view, and one on the view reaches
1338
+ * this client. `client.with({ dataset })` is one (REL-2417).
1339
+ */
1340
+ withHeaders(headers) {
1341
+ const view = new _ControlledHttpClient(this.connection.config);
1342
+ view.view = { client: this, headers: { ...headers } };
1343
+ return view;
1344
+ }
1345
+ /**
1346
+ * Run on `config` from now on: every later request — whoever holds this client — is sent to its
1347
+ * `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
1348
+ * logged by its `debug` options.
1349
+ *
1350
+ * The client's own `updateConfig()` calls this rather than building a second client, so a
1351
+ * `content()` or other sub-client taken before the update sends through the update too. Anything
1352
+ * set on this client since it was last configured — `setApiKey()` — is replaced by what `config`
1353
+ * says.
1354
+ */
1355
+ configure(config) {
1356
+ if (this.view !== void 0) return this.view.client.configure(config);
1357
+ this.connection = connectionFor(config);
1358
+ this.announce();
1359
+ }
1360
+ /**
1361
+ * Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
1362
+ * reports.
1363
+ *
1364
+ * The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
1365
+ * no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
1366
+ * before anything is sent. A key header of any other spelling — one given in `headers` — goes
1367
+ * too, from the headers sent and from the headers the configuration reports, so the old key is
1368
+ * never sent beside the new one.
1369
+ *
1370
+ * The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
1371
+ * constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
1372
+ * key sent from here on.
1373
+ *
1374
+ * This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
1375
+ * never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
1376
+ */
1377
+ setApiKey(apiKey) {
1378
+ if (this.view !== void 0) return this.view.client.setApiKey(apiKey);
1379
+ const { config } = this.connection;
1380
+ config.apiKey = apiKey;
1381
+ config.headers = layerHeaders(config.headers, { [API_KEY_HEADER]: null });
1382
+ this.connection = {
1383
+ ...this.connection,
1384
+ defaultHeaders: layerHeaders(this.connection.defaultHeaders, {
1385
+ [API_KEY_HEADER]: presentKey(apiKey) ?? null
1386
+ })
1387
+ };
1388
+ }
1389
+ };
1390
+ chunkMWMSFIWN_cjs.__name(_ControlledHttpClient, "ControlledHttpClient");
1391
+ var ControlledHttpClient = _ControlledHttpClient;
1580
1392
  var API_KEY_HEADER = "X-API-Key";
1581
1393
  var DATASET_HEADER = "X-RelyIO-Dataset";
1394
+ function derivedPreviewIn(headers) {
1395
+ const dataset = headerValue(headers, DATASET_HEADER);
1396
+ return dataset !== void 0 && isDerivedPreview(dataset) ? dataset : void 0;
1397
+ }
1398
+ chunkMWMSFIWN_cjs.__name(derivedPreviewIn, "derivedPreviewIn");
1582
1399
  var BROWSER_CONTROLLED_HEADERS = /* @__PURE__ */ new Set([
1583
1400
  "user-agent",
1584
1401
  "referer",
@@ -1607,13 +1424,7 @@ function connectionFor(config) {
1607
1424
  // The policy, not a predicate over `(error, attempt)`: whether a request may be sent again is a
1608
1425
  // property of the **route** as much as of the refusal, and a callback that never sees the
1609
1426
  // request cannot express that.
1610
- retryPolicy: new DefaultRetryPolicy({
1611
- maxAttempts: config.retryAttempts,
1612
- baseDelay: 1e3,
1613
- maxDelay: 1e4,
1614
- backoffFactor: 2,
1615
- jitter: true
1616
- })
1427
+ retryPolicy: retryPolicyFor(config.retryAttempts)
1617
1428
  };
1618
1429
  }
1619
1430
  chunkMWMSFIWN_cjs.__name(connectionFor, "connectionFor");
@@ -1642,7 +1453,7 @@ chunkMWMSFIWN_cjs.__name(credentialsModeFor, "credentialsModeFor");
1642
1453
  // src/http/write-options.ts
1643
1454
  function versionCheckOf(entry) {
1644
1455
  const { id, locale, version, sharedVersion } = entry._metadata;
1645
- return { id, locale, ifMatch: entityTag({ entryUid: id, locale, version, sharedVersion }) };
1456
+ return { id, locale, ifMatch: chunk6PTRZP5U_cjs.entityTag({ entryUid: id, locale, version, sharedVersion }) };
1646
1457
  }
1647
1458
  chunkMWMSFIWN_cjs.__name(versionCheckOf, "versionCheckOf");
1648
1459
  function mintIdempotencyKey() {
@@ -1654,11 +1465,11 @@ chunkMWMSFIWN_cjs.__name(mintIdempotencyKey, "mintIdempotencyKey");
1654
1465
  function writeHeaders(options) {
1655
1466
  const headers = {};
1656
1467
  if (options?.ifMatch !== void 0) {
1657
- headers[HEADER_IF_MATCH.name] = options.ifMatch;
1468
+ headers[chunk6PTRZP5U_cjs.HEADER_IF_MATCH.name] = options.ifMatch;
1658
1469
  }
1659
1470
  const idempotencyKey = options?.idempotencyKey ?? mintIdempotencyKey();
1660
1471
  if (idempotencyKey !== void 0) {
1661
- headers[HEADER_IDEMPOTENCY_KEY.name] = idempotencyKey;
1472
+ headers[chunk6PTRZP5U_cjs.HEADER_IDEMPOTENCY_KEY.name] = idempotencyKey;
1662
1473
  }
1663
1474
  return Object.keys(headers).length > 0 ? headers : void 0;
1664
1475
  }
@@ -1755,7 +1566,7 @@ function writeDocumentTerms(query, options, clientLocale) {
1755
1566
  query.include = options.include.join(",");
1756
1567
  }
1757
1568
  writeLocale(query, options.locale ?? clientLocale);
1758
- if (typeof options.fresh === "string") query[FRESH_PARAMETER] = options.fresh;
1569
+ if (typeof options.fresh === "string") query[chunk6PTRZP5U_cjs.FRESH_PARAMETER] = options.fresh;
1759
1570
  }
1760
1571
  chunkMWMSFIWN_cjs.__name(writeDocumentTerms, "writeDocumentTerms");
1761
1572
  function writeLocale(query, locale) {
@@ -1773,6 +1584,10 @@ function writeLocale(query, locale) {
1773
1584
  query.locales = locale.join(",");
1774
1585
  }
1775
1586
  chunkMWMSFIWN_cjs.__name(writeLocale, "writeLocale");
1587
+ function signalOf(options) {
1588
+ return options.signal === void 0 ? {} : { signal: options.signal };
1589
+ }
1590
+ chunkMWMSFIWN_cjs.__name(signalOf, "signalOf");
1776
1591
  function readHeaders(options) {
1777
1592
  const headers = {};
1778
1593
  if (options.dataset !== void 0) headers[DATASET_HEADER] = options.dataset;
@@ -1826,7 +1641,8 @@ var _EntryHandle = class _EntryHandle {
1826
1641
  {
1827
1642
  path: { contentType: this.typeName },
1828
1643
  query: listQuery(options, this.clientLocale()),
1829
- headers: readHeaders(options)
1644
+ headers: readHeaders(options),
1645
+ ...signalOf(options)
1830
1646
  }
1831
1647
  );
1832
1648
  return response.body;
@@ -1881,7 +1697,8 @@ var _EntryHandle = class _EntryHandle {
1881
1697
  return await this.httpClient.fetchPayload("/v1/{contentType}/{id}", "get", {
1882
1698
  path: { contentType: this.typeName, id: idOrSlug },
1883
1699
  query: entryQuery(options, this.clientLocale()),
1884
- headers: readHeaders(options)
1700
+ headers: readHeaders(options),
1701
+ ...signalOf(options)
1885
1702
  });
1886
1703
  } catch (error) {
1887
1704
  if (isMissingEntry(error)) return null;
@@ -1919,7 +1736,10 @@ var EntryHandle = _EntryHandle;
1919
1736
  // src/content/content-client.ts
1920
1737
  var _ContentClient = class _ContentClient extends EntryHandle {
1921
1738
  /**
1922
- * Create a new content entry.
1739
+ * Create a new content entry, published. The answer's `_metadata.warnings` lists each reference
1740
+ * the content type declares `weak` that the create made live while the entry it points at is
1741
+ * unpublished (`REFERENCE_NOT_PUBLISHED`) — `[]` when there are none; the create is never refused
1742
+ * for them.
1923
1743
  *
1924
1744
  * `locale` defaults to the client's own, and `dataset` to the client's (`client.with({ dataset })`
1925
1745
  * sets it for every call).
@@ -1948,7 +1768,7 @@ var _ContentClient = class _ContentClient extends EntryHandle {
1948
1768
  * Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
1949
1769
  * client's own, else the schema default; no fallback is applied, and a locale
1950
1770
  * with no history returns an empty array rather than another locale's rows. Every row names the
1951
- * locale it belongs to.
1771
+ * locale it belongs to, and holds that locale's fields under `fields`.
1952
1772
  */
1953
1773
  async versions(id, options) {
1954
1774
  const locale = callLocale(options?.locale, this.clientLocale());
@@ -1969,6 +1789,9 @@ var _ContentClient = class _ContentClient extends EntryHandle {
1969
1789
  * There is no `null`: a version the locale does not have, an entry that is not there, a type the
1970
1790
  * schema does not declare and a dataset with no schema all throw `ResourceNotFoundError`, its
1971
1791
  * `context.resourceType` naming which (REL-2409 Q12).
1792
+ *
1793
+ * It answers the version, not the entry: that locale's own fields as the version stored them, and
1794
+ * `_metadata` with `status: 'version'` ({@link ContentVersion}).
1972
1795
  */
1973
1796
  async version(id, options) {
1974
1797
  const locale = callLocale(options.locale, this.clientLocale());
@@ -2024,7 +1847,8 @@ var _ContentClient = class _ContentClient extends EntryHandle {
2024
1847
  const response = await this.httpClient.send("/v1/{contentType}/{id}/children", "get", {
2025
1848
  path: { contentType: this.typeName, id },
2026
1849
  query: childrenQuery(options, this.clientLocale()),
2027
- headers: readHeaders(options)
1850
+ headers: readHeaders(options),
1851
+ ...signalOf(options)
2028
1852
  });
2029
1853
  return response.body;
2030
1854
  }
@@ -2558,7 +2382,7 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
2558
2382
  }
2559
2383
  const total = this.file.size;
2560
2384
  this.emitProgress(0, total);
2561
- const uploadResponse = await fetch(presigned.uploadUrl, {
2385
+ const uploadResponse = await HttpClient.transfer(this.httpClient, presigned.uploadUrl, {
2562
2386
  method: presigned.method,
2563
2387
  headers: presigned.headers,
2564
2388
  body: this.file
@@ -2625,7 +2449,10 @@ var _AssetUploadBuilder = class _AssetUploadBuilder {
2625
2449
  for (let attempt = 0; attempt <= this._maxPartRetries; attempt += 1) {
2626
2450
  try {
2627
2451
  const { url } = await fileBuilder.signPart({ ...target, partNumber });
2628
- const response = await fetch(url, { method: "PUT", body: blob });
2452
+ const response = await HttpClient.transfer(this.httpClient, url, {
2453
+ method: "PUT",
2454
+ body: blob
2455
+ });
2629
2456
  if (!response.ok) {
2630
2457
  const retriable = response.status >= 500 || response.status === 408 || response.status === 429;
2631
2458
  if (!retriable) {
@@ -2810,14 +2637,18 @@ var _SingletonClient = class _SingletonClient extends DocumentHandle {
2810
2637
  return await this.httpClient.fetchPayload("/v1/singletons/{key}", "get", {
2811
2638
  path: { key: this.name },
2812
2639
  query: documentQuery(options, this.clientLocale()),
2813
- headers: readHeaders(options)
2640
+ headers: readHeaders(options),
2641
+ ...signalOf(options)
2814
2642
  });
2815
2643
  } catch (error) {
2816
2644
  if (isMissingEntry(error)) return null;
2817
2645
  throw error;
2818
2646
  }
2819
2647
  }
2820
- /** The API publishes on PATCH: there is no separate publish route. */
2648
+ /**
2649
+ * The API publishes on PATCH: there is no separate publish route. The answer's `_metadata` also
2650
+ * lists the links the write left pointing nowhere and its `warnings` (REL-3097).
2651
+ */
2821
2652
  patch(write, options) {
2822
2653
  return this.httpClient.fetchPayload(
2823
2654
  "/v1/singletons/{key}",
@@ -2833,14 +2664,10 @@ var _SingletonClient = class _SingletonClient extends DocumentHandle {
2833
2664
  return this.httpClient.fetchPayload("/v1/singletons/{key}/versions", "get", { path: { key: this.name }, query });
2834
2665
  }
2835
2666
  readVersion(versionNumber, query) {
2836
- return this.httpClient.fetchPayload(
2837
- "/v1/singletons/{key}/versions/{versionNumber}",
2838
- "get",
2839
- {
2840
- path: { key: this.name, versionNumber },
2841
- query
2842
- }
2843
- );
2667
+ return this.httpClient.fetchPayload("/v1/singletons/{key}/versions/{versionNumber}", "get", {
2668
+ path: { key: this.name, versionNumber },
2669
+ query
2670
+ });
2844
2671
  }
2845
2672
  };
2846
2673
  chunkMWMSFIWN_cjs.__name(_SingletonClient, "SingletonClient");
@@ -2873,22 +2700,19 @@ var _SettingsClient = class _SettingsClient extends DocumentHandle {
2873
2700
  {
2874
2701
  path: { groupId: this.name },
2875
2702
  query: documentQuery(options, this.clientLocale()),
2876
- headers: readHeaders(options)
2703
+ headers: readHeaders(options),
2704
+ ...signalOf(options)
2877
2705
  }
2878
2706
  );
2879
2707
  }
2880
2708
  async reset(...args) {
2881
2709
  const [first, second] = args;
2882
2710
  const write = first !== void 0 && isRead(first) ? { ...versionCheckOf(first), options: second } : { locale: this.localeOf(first?.locale), ifMatch: void 0, options: first };
2883
- return this.httpClient.fetchPayload(
2884
- "/v1/settings/{groupId}/reset",
2885
- "post",
2886
- {
2887
- path: { groupId: this.name },
2888
- query: write.locale === void 0 ? void 0 : { locale: write.locale },
2889
- headers: DocumentHandle.headersOf(write, write.options)
2890
- }
2891
- );
2711
+ return this.httpClient.fetchPayload("/v1/settings/{groupId}/reset", "post", {
2712
+ path: { groupId: this.name },
2713
+ query: write.locale === void 0 ? void 0 : { locale: write.locale },
2714
+ headers: DocumentHandle.headersOf(write, write.options)
2715
+ });
2892
2716
  }
2893
2717
  /** The group's default values, as the schema declares them. */
2894
2718
  async getDefaults() {
@@ -2924,7 +2748,7 @@ var SettingsClient = _SettingsClient;
2924
2748
 
2925
2749
  // src/changes/changes.ts
2926
2750
  var CHANGES_POLL_TIMEOUT_MS = 25e3 + 5e3;
2927
- var EXPIRED_REASONS = {
2751
+ var EXPIRED_REASONS2 = {
2928
2752
  retention: "retention",
2929
2753
  "dataset-replaced": "dataset-replaced",
2930
2754
  "ahead-of-head": "ahead-of-head",
@@ -2944,7 +2768,7 @@ var _ChangesExpiredError = class _ChangesExpiredError extends ResourceExpiredErr
2944
2768
  */
2945
2769
  chunkMWMSFIWN_cjs.__publicField(this, "fresh");
2946
2770
  this.name = "ChangesExpiredError";
2947
- this.reason = expiredReasonOf(message);
2771
+ this.reason = expiredReasonOf(context?.reason);
2948
2772
  this.fresh = fresh;
2949
2773
  }
2950
2774
  /** The base class rebuilds from its four arguments, which would drop the position resynced to. */
@@ -2974,16 +2798,16 @@ var _ChangesExpiredError = class _ChangesExpiredError extends ResourceExpiredErr
2974
2798
  `The live edge cannot list the changes since this cursor (${reason}). Refetch everything derived from the feed; it continues from the position it sent.`,
2975
2799
  410,
2976
2800
  void 0,
2977
- { transport: "live-edge" },
2801
+ { transport: "live-edge", reason },
2978
2802
  cursor
2979
2803
  );
2980
2804
  }
2981
2805
  };
2982
2806
  chunkMWMSFIWN_cjs.__name(_ChangesExpiredError, "ChangesExpiredError");
2983
2807
  var ChangesExpiredError = _ChangesExpiredError;
2984
- function expiredReasonOf(message) {
2985
- for (const reason of Object.values(EXPIRED_REASONS)) {
2986
- if (message.includes(`(${reason})`)) return reason;
2808
+ function expiredReasonOf(named) {
2809
+ for (const reason of Object.values(EXPIRED_REASONS2)) {
2810
+ if (named === reason) return reason;
2987
2811
  }
2988
2812
  return "unknown";
2989
2813
  }
@@ -3063,10 +2887,6 @@ async function pollOnce(http, since, options) {
3063
2887
  }
3064
2888
  chunkMWMSFIWN_cjs.__name(pollOnce, "pollOnce");
3065
2889
 
3066
- // src/config/key-kind.ts
3067
- var PUBLISHABLE_KEY_PREFIX = "rly_pub_";
3068
- var isPublishableKey = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name((apiKey) => apiKey?.startsWith(PUBLISHABLE_KEY_PREFIX) === true, "isPublishableKey");
3069
-
3070
2890
  // src/errors/live-errors.ts
3071
2891
  var _LiveEdgeError = class _LiveEdgeError extends SDKError {
3072
2892
  constructor(message, end, retry, options = {}) {
@@ -3082,19 +2902,6 @@ var _LiveEdgeError = class _LiveEdgeError extends SDKError {
3082
2902
  this.retryable = retry !== "stop";
3083
2903
  this.retryAfterMs = options.retryAfterMs;
3084
2904
  }
3085
- /**
3086
- * The base class rebuilds an error through its own four-argument constructor, which this class
3087
- * does not have; rebuilt that way, `end` would be a string and `retry` a number.
3088
- */
3089
- withContext(context) {
3090
- const rebuilt = new _LiveEdgeError(this.message, this.end, this.retry, {
3091
- ...this.statusCode === void 0 ? {} : { statusCode: this.statusCode },
3092
- ...this.cause === void 0 ? {} : { cause: this.cause },
3093
- ...this.retryAfterMs === void 0 ? {} : { retryAfterMs: this.retryAfterMs },
3094
- context: { ...this.context, ...context }
3095
- });
3096
- return rebuilt;
3097
- }
3098
2905
  getUserMessage() {
3099
2906
  return this.message;
3100
2907
  }
@@ -3114,8 +2921,8 @@ var HTTP_SCHEME_OF = {
3114
2921
  };
3115
2922
  function liveEdgeAddress(config) {
3116
2923
  if (config.liveUrl !== void 0) return readLiveUrl(config.liveUrl);
3117
- const derived = originOf(config.baseUrl);
3118
- const edge = derived === void 0 ? void 0 : LIVE_EDGE_OF_API[derived];
2924
+ const derived2 = originOf(config.baseUrl);
2925
+ const edge = derived2 === void 0 ? void 0 : LIVE_EDGE_OF_API[derived2];
3119
2926
  if (edge !== void 0) return { ok: true, url: new URL(edge) };
3120
2927
  return {
3121
2928
  ok: false,
@@ -3154,7 +2961,7 @@ chunkMWMSFIWN_cjs.__name(originOf, "originOf");
3154
2961
 
3155
2962
  // src/changes/live-edge.ts
3156
2963
  var LIVE_KEEPALIVE_INTERVAL_MS = 3e4;
3157
- var LIVE_SOCKET_OPEN_TIMEOUT_MS = VISITOR_POLL_INTERVAL_MS;
2964
+ var LIVE_SOCKET_OPEN_TIMEOUT_MS = chunk6PTRZP5U_cjs.VISITOR_POLL_INTERVAL_MS;
3158
2965
  var LIVE_POLLS_BEFORE_SOCKET = 4;
3159
2966
  async function* subscribeLiveEdge(client, options = {}) {
3160
2967
  const { signal } = options;
@@ -3224,12 +3031,12 @@ async function* followSocket(socket, reach, options) {
3224
3031
  return "unopened";
3225
3032
  }
3226
3033
  case "message": {
3227
- if (event.data === VISITOR_KEEPALIVE.response) continue;
3228
- const frame = typeof event.data === "string" ? parseVisitorFrame(event.data) : null;
3034
+ if (event.data === chunk6PTRZP5U_cjs.VISITOR_KEEPALIVE.response) continue;
3035
+ const frame = typeof event.data === "string" ? chunk6PTRZP5U_cjs.parseVisitorFrame(event.data) : null;
3229
3036
  if (frame === null)
3230
3037
  throw unreadable(`a frame the wire does not declare: ${sample(event.data)}`);
3231
3038
  switch (frame.type) {
3232
- case VISITOR_FRAMES.opened: {
3039
+ case chunk6PTRZP5U_cjs.VISITOR_FRAMES.opened: {
3233
3040
  caughtUp = true;
3234
3041
  inbox.caughtUp();
3235
3042
  reach.position = frame.cursor;
@@ -3237,7 +3044,7 @@ async function* followSocket(socket, reach, options) {
3237
3044
  options.reached?.(frame.cursor);
3238
3045
  continue;
3239
3046
  }
3240
- case VISITOR_FRAMES.changes: {
3047
+ case chunk6PTRZP5U_cjs.VISITOR_FRAMES.changes: {
3241
3048
  const prior = reach.position;
3242
3049
  if (prior === void 0) throw unreadable("changes before the socket had a position");
3243
3050
  for (const change of changesOf(frame.changes, frame.cursor, prior)) {
@@ -3248,7 +3055,7 @@ async function* followSocket(socket, reach, options) {
3248
3055
  if (frame.changes.length === 0) options.reached?.(frame.cursor);
3249
3056
  continue;
3250
3057
  }
3251
- case VISITOR_FRAMES.resync: {
3058
+ case chunk6PTRZP5U_cjs.VISITOR_FRAMES.resync: {
3252
3059
  await expire(frame.reason, frame.cursor, options);
3253
3060
  if (isAborted(signal)) return "aborted";
3254
3061
  reach.position = frame.cursor;
@@ -3320,7 +3127,7 @@ function socketInbox(socket, signal) {
3320
3127
  return;
3321
3128
  }
3322
3129
  heard = false;
3323
- if (socket.readyState === SOCKET_OPEN) socket.send(VISITOR_KEEPALIVE.request);
3130
+ if (socket.readyState === SOCKET_OPEN) socket.send(chunk6PTRZP5U_cjs.VISITOR_KEEPALIVE.request);
3324
3131
  }, LIVE_KEEPALIVE_INTERVAL_MS);
3325
3132
  },
3326
3133
  caughtUp() {
@@ -3356,28 +3163,27 @@ var AFTER_A_CLOSE = {
3356
3163
  "back-off": "Retrying after a back-off of at least a minute, without polling, which the same admission refuses."
3357
3164
  };
3358
3165
  function closeRetryOf(code) {
3359
- if (hasOwn(VISITOR_CLOSE_RETRY, code)) return VISITOR_CLOSE_RETRY[code];
3166
+ if (hasOwn(chunk6PTRZP5U_cjs.VISITOR_CLOSE_RETRY, code)) return chunk6PTRZP5U_cjs.VISITOR_CLOSE_RETRY[code];
3360
3167
  return code < 4e3 ? "retry" : "stop";
3361
3168
  }
3362
3169
  chunkMWMSFIWN_cjs.__name(closeRetryOf, "closeRetryOf");
3363
3170
  var CLOSE_MEANING = {
3364
- [VISITOR_CLOSE_CODES.requestInvalid]: "the edge could not read the request \u2014 a malformed cursor or filter",
3365
- [VISITOR_CLOSE_CODES.keyRefused]: "the key is not a publishable key the edge accepts \u2014 unknown, revoked or expired",
3366
- [VISITOR_CLOSE_CODES.originRefused]: "this page\u2019s origin is not on the publishable key\u2019s allowed origins",
3367
- [VISITOR_CLOSE_CODES.datasetRefused]: "`dataset` names no dataset the key reaches",
3368
- // Also how the edge hands a connection on when the project's live objects move to another
3369
- // placement (reason `moved`, REL-1514): either way the same request succeeds again shortly.
3370
- [VISITOR_CLOSE_CODES.unavailable]: "the edge could not serve this connection just now \u2014 it could not reach what it needed, or it moved the project\u2019s live connections elsewhere",
3371
- [VISITOR_CLOSE_CODES.allowanceReached]: "the project holds as many live connections as its plan allows",
3372
- [VISITOR_CLOSE_CODES.addressLimitReached]: "this address holds as many live connections to the project as one address may",
3373
- [VISITOR_CLOSE_CODES.ceilingReached]: "the project is at its safety ceiling of live connections"
3171
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.requestInvalid]: "the edge could not read the request \u2014 a malformed cursor or filter",
3172
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.keyRefused]: "the key is not a publishable key the edge accepts \u2014 unknown, revoked or expired",
3173
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.originRefused]: "this page\u2019s origin is not on the publishable key\u2019s allowed origins",
3174
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.datasetRefused]: "`dataset` names no dataset the key reaches",
3175
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.unavailable]: "the edge could not serve this connection just now \u2014 it could not reach what it needed",
3176
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.allowanceReached]: "the project holds as many live connections as its plan allows",
3177
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.addressLimitReached]: "this address holds as many live connections to the project as one address may",
3178
+ [chunk6PTRZP5U_cjs.VISITOR_CLOSE_CODES.ceilingReached]: "the project is at its safety ceiling of live connections"
3374
3179
  };
3375
3180
  async function* followPolls(client, request, reach, options) {
3376
3181
  const { signal } = options;
3182
+ let starting = reach.position === void 0;
3377
3183
  for (let poll = 0; poll < LIVE_POLLS_BEFORE_SOCKET; poll += 1) {
3378
3184
  if (isAborted(signal)) return "aborted";
3379
3185
  const answer = await pollOnce2(client, request, reach.position, signal);
3380
- if (answer === void 0) return "aborted";
3186
+ if (answer === void 0 || isAborted(signal)) return "aborted";
3381
3187
  options.opened?.();
3382
3188
  if (answer.kind === "resync") {
3383
3189
  await expire(answer.reason, answer.cursor, options);
@@ -3394,9 +3200,10 @@ async function* followPolls(client, request, reach, options) {
3394
3200
  if (isAborted(signal)) return "aborted";
3395
3201
  }
3396
3202
  reach.position = answer.cursor;
3397
- if (answer.changes.length === 0) options.reached?.(answer.cursor);
3203
+ if (starting) options.reached?.(answer.cursor);
3398
3204
  }
3399
- await sleep(VISITOR_POLL_INTERVAL_MS, signal);
3205
+ starting = false;
3206
+ await sleep(chunk6PTRZP5U_cjs.VISITOR_POLL_INTERVAL_MS, signal);
3400
3207
  }
3401
3208
  return isAborted(signal) ? "aborted" : "socket";
3402
3209
  }
@@ -3438,7 +3245,7 @@ async function pollOnce2(client, request, since, signal) {
3438
3245
  }
3439
3246
  const body = parseJson(text);
3440
3247
  if (!response.ok) throw refusedPoll(response, body, context);
3441
- const answer = readVisitorPollAnswer(isRecord(body) ? body["data"] : void 0);
3248
+ const answer = chunk6PTRZP5U_cjs.readVisitorPollAnswer(isRecord(body) ? body["data"] : void 0);
3442
3249
  if (answer === null)
3443
3250
  throw unreadable(`a poll answer the wire does not declare: ${sample(text)}`);
3444
3251
  return answer;
@@ -3458,13 +3265,13 @@ function refusedPoll(response, body, context) {
3458
3265
  { ...context, method: "GET" }
3459
3266
  );
3460
3267
  const refusal = readError(body);
3461
- if (refusal === void 0 || !hasOwn(VISITOR_POLL_RETRY, refusal.code)) return mapped;
3268
+ if (refusal === void 0 || !hasOwn(chunk6PTRZP5U_cjs.VISITOR_POLL_RETRY, refusal.code)) return mapped;
3462
3269
  const code = refusal.code;
3463
3270
  const retryAfterMs = parseRetryAfterMs(headerValue(headers, "Retry-After"), Date.now());
3464
3271
  return new LiveEdgeError(
3465
3272
  `The live edge refused a poll (${code}): ${refusal.messages[0] ?? mapped.message}`,
3466
3273
  { kind: "refused", code },
3467
- VISITOR_POLL_RETRY[code],
3274
+ chunk6PTRZP5U_cjs.VISITOR_POLL_RETRY[code],
3468
3275
  {
3469
3276
  statusCode: response.status,
3470
3277
  cause: mapped,
@@ -3492,17 +3299,17 @@ function edgeRequest(client, filter) {
3492
3299
  chunkMWMSFIWN_cjs.__name(edgeRequest, "edgeRequest");
3493
3300
  function edgeUrl(request, since, transport, clientId) {
3494
3301
  const url = new URL(request.base.href);
3495
- url.pathname = `${url.pathname.replace(/\/+$/, "")}${VISITOR_LIVE_PATH}`;
3302
+ url.pathname = `${url.pathname.replace(/\/+$/, "")}${chunk6PTRZP5U_cjs.VISITOR_LIVE_PATH}`;
3496
3303
  if (transport === "socket") url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
3497
3304
  const query = new URLSearchParams();
3498
- if (request.key !== void 0) query.set(VISITOR_QUERY.key, request.key);
3305
+ if (request.key !== void 0) query.set(chunk6PTRZP5U_cjs.VISITOR_QUERY.key, request.key);
3499
3306
  if (request.dataset !== void 0 && request.dataset !== "") {
3500
- query.set(VISITOR_QUERY.dataset, request.dataset);
3307
+ query.set(chunk6PTRZP5U_cjs.VISITOR_QUERY.dataset, request.dataset);
3501
3308
  }
3502
- if (since !== void 0) query.set(VISITOR_QUERY.since, since);
3503
- if (request.types !== void 0) query.set(VISITOR_QUERY.types, request.types.join(","));
3504
- if (request.ids !== void 0) query.set(VISITOR_QUERY.ids, request.ids.join(","));
3505
- if (transport === "poll" && clientId !== void 0) query.set(VISITOR_QUERY.client, clientId);
3309
+ if (since !== void 0) query.set(chunk6PTRZP5U_cjs.VISITOR_QUERY.since, since);
3310
+ if (request.types !== void 0) query.set(chunk6PTRZP5U_cjs.VISITOR_QUERY.types, request.types.join(","));
3311
+ if (request.ids !== void 0) query.set(chunk6PTRZP5U_cjs.VISITOR_QUERY.ids, request.ids.join(","));
3312
+ if (transport === "poll" && clientId !== void 0) query.set(chunk6PTRZP5U_cjs.VISITOR_QUERY.client, clientId);
3506
3313
  url.search = query.toString();
3507
3314
  return url.href;
3508
3315
  }
@@ -3587,8 +3394,9 @@ chunkMWMSFIWN_cjs.__name(given, "given");
3587
3394
  function transportOf(options) {
3588
3395
  const headers = readHeaders(options);
3589
3396
  return {
3397
+ ...signalOf(options),
3590
3398
  ...headers === void 0 ? {} : { headers },
3591
- ...typeof options.fresh === "string" ? { query: { [FRESH_PARAMETER]: options.fresh } } : {}
3399
+ ...typeof options.fresh === "string" ? { query: { [chunk6PTRZP5U_cjs.FRESH_PARAMETER]: options.fresh } } : {}
3592
3400
  };
3593
3401
  }
3594
3402
  chunkMWMSFIWN_cjs.__name(transportOf, "transportOf");
@@ -3664,7 +3472,7 @@ chunkMWMSFIWN_cjs.__name(runSimilar, "runSimilar");
3664
3472
  // src/batch/batch-operations.ts
3665
3473
  var VERBS = ["create", "update", "replace", "delete", "singleton"];
3666
3474
  async function runBatch(http, operations, options, clientLocale) {
3667
- const { atomic, dryRun, stopOnError, returnData, dataset } = options;
3475
+ const { atomic, dryRun, stopOnError, returnData, dataset, signal } = options;
3668
3476
  const runOptions = {
3669
3477
  ...atomic === void 0 ? {} : { atomic },
3670
3478
  ...dryRun === void 0 ? {} : { dryRun },
@@ -3677,7 +3485,8 @@ async function runBatch(http, operations, options, clientLocale) {
3677
3485
  operations: operations.map((operation, index) => operationOf(operation, index, clientLocale)),
3678
3486
  ...Object.keys(runOptions).length === 0 ? {} : { options: runOptions }
3679
3487
  },
3680
- ...headers === void 0 ? {} : { headers }
3488
+ ...headers === void 0 ? {} : { headers },
3489
+ ...signalOf({ signal })
3681
3490
  });
3682
3491
  return response.body;
3683
3492
  }
@@ -3757,7 +3566,7 @@ async function runAdhocQuery(http, query, clientLocale) {
3757
3566
  const order = sort === void 0 ? [] : Object.entries(sort).flatMap(
3758
3567
  ([field, direction]) => direction === void 0 ? [] : [{ [field]: direction }]
3759
3568
  );
3760
- const fetch2 = {
3569
+ const fetch = {
3761
3570
  contentType: query.from,
3762
3571
  ...where === void 0 || Object.keys(where).length === 0 ? {} : { where },
3763
3572
  ...include === void 0 || include.length === 0 ? {} : { include: [...include] },
@@ -3765,14 +3574,14 @@ async function runAdhocQuery(http, query, clientLocale) {
3765
3574
  ...limit === void 0 ? {} : { limit },
3766
3575
  ...page === void 0 ? {} : { offset: offsetOf(page, limit) }
3767
3576
  };
3768
- const locale = query.locale ?? clientLocale;
3769
- const parameters = {
3770
- ...query.params,
3771
- ...locale === void 0 || locale === "" ? {} : { locale }
3772
- };
3577
+ const terms = {};
3578
+ if (query.cursor !== void 0) terms.cursor = query.cursor;
3579
+ writeLocale(terms, query.locale ?? clientLocale);
3580
+ if (typeof query.fresh === "string") terms[chunk6PTRZP5U_cjs.FRESH_PARAMETER] = query.fresh;
3581
+ const parameters = { ...query.params };
3773
3582
  const body = {
3774
3583
  query: {
3775
- fetch: fetch2,
3584
+ fetch,
3776
3585
  ...aggregate === void 0 ? {} : { aggregate },
3777
3586
  ...select === void 0 || select.length === 0 ? {} : { select: Object.fromEntries(select.map((field) => [field, field])) },
3778
3587
  ...fullText === void 0 ? {} : { fullText }
@@ -3782,8 +3591,9 @@ async function runAdhocQuery(http, query, clientLocale) {
3782
3591
  const headers = readHeaders(query);
3783
3592
  const response = await http.send("/v1/query", "post", {
3784
3593
  body,
3594
+ ...Object.keys(terms).length === 0 ? {} : { query: terms },
3785
3595
  ...headers === void 0 ? {} : { headers },
3786
- ...typeof query.fresh === "string" ? { query: { [FRESH_PARAMETER]: query.fresh } } : {}
3596
+ ...signalOf(query)
3787
3597
  });
3788
3598
  return response.body;
3789
3599
  }
@@ -3800,6 +3610,9 @@ function offsetOf(page, limit) {
3800
3610
  chunkMWMSFIWN_cjs.__name(offsetOf, "offsetOf");
3801
3611
  async function runNamedQuery(http, name, options, clientLocale) {
3802
3612
  const locale = options.locale ?? clientLocale;
3613
+ const terms = {};
3614
+ if (locale !== void 0 && locale !== "") terms.locale = locale;
3615
+ if (typeof options.fresh === "string") terms[chunk6PTRZP5U_cjs.FRESH_PARAMETER] = options.fresh;
3803
3616
  const headers = readHeaders(options);
3804
3617
  const response = await http.send(
3805
3618
  "/v1/queries/{name}",
@@ -3807,8 +3620,9 @@ async function runNamedQuery(http, name, options, clientLocale) {
3807
3620
  {
3808
3621
  path: { name },
3809
3622
  body: options.params === void 0 ? {} : { params: options.params },
3810
- ...locale === void 0 || locale === "" ? {} : { query: { locale } },
3811
- ...headers === void 0 ? {} : { headers }
3623
+ ...Object.keys(terms).length === 0 ? {} : { query: terms },
3624
+ ...headers === void 0 ? {} : { headers },
3625
+ ...signalOf(options)
3812
3626
  }
3813
3627
  );
3814
3628
  return response.body;
@@ -3916,6 +3730,17 @@ function resolveDevOverride(dev) {
3916
3730
  }
3917
3731
  chunkMWMSFIWN_cjs.__name(resolveDevOverride, "resolveDevOverride");
3918
3732
 
3733
+ // src/config/preview-environment.ts
3734
+ function readPreviewAtRequest() {
3735
+ const env = typeof process === "undefined" ? void 0 : process.env;
3736
+ return chunk6PTRZP5U_cjs.previewAtRequest(isEnvironment(env) ? env : {});
3737
+ }
3738
+ chunkMWMSFIWN_cjs.__name(readPreviewAtRequest, "readPreviewAtRequest");
3739
+ function isEnvironment(value) {
3740
+ return typeof value === "object" && value !== null;
3741
+ }
3742
+ chunkMWMSFIWN_cjs.__name(isEnvironment, "isEnvironment");
3743
+
3919
3744
  // src/config/types.ts
3920
3745
  var DEFAULT_CONFIG = {
3921
3746
  baseUrl: "https://api.relyio.com",
@@ -3937,12 +3762,6 @@ var DEFAULT_CONFIG = {
3937
3762
  // 50MB
3938
3763
  strategies: ["memory", "stale-while-revalidate"]
3939
3764
  },
3940
- realtime: {
3941
- enabled: true,
3942
- maxReconnectAttempts: 10,
3943
- reconnectDelay: 1e3,
3944
- heartbeatInterval: 3e4
3945
- },
3946
3765
  debug: {
3947
3766
  enabled: false,
3948
3767
  logRequests: false,
@@ -3994,7 +3813,7 @@ chunkMWMSFIWN_cjs.__name(withoutKeyHeader, "withoutKeyHeader");
3994
3813
  function withHandshake(configured) {
3995
3814
  const dev = resolveDevOverride(configured.dev);
3996
3815
  const merged = withDefaults(
3997
- configured,
3816
+ withPreview(configured),
3998
3817
  dev.state === "active" ? { apiKey: dev.apiKey, dataset: dev.sandbox.datasetId } : {},
3999
3818
  DEFAULT_CONFIG
4000
3819
  );
@@ -4019,6 +3838,22 @@ function withHandshake(configured) {
4019
3838
  return { config: merged, sandbox: sandboxStateOf(dev), configured };
4020
3839
  }
4021
3840
  chunkMWMSFIWN_cjs.__name(withHandshake, "withHandshake");
3841
+ var previewNotified = false;
3842
+ function withPreview(configured) {
3843
+ if (configured.dataset !== void 0 || !isPreviewKey(configured.apiKey)) return configured;
3844
+ const preview = readPreviewAtRequest();
3845
+ if (preview.state !== "preview") return configured;
3846
+ const dataset = chunk6PTRZP5U_cjs.previewDatasetSlug(preview.branch);
3847
+ noteDerivedPreview(dataset);
3848
+ if (!previewNotified) {
3849
+ previewNotified = true;
3850
+ console.info(
3851
+ `[RelyIO] ${preview.host} preview deployment of "${preview.branch}" \u2014 reading its preview dataset "${dataset}".`
3852
+ );
3853
+ }
3854
+ return { ...configured, dataset };
3855
+ }
3856
+ chunkMWMSFIWN_cjs.__name(withPreview, "withPreview");
4022
3857
  function withDefaults(base, given2, defaults) {
4023
3858
  const merged = new Map(Object.entries(base));
4024
3859
  const givenValues = new Map(Object.entries(given2 ?? {}));
@@ -4085,7 +3920,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4085
3920
  this.config = resolved.config;
4086
3921
  this.configured = resolved.configured;
4087
3922
  this._sandbox = resolved.sandbox;
4088
- this.httpClient = new HttpClient(this.config);
3923
+ this.httpClient = new ControlledHttpClient(this.config);
4089
3924
  }
4090
3925
  // ============================================================================
4091
3926
  // CORE CLIENTS
@@ -4110,14 +3945,16 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4110
3945
  /**
4111
3946
  * Run a query in one call (REL-2421, REL-2409 Q22):
4112
3947
  *
4113
- * - `query({ from, … })` runs one inline, with `list`'s option names — `where` (the query
4114
- * route's dialect), `include`, `select`, `sort`, `limit`, `page`, `locale`, `dataset`, `fresh` —
4115
- * plus `aggregate`, `params` and `fullText`;
3948
+ * - `query({ from, … })` runs one inline, with `list`'s options — `where`, `include`, `select`
3949
+ * (beside `include`), `sort`, `limit`, `cursor`, `page`, `locale` (a code, a list or `'*'`),
3950
+ * `dataset`, `fresh` — plus `aggregate`, `params` and `fullText`. It answers a list's envelope,
3951
+ * `{ data, page, meta }` (REL-2460);
4116
3952
  * - `query(name, { params, … })` runs the saved query the schema declares under `name`, its
4117
- * `params` typed from that declaration.
3953
+ * `params` typed from that declaration. It answers the API's body,
3954
+ * `{ data: { result, metadata } }`.
4118
3955
  *
4119
- * Both answer the API's body, `{ data: { result, metadata } }`. See {@link QueryCall}. Every query
4120
- * is sent in the client's locale as it is then, unless it names its own.
3956
+ * See {@link QueryCall}. Every query is sent in the client's locale as it is then, unless it names
3957
+ * its own.
4121
3958
  */
4122
3959
  get query() {
4123
3960
  const call = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name((target, options = {}) => typeof target === "string" ? runNamedQuery(this.httpClient, target, options, this.currentLocale()) : runAdhocQuery(this.httpClient, target, this.currentLocale()), "call");
@@ -4302,7 +4139,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4302
4139
  * edge's URL. On a server, follow `changes()` with it instead.
4303
4140
  */
4304
4141
  liveChanges(options = {}) {
4305
- const { apiKey, dataset, baseUrl, liveUrl, fetch: fetch2, webSocket, timeout } = this.getConfig();
4142
+ const { apiKey, dataset, baseUrl, liveUrl, fetch, webSocket, timeout } = this.getConfig();
4306
4143
  this._liveClientId ?? (this._liveClientId = randomClientId());
4307
4144
  return subscribeLiveEdge(
4308
4145
  {
@@ -4310,7 +4147,7 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4310
4147
  dataset,
4311
4148
  baseUrl,
4312
4149
  liveUrl,
4313
- fetch: fetch2,
4150
+ fetch,
4314
4151
  webSocket,
4315
4152
  timeout,
4316
4153
  clientId: this._liveClientId
@@ -4419,9 +4256,9 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
4419
4256
  * - an option you name replaces the value the client holds;
4420
4257
  * - an option left out, or given as `undefined`, keeps the value the client holds;
4421
4258
  * - an option with no default given as `null` is cleared — `locale`, `dataset`, `apiKey`, `dev`,
4422
- * `fetch`, `browser.onCorsError`, `realtime.wsUrl`, `debug.logger` — so the client runs as though
4259
+ * `fetch`, `browser.onCorsError`, `debug.logger` — so the client runs as though
4423
4260
  * it had never been given one. An option with a default takes no `null`;
4424
- * - a bag of options you name — `browser`, `cache`, `realtime`, `debug` — keeps every field of it
4261
+ * - a bag of options you name — `browser`, `cache`, `debug` — keeps every field of it
4425
4262
  * you do not name, so `updateConfig({ browser: { includeCredentials: true } })` keeps a
4426
4263
  * configured `onCorsError`;
4427
4264
  * - `headers` is laid over the headers the client sends, a name matched without regard to case: a
@@ -4605,6 +4442,7 @@ exports.BaseValidationError = BaseValidationError;
4605
4442
  exports.ChangesExpiredError = ChangesExpiredError;
4606
4443
  exports.ConnectionError = ConnectionError;
4607
4444
  exports.ContentClient = ContentClient;
4445
+ exports.DefaultRetryPolicy = DefaultRetryPolicy;
4608
4446
  exports.ErrorMapper = ErrorMapper;
4609
4447
  exports.FileUploadError = FileUploadError;
4610
4448
  exports.FileValidationError = FileValidationError;
@@ -4617,6 +4455,7 @@ exports.LiveEdgeError = LiveEdgeError;
4617
4455
  exports.MethodNotAllowedError = MethodNotAllowedError;
4618
4456
  exports.MissingApiKeyError = MissingApiKeyError;
4619
4457
  exports.NetworkError = NetworkError;
4458
+ exports.PREVIEW_KEY_PREFIX = PREVIEW_KEY_PREFIX;
4620
4459
  exports.PUBLISHABLE_KEY_PREFIX = PUBLISHABLE_KEY_PREFIX;
4621
4460
  exports.PayloadTooLargeError = PayloadTooLargeError;
4622
4461
  exports.PlanFeatureUnavailableError = PlanFeatureUnavailableError;
@@ -4635,18 +4474,20 @@ exports.TransactionRolledBackError = TransactionRolledBackError;
4635
4474
  exports.TypedRelyIOClient = TypedRelyIOClient;
4636
4475
  exports.UnknownContractError = UnknownContractError;
4637
4476
  exports.UsageQuotaExceededError = UsageQuotaExceededError;
4638
- exports.VISITOR_ADMISSION_RETRY_AFTER_SECONDS = VISITOR_ADMISSION_RETRY_AFTER_SECONDS;
4639
4477
  exports.ValidationError = ValidationError;
4640
4478
  exports.createClient = createClient;
4641
4479
  exports.isAborted = isAborted;
4642
4480
  exports.isAssetEntry = isAssetEntry;
4643
4481
  exports.isMissingEntry = isMissingEntry;
4482
+ exports.isPreviewKey = isPreviewKey;
4644
4483
  exports.isPublishableKey = isPublishableKey;
4484
+ exports.isReplaySafe = isReplaySafe;
4645
4485
  exports.isResourceNotFound = isResourceNotFound;
4646
4486
  exports.matchRoute = matchRoute;
4487
+ exports.retryPolicyFor = retryPolicyFor;
4647
4488
  exports.serviceInstructedDelayMs = serviceInstructedDelayMs;
4648
4489
  exports.sleep = sleep;
4649
4490
  exports.validateFile = validateFile;
4650
4491
  exports.versionCheckOf = versionCheckOf;
4651
- //# sourceMappingURL=chunk-3BHDGUNS.cjs.map
4652
- //# sourceMappingURL=chunk-3BHDGUNS.cjs.map
4492
+ //# sourceMappingURL=chunk-6E22GYPB.cjs.map
4493
+ //# sourceMappingURL=chunk-6E22GYPB.cjs.map