@relyio/sdk 0.7.0 → 0.9.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/.tsbuildinfo +1 -1
- package/dist/{chunk-GYHAVYND.js → chunk-LGNJIGHL.js} +884 -16
- package/dist/{chunk-VH2DE7HZ.cjs → chunk-SPFRDXAF.cjs} +889 -15
- package/dist/client/index.cjs +3 -3
- package/dist/client/index.d.cts +5 -4
- package/dist/client/index.d.ts +5 -4
- package/dist/client/index.js +1 -1
- package/dist/{define-content-type-DiVpbwNs.d.cts → define-content-type-cEGjIwT5.d.cts} +205 -10
- package/dist/{define-content-type-DiVpbwNs.d.ts → define-content-type-cEGjIwT5.d.ts} +205 -10
- package/dist/{define-schema-C-5an28C.d.ts → define-schema-BPj2srgh.d.ts} +1 -1
- package/dist/{define-schema-D7MButVt.d.cts → define-schema-DgbJ5Kwn.d.cts} +1 -1
- package/dist/{index-M0X45k7J.d.cts → index-B9axQW8s.d.cts} +265 -14
- package/dist/{index-DbsTUw3Q.d.cts → index-B_rIWO_l.d.cts} +47 -5
- package/dist/{index-BOQIHnsh.d.ts → index-Cv4tmcrw.d.ts} +47 -5
- package/dist/{index-1G97sNA8.d.ts → index-GIfaMlQ7.d.ts} +265 -14
- package/dist/index.cjs +119 -75
- package/dist/index.d.cts +152 -41
- package/dist/index.d.ts +152 -41
- package/dist/index.js +37 -12
- package/dist/schema/index.d.cts +3 -3
- package/dist/schema/index.d.ts +3 -3
- package/dist/types/index.d.cts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -412,6 +412,45 @@ var _InvalidPayloadError = class _InvalidPayloadError extends BaseValidationErro
|
|
|
412
412
|
chunkMWMSFIWN_cjs.__name(_InvalidPayloadError, "InvalidPayloadError");
|
|
413
413
|
var InvalidPayloadError = _InvalidPayloadError;
|
|
414
414
|
|
|
415
|
+
// ../../platform/api-contract/dist/chunk-PYZCLRXR.js
|
|
416
|
+
function defineRoute(route) {
|
|
417
|
+
if (route.kind === "raw" && route.standardShape === void 0) {
|
|
418
|
+
throw new Error("kind 'raw' requires a named StandardShape");
|
|
419
|
+
}
|
|
420
|
+
if (route.kind === "raw" && route.success === 302 && !route.headers.some((header) => header.name === "Location")) {
|
|
421
|
+
throw new Error("a raw route declaring success 302 must declare its 'Location' header");
|
|
422
|
+
}
|
|
423
|
+
if (route.kind === "stream" && route.stream === void 0) {
|
|
424
|
+
throw new Error("kind 'stream' requires a StreamDeclaration");
|
|
425
|
+
}
|
|
426
|
+
if (route.kind === "collection" && route.page === void 0) {
|
|
427
|
+
throw new Error("kind 'collection' requires a page dialect");
|
|
428
|
+
}
|
|
429
|
+
if ((route.kind === "object" || route.kind === "collection") && route.negotiated !== void 0) {
|
|
430
|
+
refuseMismatchedAlternate(route, route.negotiated["text/event-stream"]);
|
|
431
|
+
}
|
|
432
|
+
return route;
|
|
433
|
+
}
|
|
434
|
+
chunkMWMSFIWN_cjs.__name(defineRoute, "defineRoute");
|
|
435
|
+
function refuseMismatchedAlternate(route, stream) {
|
|
436
|
+
if (stream.kind !== "stream") {
|
|
437
|
+
throw new Error("a negotiated 'text/event-stream' alternate must be kind 'stream'");
|
|
438
|
+
}
|
|
439
|
+
if (stream.stream.mediaType !== "text/event-stream") {
|
|
440
|
+
throw new Error(
|
|
441
|
+
`a negotiated 'text/event-stream' alternate declares media type "${stream.stream.mediaType}"`
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
const own = [...new Set(route.codes)].sort();
|
|
445
|
+
const alternate = [...new Set(stream.codes)].sort();
|
|
446
|
+
if (own.length !== alternate.length || own.some((code, index) => code !== alternate[index])) {
|
|
447
|
+
throw new Error(
|
|
448
|
+
`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`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
chunkMWMSFIWN_cjs.__name(refuseMismatchedAlternate, "refuseMismatchedAlternate");
|
|
453
|
+
|
|
415
454
|
// ../../platform/api-contract/dist/index.js
|
|
416
455
|
var HEADER_RETRY_AFTER = { name: "Retry-After" };
|
|
417
456
|
var HEADER_ENTITY_TAG = { name: "X-Entity-Tag" };
|
|
@@ -419,6 +458,169 @@ var HEADER_IF_MATCH = {
|
|
|
419
458
|
name: "If-Match"};
|
|
420
459
|
var HEADER_IDEMPOTENCY_KEY = {
|
|
421
460
|
name: "Idempotency-Key"};
|
|
461
|
+
var FRESH_PARAMETER = "_fresh";
|
|
462
|
+
var VISITOR_LIVE_PATH = "/visitor/changes";
|
|
463
|
+
var VISITOR_QUERY = {
|
|
464
|
+
/** The publishable key. */
|
|
465
|
+
key: "key",
|
|
466
|
+
/** A dataset id or name the key reaches; absent, the key's default dataset. */
|
|
467
|
+
dataset: "dataset",
|
|
468
|
+
/** The cursor to continue from; absent, the socket starts now. */
|
|
469
|
+
since: "since",
|
|
470
|
+
/** Comma-separated content types to keep; absent keeps every type. */
|
|
471
|
+
types: "types",
|
|
472
|
+
/** Comma-separated entry ids to keep; absent keeps every entry. */
|
|
473
|
+
ids: "ids",
|
|
474
|
+
/** The poll's client id. Required on a poll, and not read on a socket. */
|
|
475
|
+
client: "client"
|
|
476
|
+
};
|
|
477
|
+
var VISITOR_CURSOR = /^[\w.~-]{1,256}$/;
|
|
478
|
+
var VISITOR_POLL_INTERVAL_MS = 15e3;
|
|
479
|
+
var VISITOR_KEEPALIVE = { request: "ping", response: "pong" };
|
|
480
|
+
var VISITOR_FRAMES = {
|
|
481
|
+
opened: "feed.opened",
|
|
482
|
+
changes: "feed.changes",
|
|
483
|
+
resync: "feed.resync"
|
|
484
|
+
};
|
|
485
|
+
defineRoute({
|
|
486
|
+
kind: "object",
|
|
487
|
+
headers: [HEADER_RETRY_AFTER],
|
|
488
|
+
codes: [
|
|
489
|
+
"REQUEST_INVALID",
|
|
490
|
+
"MISSING_API_KEY",
|
|
491
|
+
"INVALID_API_KEY",
|
|
492
|
+
"ACCESS_DENIED",
|
|
493
|
+
"METHOD_NOT_ALLOWED",
|
|
494
|
+
"SERVICE_INDETERMINATE",
|
|
495
|
+
"USAGE_QUOTA_EXCEEDED",
|
|
496
|
+
"RATE_LIMIT_EXCEEDED"
|
|
497
|
+
]
|
|
498
|
+
});
|
|
499
|
+
var VISITOR_CLOSE_CODES = {
|
|
500
|
+
/** A query the door cannot read: a malformed `since`, filter, `dataset` or `client`. */
|
|
501
|
+
requestInvalid: 4400,
|
|
502
|
+
/** No publishable key, or one that is unknown, revoked, expired, a secret key or a preview key. */
|
|
503
|
+
keyRefused: 4401,
|
|
504
|
+
/** The page's `Origin` is absent, or not on the key's allowed origins. */
|
|
505
|
+
originRefused: 4403,
|
|
506
|
+
/** `dataset` names nothing the key reaches. */
|
|
507
|
+
datasetRefused: 4404,
|
|
508
|
+
/** The key's scope, the project's counter or the feed could not be reached just now. */
|
|
509
|
+
unavailable: 1013,
|
|
510
|
+
/**
|
|
511
|
+
* The project holds as many visitor connections as its plan allows — Starter's 100 — or its
|
|
512
|
+
* Organization is suspended. As HTTP's 402: more needs a bigger plan, or visitors leaving.
|
|
513
|
+
*/
|
|
514
|
+
allowanceReached: 4402,
|
|
515
|
+
/** This client's address holds as many connections to the project as one address may. */
|
|
516
|
+
addressLimitReached: 4429,
|
|
517
|
+
/** The project is at its per-project safety ceiling — Pro's 50,000 — whatever it would pay for. */
|
|
518
|
+
ceilingReached: 4503
|
|
519
|
+
};
|
|
520
|
+
var VISITOR_CLOSE_RETRY = {
|
|
521
|
+
4400: "stop",
|
|
522
|
+
4401: "stop",
|
|
523
|
+
4403: "stop",
|
|
524
|
+
4404: "stop",
|
|
525
|
+
1013: "retry",
|
|
526
|
+
4402: "back-off",
|
|
527
|
+
4429: "back-off",
|
|
528
|
+
4503: "back-off"
|
|
529
|
+
};
|
|
530
|
+
var VISITOR_POLL_RETRY = {
|
|
531
|
+
REQUEST_INVALID: "stop",
|
|
532
|
+
MISSING_API_KEY: "stop",
|
|
533
|
+
INVALID_API_KEY: "stop",
|
|
534
|
+
ACCESS_DENIED: "stop",
|
|
535
|
+
METHOD_NOT_ALLOWED: "stop",
|
|
536
|
+
SERVICE_INDETERMINATE: "retry",
|
|
537
|
+
USAGE_QUOTA_EXCEEDED: "back-off",
|
|
538
|
+
RATE_LIMIT_EXCEEDED: "back-off"
|
|
539
|
+
};
|
|
540
|
+
var VISITOR_ADMISSION_RETRY_AFTER_SECONDS = 60;
|
|
541
|
+
function parseVisitorFrame(text) {
|
|
542
|
+
let value;
|
|
543
|
+
try {
|
|
544
|
+
value = JSON.parse(text);
|
|
545
|
+
} catch {
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
if (!isRecord2(value) || !isCursor(value.cursor)) return null;
|
|
549
|
+
switch (value.type) {
|
|
550
|
+
case VISITOR_FRAMES.opened: {
|
|
551
|
+
return hasOnly(value, ["type", "cursor"]) ? { type: VISITOR_FRAMES.opened, cursor: value.cursor } : null;
|
|
552
|
+
}
|
|
553
|
+
case VISITOR_FRAMES.changes: {
|
|
554
|
+
const changes = hasOnly(value, ["type", "changes", "cursor"]) ? readVisitorChanges(value.changes) : null;
|
|
555
|
+
return changes === null ? null : { type: VISITOR_FRAMES.changes, changes, cursor: value.cursor };
|
|
556
|
+
}
|
|
557
|
+
case VISITOR_FRAMES.resync: {
|
|
558
|
+
return hasOnly(value, ["type", "reason", "cursor"]) && isResyncReason(value.reason) ? { type: VISITOR_FRAMES.resync, reason: value.reason, cursor: value.cursor } : null;
|
|
559
|
+
}
|
|
560
|
+
default: {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
chunkMWMSFIWN_cjs.__name(parseVisitorFrame, "parseVisitorFrame");
|
|
566
|
+
function readVisitorPollAnswer(value) {
|
|
567
|
+
if (!isRecord2(value) || !isCursor(value.cursor)) return null;
|
|
568
|
+
if (value.kind === "resync") {
|
|
569
|
+
return hasOnly(value, ["kind", "reason", "cursor"]) && isResyncReason(value.reason) ? { kind: "resync", reason: value.reason, cursor: value.cursor } : null;
|
|
570
|
+
}
|
|
571
|
+
if (value.kind !== "changes" || !hasOnly(value, ["kind", "changes", "cursor"])) return null;
|
|
572
|
+
const changes = readVisitorChanges(value.changes);
|
|
573
|
+
return changes === null ? null : { kind: "changes", changes, cursor: value.cursor };
|
|
574
|
+
}
|
|
575
|
+
chunkMWMSFIWN_cjs.__name(readVisitorPollAnswer, "readVisitorPollAnswer");
|
|
576
|
+
var CHANGE_KINDS = /* @__PURE__ */ new Set([
|
|
577
|
+
"published",
|
|
578
|
+
"updated",
|
|
579
|
+
"unpublished",
|
|
580
|
+
"deleted"
|
|
581
|
+
]);
|
|
582
|
+
var RESYNC_REASONS = /* @__PURE__ */ new Set([
|
|
583
|
+
"retention",
|
|
584
|
+
"dataset-replaced",
|
|
585
|
+
"ahead-of-head",
|
|
586
|
+
"foreign-cursor",
|
|
587
|
+
"too-far-behind"
|
|
588
|
+
]);
|
|
589
|
+
function isResyncReason(value) {
|
|
590
|
+
return typeof value === "string" && RESYNC_REASONS.has(value);
|
|
591
|
+
}
|
|
592
|
+
chunkMWMSFIWN_cjs.__name(isResyncReason, "isResyncReason");
|
|
593
|
+
function readVisitorChanges(value) {
|
|
594
|
+
if (!Array.isArray(value)) return null;
|
|
595
|
+
const changes = [];
|
|
596
|
+
for (const item of value) {
|
|
597
|
+
if (!isRecord2(item) || !hasOnly(item, ["entryId", "contentType", "locale", "kind"])) return null;
|
|
598
|
+
const { entryId, contentType, locale, kind } = item;
|
|
599
|
+
if (!isNonEmptyString2(entryId) || !isNonEmptyString2(contentType)) return null;
|
|
600
|
+
if (locale !== null && typeof locale !== "string") return null;
|
|
601
|
+
if (typeof kind !== "string" || !CHANGE_KINDS.has(kind)) return null;
|
|
602
|
+
changes.push({ entryId, contentType, locale, kind });
|
|
603
|
+
}
|
|
604
|
+
return changes;
|
|
605
|
+
}
|
|
606
|
+
chunkMWMSFIWN_cjs.__name(readVisitorChanges, "readVisitorChanges");
|
|
607
|
+
function isCursor(value) {
|
|
608
|
+
return typeof value === "string" && VISITOR_CURSOR.test(value);
|
|
609
|
+
}
|
|
610
|
+
chunkMWMSFIWN_cjs.__name(isCursor, "isCursor");
|
|
611
|
+
function isRecord2(value) {
|
|
612
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
613
|
+
}
|
|
614
|
+
chunkMWMSFIWN_cjs.__name(isRecord2, "isRecord2");
|
|
615
|
+
function isNonEmptyString2(value) {
|
|
616
|
+
return typeof value === "string" && value.length > 0;
|
|
617
|
+
}
|
|
618
|
+
chunkMWMSFIWN_cjs.__name(isNonEmptyString2, "isNonEmptyString2");
|
|
619
|
+
function hasOnly(value, keys) {
|
|
620
|
+
const present = Object.keys(value);
|
|
621
|
+
return present.length === keys.length && present.every((key) => keys.includes(key));
|
|
622
|
+
}
|
|
623
|
+
chunkMWMSFIWN_cjs.__name(hasOnly, "hasOnly");
|
|
422
624
|
|
|
423
625
|
// ../../platform/api-contract/dist/client/index.js
|
|
424
626
|
var _a;
|
|
@@ -687,6 +889,8 @@ var DECLARED_PATHS = {
|
|
|
687
889
|
"/health/cache": true,
|
|
688
890
|
"/health/live": true,
|
|
689
891
|
"/health/ready": true,
|
|
892
|
+
"/internal/live/visitor-feed/{projectId}/{datasetId}/changes": true,
|
|
893
|
+
"/internal/live/visitor-key": true,
|
|
690
894
|
"/internal/media/claim": true,
|
|
691
895
|
"/internal/media/file-complete": true,
|
|
692
896
|
"/internal/media/progress": true,
|
|
@@ -1425,8 +1629,20 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1425
1629
|
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
1426
1630
|
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
1427
1631
|
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
1632
|
+
chunkMWMSFIWN_cjs.__publicField(this, "freshValue");
|
|
1428
1633
|
this.clientLocale = readClientLocale(locale);
|
|
1429
1634
|
}
|
|
1635
|
+
/**
|
|
1636
|
+
* The feed position this read follows — a change's `fresh` (`FeedChange`), or a resync's. Sent as
|
|
1637
|
+
* `?_fresh`, the one term the API declares for it: no cache — the Content API's edge or the
|
|
1638
|
+
* browser's own — holds an answer for that position from before it, so the read is answered after
|
|
1639
|
+
* the change, and every read naming the same position shares that answer. The answer is the
|
|
1640
|
+
* read's own; omit it for a read no change prompted.
|
|
1641
|
+
*/
|
|
1642
|
+
fresh(position) {
|
|
1643
|
+
this.freshValue = position;
|
|
1644
|
+
return this;
|
|
1645
|
+
}
|
|
1430
1646
|
/**
|
|
1431
1647
|
* Headers this query adds to the client's own, e.g. `X-RelyIO-Dataset` to list another dataset
|
|
1432
1648
|
* the key can see. A name the client already sends is replaced for this query only; the client
|
|
@@ -1711,6 +1927,7 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1711
1927
|
cloned.pageNumber = this.pageNumber;
|
|
1712
1928
|
cloned.pageSizeValue = this.pageSizeValue;
|
|
1713
1929
|
cloned.requestHeaders = this.requestHeaders ? { ...this.requestHeaders } : void 0;
|
|
1930
|
+
cloned.freshValue = this.freshValue;
|
|
1714
1931
|
return cloned;
|
|
1715
1932
|
}
|
|
1716
1933
|
/**
|
|
@@ -1803,6 +2020,9 @@ var _ContentQueryBuilder = class _ContentQueryBuilder {
|
|
|
1803
2020
|
params.childrenLimit = this.childrenOptions.limit;
|
|
1804
2021
|
}
|
|
1805
2022
|
}
|
|
2023
|
+
if (this.freshValue !== void 0) {
|
|
2024
|
+
params[FRESH_PARAMETER] = this.freshValue;
|
|
2025
|
+
}
|
|
1806
2026
|
return params;
|
|
1807
2027
|
}
|
|
1808
2028
|
};
|
|
@@ -1825,8 +2045,20 @@ var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
|
1825
2045
|
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
1826
2046
|
/** The client's locale, asked when the read is sent rather than copied when it was built. */
|
|
1827
2047
|
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
2048
|
+
chunkMWMSFIWN_cjs.__publicField(this, "freshValue");
|
|
1828
2049
|
this.clientLocale = readClientLocale(locale);
|
|
1829
2050
|
}
|
|
2051
|
+
/**
|
|
2052
|
+
* The feed position this read follows — a change's `fresh` (`FeedChange`), or a resync's. Sent as
|
|
2053
|
+
* `?_fresh`, the one term the API declares for it: no cache — the Content API's edge or the
|
|
2054
|
+
* browser's own — holds an answer for that position from before it, so the read is answered after
|
|
2055
|
+
* the change, and every read naming the same position shares that answer. The answer is the
|
|
2056
|
+
* read's own; omit it for a read no change prompted.
|
|
2057
|
+
*/
|
|
2058
|
+
fresh(position) {
|
|
2059
|
+
this.freshValue = position;
|
|
2060
|
+
return this;
|
|
2061
|
+
}
|
|
1830
2062
|
/**
|
|
1831
2063
|
* Include related content in the response
|
|
1832
2064
|
*/
|
|
@@ -1915,6 +2147,9 @@ var _ContentByIdBuilder = class _ContentByIdBuilder {
|
|
|
1915
2147
|
params.childrenLimit = this.childrenOptions.limit;
|
|
1916
2148
|
}
|
|
1917
2149
|
}
|
|
2150
|
+
if (this.freshValue !== void 0) {
|
|
2151
|
+
params[FRESH_PARAMETER] = this.freshValue;
|
|
2152
|
+
}
|
|
1918
2153
|
try {
|
|
1919
2154
|
return await this.httpClient.fetchPayload(
|
|
1920
2155
|
"/v1/{contentType}/{id}",
|
|
@@ -3081,6 +3316,7 @@ var _SingletonClient = class _SingletonClient {
|
|
|
3081
3316
|
const localeValueFinal = options?.locale ?? this.localeValue ?? this.clientLocale();
|
|
3082
3317
|
if (includeValue) query.include = includeValue.join(",");
|
|
3083
3318
|
if (localeValueFinal != null && localeValueFinal !== "") query.locale = localeValueFinal;
|
|
3319
|
+
if (options?.fresh !== void 0) query[FRESH_PARAMETER] = options.fresh;
|
|
3084
3320
|
const response = await this.httpClient.send(
|
|
3085
3321
|
"/v1/singletons/{key}",
|
|
3086
3322
|
"get",
|
|
@@ -3376,6 +3612,7 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3376
3612
|
chunkMWMSFIWN_cjs.__publicField(this, "query");
|
|
3377
3613
|
chunkMWMSFIWN_cjs.__publicField(this, "searchOptions", {});
|
|
3378
3614
|
chunkMWMSFIWN_cjs.__publicField(this, "requestHeaders");
|
|
3615
|
+
chunkMWMSFIWN_cjs.__publicField(this, "freshValue");
|
|
3379
3616
|
/** The client's locale, asked when the query is sent rather than copied when it was built. */
|
|
3380
3617
|
chunkMWMSFIWN_cjs.__publicField(this, "clientLocale");
|
|
3381
3618
|
this.query = query;
|
|
@@ -3389,6 +3626,15 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3389
3626
|
this.requestHeaders = headers;
|
|
3390
3627
|
return this;
|
|
3391
3628
|
}
|
|
3629
|
+
/**
|
|
3630
|
+
* The feed position this search follows — a change's `fresh` (`FeedChange`), or a resync's. Sent
|
|
3631
|
+
* as `?_fresh` on the query string beside the body: the edge keys a search on both, so no answer
|
|
3632
|
+
* it holds from before that position can answer it. The answer is the search's own.
|
|
3633
|
+
*/
|
|
3634
|
+
fresh(position) {
|
|
3635
|
+
this.freshValue = position;
|
|
3636
|
+
return this;
|
|
3637
|
+
}
|
|
3392
3638
|
/**
|
|
3393
3639
|
* Search within a single content type. Where a schema types the client, the name is one of its
|
|
3394
3640
|
* content types and the results are that type's entries.
|
|
@@ -3530,7 +3776,11 @@ var _SearchBuilder = class _SearchBuilder {
|
|
|
3530
3776
|
const response = await this.httpClient.send(
|
|
3531
3777
|
"/v1/search",
|
|
3532
3778
|
"post",
|
|
3533
|
-
{
|
|
3779
|
+
{
|
|
3780
|
+
body,
|
|
3781
|
+
headers: this.requestHeaders,
|
|
3782
|
+
...this.freshValue === void 0 ? {} : { query: { [FRESH_PARAMETER]: this.freshValue } }
|
|
3783
|
+
}
|
|
3534
3784
|
);
|
|
3535
3785
|
return response.body;
|
|
3536
3786
|
}
|
|
@@ -4546,23 +4796,67 @@ var AdhocQueryClient = _AdhocQueryClient;
|
|
|
4546
4796
|
|
|
4547
4797
|
// src/changes/changes.ts
|
|
4548
4798
|
var CHANGES_POLL_TIMEOUT_MS = 25e3 + 5e3;
|
|
4799
|
+
var EXPIRED_REASONS = {
|
|
4800
|
+
retention: "retention",
|
|
4801
|
+
"dataset-replaced": "dataset-replaced",
|
|
4802
|
+
"ahead-of-head": "ahead-of-head",
|
|
4803
|
+
"foreign-cursor": "foreign-cursor",
|
|
4804
|
+
"too-far-behind": "too-far-behind"
|
|
4805
|
+
};
|
|
4549
4806
|
var _ChangesExpiredError = class _ChangesExpiredError extends ResourceExpiredError {
|
|
4550
|
-
/** The base class's signature, so `withContext` can rebuild one. */
|
|
4551
|
-
constructor(message, statusCode = 410, cause, context) {
|
|
4807
|
+
/** The base class's signature, so `withContext` can rebuild one; then the position resynced to. */
|
|
4808
|
+
constructor(message, statusCode = 410, cause, context, fresh) {
|
|
4552
4809
|
super(message, statusCode, cause, context);
|
|
4553
4810
|
chunkMWMSFIWN_cjs.__publicField(this, "reason");
|
|
4811
|
+
/**
|
|
4812
|
+
* The position the feed resynced to, which a refetch of everything names as `?_fresh`, as a
|
|
4813
|
+
* change's {@link FeedChange.fresh} is named: the head a `/v1/changes` resync took, or the cursor
|
|
4814
|
+
* the edge's `feed.resync` sent. `undefined` when there was no resync to take one — the error was
|
|
4815
|
+
* thrown (`onExpired: 'throw'`) — and on an error a caller built itself.
|
|
4816
|
+
*/
|
|
4817
|
+
chunkMWMSFIWN_cjs.__publicField(this, "fresh");
|
|
4554
4818
|
this.name = "ChangesExpiredError";
|
|
4555
4819
|
this.reason = expiredReasonOf(message);
|
|
4820
|
+
this.fresh = fresh;
|
|
4821
|
+
}
|
|
4822
|
+
/** The base class rebuilds from its four arguments, which would drop the position resynced to. */
|
|
4823
|
+
withContext(context) {
|
|
4824
|
+
const Constructor = this.constructor;
|
|
4825
|
+
return new Constructor(
|
|
4826
|
+
this.message,
|
|
4827
|
+
this.statusCode,
|
|
4828
|
+
this.cause,
|
|
4829
|
+
{ ...this.context, ...context },
|
|
4830
|
+
this.fresh
|
|
4831
|
+
);
|
|
4556
4832
|
}
|
|
4557
|
-
|
|
4558
|
-
|
|
4833
|
+
/** `/v1/changes`' refusal, with the head the feed resynced to when it did. */
|
|
4834
|
+
static of(expired, fresh) {
|
|
4835
|
+
return new _ChangesExpiredError(
|
|
4836
|
+
expired.message,
|
|
4837
|
+
expired.statusCode,
|
|
4838
|
+
expired,
|
|
4839
|
+
expired.context,
|
|
4840
|
+
fresh
|
|
4841
|
+
);
|
|
4842
|
+
}
|
|
4843
|
+
/** The live edge's `feed.resync`: refetch everything, then continue from the cursor it sent. */
|
|
4844
|
+
static resync(reason, cursor) {
|
|
4845
|
+
return new _ChangesExpiredError(
|
|
4846
|
+
`The live edge cannot list the changes since this cursor (${reason}). Refetch everything derived from the feed; it continues from the position it sent.`,
|
|
4847
|
+
410,
|
|
4848
|
+
void 0,
|
|
4849
|
+
{ transport: "live-edge" },
|
|
4850
|
+
cursor
|
|
4851
|
+
);
|
|
4559
4852
|
}
|
|
4560
4853
|
};
|
|
4561
4854
|
chunkMWMSFIWN_cjs.__name(_ChangesExpiredError, "ChangesExpiredError");
|
|
4562
4855
|
var ChangesExpiredError = _ChangesExpiredError;
|
|
4563
4856
|
function expiredReasonOf(message) {
|
|
4564
|
-
|
|
4565
|
-
|
|
4857
|
+
for (const reason of Object.values(EXPIRED_REASONS)) {
|
|
4858
|
+
if (message.includes(`(${reason})`)) return reason;
|
|
4859
|
+
}
|
|
4566
4860
|
return "unknown";
|
|
4567
4861
|
}
|
|
4568
4862
|
chunkMWMSFIWN_cjs.__name(expiredReasonOf, "expiredReasonOf");
|
|
@@ -4570,6 +4864,7 @@ async function* pollChanges(http, options = {}) {
|
|
|
4570
4864
|
const { signal } = options;
|
|
4571
4865
|
let since = options.since;
|
|
4572
4866
|
let resynced;
|
|
4867
|
+
let starting = since === void 0;
|
|
4573
4868
|
for (; ; ) {
|
|
4574
4869
|
if (isAborted(signal)) return;
|
|
4575
4870
|
let response;
|
|
@@ -4582,7 +4877,7 @@ async function* pollChanges(http, options = {}) {
|
|
|
4582
4877
|
const onExpired = options.onExpired ?? "throw";
|
|
4583
4878
|
if (onExpired === "throw") throw expired;
|
|
4584
4879
|
since = void 0;
|
|
4585
|
-
resynced = typeof onExpired === "function" ?
|
|
4880
|
+
resynced = typeof onExpired === "function" ? error : void 0;
|
|
4586
4881
|
continue;
|
|
4587
4882
|
}
|
|
4588
4883
|
const { data, page } = response.body;
|
|
@@ -4591,15 +4886,19 @@ async function* pollChanges(http, options = {}) {
|
|
|
4591
4886
|
}
|
|
4592
4887
|
since = page.nextCursor;
|
|
4593
4888
|
if (resynced !== void 0 && typeof options.onExpired === "function") {
|
|
4594
|
-
const expired = resynced;
|
|
4889
|
+
const expired = ChangesExpiredError.of(resynced, page.nextCursor);
|
|
4595
4890
|
resynced = void 0;
|
|
4596
4891
|
await options.onExpired(expired);
|
|
4597
4892
|
if (isAborted(signal)) return;
|
|
4598
4893
|
}
|
|
4599
4894
|
for (const change of data) {
|
|
4600
|
-
yield change;
|
|
4895
|
+
yield { ...change, fresh: change.cursor };
|
|
4601
4896
|
if (isAborted(signal)) return;
|
|
4602
4897
|
}
|
|
4898
|
+
if (starting) {
|
|
4899
|
+
starting = false;
|
|
4900
|
+
options.reached?.(page.nextCursor);
|
|
4901
|
+
}
|
|
4603
4902
|
if (data.length === 0) {
|
|
4604
4903
|
const wait = parseRetryAfterMs(headerValue(response.headers, "Retry-After"), Date.now());
|
|
4605
4904
|
if (wait !== void 0 && wait > 0) await sleep(wait, signal);
|
|
@@ -4636,6 +4935,500 @@ async function pollOnce(http, since, options) {
|
|
|
4636
4935
|
}
|
|
4637
4936
|
chunkMWMSFIWN_cjs.__name(pollOnce, "pollOnce");
|
|
4638
4937
|
|
|
4938
|
+
// src/config/key-kind.ts
|
|
4939
|
+
var PUBLISHABLE_KEY_PREFIX = "rly_pub_";
|
|
4940
|
+
var isPublishableKey = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name((apiKey) => apiKey?.startsWith(PUBLISHABLE_KEY_PREFIX) === true, "isPublishableKey");
|
|
4941
|
+
|
|
4942
|
+
// src/errors/live-errors.ts
|
|
4943
|
+
var _LiveEdgeError = class _LiveEdgeError extends SDKError {
|
|
4944
|
+
constructor(message, end, retry, options = {}) {
|
|
4945
|
+
super(message, options.statusCode, options.cause, options.context);
|
|
4946
|
+
chunkMWMSFIWN_cjs.__publicField(this, "code", "LIVE_EDGE_ENDED");
|
|
4947
|
+
chunkMWMSFIWN_cjs.__publicField(this, "retryable");
|
|
4948
|
+
chunkMWMSFIWN_cjs.__publicField(this, "end");
|
|
4949
|
+
chunkMWMSFIWN_cjs.__publicField(this, "retry");
|
|
4950
|
+
/** A refused poll's `Retry-After`, in milliseconds, where it carried a readable one. */
|
|
4951
|
+
chunkMWMSFIWN_cjs.__publicField(this, "retryAfterMs");
|
|
4952
|
+
this.end = end;
|
|
4953
|
+
this.retry = retry;
|
|
4954
|
+
this.retryable = retry !== "stop";
|
|
4955
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
4956
|
+
}
|
|
4957
|
+
/**
|
|
4958
|
+
* The base class rebuilds an error through its own four-argument constructor, which this class
|
|
4959
|
+
* does not have; rebuilt that way, `end` would be a string and `retry` a number.
|
|
4960
|
+
*/
|
|
4961
|
+
withContext(context) {
|
|
4962
|
+
const rebuilt = new _LiveEdgeError(this.message, this.end, this.retry, {
|
|
4963
|
+
...this.statusCode === void 0 ? {} : { statusCode: this.statusCode },
|
|
4964
|
+
...this.cause === void 0 ? {} : { cause: this.cause },
|
|
4965
|
+
...this.retryAfterMs === void 0 ? {} : { retryAfterMs: this.retryAfterMs },
|
|
4966
|
+
context: { ...this.context, ...context }
|
|
4967
|
+
});
|
|
4968
|
+
return rebuilt;
|
|
4969
|
+
}
|
|
4970
|
+
getUserMessage() {
|
|
4971
|
+
return this.message;
|
|
4972
|
+
}
|
|
4973
|
+
};
|
|
4974
|
+
chunkMWMSFIWN_cjs.__name(_LiveEdgeError, "LiveEdgeError");
|
|
4975
|
+
var LiveEdgeError = _LiveEdgeError;
|
|
4976
|
+
|
|
4977
|
+
// src/config/live-url.ts
|
|
4978
|
+
var LIVE_EDGE_OF_API = {
|
|
4979
|
+
"https://api.relyio.com": "https://live.relyio.com"
|
|
4980
|
+
};
|
|
4981
|
+
var HTTP_SCHEME_OF = {
|
|
4982
|
+
"http:": "http:",
|
|
4983
|
+
"https:": "https:",
|
|
4984
|
+
"ws:": "http:",
|
|
4985
|
+
"wss:": "https:"
|
|
4986
|
+
};
|
|
4987
|
+
function liveEdgeAddress(config) {
|
|
4988
|
+
if (config.liveUrl !== void 0) return readLiveUrl(config.liveUrl);
|
|
4989
|
+
const derived = originOf(config.baseUrl);
|
|
4990
|
+
const edge = derived === void 0 ? void 0 : LIVE_EDGE_OF_API[derived];
|
|
4991
|
+
if (edge !== void 0) return { ok: true, url: new URL(edge) };
|
|
4992
|
+
return {
|
|
4993
|
+
ok: false,
|
|
4994
|
+
message: `Live updates need the address of RelyIO\u2019s live edge, and this client cannot derive it: \`baseUrl\` is not RelyIO\u2019s API (${Object.keys(LIVE_EDGE_OF_API).join(", ")}). Set \`liveUrl\` in createClient() to the live edge this API belongs with. Nothing was sent.`
|
|
4995
|
+
};
|
|
4996
|
+
}
|
|
4997
|
+
chunkMWMSFIWN_cjs.__name(liveEdgeAddress, "liveEdgeAddress");
|
|
4998
|
+
function readLiveUrl(liveUrl) {
|
|
4999
|
+
let url;
|
|
5000
|
+
try {
|
|
5001
|
+
url = new URL(liveUrl);
|
|
5002
|
+
} catch {
|
|
5003
|
+
return { ok: false, message: `\`liveUrl\` is not a URL: "${liveUrl}". Nothing was sent.` };
|
|
5004
|
+
}
|
|
5005
|
+
const scheme = HTTP_SCHEME_OF[url.protocol];
|
|
5006
|
+
if (scheme === void 0) {
|
|
5007
|
+
return {
|
|
5008
|
+
ok: false,
|
|
5009
|
+
message: `\`liveUrl\` must be an https:, wss:, http: or ws: URL, not ${url.protocol}. Nothing was sent.`
|
|
5010
|
+
};
|
|
5011
|
+
}
|
|
5012
|
+
url.protocol = scheme;
|
|
5013
|
+
url.search = "";
|
|
5014
|
+
url.hash = "";
|
|
5015
|
+
return { ok: true, url };
|
|
5016
|
+
}
|
|
5017
|
+
chunkMWMSFIWN_cjs.__name(readLiveUrl, "readLiveUrl");
|
|
5018
|
+
function originOf(baseUrl) {
|
|
5019
|
+
try {
|
|
5020
|
+
return new URL(baseUrl).origin;
|
|
5021
|
+
} catch {
|
|
5022
|
+
return void 0;
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
chunkMWMSFIWN_cjs.__name(originOf, "originOf");
|
|
5026
|
+
|
|
5027
|
+
// src/changes/live-edge.ts
|
|
5028
|
+
var LIVE_KEEPALIVE_INTERVAL_MS = 3e4;
|
|
5029
|
+
var LIVE_SOCKET_OPEN_TIMEOUT_MS = VISITOR_POLL_INTERVAL_MS;
|
|
5030
|
+
var LIVE_POLLS_BEFORE_SOCKET = 4;
|
|
5031
|
+
async function* subscribeLiveEdge(client, options = {}) {
|
|
5032
|
+
const { signal } = options;
|
|
5033
|
+
if (isAborted(signal)) return;
|
|
5034
|
+
const request = edgeRequest(client, options);
|
|
5035
|
+
const reach = { position: options.since };
|
|
5036
|
+
for (; ; ) {
|
|
5037
|
+
const socket = openSocket(client, edgeUrl(request, reach.position, "socket"));
|
|
5038
|
+
if (socket !== void 0) {
|
|
5039
|
+
const ended = yield* followSocket(socket, reach, options);
|
|
5040
|
+
if (ended === "aborted") return;
|
|
5041
|
+
}
|
|
5042
|
+
const polled = yield* followPolls(client, request, reach, options);
|
|
5043
|
+
if (polled === "aborted") return;
|
|
5044
|
+
}
|
|
5045
|
+
}
|
|
5046
|
+
chunkMWMSFIWN_cjs.__name(subscribeLiveEdge, "subscribeLiveEdge");
|
|
5047
|
+
var SOCKET_CONNECTING = 0;
|
|
5048
|
+
var SOCKET_OPEN = 1;
|
|
5049
|
+
function runtimeWebSocket() {
|
|
5050
|
+
const candidate = globalThis.WebSocket;
|
|
5051
|
+
return typeof candidate === "function" ? candidate : void 0;
|
|
5052
|
+
}
|
|
5053
|
+
chunkMWMSFIWN_cjs.__name(runtimeWebSocket, "runtimeWebSocket");
|
|
5054
|
+
function openSocket(client, url) {
|
|
5055
|
+
const Socket = client.webSocket ?? runtimeWebSocket();
|
|
5056
|
+
if (Socket === void 0) return void 0;
|
|
5057
|
+
try {
|
|
5058
|
+
return new Socket(url);
|
|
5059
|
+
} catch {
|
|
5060
|
+
return void 0;
|
|
5061
|
+
}
|
|
5062
|
+
}
|
|
5063
|
+
chunkMWMSFIWN_cjs.__name(openSocket, "openSocket");
|
|
5064
|
+
async function* followSocket(socket, reach, options) {
|
|
5065
|
+
const { signal } = options;
|
|
5066
|
+
const inbox = socketInbox(socket, signal);
|
|
5067
|
+
let open = false;
|
|
5068
|
+
let caughtUp = false;
|
|
5069
|
+
try {
|
|
5070
|
+
for (; ; ) {
|
|
5071
|
+
const event = await inbox.next();
|
|
5072
|
+
if (event === void 0) return "aborted";
|
|
5073
|
+
switch (event.kind) {
|
|
5074
|
+
case "open": {
|
|
5075
|
+
open = true;
|
|
5076
|
+
inbox.keepAlive();
|
|
5077
|
+
continue;
|
|
5078
|
+
}
|
|
5079
|
+
case "error": {
|
|
5080
|
+
if (!open) return "unopened";
|
|
5081
|
+
continue;
|
|
5082
|
+
}
|
|
5083
|
+
case "close": {
|
|
5084
|
+
if (!open) return "unopened";
|
|
5085
|
+
throw closedBy(event.code, event.reason);
|
|
5086
|
+
}
|
|
5087
|
+
case "silent": {
|
|
5088
|
+
throw new LiveEdgeError(
|
|
5089
|
+
"The live edge\u2019s socket stopped answering its keepalive, so the connection is presumed dead; reconnecting from the last cursor.",
|
|
5090
|
+
{ kind: "lost" },
|
|
5091
|
+
"retry"
|
|
5092
|
+
);
|
|
5093
|
+
}
|
|
5094
|
+
case "late": {
|
|
5095
|
+
if (caughtUp) continue;
|
|
5096
|
+
return "unopened";
|
|
5097
|
+
}
|
|
5098
|
+
case "message": {
|
|
5099
|
+
if (event.data === VISITOR_KEEPALIVE.response) continue;
|
|
5100
|
+
const frame = typeof event.data === "string" ? parseVisitorFrame(event.data) : null;
|
|
5101
|
+
if (frame === null)
|
|
5102
|
+
throw unreadable(`a frame the wire does not declare: ${sample(event.data)}`);
|
|
5103
|
+
switch (frame.type) {
|
|
5104
|
+
case VISITOR_FRAMES.opened: {
|
|
5105
|
+
caughtUp = true;
|
|
5106
|
+
inbox.caughtUp();
|
|
5107
|
+
reach.position = frame.cursor;
|
|
5108
|
+
options.opened?.();
|
|
5109
|
+
options.reached?.(frame.cursor);
|
|
5110
|
+
continue;
|
|
5111
|
+
}
|
|
5112
|
+
case VISITOR_FRAMES.changes: {
|
|
5113
|
+
const prior = reach.position;
|
|
5114
|
+
if (prior === void 0) throw unreadable("changes before the socket had a position");
|
|
5115
|
+
for (const change of changesOf(frame.changes, frame.cursor, prior)) {
|
|
5116
|
+
yield change;
|
|
5117
|
+
if (isAborted(signal)) return "aborted";
|
|
5118
|
+
}
|
|
5119
|
+
reach.position = frame.cursor;
|
|
5120
|
+
if (frame.changes.length === 0) options.reached?.(frame.cursor);
|
|
5121
|
+
continue;
|
|
5122
|
+
}
|
|
5123
|
+
case VISITOR_FRAMES.resync: {
|
|
5124
|
+
await expire(frame.reason, frame.cursor, options);
|
|
5125
|
+
if (isAborted(signal)) return "aborted";
|
|
5126
|
+
reach.position = frame.cursor;
|
|
5127
|
+
options.reached?.(frame.cursor);
|
|
5128
|
+
continue;
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
5132
|
+
}
|
|
5133
|
+
}
|
|
5134
|
+
} finally {
|
|
5135
|
+
inbox.dispose();
|
|
5136
|
+
}
|
|
5137
|
+
}
|
|
5138
|
+
chunkMWMSFIWN_cjs.__name(followSocket, "followSocket");
|
|
5139
|
+
function socketInbox(socket, signal) {
|
|
5140
|
+
const events = [];
|
|
5141
|
+
let wake;
|
|
5142
|
+
let disposed = false;
|
|
5143
|
+
let heard = true;
|
|
5144
|
+
let keepalive;
|
|
5145
|
+
const rouse = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => {
|
|
5146
|
+
const waking = wake;
|
|
5147
|
+
wake = void 0;
|
|
5148
|
+
waking?.();
|
|
5149
|
+
}, "rouse");
|
|
5150
|
+
const push = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name((event) => {
|
|
5151
|
+
if (disposed) return;
|
|
5152
|
+
events.push(event);
|
|
5153
|
+
rouse();
|
|
5154
|
+
}, "push");
|
|
5155
|
+
socket.addEventListener("open", () => push({ kind: "open" }));
|
|
5156
|
+
socket.addEventListener("message", (event) => {
|
|
5157
|
+
heard = true;
|
|
5158
|
+
push({ kind: "message", data: isRecord(event) ? event["data"] : void 0 });
|
|
5159
|
+
});
|
|
5160
|
+
socket.addEventListener("close", (event) => {
|
|
5161
|
+
const code = isRecord(event) ? event["code"] : void 0;
|
|
5162
|
+
const reason = isRecord(event) ? event["reason"] : void 0;
|
|
5163
|
+
push({
|
|
5164
|
+
kind: "close",
|
|
5165
|
+
// A close event always carries both; a socket that somehow raised one without them closed
|
|
5166
|
+
// abnormally, which is what 1006 says.
|
|
5167
|
+
code: typeof code === "number" ? code : 1006,
|
|
5168
|
+
reason: typeof reason === "string" ? reason : ""
|
|
5169
|
+
});
|
|
5170
|
+
});
|
|
5171
|
+
socket.addEventListener("error", () => push({ kind: "error" }));
|
|
5172
|
+
signal?.addEventListener("abort", rouse, { once: true });
|
|
5173
|
+
let connecting = setTimeout(() => {
|
|
5174
|
+
connecting = void 0;
|
|
5175
|
+
push({ kind: "late" });
|
|
5176
|
+
}, LIVE_SOCKET_OPEN_TIMEOUT_MS);
|
|
5177
|
+
return {
|
|
5178
|
+
async next() {
|
|
5179
|
+
for (; ; ) {
|
|
5180
|
+
if (isAborted(signal)) return void 0;
|
|
5181
|
+
const event = events.shift();
|
|
5182
|
+
if (event !== void 0) return event;
|
|
5183
|
+
await new Promise((resolve) => {
|
|
5184
|
+
wake = resolve;
|
|
5185
|
+
});
|
|
5186
|
+
}
|
|
5187
|
+
},
|
|
5188
|
+
keepAlive() {
|
|
5189
|
+
keepalive = setInterval(() => {
|
|
5190
|
+
if (!heard) {
|
|
5191
|
+
push({ kind: "silent" });
|
|
5192
|
+
return;
|
|
5193
|
+
}
|
|
5194
|
+
heard = false;
|
|
5195
|
+
if (socket.readyState === SOCKET_OPEN) socket.send(VISITOR_KEEPALIVE.request);
|
|
5196
|
+
}, LIVE_KEEPALIVE_INTERVAL_MS);
|
|
5197
|
+
},
|
|
5198
|
+
caughtUp() {
|
|
5199
|
+
if (connecting !== void 0) clearTimeout(connecting);
|
|
5200
|
+
connecting = void 0;
|
|
5201
|
+
},
|
|
5202
|
+
dispose() {
|
|
5203
|
+
disposed = true;
|
|
5204
|
+
if (connecting !== void 0) clearTimeout(connecting);
|
|
5205
|
+
if (keepalive !== void 0) clearInterval(keepalive);
|
|
5206
|
+
signal?.removeEventListener("abort", rouse);
|
|
5207
|
+
if (socket.readyState === SOCKET_CONNECTING || socket.readyState === SOCKET_OPEN) {
|
|
5208
|
+
socket.close(1e3);
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
};
|
|
5212
|
+
}
|
|
5213
|
+
chunkMWMSFIWN_cjs.__name(socketInbox, "socketInbox");
|
|
5214
|
+
function closedBy(code, reason) {
|
|
5215
|
+
const retry = closeRetryOf(code);
|
|
5216
|
+
const meaning = hasOwn(CLOSE_MEANING, code) ? CLOSE_MEANING[code] : code < 4e3 ? "the connection dropped" : "a refusal this version of the SDK does not know";
|
|
5217
|
+
const said = `close ${code}${reason === "" ? "" : ` ${reason}`}`;
|
|
5218
|
+
return new LiveEdgeError(
|
|
5219
|
+
`The live edge ended this subscription (${said}): ${meaning}. ${AFTER_A_CLOSE[retry]}`,
|
|
5220
|
+
{ kind: "closed", code, reason },
|
|
5221
|
+
retry
|
|
5222
|
+
);
|
|
5223
|
+
}
|
|
5224
|
+
chunkMWMSFIWN_cjs.__name(closedBy, "closedBy");
|
|
5225
|
+
var AFTER_A_CLOSE = {
|
|
5226
|
+
stop: "The same request would be refused again, so it was not retried.",
|
|
5227
|
+
retry: "Reconnecting from the last cursor after a short back-off.",
|
|
5228
|
+
"back-off": "Retrying after a back-off of at least a minute, without polling, which the same admission refuses."
|
|
5229
|
+
};
|
|
5230
|
+
function closeRetryOf(code) {
|
|
5231
|
+
if (hasOwn(VISITOR_CLOSE_RETRY, code)) return VISITOR_CLOSE_RETRY[code];
|
|
5232
|
+
return code < 4e3 ? "retry" : "stop";
|
|
5233
|
+
}
|
|
5234
|
+
chunkMWMSFIWN_cjs.__name(closeRetryOf, "closeRetryOf");
|
|
5235
|
+
var CLOSE_MEANING = {
|
|
5236
|
+
[VISITOR_CLOSE_CODES.requestInvalid]: "the edge could not read the request \u2014 a malformed cursor or filter",
|
|
5237
|
+
[VISITOR_CLOSE_CODES.keyRefused]: "the key is not a publishable key the edge accepts \u2014 unknown, revoked or expired",
|
|
5238
|
+
[VISITOR_CLOSE_CODES.originRefused]: "this page\u2019s origin is not on the publishable key\u2019s allowed origins",
|
|
5239
|
+
[VISITOR_CLOSE_CODES.datasetRefused]: "`dataset` names no dataset the key reaches",
|
|
5240
|
+
// Also how the edge hands a connection on when the project's live objects move to another
|
|
5241
|
+
// placement (reason `moved`, REL-1514): either way the same request succeeds again shortly.
|
|
5242
|
+
[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",
|
|
5243
|
+
[VISITOR_CLOSE_CODES.allowanceReached]: "the project holds as many live connections as its plan allows",
|
|
5244
|
+
[VISITOR_CLOSE_CODES.addressLimitReached]: "this address holds as many live connections to the project as one address may",
|
|
5245
|
+
[VISITOR_CLOSE_CODES.ceilingReached]: "the project is at its safety ceiling of live connections"
|
|
5246
|
+
};
|
|
5247
|
+
async function* followPolls(client, request, reach, options) {
|
|
5248
|
+
const { signal } = options;
|
|
5249
|
+
for (let poll = 0; poll < LIVE_POLLS_BEFORE_SOCKET; poll += 1) {
|
|
5250
|
+
if (isAborted(signal)) return "aborted";
|
|
5251
|
+
const answer = await pollOnce2(client, request, reach.position, signal);
|
|
5252
|
+
if (answer === void 0) return "aborted";
|
|
5253
|
+
options.opened?.();
|
|
5254
|
+
if (answer.kind === "resync") {
|
|
5255
|
+
await expire(answer.reason, answer.cursor, options);
|
|
5256
|
+
if (isAborted(signal)) return "aborted";
|
|
5257
|
+
reach.position = answer.cursor;
|
|
5258
|
+
options.reached?.(answer.cursor);
|
|
5259
|
+
} else {
|
|
5260
|
+
const prior = reach.position;
|
|
5261
|
+
if (answer.changes.length > 0 && prior === void 0) {
|
|
5262
|
+
throw unreadable("a poll without a cursor answered changes");
|
|
5263
|
+
}
|
|
5264
|
+
for (const change of changesOf(answer.changes, answer.cursor, prior ?? answer.cursor)) {
|
|
5265
|
+
yield change;
|
|
5266
|
+
if (isAborted(signal)) return "aborted";
|
|
5267
|
+
}
|
|
5268
|
+
reach.position = answer.cursor;
|
|
5269
|
+
if (answer.changes.length === 0) options.reached?.(answer.cursor);
|
|
5270
|
+
}
|
|
5271
|
+
await sleep(VISITOR_POLL_INTERVAL_MS, signal);
|
|
5272
|
+
}
|
|
5273
|
+
return isAborted(signal) ? "aborted" : "socket";
|
|
5274
|
+
}
|
|
5275
|
+
chunkMWMSFIWN_cjs.__name(followPolls, "followPolls");
|
|
5276
|
+
async function pollOnce2(client, request, since, signal) {
|
|
5277
|
+
if (isAborted(signal)) return void 0;
|
|
5278
|
+
const url = edgeUrl(request, since, "poll", client.clientId);
|
|
5279
|
+
const context = { url: edgeUrl({ ...request, key: void 0 }, since, "poll", client.clientId) };
|
|
5280
|
+
const controller = new AbortController();
|
|
5281
|
+
let timedOut = false;
|
|
5282
|
+
const timer = setTimeout(() => {
|
|
5283
|
+
timedOut = true;
|
|
5284
|
+
controller.abort();
|
|
5285
|
+
}, client.timeout);
|
|
5286
|
+
const onAbort = /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => controller.abort(), "onAbort");
|
|
5287
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
5288
|
+
try {
|
|
5289
|
+
let response;
|
|
5290
|
+
let text;
|
|
5291
|
+
try {
|
|
5292
|
+
const send = client.fetch ?? globalThis.fetch;
|
|
5293
|
+
response = await send(url, { method: "GET", signal: controller.signal });
|
|
5294
|
+
text = await response.text();
|
|
5295
|
+
} catch (error) {
|
|
5296
|
+
if (isAborted(signal)) return void 0;
|
|
5297
|
+
if (timedOut) {
|
|
5298
|
+
throw new TimeoutError(
|
|
5299
|
+
`The live edge did not answer a poll within ${client.timeout}ms`,
|
|
5300
|
+
client.timeout,
|
|
5301
|
+
void 0,
|
|
5302
|
+
void 0,
|
|
5303
|
+
context
|
|
5304
|
+
);
|
|
5305
|
+
}
|
|
5306
|
+
throw ErrorMapper.mapGenericError(
|
|
5307
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
5308
|
+
context
|
|
5309
|
+
);
|
|
5310
|
+
}
|
|
5311
|
+
const body = parseJson(text);
|
|
5312
|
+
if (!response.ok) throw refusedPoll(response, body, context);
|
|
5313
|
+
const answer = readVisitorPollAnswer(isRecord(body) ? body["data"] : void 0);
|
|
5314
|
+
if (answer === null)
|
|
5315
|
+
throw unreadable(`a poll answer the wire does not declare: ${sample(text)}`);
|
|
5316
|
+
return answer;
|
|
5317
|
+
} finally {
|
|
5318
|
+
clearTimeout(timer);
|
|
5319
|
+
signal?.removeEventListener("abort", onAbort);
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
chunkMWMSFIWN_cjs.__name(pollOnce2, "pollOnce");
|
|
5323
|
+
function refusedPoll(response, body, context) {
|
|
5324
|
+
const headers = {};
|
|
5325
|
+
response.headers.forEach((value, name) => {
|
|
5326
|
+
headers[name] = value;
|
|
5327
|
+
});
|
|
5328
|
+
const mapped = ErrorMapper.mapHttpError(
|
|
5329
|
+
{ status: response.status, statusText: response.statusText, body, headers },
|
|
5330
|
+
{ ...context, method: "GET" }
|
|
5331
|
+
);
|
|
5332
|
+
const refusal = readError(body);
|
|
5333
|
+
if (refusal === void 0 || !hasOwn(VISITOR_POLL_RETRY, refusal.code)) return mapped;
|
|
5334
|
+
const code = refusal.code;
|
|
5335
|
+
const retryAfterMs = parseRetryAfterMs(headerValue(headers, "Retry-After"), Date.now());
|
|
5336
|
+
return new LiveEdgeError(
|
|
5337
|
+
`The live edge refused a poll (${code}): ${refusal.messages[0] ?? mapped.message}`,
|
|
5338
|
+
{ kind: "refused", code },
|
|
5339
|
+
VISITOR_POLL_RETRY[code],
|
|
5340
|
+
{
|
|
5341
|
+
statusCode: response.status,
|
|
5342
|
+
cause: mapped,
|
|
5343
|
+
...retryAfterMs === void 0 ? {} : { retryAfterMs },
|
|
5344
|
+
context
|
|
5345
|
+
}
|
|
5346
|
+
);
|
|
5347
|
+
}
|
|
5348
|
+
chunkMWMSFIWN_cjs.__name(refusedPoll, "refusedPoll");
|
|
5349
|
+
function edgeRequest(client, filter) {
|
|
5350
|
+
const key = client.apiKey;
|
|
5351
|
+
if (key === void 0 || !isPublishableKey(key)) {
|
|
5352
|
+
throw new LiveEdgeError(NEEDS_PUBLISHABLE_KEY, { kind: "needs-publishable-key" }, "stop");
|
|
5353
|
+
}
|
|
5354
|
+
const address = liveEdgeAddress(client);
|
|
5355
|
+
if (!address.ok) throw new LiveEdgeError(address.message, { kind: "needs-live-url" }, "stop");
|
|
5356
|
+
return {
|
|
5357
|
+
base: address.url,
|
|
5358
|
+
key,
|
|
5359
|
+
dataset: client.dataset,
|
|
5360
|
+
types: filter.types,
|
|
5361
|
+
ids: filter.ids
|
|
5362
|
+
};
|
|
5363
|
+
}
|
|
5364
|
+
chunkMWMSFIWN_cjs.__name(edgeRequest, "edgeRequest");
|
|
5365
|
+
function edgeUrl(request, since, transport, clientId) {
|
|
5366
|
+
const url = new URL(request.base.href);
|
|
5367
|
+
url.pathname = `${url.pathname.replace(/\/+$/, "")}${VISITOR_LIVE_PATH}`;
|
|
5368
|
+
if (transport === "socket") url.protocol = url.protocol === "http:" ? "ws:" : "wss:";
|
|
5369
|
+
const query = new URLSearchParams();
|
|
5370
|
+
if (request.key !== void 0) query.set(VISITOR_QUERY.key, request.key);
|
|
5371
|
+
if (request.dataset !== void 0 && request.dataset !== "") {
|
|
5372
|
+
query.set(VISITOR_QUERY.dataset, request.dataset);
|
|
5373
|
+
}
|
|
5374
|
+
if (since !== void 0) query.set(VISITOR_QUERY.since, since);
|
|
5375
|
+
if (request.types !== void 0) query.set(VISITOR_QUERY.types, request.types.join(","));
|
|
5376
|
+
if (request.ids !== void 0) query.set(VISITOR_QUERY.ids, request.ids.join(","));
|
|
5377
|
+
if (transport === "poll" && clientId !== void 0) query.set(VISITOR_QUERY.client, clientId);
|
|
5378
|
+
url.search = query.toString();
|
|
5379
|
+
return url.href;
|
|
5380
|
+
}
|
|
5381
|
+
chunkMWMSFIWN_cjs.__name(edgeUrl, "edgeUrl");
|
|
5382
|
+
function changesOf(changes, cursor, prior) {
|
|
5383
|
+
const last = changes.length - 1;
|
|
5384
|
+
return changes.map((change, index) => ({
|
|
5385
|
+
entryId: change.entryId,
|
|
5386
|
+
contentType: change.contentType,
|
|
5387
|
+
locale: change.locale,
|
|
5388
|
+
kind: change.kind,
|
|
5389
|
+
cursor: index === last ? cursor : prior,
|
|
5390
|
+
fresh: cursor
|
|
5391
|
+
}));
|
|
5392
|
+
}
|
|
5393
|
+
chunkMWMSFIWN_cjs.__name(changesOf, "changesOf");
|
|
5394
|
+
async function expire(reason, cursor, options) {
|
|
5395
|
+
const expired = ChangesExpiredError.resync(reason, cursor);
|
|
5396
|
+
const onExpired = options.onExpired ?? "throw";
|
|
5397
|
+
if (onExpired === "throw") throw expired;
|
|
5398
|
+
if (typeof onExpired === "function") await onExpired(expired);
|
|
5399
|
+
}
|
|
5400
|
+
chunkMWMSFIWN_cjs.__name(expire, "expire");
|
|
5401
|
+
function unreadable(what) {
|
|
5402
|
+
return new LiveEdgeError(
|
|
5403
|
+
`The live edge sent ${what}. This version of the SDK cannot follow it, so it stopped.`,
|
|
5404
|
+
{ kind: "unreadable", what },
|
|
5405
|
+
"stop"
|
|
5406
|
+
);
|
|
5407
|
+
}
|
|
5408
|
+
chunkMWMSFIWN_cjs.__name(unreadable, "unreadable");
|
|
5409
|
+
var NEEDS_PUBLISHABLE_KEY = `Live updates at RelyIO\u2019s edge need a publishable key (\`${PUBLISHABLE_KEY_PREFIX}\u2026\`), and this client holds none. A secret or preview key is never sent to the edge; on a server, follow \`changes()\` with it instead. Nothing was sent.`;
|
|
5410
|
+
function sample(value) {
|
|
5411
|
+
const text = typeof value === "string" ? value : `(${typeof value})`;
|
|
5412
|
+
return text.length > 200 ? `${text.slice(0, 200)}\u2026` : text;
|
|
5413
|
+
}
|
|
5414
|
+
chunkMWMSFIWN_cjs.__name(sample, "sample");
|
|
5415
|
+
function parseJson(text) {
|
|
5416
|
+
try {
|
|
5417
|
+
return JSON.parse(text);
|
|
5418
|
+
} catch {
|
|
5419
|
+
return void 0;
|
|
5420
|
+
}
|
|
5421
|
+
}
|
|
5422
|
+
chunkMWMSFIWN_cjs.__name(parseJson, "parseJson");
|
|
5423
|
+
function isRecord(value) {
|
|
5424
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5425
|
+
}
|
|
5426
|
+
chunkMWMSFIWN_cjs.__name(isRecord, "isRecord");
|
|
5427
|
+
function hasOwn(object, key) {
|
|
5428
|
+
return Object.prototype.hasOwnProperty.call(object, key);
|
|
5429
|
+
}
|
|
5430
|
+
chunkMWMSFIWN_cjs.__name(hasOwn, "hasOwn");
|
|
5431
|
+
|
|
4639
5432
|
// src/config/dev-detection.ts
|
|
4640
5433
|
function sandboxStateOf(resolution) {
|
|
4641
5434
|
return resolution.state === "active" ? resolution.sandbox : resolution;
|
|
@@ -4778,6 +5571,12 @@ function validateConfig(config) {
|
|
|
4778
5571
|
if (config.baseUrl != null && typeof config.baseUrl !== "string") {
|
|
4779
5572
|
throw new Error("Base URL must be a string");
|
|
4780
5573
|
}
|
|
5574
|
+
if (config.liveUrl != null && typeof config.liveUrl !== "string") {
|
|
5575
|
+
throw new Error("liveUrl must be a string");
|
|
5576
|
+
}
|
|
5577
|
+
if (config.webSocket != null && typeof config.webSocket !== "function") {
|
|
5578
|
+
throw new Error("webSocket must be a WebSocket class");
|
|
5579
|
+
}
|
|
4781
5580
|
if (config.timeout != null) assertRequestTimeout(config.timeout);
|
|
4782
5581
|
if (config.retryAttempts != null && !(Number.isInteger(config.retryAttempts) && config.retryAttempts >= 1)) {
|
|
4783
5582
|
throw new Error(
|
|
@@ -4885,6 +5684,8 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
4885
5684
|
* locale, or none after `locale: null` (REL-1453).
|
|
4886
5685
|
*/
|
|
4887
5686
|
chunkMWMSFIWN_cjs.__publicField(this, "currentLocale", /* @__PURE__ */ chunkMWMSFIWN_cjs.__name(() => this.config.locale, "currentLocale"));
|
|
5687
|
+
/** The live edge's poll client id: chosen once, when first needed, and kept for this client's life. */
|
|
5688
|
+
chunkMWMSFIWN_cjs.__publicField(this, "_liveClientId");
|
|
4888
5689
|
const { schema, ...clientConfig } = config;
|
|
4889
5690
|
this._schema = schema;
|
|
4890
5691
|
const resolved = resolveConfig(clientConfig);
|
|
@@ -5093,13 +5894,15 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
5093
5894
|
* Lazy — nothing is requested until the first `next()`. It runs until
|
|
5094
5895
|
* `signal` aborts, which ends the `for await` cleanly rather than throwing.
|
|
5095
5896
|
* A change names what changed; refetch it through the ordinary read path
|
|
5096
|
-
* (`INV-SS-CHANGE-IS-IDS`)
|
|
5897
|
+
* (`INV-SS-CHANGE-IS-IDS`), naming its `fresh` so no cache answers with the
|
|
5898
|
+
* body from before it (`FeedChange`).
|
|
5097
5899
|
*
|
|
5098
5900
|
* @example
|
|
5099
5901
|
* ```typescript
|
|
5100
5902
|
* const controller = new AbortController()
|
|
5101
5903
|
* for await (const change of relyio.changes({ since: cursor, types: ['post'], signal: controller.signal })) {
|
|
5102
|
-
* // { entryId, contentType, locale, kind, cursor }
|
|
5904
|
+
* // { entryId, contentType, locale, kind, cursor, fresh }
|
|
5905
|
+
* await relyio.content(change.contentType).findById(change.entryId).fresh(change.fresh).execute()
|
|
5103
5906
|
* }
|
|
5104
5907
|
* ```
|
|
5105
5908
|
*
|
|
@@ -5107,13 +5910,65 @@ var _TypedRelyIOClient = class _TypedRelyIOClient {
|
|
|
5107
5910
|
* ```typescript
|
|
5108
5911
|
* for await (const change of relyio.changes({
|
|
5109
5912
|
* since: cursor,
|
|
5110
|
-
* onExpired: async
|
|
5913
|
+
* onExpired: async expired => refetchEverything(expired.fresh),
|
|
5111
5914
|
* })) { … }
|
|
5112
5915
|
* ```
|
|
5113
5916
|
*/
|
|
5114
5917
|
changes(options = {}) {
|
|
5115
5918
|
return pollChanges(this.httpClient, options);
|
|
5116
5919
|
}
|
|
5920
|
+
/**
|
|
5921
|
+
* Follow the dataset's **published** changes at RelyIO's live edge, with a publishable key
|
|
5922
|
+
* (`rly_pub_…`): each change as ids, in order — the transport a browser follows changes with.
|
|
5923
|
+
*
|
|
5924
|
+
* A WebSocket to the edge, from `since` or the dataset's current position; where a socket cannot
|
|
5925
|
+
* open — the runtime has none, the network refuses it, or it has not opened and been told its
|
|
5926
|
+
* position within `LIVE_SOCKET_OPEN_TIMEOUT_MS` — it polls the edge instead, about every fifteen
|
|
5927
|
+
* seconds, from the same cursor. The edge is `liveUrl`, or derived from the default `baseUrl`
|
|
5928
|
+
* (see `RelyIOConfig.liveUrl`).
|
|
5929
|
+
*
|
|
5930
|
+
* Without `since` it starts at the dataset's current position, which it hands `reached` before
|
|
5931
|
+
* anything after it: read what you show after that call, and a publish your read did not see is
|
|
5932
|
+
* one this subscription announces (see `LiveChangesOptions.since`).
|
|
5933
|
+
*
|
|
5934
|
+
* One subscription ends only when `signal` aborts, which ends the `for await` cleanly; every other
|
|
5935
|
+
* end — a socket a deploy dropped, a refusal, a refused poll — is thrown as a `LiveEdgeError`
|
|
5936
|
+
* that says whether to stop, retry or back off. Hand it to `followChanges()`, the one loop that
|
|
5937
|
+
* reconnects from the last cursor with jittered back-off and honours those answers:
|
|
5938
|
+
*
|
|
5939
|
+
* @example
|
|
5940
|
+
* ```typescript
|
|
5941
|
+
* const relyio = createClient({ apiKey: 'rly_pub_…' })
|
|
5942
|
+
* const controller = new AbortController()
|
|
5943
|
+
* await followChanges(from => relyio.liveChanges({ ...from, types: ['post'] }), {
|
|
5944
|
+
* signal: controller.signal,
|
|
5945
|
+
* // `fresh` names a position no cache holds a body for from before the change.
|
|
5946
|
+
* onChange: change =>
|
|
5947
|
+
* relyio.content(change.contentType).findById(change.entryId).fresh(change.fresh).execute(),
|
|
5948
|
+
* onResync: resync => refetchEverything(resync.cause === 'expired' ? resync.expired.fresh : undefined),
|
|
5949
|
+
* })
|
|
5950
|
+
* ```
|
|
5951
|
+
*
|
|
5952
|
+
* A client without a publishable key sends nothing: a secret or preview key is never put in the
|
|
5953
|
+
* edge's URL. On a server, follow `changes()` with it instead.
|
|
5954
|
+
*/
|
|
5955
|
+
liveChanges(options = {}) {
|
|
5956
|
+
const { apiKey, dataset, baseUrl, liveUrl, fetch: fetch2, webSocket, timeout } = this.config;
|
|
5957
|
+
this._liveClientId ?? (this._liveClientId = randomClientId());
|
|
5958
|
+
return subscribeLiveEdge(
|
|
5959
|
+
{
|
|
5960
|
+
apiKey,
|
|
5961
|
+
dataset,
|
|
5962
|
+
baseUrl,
|
|
5963
|
+
liveUrl,
|
|
5964
|
+
fetch: fetch2,
|
|
5965
|
+
webSocket,
|
|
5966
|
+
timeout,
|
|
5967
|
+
clientId: this._liveClientId
|
|
5968
|
+
},
|
|
5969
|
+
options
|
|
5970
|
+
);
|
|
5971
|
+
}
|
|
5117
5972
|
/**
|
|
5118
5973
|
* The dataset's current position in the changes feed, as a cursor to start
|
|
5119
5974
|
* `changes({ since })` or `followChanges(…, { since })` from. One
|
|
@@ -5406,6 +6261,19 @@ function createClient(config) {
|
|
|
5406
6261
|
return new TypedRelyIOClient(config);
|
|
5407
6262
|
}
|
|
5408
6263
|
chunkMWMSFIWN_cjs.__name(createClient, "createClient");
|
|
6264
|
+
function randomClientId() {
|
|
6265
|
+
const bytes = new Uint8Array(16);
|
|
6266
|
+
const random = globalThis.crypto;
|
|
6267
|
+
if (typeof random?.getRandomValues === "function") {
|
|
6268
|
+
random.getRandomValues.call(random, bytes);
|
|
6269
|
+
} else {
|
|
6270
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
6271
|
+
bytes[index] = Math.floor(Math.random() * 256);
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
6275
|
+
}
|
|
6276
|
+
chunkMWMSFIWN_cjs.__name(randomClientId, "randomClientId");
|
|
5409
6277
|
|
|
5410
6278
|
exports.AdhocQueryBuilder = AdhocQueryBuilder;
|
|
5411
6279
|
exports.AdhocQueryClient = AdhocQueryClient;
|
|
@@ -5428,9 +6296,13 @@ exports.FileValidationError = FileValidationError;
|
|
|
5428
6296
|
exports.HttpClient = HttpClient;
|
|
5429
6297
|
exports.InvalidApiKeyError = InvalidApiKeyError;
|
|
5430
6298
|
exports.InvalidPayloadError = InvalidPayloadError;
|
|
6299
|
+
exports.LIVE_KEEPALIVE_INTERVAL_MS = LIVE_KEEPALIVE_INTERVAL_MS;
|
|
6300
|
+
exports.LIVE_SOCKET_OPEN_TIMEOUT_MS = LIVE_SOCKET_OPEN_TIMEOUT_MS;
|
|
6301
|
+
exports.LiveEdgeError = LiveEdgeError;
|
|
5431
6302
|
exports.MethodNotAllowedError = MethodNotAllowedError;
|
|
5432
6303
|
exports.MissingApiKeyError = MissingApiKeyError;
|
|
5433
6304
|
exports.NetworkError = NetworkError;
|
|
6305
|
+
exports.PUBLISHABLE_KEY_PREFIX = PUBLISHABLE_KEY_PREFIX;
|
|
5434
6306
|
exports.PayloadTooLargeError = PayloadTooLargeError;
|
|
5435
6307
|
exports.PlanFeatureUnavailableError = PlanFeatureUnavailableError;
|
|
5436
6308
|
exports.RateLimitError = RateLimitError;
|
|
@@ -5451,15 +6323,17 @@ exports.TransactionRolledBackError = TransactionRolledBackError;
|
|
|
5451
6323
|
exports.TypedRelyIOClient = TypedRelyIOClient;
|
|
5452
6324
|
exports.UnknownContractError = UnknownContractError;
|
|
5453
6325
|
exports.UsageQuotaExceededError = UsageQuotaExceededError;
|
|
6326
|
+
exports.VISITOR_ADMISSION_RETRY_AFTER_SECONDS = VISITOR_ADMISSION_RETRY_AFTER_SECONDS;
|
|
5454
6327
|
exports.ValidationError = ValidationError;
|
|
5455
6328
|
exports.createClient = createClient;
|
|
5456
6329
|
exports.entityTagOf = entityTagOf;
|
|
5457
6330
|
exports.isAborted = isAborted;
|
|
5458
6331
|
exports.isAssetEntry = isAssetEntry;
|
|
6332
|
+
exports.isPublishableKey = isPublishableKey;
|
|
5459
6333
|
exports.isResourceNotFound = isResourceNotFound;
|
|
5460
6334
|
exports.matchRoute = matchRoute;
|
|
5461
6335
|
exports.serviceInstructedDelayMs = serviceInstructedDelayMs;
|
|
5462
6336
|
exports.sleep = sleep;
|
|
5463
6337
|
exports.validateFile = validateFile;
|
|
5464
|
-
//# sourceMappingURL=chunk-
|
|
5465
|
-
//# sourceMappingURL=chunk-
|
|
6338
|
+
//# sourceMappingURL=chunk-SPFRDXAF.cjs.map
|
|
6339
|
+
//# sourceMappingURL=chunk-SPFRDXAF.cjs.map
|