@pollar/core 0.8.0 → 0.8.1
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/README.md +118 -6
- package/dist/adapters/react-native-appstate.d.mts +10 -0
- package/dist/adapters/react-native-appstate.d.ts +10 -0
- package/dist/adapters/react-native-appstate.js +38 -0
- package/dist/adapters/react-native-appstate.js.map +1 -0
- package/dist/adapters/react-native-appstate.mjs +36 -0
- package/dist/adapters/react-native-appstate.mjs.map +1 -0
- package/dist/index.d.mts +194 -39
- package/dist/index.d.ts +194 -39
- package/dist/index.js +171 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +171 -56
- package/dist/index.mjs.map +1 -1
- package/dist/index.rn.d.mts +2 -1
- package/dist/index.rn.d.ts +2 -1
- package/dist/index.rn.js +171 -56
- package/dist/index.rn.js.map +1 -1
- package/dist/index.rn.mjs +171 -56
- package/dist/index.rn.mjs.map +1 -1
- package/dist/types-84G_htcn.d.mts +38 -0
- package/dist/types-84G_htcn.d.ts +38 -0
- package/package.json +11 -1
package/dist/index.js
CHANGED
|
@@ -981,6 +981,26 @@ async function pollRampTransaction(api, txId, { intervalMs = 5e3, timeoutMs = 6e
|
|
|
981
981
|
throw new Error("Ramp transaction polling timed out");
|
|
982
982
|
}
|
|
983
983
|
|
|
984
|
+
// src/lib/random-uuid.ts
|
|
985
|
+
function randomUUID() {
|
|
986
|
+
const c = globalThis.crypto;
|
|
987
|
+
if (c && typeof c.randomUUID === "function") {
|
|
988
|
+
return c.randomUUID();
|
|
989
|
+
}
|
|
990
|
+
if (c && typeof c.getRandomValues === "function") {
|
|
991
|
+
const bytes = new Uint8Array(16);
|
|
992
|
+
c.getRandomValues(bytes);
|
|
993
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
994
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
995
|
+
const hex = [];
|
|
996
|
+
for (let i = 0; i < 16; i++) hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
997
|
+
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
|
|
998
|
+
}
|
|
999
|
+
throw new Error(
|
|
1000
|
+
"[PollarClient] No secure random source available (crypto.randomUUID / crypto.getRandomValues). DPoP requires a secure context (HTTPS) or, in React Native, the `react-native-get-random-values` polyfill."
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
984
1004
|
// src/dpop.ts
|
|
985
1005
|
async function buildProof(args, keyManager) {
|
|
986
1006
|
const jwk = await keyManager.getPublicJwk();
|
|
@@ -990,7 +1010,7 @@ async function buildProof(args, keyManager) {
|
|
|
990
1010
|
jwk
|
|
991
1011
|
};
|
|
992
1012
|
const payload = {
|
|
993
|
-
jti:
|
|
1013
|
+
jti: randomUUID(),
|
|
994
1014
|
htm: args.htm.toUpperCase(),
|
|
995
1015
|
htu: normalizeHtu(args.htu),
|
|
996
1016
|
iat: Math.floor(Date.now() / 1e3)
|
|
@@ -1024,24 +1044,6 @@ function normalizeHtu(rawUrl) {
|
|
|
1024
1044
|
const portPart = port ? `:${port}` : "";
|
|
1025
1045
|
return `${scheme}//${host}${portPart}${url.pathname}`;
|
|
1026
1046
|
}
|
|
1027
|
-
function generateJti() {
|
|
1028
|
-
const c = globalThis.crypto;
|
|
1029
|
-
if (c && typeof c.randomUUID === "function") {
|
|
1030
|
-
return c.randomUUID();
|
|
1031
|
-
}
|
|
1032
|
-
if (c && typeof c.getRandomValues === "function") {
|
|
1033
|
-
const bytes = new Uint8Array(16);
|
|
1034
|
-
c.getRandomValues(bytes);
|
|
1035
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
1036
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
1037
|
-
const hex = [];
|
|
1038
|
-
for (let i = 0; i < 16; i++) hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
1039
|
-
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
|
|
1040
|
-
}
|
|
1041
|
-
throw new Error(
|
|
1042
|
-
"[PollarClient:dpop] No secure random source available (crypto.randomUUID / crypto.getRandomValues). DPoP requires a secure context (HTTPS) or, in React Native, the `react-native-get-random-values` polyfill."
|
|
1043
|
-
);
|
|
1044
|
-
}
|
|
1045
1047
|
|
|
1046
1048
|
// src/storage/web.ts
|
|
1047
1049
|
var LOG_PREFIX = "[PollarClient:storage]";
|
|
@@ -1184,6 +1186,8 @@ function defaultVisibilityProvider() {
|
|
|
1184
1186
|
// src/types.ts
|
|
1185
1187
|
var AUTH_ERROR_CODES = {
|
|
1186
1188
|
SESSION_CREATE_FAILED: "SESSION_CREATE_FAILED",
|
|
1189
|
+
SESSION_EXPIRED: "SESSION_EXPIRED",
|
|
1190
|
+
SESSION_INVALID: "SESSION_INVALID",
|
|
1187
1191
|
EMAIL_SEND_FAILED: "EMAIL_SEND_FAILED",
|
|
1188
1192
|
EMAIL_VERIFY_FAILED: "EMAIL_VERIFY_FAILED",
|
|
1189
1193
|
EMAIL_CODE_EXPIRED: "EMAIL_CODE_EXPIRED",
|
|
@@ -1497,7 +1501,32 @@ async function readWalletType(storage, apiKeyHash) {
|
|
|
1497
1501
|
return storage.get(walletTypeStorageKey(apiKeyHash));
|
|
1498
1502
|
}
|
|
1499
1503
|
|
|
1504
|
+
// src/lib/abort.ts
|
|
1505
|
+
function abortError() {
|
|
1506
|
+
if (typeof DOMException !== "undefined") {
|
|
1507
|
+
return new DOMException("Aborted", "AbortError");
|
|
1508
|
+
}
|
|
1509
|
+
const err = new Error("Aborted");
|
|
1510
|
+
err.name = "AbortError";
|
|
1511
|
+
return err;
|
|
1512
|
+
}
|
|
1513
|
+
function throwIfAborted(signal) {
|
|
1514
|
+
if (signal?.aborted) throw abortError();
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1500
1517
|
// src/client/stream.ts
|
|
1518
|
+
var SessionStatusError = class extends Error {
|
|
1519
|
+
constructor(code) {
|
|
1520
|
+
super(`[PollarClient] Session status terminal: ${code}`);
|
|
1521
|
+
this.code = code;
|
|
1522
|
+
this.name = "SessionStatusError";
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
function terminalStatusCode(parsed) {
|
|
1526
|
+
const err = parsed?.error;
|
|
1527
|
+
if (err === "INVALID_CLIENT_SESSION_ID" || err === "EXPIRED_CLIENT_ID") return err;
|
|
1528
|
+
return null;
|
|
1529
|
+
}
|
|
1501
1530
|
function abortableDelay(ms, signal) {
|
|
1502
1531
|
return new Promise((resolve, reject) => {
|
|
1503
1532
|
const t = setTimeout(resolve, ms);
|
|
@@ -1505,7 +1534,7 @@ function abortableDelay(ms, signal) {
|
|
|
1505
1534
|
"abort",
|
|
1506
1535
|
() => {
|
|
1507
1536
|
clearTimeout(t);
|
|
1508
|
-
reject(
|
|
1537
|
+
reject(abortError());
|
|
1509
1538
|
},
|
|
1510
1539
|
{ once: true }
|
|
1511
1540
|
);
|
|
@@ -1520,7 +1549,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1520
1549
|
else await new Promise((r) => setTimeout(r, ms));
|
|
1521
1550
|
};
|
|
1522
1551
|
while (true) {
|
|
1523
|
-
|
|
1552
|
+
throwIfAborted(signal);
|
|
1524
1553
|
let data, error;
|
|
1525
1554
|
try {
|
|
1526
1555
|
({ data, error } = await api.GET("/auth/session/status/{clientSessionId}", {
|
|
@@ -1543,7 +1572,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1543
1572
|
let sawAnyChunk = false;
|
|
1544
1573
|
try {
|
|
1545
1574
|
while (true) {
|
|
1546
|
-
|
|
1575
|
+
throwIfAborted(signal);
|
|
1547
1576
|
const { done, value } = await reader.read();
|
|
1548
1577
|
if (done) {
|
|
1549
1578
|
streamDone = true;
|
|
@@ -1554,17 +1583,22 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1554
1583
|
for (const message of chunk.split("\n\n").filter(Boolean)) {
|
|
1555
1584
|
const dataLine = message.split("\n").find((l) => l.startsWith("data:"));
|
|
1556
1585
|
if (!dataLine) continue;
|
|
1586
|
+
let parsed;
|
|
1557
1587
|
try {
|
|
1558
|
-
|
|
1559
|
-
if (check(parsed)) {
|
|
1560
|
-
return parsed;
|
|
1561
|
-
}
|
|
1588
|
+
parsed = JSON.parse(dataLine.slice("data:".length).trim());
|
|
1562
1589
|
} catch {
|
|
1590
|
+
continue;
|
|
1591
|
+
}
|
|
1592
|
+
const terminal = terminalStatusCode(parsed);
|
|
1593
|
+
if (terminal) throw new SessionStatusError(terminal);
|
|
1594
|
+
if (check(parsed)) {
|
|
1595
|
+
return parsed;
|
|
1563
1596
|
}
|
|
1564
1597
|
}
|
|
1565
1598
|
}
|
|
1566
1599
|
} catch (e) {
|
|
1567
1600
|
if (e instanceof Error && e.name === "AbortError") throw e;
|
|
1601
|
+
if (e instanceof SessionStatusError) throw e;
|
|
1568
1602
|
console.warn(e);
|
|
1569
1603
|
} finally {
|
|
1570
1604
|
reader.releaseLock();
|
|
@@ -1575,12 +1609,72 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1575
1609
|
if (delay) await sleep(delay);
|
|
1576
1610
|
}
|
|
1577
1611
|
}
|
|
1612
|
+
async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500, signal) {
|
|
1613
|
+
const url = `${baseUrl}/auth/session/status/${encodeURIComponent(clientSessionId)}/poll`;
|
|
1614
|
+
let backoff = intervalMs;
|
|
1615
|
+
const sleep = async (ms) => {
|
|
1616
|
+
if (ms <= 0) return;
|
|
1617
|
+
if (signal) await abortableDelay(ms, signal);
|
|
1618
|
+
else await new Promise((r) => setTimeout(r, ms));
|
|
1619
|
+
};
|
|
1620
|
+
while (true) {
|
|
1621
|
+
throwIfAborted(signal);
|
|
1622
|
+
let envelope = null;
|
|
1623
|
+
let httpStatus = 0;
|
|
1624
|
+
try {
|
|
1625
|
+
const response = await fetch(url, { headers: { accept: "application/json" }, signal: signal ?? null });
|
|
1626
|
+
httpStatus = response.status;
|
|
1627
|
+
envelope = await response.json().catch(() => null);
|
|
1628
|
+
} catch (e) {
|
|
1629
|
+
if (e instanceof Error && e.name === "AbortError") throw e;
|
|
1630
|
+
console.warn(e);
|
|
1631
|
+
}
|
|
1632
|
+
if (httpStatus === 404 || envelope?.code === "INVALID_CLIENT_SESSION_ID") {
|
|
1633
|
+
throw new SessionStatusError("INVALID_CLIENT_SESSION_ID");
|
|
1634
|
+
}
|
|
1635
|
+
if (httpStatus === 410 || envelope?.code === "EXPIRED_CLIENT_ID") {
|
|
1636
|
+
throw new SessionStatusError("EXPIRED_CLIENT_ID");
|
|
1637
|
+
}
|
|
1638
|
+
if (envelope?.success && envelope.content && check(envelope.content)) {
|
|
1639
|
+
return envelope.content;
|
|
1640
|
+
}
|
|
1641
|
+
if (envelope) backoff = intervalMs;
|
|
1642
|
+
else backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
|
|
1643
|
+
await sleep(backoff);
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
function waitForSessionReady(args) {
|
|
1647
|
+
const { api, baseUrl, clientSessionId, check, useStreaming, retryDelayMs, signal } = args;
|
|
1648
|
+
return useStreaming ? streamUntilFound(api, clientSessionId, check, retryDelayMs ?? 200, signal) : pollUntilFound(baseUrl, clientSessionId, check, retryDelayMs ?? 500, signal);
|
|
1649
|
+
}
|
|
1578
1650
|
|
|
1579
1651
|
// src/client/auth/authenticate.ts
|
|
1580
1652
|
async function authenticate(clientSessionId, deps, expectedWallet) {
|
|
1581
|
-
const { api, signal, setAuthState, storeSession, clearSession } = deps;
|
|
1653
|
+
const { api, basePath, useStreaming, signal, setAuthState, storeSession, clearSession } = deps;
|
|
1582
1654
|
setAuthState({ step: "authenticating" });
|
|
1583
|
-
|
|
1655
|
+
try {
|
|
1656
|
+
await waitForSessionReady({
|
|
1657
|
+
api,
|
|
1658
|
+
baseUrl: basePath,
|
|
1659
|
+
clientSessionId,
|
|
1660
|
+
check: (data2) => data2?.status === "READY",
|
|
1661
|
+
useStreaming,
|
|
1662
|
+
signal
|
|
1663
|
+
});
|
|
1664
|
+
} catch (err) {
|
|
1665
|
+
if (err instanceof SessionStatusError) {
|
|
1666
|
+
const expired = err.code === "EXPIRED_CLIENT_ID";
|
|
1667
|
+
setAuthState({
|
|
1668
|
+
step: "error",
|
|
1669
|
+
previousStep: "authenticating",
|
|
1670
|
+
message: expired ? "Login session expired \u2014 please try again" : "Login session is no longer valid \u2014 please try again",
|
|
1671
|
+
errorCode: expired ? AUTH_ERROR_CODES.SESSION_EXPIRED : AUTH_ERROR_CODES.SESSION_INVALID
|
|
1672
|
+
});
|
|
1673
|
+
await clearSession();
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
throw err;
|
|
1677
|
+
}
|
|
1584
1678
|
const dpopJwk = await deps.getPublicJwk();
|
|
1585
1679
|
const { data } = await api.POST("/auth/login", {
|
|
1586
1680
|
body: {
|
|
@@ -1704,26 +1798,36 @@ function severOpener(popup) {
|
|
|
1704
1798
|
} catch {
|
|
1705
1799
|
}
|
|
1706
1800
|
}
|
|
1707
|
-
async
|
|
1708
|
-
const
|
|
1709
|
-
const popup = window.open("about:blank", "_blank");
|
|
1801
|
+
var defaultWebOAuthOpener = async ({ getUrl }) => {
|
|
1802
|
+
const popup = typeof window !== "undefined" ? window.open("about:blank", "_blank") : null;
|
|
1710
1803
|
severOpener(popup);
|
|
1711
|
-
const
|
|
1712
|
-
if (!
|
|
1804
|
+
const url = await getUrl();
|
|
1805
|
+
if (!url) {
|
|
1713
1806
|
popup?.close();
|
|
1714
1807
|
return;
|
|
1715
1808
|
}
|
|
1716
|
-
setAuthState({ step: "opening_oauth", provider });
|
|
1717
|
-
const url = new URL(`${basePath}/auth/${provider}`);
|
|
1718
|
-
url.searchParams.set("api_key", apiKey);
|
|
1719
|
-
url.searchParams.set("client_session_id", clientSessionId);
|
|
1720
|
-
url.searchParams.set("redirect_uri", window.location.origin);
|
|
1721
1809
|
if (popup) {
|
|
1722
|
-
popup.location.href = url
|
|
1810
|
+
popup.location.href = url;
|
|
1723
1811
|
severOpener(popup);
|
|
1724
|
-
} else {
|
|
1725
|
-
window.open(url
|
|
1812
|
+
} else if (typeof window !== "undefined") {
|
|
1813
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
1726
1814
|
}
|
|
1815
|
+
};
|
|
1816
|
+
async function loginOAuth(provider, deps) {
|
|
1817
|
+
const { setAuthState, basePath, apiKey, openAuthUrl, redirectUri, signal } = deps;
|
|
1818
|
+
let clientSessionId = null;
|
|
1819
|
+
const getUrl = async () => {
|
|
1820
|
+
clientSessionId = await createAuthSession(deps);
|
|
1821
|
+
if (!clientSessionId) return null;
|
|
1822
|
+
setAuthState({ step: "opening_oauth", provider });
|
|
1823
|
+
const url = new URL(`${basePath}/auth/${provider}`);
|
|
1824
|
+
url.searchParams.set("api_key", apiKey);
|
|
1825
|
+
url.searchParams.set("client_session_id", clientSessionId);
|
|
1826
|
+
url.searchParams.set("redirect_uri", redirectUri);
|
|
1827
|
+
return url.toString();
|
|
1828
|
+
};
|
|
1829
|
+
await openAuthUrl({ provider, getUrl, redirectUri, signal });
|
|
1830
|
+
if (!clientSessionId) return;
|
|
1727
1831
|
await authenticate(clientSessionId, deps);
|
|
1728
1832
|
}
|
|
1729
1833
|
|
|
@@ -1733,10 +1837,10 @@ function withSignal(promise, signal) {
|
|
|
1733
1837
|
promise,
|
|
1734
1838
|
new Promise((_, reject) => {
|
|
1735
1839
|
if (signal.aborted) {
|
|
1736
|
-
reject(
|
|
1840
|
+
reject(abortError());
|
|
1737
1841
|
return;
|
|
1738
1842
|
}
|
|
1739
|
-
signal.addEventListener("abort", () => reject(
|
|
1843
|
+
signal.addEventListener("abort", () => reject(abortError()), { once: true });
|
|
1740
1844
|
})
|
|
1741
1845
|
]);
|
|
1742
1846
|
}
|
|
@@ -1784,6 +1888,8 @@ async function loginWallet(type, deps) {
|
|
|
1784
1888
|
|
|
1785
1889
|
// src/client/client.ts
|
|
1786
1890
|
var isBrowser = typeof window !== "undefined" && typeof localStorage !== "undefined";
|
|
1891
|
+
var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
|
|
1892
|
+
var isClientRuntime = isBrowser || isReactNative;
|
|
1787
1893
|
var REFRESH_SKEW_SECONDS = 60;
|
|
1788
1894
|
function warnServerSide(method) {
|
|
1789
1895
|
console.warn(
|
|
@@ -1839,7 +1945,7 @@ var PollarClient = class {
|
|
|
1839
1945
|
this._walletAdapter = null;
|
|
1840
1946
|
this._loginController = null;
|
|
1841
1947
|
this.apiKey = config.apiKey;
|
|
1842
|
-
this.id =
|
|
1948
|
+
this.id = randomUUID();
|
|
1843
1949
|
this.basePath = `${config.baseUrl || "https://sdk.api.pollar.xyz"}/v1`;
|
|
1844
1950
|
this._storage = config.storage ?? defaultStorage({
|
|
1845
1951
|
onDegrade: (reason, error) => {
|
|
@@ -1853,10 +1959,12 @@ var PollarClient = class {
|
|
|
1853
1959
|
this._deviceLabel = config.deviceLabel;
|
|
1854
1960
|
this._visibilityProvider = config.visibilityProvider ?? defaultVisibilityProvider();
|
|
1855
1961
|
this._maxIdleMs = config.maxIdleMs;
|
|
1962
|
+
this._openAuthUrl = config.openAuthUrl ?? defaultWebOAuthOpener;
|
|
1963
|
+
this._oauthRedirectUri = config.oauthRedirectUri ?? (isBrowser ? window.location.origin : "");
|
|
1856
1964
|
this._api = createApiClient(this.basePath);
|
|
1857
1965
|
this._wireMiddlewares();
|
|
1858
1966
|
this._networkState = { step: "connected", network: config.stellarNetwork ?? "testnet" };
|
|
1859
|
-
if (!
|
|
1967
|
+
if (!isClientRuntime) {
|
|
1860
1968
|
warnServerSide("constructor");
|
|
1861
1969
|
this._initialized = Promise.resolve();
|
|
1862
1970
|
return;
|
|
@@ -1882,7 +1990,7 @@ var PollarClient = class {
|
|
|
1882
1990
|
// ─── Lifecycle ────────────────────────────────────────────────────────────
|
|
1883
1991
|
async _initialize() {
|
|
1884
1992
|
this._apiKeyHash = await hashApiKey(this.apiKey);
|
|
1885
|
-
if (
|
|
1993
|
+
if (isBrowser) {
|
|
1886
1994
|
const sessionKey = sessionStorageKey(this._apiKeyHash);
|
|
1887
1995
|
const handler = (e) => {
|
|
1888
1996
|
if (e.key === sessionKey) {
|
|
@@ -1904,7 +2012,7 @@ var PollarClient = class {
|
|
|
1904
2012
|
}
|
|
1905
2013
|
/** Detach the cross-tab storage listener and abort any in-flight login. */
|
|
1906
2014
|
destroy() {
|
|
1907
|
-
if (this._storageEventHandler &&
|
|
2015
|
+
if (this._storageEventHandler && isBrowser) {
|
|
1908
2016
|
window.removeEventListener("storage", this._storageEventHandler);
|
|
1909
2017
|
this._storageEventHandler = null;
|
|
1910
2018
|
}
|
|
@@ -2187,7 +2295,7 @@ var PollarClient = class {
|
|
|
2187
2295
|
}
|
|
2188
2296
|
// ─── Login (unified entry point) ─────────────────────────────────────────
|
|
2189
2297
|
login(options) {
|
|
2190
|
-
if (!
|
|
2298
|
+
if (!isClientRuntime) {
|
|
2191
2299
|
warnServerSide("login");
|
|
2192
2300
|
return;
|
|
2193
2301
|
}
|
|
@@ -2198,7 +2306,9 @@ var PollarClient = class {
|
|
|
2198
2306
|
loginOAuth(options.provider, {
|
|
2199
2307
|
...deps,
|
|
2200
2308
|
basePath: this.basePath,
|
|
2201
|
-
apiKey: this.apiKey
|
|
2309
|
+
apiKey: this.apiKey,
|
|
2310
|
+
openAuthUrl: this._openAuthUrl,
|
|
2311
|
+
redirectUri: this._oauthRedirectUri
|
|
2202
2312
|
}).catch((err) => this._handleFlowError(err));
|
|
2203
2313
|
} else if (options.provider === "email") {
|
|
2204
2314
|
const { email } = options;
|
|
@@ -2214,7 +2324,7 @@ var PollarClient = class {
|
|
|
2214
2324
|
}
|
|
2215
2325
|
// ─── Email OTP flow (3 steps) ─────────────────────────────────────────────
|
|
2216
2326
|
beginEmailLogin() {
|
|
2217
|
-
if (!
|
|
2327
|
+
if (!isClientRuntime) {
|
|
2218
2328
|
warnServerSide("beginEmailLogin");
|
|
2219
2329
|
return;
|
|
2220
2330
|
}
|
|
@@ -2222,7 +2332,7 @@ var PollarClient = class {
|
|
|
2222
2332
|
initEmailSession(this._flowDeps(controller.signal)).catch((err) => this._handleFlowError(err));
|
|
2223
2333
|
}
|
|
2224
2334
|
sendEmailCode(email) {
|
|
2225
|
-
if (!
|
|
2335
|
+
if (!isClientRuntime) {
|
|
2226
2336
|
warnServerSide("sendEmailCode");
|
|
2227
2337
|
return;
|
|
2228
2338
|
}
|
|
@@ -2234,7 +2344,7 @@ var PollarClient = class {
|
|
|
2234
2344
|
sendEmailCode(email, clientSessionId, this._flowDeps(signal)).catch((err) => this._handleFlowError(err));
|
|
2235
2345
|
}
|
|
2236
2346
|
verifyEmailCode(code) {
|
|
2237
|
-
if (!
|
|
2347
|
+
if (!isClientRuntime) {
|
|
2238
2348
|
warnServerSide("verifyEmailCode");
|
|
2239
2349
|
return;
|
|
2240
2350
|
}
|
|
@@ -2252,7 +2362,7 @@ var PollarClient = class {
|
|
|
2252
2362
|
}
|
|
2253
2363
|
// ─── Wallet flow (single call) ────────────────────────────────────────────
|
|
2254
2364
|
loginWallet(type) {
|
|
2255
|
-
if (!
|
|
2365
|
+
if (!isClientRuntime) {
|
|
2256
2366
|
warnServerSide("loginWallet");
|
|
2257
2367
|
return;
|
|
2258
2368
|
}
|
|
@@ -2278,7 +2388,7 @@ var PollarClient = class {
|
|
|
2278
2388
|
* across all devices.
|
|
2279
2389
|
*/
|
|
2280
2390
|
async logout(options = {}) {
|
|
2281
|
-
if (!
|
|
2391
|
+
if (!isClientRuntime) {
|
|
2282
2392
|
warnServerSide("logout");
|
|
2283
2393
|
return;
|
|
2284
2394
|
}
|
|
@@ -2308,7 +2418,7 @@ var PollarClient = class {
|
|
|
2308
2418
|
* `current` flag identifies which entry corresponds to this client.
|
|
2309
2419
|
*/
|
|
2310
2420
|
async listSessions() {
|
|
2311
|
-
if (!
|
|
2421
|
+
if (!isClientRuntime) {
|
|
2312
2422
|
warnServerSide("listSessions");
|
|
2313
2423
|
return [];
|
|
2314
2424
|
}
|
|
@@ -2327,7 +2437,7 @@ var PollarClient = class {
|
|
|
2327
2437
|
* does NOT clear local state — call `logout()` for that case.
|
|
2328
2438
|
*/
|
|
2329
2439
|
async revokeSession(familyId) {
|
|
2330
|
-
if (!
|
|
2440
|
+
if (!isClientRuntime) {
|
|
2331
2441
|
warnServerSide("revokeSession");
|
|
2332
2442
|
return;
|
|
2333
2443
|
}
|
|
@@ -2825,6 +2935,11 @@ var PollarClient = class {
|
|
|
2825
2935
|
_flowDeps(signal) {
|
|
2826
2936
|
return {
|
|
2827
2937
|
api: this._api,
|
|
2938
|
+
basePath: this.basePath,
|
|
2939
|
+
// SSE status streaming works on web; React Native's `fetch` has no
|
|
2940
|
+
// readable `response.body`, so those clients poll the non-streaming
|
|
2941
|
+
// status endpoint instead. `isBrowser` is false in RN and SSR alike.
|
|
2942
|
+
useStreaming: isBrowser,
|
|
2828
2943
|
signal,
|
|
2829
2944
|
setAuthState: this._setAuthState.bind(this),
|
|
2830
2945
|
storeSession: this._storeSession.bind(this),
|