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