@rebasepro/client 0.11.1-canary.gfd39654 → 0.12.1-canary.g181d0fe
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/dist/api-keys.d.ts +10 -38
- package/dist/auth.d.ts +1 -0
- package/dist/functions.d.ts +2 -8
- package/dist/index.d.ts +3 -0
- package/dist/index.es.js +97 -9
- package/dist/index.es.js.map +1 -1
- package/dist/realtime-channel.d.ts +8 -8
- package/dist/transport.d.ts +35 -1
- package/dist/websocket.d.ts +18 -0
- package/package.json +8 -8
- package/src/anonymous-client-guard.test.ts +190 -0
- package/src/api-keys.ts +21 -44
- package/src/auth.ts +5 -0
- package/src/collection.test.ts +1 -1
- package/src/collection.ts +14 -0
- package/src/functions.ts +11 -9
- package/src/index.ts +11 -1
- package/src/offline-idb-store.test.ts +58 -4
- package/src/offline-integration.test.ts +5 -0
- package/src/offline.ts +9 -1
- package/src/realtime-channel.ts +8 -8
- package/src/transport.ts +80 -1
- package/src/websocket.ts +51 -1
package/dist/api-keys.d.ts
CHANGED
|
@@ -1,42 +1,14 @@
|
|
|
1
1
|
import type { Transport } from "./transport";
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
permissions: ApiKeyPermission[];
|
|
13
|
-
admin: boolean;
|
|
14
|
-
rate_limit: number | null;
|
|
15
|
-
created_by: string;
|
|
16
|
-
created_at: string;
|
|
17
|
-
updated_at: string;
|
|
18
|
-
last_used_at: string | null;
|
|
19
|
-
expires_at: string | null;
|
|
20
|
-
revoked_at: string | null;
|
|
21
|
-
}
|
|
22
|
-
/** An API key including the full secret (returned only on creation). */
|
|
23
|
-
export interface ApiKeyWithSecret extends ApiKeyMasked {
|
|
24
|
-
key: string;
|
|
25
|
-
}
|
|
26
|
-
/** Payload for creating a new API key. */
|
|
27
|
-
export interface CreateApiKeyRequest {
|
|
28
|
-
name: string;
|
|
29
|
-
permissions: ApiKeyPermission[];
|
|
30
|
-
rate_limit?: number | null;
|
|
31
|
-
expires_at?: string | null;
|
|
32
|
-
}
|
|
33
|
-
/** Payload for updating an existing API key. */
|
|
34
|
-
export interface UpdateApiKeyRequest {
|
|
35
|
-
name?: string;
|
|
36
|
-
permissions?: ApiKeyPermission[];
|
|
37
|
-
rate_limit?: number | null;
|
|
38
|
-
expires_at?: string | null;
|
|
39
|
-
}
|
|
2
|
+
/**
|
|
3
|
+
* These were re-declared here, under a comment saying they lived in the server
|
|
4
|
+
* package rather than in `@rebasepro/types`. That stopped being true, and the
|
|
5
|
+
* copy drifted: it never gained `admin`, the flag that grants a key the `admin`
|
|
6
|
+
* role — admin routes plus the RLS `default_admin` policies — so the SDK could
|
|
7
|
+
* describe every kind of key except a privileged one, and
|
|
8
|
+
* `createKey({ …, admin: true })` was an excess-property error.
|
|
9
|
+
*/
|
|
10
|
+
export type { ApiKeyPermission, ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, UpdateApiKeyRequest } from "@rebasepro/types";
|
|
11
|
+
import type { ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, UpdateApiKeyRequest } from "@rebasepro/types";
|
|
40
12
|
/** Options for the `createApiKeys` factory. */
|
|
41
13
|
export interface CreateApiKeysOptions {
|
|
42
14
|
apiKeysPath?: string;
|
package/dist/auth.d.ts
CHANGED
|
@@ -180,6 +180,7 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
|
|
|
180
180
|
getAuthConfig: () => Promise<AuthConfig>;
|
|
181
181
|
getSession: () => RebaseSession | null;
|
|
182
182
|
onAuthStateChange: (callback: (event: AuthChangeEvent, session: RebaseSession | null) => void) => () => boolean;
|
|
183
|
+
canRestoreSession: () => boolean;
|
|
183
184
|
isInitialized: () => Promise<void>;
|
|
184
185
|
};
|
|
185
186
|
export interface CookieStorageOptions {
|
package/dist/functions.d.ts
CHANGED
|
@@ -27,14 +27,8 @@ export interface FunctionsClient {
|
|
|
27
27
|
*/
|
|
28
28
|
invoke<T = unknown>(name: string, payload?: unknown, options?: FunctionInvokeOptions): Promise<T>;
|
|
29
29
|
}
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
33
|
-
/** Sub-path appended after the function name, e.g. `"status/123"`. */
|
|
34
|
-
path?: string;
|
|
35
|
-
/** Extra headers merged into the request (auth is still injected automatically). */
|
|
36
|
-
headers?: Record<string, string>;
|
|
37
|
-
}
|
|
30
|
+
export type { FunctionInvokeOptions } from "@rebasepro/types";
|
|
31
|
+
import type { FunctionInvokeOptions } from "@rebasepro/types";
|
|
38
32
|
/**
|
|
39
33
|
* Create a `FunctionsClient` backed by the given transport.
|
|
40
34
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export { RebaseClientError } from "./errors";
|
|
|
15
15
|
export type { RebaseClientConfig, FindParams, FindResponse } from "./transport";
|
|
16
16
|
export type { CollectionClient } from "./collection";
|
|
17
17
|
export type { FindResult, SDKCollectionClient, SDKQueryBuilderInterface, PaginationMeta } from "@rebasepro/types";
|
|
18
|
+
export type { IterateParams, FindAllParams, PageWalkOptions, CursorSpec } from "@rebasepro/types";
|
|
19
|
+
export { RebasePaginationError } from "@rebasepro/common";
|
|
20
|
+
export type { PaginationErrorCode } from "@rebasepro/common";
|
|
18
21
|
export { QueryBuilder, or, and, cond } from "@rebasepro/common";
|
|
19
22
|
export { createCookieStorage, createMemoryStorage } from "./auth";
|
|
20
23
|
export type { AuthConfig, AuthStorage, CookieStorageOptions, CreateAuthOptions } from "./auth";
|
package/dist/index.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_STORAGE_SOURCE_KEY, EntityReference, EntityRelation, GeoPoint, PUBLIC_STORAGE_PREFIX, RebaseApiError, RebaseApiError as RebaseApiError$1, RebaseClientError, Vector, isPublicStoragePath, toCanonicalOp } from "@rebasepro/types";
|
|
2
|
-
import { COMPOSITE_ID_SEPARATOR, QueryBuilder, and, buildCompositeId, cond, or, serializeFilter, serializeLogicalCondition, serializeOrderBy } from "@rebasepro/common";
|
|
2
|
+
import { COMPOSITE_ID_SEPARATOR, QueryBuilder, RebasePaginationError, and, buildCompositeId, collectAllPages, cond, or, paginateFind, serializeFilter, serializeLogicalCondition, serializeOrderBy } from "@rebasepro/common";
|
|
3
3
|
import { toSnakeCase } from "@rebasepro/utils";
|
|
4
4
|
//#region src/reviver.ts
|
|
5
5
|
function rebaseReviver(_key, value) {
|
|
@@ -30,6 +30,25 @@ function rebaseReviver(_key, value) {
|
|
|
30
30
|
}
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region src/transport.ts
|
|
33
|
+
/**
|
|
34
|
+
* True when there is no browser to have signed a user in — a Node script, a
|
|
35
|
+
* cron job, an edge worker.
|
|
36
|
+
*
|
|
37
|
+
* Anonymous is an ordinary, correct state in a browser: before sign-in, on a
|
|
38
|
+
* marketing page, for public reads. Warning there would be noise that teaches
|
|
39
|
+
* people to ignore warnings, so the guard is off entirely. This uses the same
|
|
40
|
+
* `typeof window` test as {@link resolveBaseUrl}, and additionally treats a
|
|
41
|
+
* defined `document` as a browser so an SSR shim or test harness that installs
|
|
42
|
+
* only one of the two is still excluded.
|
|
43
|
+
*/
|
|
44
|
+
function isServerLikeEnvironment() {
|
|
45
|
+
return typeof window === "undefined" && typeof document === "undefined";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Emitted once per client. Kept as a constant so the wording is testable and
|
|
49
|
+
* greppable — this is the string a user will paste into a search.
|
|
50
|
+
*/
|
|
51
|
+
var ANONYMOUS_SERVER_CLIENT_WARNING = "[rebase] This client was created outside a browser with no credential — no `token`, no auth token getter, and no cookie auth flow — so every request runs as an anonymous caller. Row-level security will return only publicly readable rows, which is usually nothing and occasionally the wrong thing. Inside a cron or function handler, use the `client` you were handed instead of building a new one: its data plane is already admin-scoped. In a standalone script or job, pass the service key as `token`. If you really do want anonymous access, pass `anonymous: true` to silence this.";
|
|
33
52
|
function buildQueryString(params) {
|
|
34
53
|
if (!params) return "";
|
|
35
54
|
const parts = [];
|
|
@@ -76,12 +95,31 @@ function resolveBaseUrl(configured) {
|
|
|
76
95
|
if (typeof window !== "undefined" && window.location?.origin) return window.location.origin;
|
|
77
96
|
return "";
|
|
78
97
|
}
|
|
79
|
-
function createTransport(config) {
|
|
98
|
+
function createTransport(config, environment) {
|
|
80
99
|
const fetchFn = config.fetch || globalThis.fetch;
|
|
81
100
|
const apiPath = config.apiPath || "/api";
|
|
82
101
|
let token = config.token;
|
|
83
102
|
let tokenGetter;
|
|
84
103
|
let onUnauthorizedHandler = config.onUnauthorized;
|
|
104
|
+
/** Once per client, never per request — log spam is its own bug. */
|
|
105
|
+
let anonymousWarningIssued = false;
|
|
106
|
+
/**
|
|
107
|
+
* Warn a server-side caller that it built a client that can only ever be
|
|
108
|
+
* anonymous. Deliberately checked at the *first request* rather than at
|
|
109
|
+
* construction: `setToken()` / `setAuthTokenGetter()` and a server-side
|
|
110
|
+
* `auth.signIn…()` (which calls `transport.setToken`) all land after the
|
|
111
|
+
* constructor, and warning at construction would fire on every one of them.
|
|
112
|
+
*/
|
|
113
|
+
function warnIfAnonymousServerClient(activeToken) {
|
|
114
|
+
if (anonymousWarningIssued) return;
|
|
115
|
+
if (activeToken) return;
|
|
116
|
+
if (tokenGetter) return;
|
|
117
|
+
if (config.anonymous) return;
|
|
118
|
+
if (environment?.credentialOutOfBand) return;
|
|
119
|
+
if (!isServerLikeEnvironment()) return;
|
|
120
|
+
anonymousWarningIssued = true;
|
|
121
|
+
console.warn(ANONYMOUS_SERVER_CLIENT_WARNING);
|
|
122
|
+
}
|
|
85
123
|
function getHeaders(activeToken, init) {
|
|
86
124
|
return {
|
|
87
125
|
"Content-Type": "application/json",
|
|
@@ -96,6 +134,7 @@ function createTransport(config) {
|
|
|
96
134
|
const fetched = await tokenGetter();
|
|
97
135
|
if (fetched !== null && fetched !== void 0) activeToken = fetched;
|
|
98
136
|
} catch (e) {}
|
|
137
|
+
warnIfAnonymousServerClient(activeToken);
|
|
99
138
|
const headers = getHeaders(activeToken, init);
|
|
100
139
|
if (init?.body instanceof FormData) delete headers["Content-Type"];
|
|
101
140
|
const res = await fetchFn(url, {
|
|
@@ -868,6 +907,7 @@ function createAuth(transport, options) {
|
|
|
868
907
|
getAuthConfig,
|
|
869
908
|
getSession,
|
|
870
909
|
onAuthStateChange,
|
|
910
|
+
canRestoreSession: () => persistSession || authFlowMode === "cookie",
|
|
871
911
|
isInitialized: () => isInitialized
|
|
872
912
|
};
|
|
873
913
|
}
|
|
@@ -1184,6 +1224,12 @@ function createCollectionClient(transport, slug, ws) {
|
|
|
1184
1224
|
meta: raw.meta
|
|
1185
1225
|
};
|
|
1186
1226
|
},
|
|
1227
|
+
iterate(params) {
|
|
1228
|
+
return paginateFind((p) => client.find(p), params, slug);
|
|
1229
|
+
},
|
|
1230
|
+
findAll(params) {
|
|
1231
|
+
return collectAllPages((p) => client.find(p), params, slug);
|
|
1232
|
+
},
|
|
1187
1233
|
async findById(id) {
|
|
1188
1234
|
try {
|
|
1189
1235
|
const raw = await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, { method: "GET" });
|
|
@@ -1373,7 +1419,8 @@ function createCollectionClient(transport, slug, ws) {
|
|
|
1373
1419
|
function createFunctionsClient(transport) {
|
|
1374
1420
|
return { async invoke(name, payload, options) {
|
|
1375
1421
|
const method = options?.method ?? "POST";
|
|
1376
|
-
const
|
|
1422
|
+
const rawPath = options?.path;
|
|
1423
|
+
const subPath = rawPath ? /^[?#]/.test(rawPath) ? rawPath : `/${rawPath.replace(/^\//, "")}` : "";
|
|
1377
1424
|
const routePath = `/functions/${encodeURIComponent(name)}${subPath}`;
|
|
1378
1425
|
const init = { method };
|
|
1379
1426
|
if (payload !== void 0 && method !== "GET") init.body = JSON.stringify(payload);
|
|
@@ -1587,7 +1634,7 @@ function extractMessageError(message) {
|
|
|
1587
1634
|
* Fire-and-forget (the server sends no response envelope), and exempt from the
|
|
1588
1635
|
* client-side auth gate — a public channel is usable without an account.
|
|
1589
1636
|
*/
|
|
1590
|
-
var CHANNEL_MESSAGE_TYPES = new Set([
|
|
1637
|
+
var CHANNEL_MESSAGE_TYPES = /* @__PURE__ */ new Set([
|
|
1591
1638
|
"join_channel",
|
|
1592
1639
|
"leave_channel",
|
|
1593
1640
|
"broadcast",
|
|
@@ -1616,6 +1663,17 @@ var RebaseWebSocketClient = class {
|
|
|
1616
1663
|
/** Set by `close()`. Blocks any later operation from silently redialling. */
|
|
1617
1664
|
closedByCaller = false;
|
|
1618
1665
|
/**
|
|
1666
|
+
* Set when the backoff budget ran out, cleared by anything that earns a
|
|
1667
|
+
* fresh one.
|
|
1668
|
+
*
|
|
1669
|
+
* Unlike {@link closedByCaller} this is not final — nobody *asked* for the
|
|
1670
|
+
* socket to stay down. Five attempts with exponential backoff is about a
|
|
1671
|
+
* minute, which a laptop lid, a wifi handover or a backend rollout all
|
|
1672
|
+
* exceed routinely; treating that as permanent meant realtime silently
|
|
1673
|
+
* stopped for the rest of the page's life, with a reload the only cure.
|
|
1674
|
+
*/
|
|
1675
|
+
gaveUp = false;
|
|
1676
|
+
/**
|
|
1619
1677
|
* Whether a socket exists at all (open or still opening).
|
|
1620
1678
|
*
|
|
1621
1679
|
* Lets callers distinguish "authenticate the live socket" from "there is
|
|
@@ -1688,10 +1746,30 @@ var RebaseWebSocketClient = class {
|
|
|
1688
1746
|
}
|
|
1689
1747
|
return;
|
|
1690
1748
|
}
|
|
1749
|
+
this.installOnlineListener();
|
|
1691
1750
|
if (this.ws || this.reconnectTimeout) return;
|
|
1751
|
+
if (this.gaveUp) {
|
|
1752
|
+
this.gaveUp = false;
|
|
1753
|
+
this.reconnectAttempts = 0;
|
|
1754
|
+
}
|
|
1692
1755
|
this.initWebSocket();
|
|
1693
1756
|
}
|
|
1694
1757
|
/**
|
|
1758
|
+
* The browser says the network is back — the usual reason the budget ran
|
|
1759
|
+
* out in the first place. Registered lazily so a Node client, or a page
|
|
1760
|
+
* that never subscribes, adds no listener.
|
|
1761
|
+
*/
|
|
1762
|
+
installOnlineListener() {
|
|
1763
|
+
if (this.onlineListener || typeof window === "undefined" || typeof window.addEventListener !== "function") return;
|
|
1764
|
+
this.onlineListener = () => {
|
|
1765
|
+
if (this.closedByCaller || !this.gaveUp) return;
|
|
1766
|
+
console.debug("Network is back — retrying the realtime connection");
|
|
1767
|
+
this.ensureConnected();
|
|
1768
|
+
};
|
|
1769
|
+
window.addEventListener("online", this.onlineListener);
|
|
1770
|
+
}
|
|
1771
|
+
onlineListener = null;
|
|
1772
|
+
/**
|
|
1695
1773
|
* Authenticate the WebSocket connection
|
|
1696
1774
|
*/
|
|
1697
1775
|
async authenticate(token) {
|
|
@@ -1749,6 +1827,10 @@ var RebaseWebSocketClient = class {
|
|
|
1749
1827
|
*/
|
|
1750
1828
|
disconnect(permanent = false) {
|
|
1751
1829
|
if (permanent) this.closedByCaller = true;
|
|
1830
|
+
if (permanent && this.onlineListener && typeof window !== "undefined") {
|
|
1831
|
+
window.removeEventListener("online", this.onlineListener);
|
|
1832
|
+
this.onlineListener = null;
|
|
1833
|
+
}
|
|
1752
1834
|
this.isAuthenticated = false;
|
|
1753
1835
|
this.authPromise = null;
|
|
1754
1836
|
if (this.reconnectTimeout) {
|
|
@@ -1773,7 +1855,8 @@ var RebaseWebSocketClient = class {
|
|
|
1773
1855
|
this.ws = null;
|
|
1774
1856
|
}
|
|
1775
1857
|
try {
|
|
1776
|
-
|
|
1858
|
+
const socket = new this.WebSocketConstructor(this.websocketUrl);
|
|
1859
|
+
this.ws = socket;
|
|
1777
1860
|
this.ws.onopen = async () => {
|
|
1778
1861
|
console.debug("Connected to PostgreSQL backend");
|
|
1779
1862
|
const wasReconnect = this.reconnectAttempts > 0;
|
|
@@ -1803,6 +1886,7 @@ var RebaseWebSocketClient = class {
|
|
|
1803
1886
|
};
|
|
1804
1887
|
this.ws.onclose = () => {
|
|
1805
1888
|
console.debug("Disconnected from PostgreSQL backend");
|
|
1889
|
+
if (this.ws === socket) this.ws = null;
|
|
1806
1890
|
this.isConnected = false;
|
|
1807
1891
|
this.isAuthenticated = false;
|
|
1808
1892
|
this.authPromise = null;
|
|
@@ -1838,6 +1922,7 @@ var RebaseWebSocketClient = class {
|
|
|
1838
1922
|
attemptReconnect() {
|
|
1839
1923
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
1840
1924
|
console.error("Max reconnection attempts reached");
|
|
1925
|
+
this.gaveUp = true;
|
|
1841
1926
|
this.failAllPendingSubscriptions(new RebaseApiError$1("Connection lost", { code: "CONNECTION_LOST" }));
|
|
1842
1927
|
return;
|
|
1843
1928
|
}
|
|
@@ -2380,7 +2465,7 @@ var RebaseWebSocketClient = class {
|
|
|
2380
2465
|
if (this.deepEqual(normCached, normIncoming)) return cachedRow;
|
|
2381
2466
|
else {
|
|
2382
2467
|
const mismatches = {};
|
|
2383
|
-
const allKeys = new Set([...Object.keys(normCached), ...Object.keys(normIncoming)]);
|
|
2468
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(normCached), ...Object.keys(normIncoming)]);
|
|
2384
2469
|
for (const key of allKeys) if (!this.deepEqual(normCached[key], normIncoming[key])) mismatches[key] = {
|
|
2385
2470
|
cached: normCached[key],
|
|
2386
2471
|
incoming: normIncoming[key]
|
|
@@ -3183,7 +3268,7 @@ function isNetworkError(error) {
|
|
|
3183
3268
|
* bug the same payload will hit again than a blip, and retrying it forever
|
|
3184
3269
|
* jams every write behind it.
|
|
3185
3270
|
*/
|
|
3186
|
-
var RETRYABLE_STATUSES = new Set([
|
|
3271
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([
|
|
3187
3272
|
408,
|
|
3188
3273
|
425,
|
|
3189
3274
|
429,
|
|
@@ -4008,6 +4093,8 @@ var OfflineManager = class {
|
|
|
4008
4093
|
meta: answer.meta
|
|
4009
4094
|
};
|
|
4010
4095
|
},
|
|
4096
|
+
iterate: (params) => paginateFind((p) => wrapped.find(p), params, slug),
|
|
4097
|
+
findAll: (params) => collectAllPages((p) => wrapped.find(p), params, slug),
|
|
4011
4098
|
findById: async (id) => {
|
|
4012
4099
|
await this.ensureCollection(slug);
|
|
4013
4100
|
if (this.connectivity.shouldAttempt()) try {
|
|
@@ -5077,7 +5164,7 @@ function deriveWebSocketUrl(baseUrl) {
|
|
|
5077
5164
|
return baseUrl.replace(/^https?:\/\//i, (match) => match.toLowerCase() === "https://" ? "wss://" : "ws://").replace(/\/$/, "");
|
|
5078
5165
|
}
|
|
5079
5166
|
function createRebaseClient(options) {
|
|
5080
|
-
const transport = createTransport(options);
|
|
5167
|
+
const transport = createTransport(options, { credentialOutOfBand: options.auth?.authFlowMode === "cookie" });
|
|
5081
5168
|
const auth = createAuth(transport, options.auth);
|
|
5082
5169
|
const admin = createAdmin(transport, options.admin);
|
|
5083
5170
|
const cron = createCron(transport, options.cron);
|
|
@@ -5248,6 +5335,7 @@ channel: (name, options) => {
|
|
|
5248
5335
|
setOnUnauthorized: transport.setOnUnauthorized,
|
|
5249
5336
|
resolveToken: transport.resolveToken,
|
|
5250
5337
|
baseUrl: transport.baseUrl,
|
|
5338
|
+
apiPath: transport.apiPath,
|
|
5251
5339
|
collection,
|
|
5252
5340
|
call: async (endpoint, payload) => {
|
|
5253
5341
|
const prefix = endpoint.startsWith("/") ? "" : "/";
|
|
@@ -5262,6 +5350,6 @@ channel: (name, options) => {
|
|
|
5262
5350
|
};
|
|
5263
5351
|
}
|
|
5264
5352
|
//#endregion
|
|
5265
|
-
export { MemoryOfflineStore, QueryBuilder, RebaseApiError, RebaseClientError, RebaseRealtimeChannel, RebaseWebSocketClient, and, cond, createBackups, createCookieStorage, createMemoryStorage, createRebaseClient, isOfflineError, or };
|
|
5353
|
+
export { MemoryOfflineStore, QueryBuilder, RebaseApiError, RebaseClientError, RebasePaginationError, RebaseRealtimeChannel, RebaseWebSocketClient, and, cond, createBackups, createCookieStorage, createMemoryStorage, createRebaseClient, isOfflineError, or };
|
|
5266
5354
|
|
|
5267
5355
|
//# sourceMappingURL=index.es.js.map
|