@pollar/core 0.8.0 → 0.8.2
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 +125 -5
- package/dist/adapters/expo-secure-store.d.mts +11 -1
- package/dist/adapters/expo-secure-store.d.ts +11 -1
- package/dist/adapters/expo-secure-store.js +11 -3
- package/dist/adapters/expo-secure-store.js.map +1 -1
- package/dist/adapters/expo-secure-store.mjs +11 -4
- package/dist/adapters/expo-secure-store.mjs.map +1 -1
- 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 +174 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -60
- 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 +177 -64
- package/dist/index.rn.js.map +1 -1
- package/dist/index.rn.mjs +174 -61
- 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 +12 -1
package/dist/index.rn.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { p256 } from '@noble/curves/
|
|
1
|
+
import { p256 } from '@noble/curves/nist';
|
|
2
|
+
import { sha256 as sha256$1 } from '@noble/hashes/sha2';
|
|
2
3
|
|
|
3
4
|
var __create = Object.create;
|
|
4
5
|
var __defProp = Object.defineProperty;
|
|
@@ -184,11 +185,8 @@ function defaultKeyManager(storage, apiKey) {
|
|
|
184
185
|
}
|
|
185
186
|
return _factory(storage, apiKey);
|
|
186
187
|
}
|
|
187
|
-
|
|
188
|
-
// src/lib/sha256.ts
|
|
189
188
|
async function sha256(data) {
|
|
190
|
-
|
|
191
|
-
return new Uint8Array(buf);
|
|
189
|
+
return sha256$1(data);
|
|
192
190
|
}
|
|
193
191
|
|
|
194
192
|
// src/lib/api-key-hash.ts
|
|
@@ -1106,6 +1104,26 @@ async function pollRampTransaction(api, txId, { intervalMs = 5e3, timeoutMs = 6e
|
|
|
1106
1104
|
throw new Error("Ramp transaction polling timed out");
|
|
1107
1105
|
}
|
|
1108
1106
|
|
|
1107
|
+
// src/lib/random-uuid.ts
|
|
1108
|
+
function randomUUID() {
|
|
1109
|
+
const c = globalThis.crypto;
|
|
1110
|
+
if (c && typeof c.randomUUID === "function") {
|
|
1111
|
+
return c.randomUUID();
|
|
1112
|
+
}
|
|
1113
|
+
if (c && typeof c.getRandomValues === "function") {
|
|
1114
|
+
const bytes = new Uint8Array(16);
|
|
1115
|
+
c.getRandomValues(bytes);
|
|
1116
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
1117
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
1118
|
+
const hex = [];
|
|
1119
|
+
for (let i = 0; i < 16; i++) hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
1120
|
+
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("")}`;
|
|
1121
|
+
}
|
|
1122
|
+
throw new Error(
|
|
1123
|
+
"[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."
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1109
1127
|
// src/dpop.ts
|
|
1110
1128
|
async function buildProof(args, keyManager) {
|
|
1111
1129
|
const jwk = await keyManager.getPublicJwk();
|
|
@@ -1115,7 +1133,7 @@ async function buildProof(args, keyManager) {
|
|
|
1115
1133
|
jwk
|
|
1116
1134
|
};
|
|
1117
1135
|
const payload = {
|
|
1118
|
-
jti:
|
|
1136
|
+
jti: randomUUID(),
|
|
1119
1137
|
htm: args.htm.toUpperCase(),
|
|
1120
1138
|
htu: normalizeHtu(args.htu),
|
|
1121
1139
|
iat: Math.floor(Date.now() / 1e3)
|
|
@@ -1149,24 +1167,6 @@ function normalizeHtu(rawUrl) {
|
|
|
1149
1167
|
const portPart = port ? `:${port}` : "";
|
|
1150
1168
|
return `${scheme}//${host}${portPart}${url.pathname}`;
|
|
1151
1169
|
}
|
|
1152
|
-
function generateJti() {
|
|
1153
|
-
const c = globalThis.crypto;
|
|
1154
|
-
if (c && typeof c.randomUUID === "function") {
|
|
1155
|
-
return c.randomUUID();
|
|
1156
|
-
}
|
|
1157
|
-
if (c && typeof c.getRandomValues === "function") {
|
|
1158
|
-
const bytes = new Uint8Array(16);
|
|
1159
|
-
c.getRandomValues(bytes);
|
|
1160
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
1161
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
1162
|
-
const hex = [];
|
|
1163
|
-
for (let i = 0; i < 16; i++) hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
1164
|
-
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("")}`;
|
|
1165
|
-
}
|
|
1166
|
-
throw new Error(
|
|
1167
|
-
"[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."
|
|
1168
|
-
);
|
|
1169
|
-
}
|
|
1170
1170
|
|
|
1171
1171
|
// src/storage/web.ts
|
|
1172
1172
|
var LOG_PREFIX = "[PollarClient:storage]";
|
|
@@ -1309,6 +1309,8 @@ function defaultVisibilityProvider() {
|
|
|
1309
1309
|
// src/types.ts
|
|
1310
1310
|
var AUTH_ERROR_CODES = {
|
|
1311
1311
|
SESSION_CREATE_FAILED: "SESSION_CREATE_FAILED",
|
|
1312
|
+
SESSION_EXPIRED: "SESSION_EXPIRED",
|
|
1313
|
+
SESSION_INVALID: "SESSION_INVALID",
|
|
1312
1314
|
EMAIL_SEND_FAILED: "EMAIL_SEND_FAILED",
|
|
1313
1315
|
EMAIL_VERIFY_FAILED: "EMAIL_VERIFY_FAILED",
|
|
1314
1316
|
EMAIL_CODE_EXPIRED: "EMAIL_CODE_EXPIRED",
|
|
@@ -1622,7 +1624,32 @@ async function readWalletType(storage, apiKeyHash) {
|
|
|
1622
1624
|
return storage.get(walletTypeStorageKey(apiKeyHash));
|
|
1623
1625
|
}
|
|
1624
1626
|
|
|
1627
|
+
// src/lib/abort.ts
|
|
1628
|
+
function abortError() {
|
|
1629
|
+
if (typeof DOMException !== "undefined") {
|
|
1630
|
+
return new DOMException("Aborted", "AbortError");
|
|
1631
|
+
}
|
|
1632
|
+
const err = new Error("Aborted");
|
|
1633
|
+
err.name = "AbortError";
|
|
1634
|
+
return err;
|
|
1635
|
+
}
|
|
1636
|
+
function throwIfAborted(signal) {
|
|
1637
|
+
if (signal?.aborted) throw abortError();
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1625
1640
|
// src/client/stream.ts
|
|
1641
|
+
var SessionStatusError = class extends Error {
|
|
1642
|
+
constructor(code) {
|
|
1643
|
+
super(`[PollarClient] Session status terminal: ${code}`);
|
|
1644
|
+
this.code = code;
|
|
1645
|
+
this.name = "SessionStatusError";
|
|
1646
|
+
}
|
|
1647
|
+
};
|
|
1648
|
+
function terminalStatusCode(parsed) {
|
|
1649
|
+
const err = parsed?.error;
|
|
1650
|
+
if (err === "INVALID_CLIENT_SESSION_ID" || err === "EXPIRED_CLIENT_ID") return err;
|
|
1651
|
+
return null;
|
|
1652
|
+
}
|
|
1626
1653
|
function abortableDelay(ms, signal) {
|
|
1627
1654
|
return new Promise((resolve, reject) => {
|
|
1628
1655
|
const t = setTimeout(resolve, ms);
|
|
@@ -1630,7 +1657,7 @@ function abortableDelay(ms, signal) {
|
|
|
1630
1657
|
"abort",
|
|
1631
1658
|
() => {
|
|
1632
1659
|
clearTimeout(t);
|
|
1633
|
-
reject(
|
|
1660
|
+
reject(abortError());
|
|
1634
1661
|
},
|
|
1635
1662
|
{ once: true }
|
|
1636
1663
|
);
|
|
@@ -1645,7 +1672,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1645
1672
|
else await new Promise((r) => setTimeout(r, ms));
|
|
1646
1673
|
};
|
|
1647
1674
|
while (true) {
|
|
1648
|
-
|
|
1675
|
+
throwIfAborted(signal);
|
|
1649
1676
|
let data, error;
|
|
1650
1677
|
try {
|
|
1651
1678
|
({ data, error } = await api.GET("/auth/session/status/{clientSessionId}", {
|
|
@@ -1668,7 +1695,7 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1668
1695
|
let sawAnyChunk = false;
|
|
1669
1696
|
try {
|
|
1670
1697
|
while (true) {
|
|
1671
|
-
|
|
1698
|
+
throwIfAborted(signal);
|
|
1672
1699
|
const { done, value } = await reader.read();
|
|
1673
1700
|
if (done) {
|
|
1674
1701
|
streamDone = true;
|
|
@@ -1679,17 +1706,22 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1679
1706
|
for (const message of chunk.split("\n\n").filter(Boolean)) {
|
|
1680
1707
|
const dataLine = message.split("\n").find((l) => l.startsWith("data:"));
|
|
1681
1708
|
if (!dataLine) continue;
|
|
1709
|
+
let parsed;
|
|
1682
1710
|
try {
|
|
1683
|
-
|
|
1684
|
-
if (check(parsed)) {
|
|
1685
|
-
return parsed;
|
|
1686
|
-
}
|
|
1711
|
+
parsed = JSON.parse(dataLine.slice("data:".length).trim());
|
|
1687
1712
|
} catch {
|
|
1713
|
+
continue;
|
|
1714
|
+
}
|
|
1715
|
+
const terminal = terminalStatusCode(parsed);
|
|
1716
|
+
if (terminal) throw new SessionStatusError(terminal);
|
|
1717
|
+
if (check(parsed)) {
|
|
1718
|
+
return parsed;
|
|
1688
1719
|
}
|
|
1689
1720
|
}
|
|
1690
1721
|
}
|
|
1691
1722
|
} catch (e) {
|
|
1692
1723
|
if (e instanceof Error && e.name === "AbortError") throw e;
|
|
1724
|
+
if (e instanceof SessionStatusError) throw e;
|
|
1693
1725
|
console.warn(e);
|
|
1694
1726
|
} finally {
|
|
1695
1727
|
reader.releaseLock();
|
|
@@ -1700,12 +1732,72 @@ async function streamUntilFound(api, clientSessionId, check, retryDelayMs = 200,
|
|
|
1700
1732
|
if (delay) await sleep(delay);
|
|
1701
1733
|
}
|
|
1702
1734
|
}
|
|
1735
|
+
async function pollUntilFound(baseUrl, clientSessionId, check, intervalMs = 500, signal) {
|
|
1736
|
+
const url = `${baseUrl}/auth/session/status/${encodeURIComponent(clientSessionId)}/poll`;
|
|
1737
|
+
let backoff = intervalMs;
|
|
1738
|
+
const sleep = async (ms) => {
|
|
1739
|
+
if (ms <= 0) return;
|
|
1740
|
+
if (signal) await abortableDelay(ms, signal);
|
|
1741
|
+
else await new Promise((r) => setTimeout(r, ms));
|
|
1742
|
+
};
|
|
1743
|
+
while (true) {
|
|
1744
|
+
throwIfAborted(signal);
|
|
1745
|
+
let envelope = null;
|
|
1746
|
+
let httpStatus = 0;
|
|
1747
|
+
try {
|
|
1748
|
+
const response = await fetch(url, { headers: { accept: "application/json" }, signal: signal ?? null });
|
|
1749
|
+
httpStatus = response.status;
|
|
1750
|
+
envelope = await response.json().catch(() => null);
|
|
1751
|
+
} catch (e) {
|
|
1752
|
+
if (e instanceof Error && e.name === "AbortError") throw e;
|
|
1753
|
+
console.warn(e);
|
|
1754
|
+
}
|
|
1755
|
+
if (httpStatus === 404 || envelope?.code === "INVALID_CLIENT_SESSION_ID") {
|
|
1756
|
+
throw new SessionStatusError("INVALID_CLIENT_SESSION_ID");
|
|
1757
|
+
}
|
|
1758
|
+
if (httpStatus === 410 || envelope?.code === "EXPIRED_CLIENT_ID") {
|
|
1759
|
+
throw new SessionStatusError("EXPIRED_CLIENT_ID");
|
|
1760
|
+
}
|
|
1761
|
+
if (envelope?.success && envelope.content && check(envelope.content)) {
|
|
1762
|
+
return envelope.content;
|
|
1763
|
+
}
|
|
1764
|
+
if (envelope) backoff = intervalMs;
|
|
1765
|
+
else backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
|
|
1766
|
+
await sleep(backoff);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
function waitForSessionReady(args) {
|
|
1770
|
+
const { api, baseUrl, clientSessionId, check, useStreaming, retryDelayMs, signal } = args;
|
|
1771
|
+
return useStreaming ? streamUntilFound(api, clientSessionId, check, retryDelayMs ?? 200, signal) : pollUntilFound(baseUrl, clientSessionId, check, retryDelayMs ?? 500, signal);
|
|
1772
|
+
}
|
|
1703
1773
|
|
|
1704
1774
|
// src/client/auth/authenticate.ts
|
|
1705
1775
|
async function authenticate(clientSessionId, deps, expectedWallet) {
|
|
1706
|
-
const { api, signal, setAuthState, storeSession, clearSession } = deps;
|
|
1776
|
+
const { api, basePath, useStreaming, signal, setAuthState, storeSession, clearSession } = deps;
|
|
1707
1777
|
setAuthState({ step: "authenticating" });
|
|
1708
|
-
|
|
1778
|
+
try {
|
|
1779
|
+
await waitForSessionReady({
|
|
1780
|
+
api,
|
|
1781
|
+
baseUrl: basePath,
|
|
1782
|
+
clientSessionId,
|
|
1783
|
+
check: (data2) => data2?.status === "READY",
|
|
1784
|
+
useStreaming,
|
|
1785
|
+
signal
|
|
1786
|
+
});
|
|
1787
|
+
} catch (err) {
|
|
1788
|
+
if (err instanceof SessionStatusError) {
|
|
1789
|
+
const expired = err.code === "EXPIRED_CLIENT_ID";
|
|
1790
|
+
setAuthState({
|
|
1791
|
+
step: "error",
|
|
1792
|
+
previousStep: "authenticating",
|
|
1793
|
+
message: expired ? "Login session expired \u2014 please try again" : "Login session is no longer valid \u2014 please try again",
|
|
1794
|
+
errorCode: expired ? AUTH_ERROR_CODES.SESSION_EXPIRED : AUTH_ERROR_CODES.SESSION_INVALID
|
|
1795
|
+
});
|
|
1796
|
+
await clearSession();
|
|
1797
|
+
return;
|
|
1798
|
+
}
|
|
1799
|
+
throw err;
|
|
1800
|
+
}
|
|
1709
1801
|
const dpopJwk = await deps.getPublicJwk();
|
|
1710
1802
|
const { data } = await api.POST("/auth/login", {
|
|
1711
1803
|
body: {
|
|
@@ -1829,26 +1921,36 @@ function severOpener(popup) {
|
|
|
1829
1921
|
} catch {
|
|
1830
1922
|
}
|
|
1831
1923
|
}
|
|
1832
|
-
async
|
|
1833
|
-
const
|
|
1834
|
-
const popup = window.open("about:blank", "_blank");
|
|
1924
|
+
var defaultWebOAuthOpener = async ({ getUrl }) => {
|
|
1925
|
+
const popup = typeof window !== "undefined" ? window.open("about:blank", "_blank") : null;
|
|
1835
1926
|
severOpener(popup);
|
|
1836
|
-
const
|
|
1837
|
-
if (!
|
|
1927
|
+
const url = await getUrl();
|
|
1928
|
+
if (!url) {
|
|
1838
1929
|
popup?.close();
|
|
1839
1930
|
return;
|
|
1840
1931
|
}
|
|
1841
|
-
setAuthState({ step: "opening_oauth", provider });
|
|
1842
|
-
const url = new URL(`${basePath}/auth/${provider}`);
|
|
1843
|
-
url.searchParams.set("api_key", apiKey);
|
|
1844
|
-
url.searchParams.set("client_session_id", clientSessionId);
|
|
1845
|
-
url.searchParams.set("redirect_uri", window.location.origin);
|
|
1846
1932
|
if (popup) {
|
|
1847
|
-
popup.location.href = url
|
|
1933
|
+
popup.location.href = url;
|
|
1848
1934
|
severOpener(popup);
|
|
1849
|
-
} else {
|
|
1850
|
-
window.open(url
|
|
1935
|
+
} else if (typeof window !== "undefined") {
|
|
1936
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
1851
1937
|
}
|
|
1938
|
+
};
|
|
1939
|
+
async function loginOAuth(provider, deps) {
|
|
1940
|
+
const { setAuthState, basePath, apiKey, openAuthUrl, redirectUri, signal } = deps;
|
|
1941
|
+
let clientSessionId = null;
|
|
1942
|
+
const getUrl = async () => {
|
|
1943
|
+
clientSessionId = await createAuthSession(deps);
|
|
1944
|
+
if (!clientSessionId) return null;
|
|
1945
|
+
setAuthState({ step: "opening_oauth", provider });
|
|
1946
|
+
const url = new URL(`${basePath}/auth/${provider}`);
|
|
1947
|
+
url.searchParams.set("api_key", apiKey);
|
|
1948
|
+
url.searchParams.set("client_session_id", clientSessionId);
|
|
1949
|
+
url.searchParams.set("redirect_uri", redirectUri);
|
|
1950
|
+
return url.toString();
|
|
1951
|
+
};
|
|
1952
|
+
await openAuthUrl({ provider, getUrl, redirectUri, signal });
|
|
1953
|
+
if (!clientSessionId) return;
|
|
1852
1954
|
await authenticate(clientSessionId, deps);
|
|
1853
1955
|
}
|
|
1854
1956
|
|
|
@@ -1858,10 +1960,10 @@ function withSignal(promise, signal) {
|
|
|
1858
1960
|
promise,
|
|
1859
1961
|
new Promise((_, reject) => {
|
|
1860
1962
|
if (signal.aborted) {
|
|
1861
|
-
reject(
|
|
1963
|
+
reject(abortError());
|
|
1862
1964
|
return;
|
|
1863
1965
|
}
|
|
1864
|
-
signal.addEventListener("abort", () => reject(
|
|
1966
|
+
signal.addEventListener("abort", () => reject(abortError()), { once: true });
|
|
1865
1967
|
})
|
|
1866
1968
|
]);
|
|
1867
1969
|
}
|
|
@@ -1909,6 +2011,8 @@ async function loginWallet(type, deps) {
|
|
|
1909
2011
|
|
|
1910
2012
|
// src/client/client.ts
|
|
1911
2013
|
var isBrowser = typeof window !== "undefined" && typeof localStorage !== "undefined";
|
|
2014
|
+
var isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
|
|
2015
|
+
var isClientRuntime = isBrowser || isReactNative;
|
|
1912
2016
|
var REFRESH_SKEW_SECONDS = 60;
|
|
1913
2017
|
function warnServerSide(method) {
|
|
1914
2018
|
console.warn(
|
|
@@ -1964,7 +2068,7 @@ var PollarClient = class {
|
|
|
1964
2068
|
this._walletAdapter = null;
|
|
1965
2069
|
this._loginController = null;
|
|
1966
2070
|
this.apiKey = config.apiKey;
|
|
1967
|
-
this.id =
|
|
2071
|
+
this.id = randomUUID();
|
|
1968
2072
|
this.basePath = `${config.baseUrl || "https://sdk.api.pollar.xyz"}/v1`;
|
|
1969
2073
|
this._storage = config.storage ?? defaultStorage({
|
|
1970
2074
|
onDegrade: (reason, error) => {
|
|
@@ -1978,10 +2082,12 @@ var PollarClient = class {
|
|
|
1978
2082
|
this._deviceLabel = config.deviceLabel;
|
|
1979
2083
|
this._visibilityProvider = config.visibilityProvider ?? defaultVisibilityProvider();
|
|
1980
2084
|
this._maxIdleMs = config.maxIdleMs;
|
|
2085
|
+
this._openAuthUrl = config.openAuthUrl ?? defaultWebOAuthOpener;
|
|
2086
|
+
this._oauthRedirectUri = config.oauthRedirectUri ?? (isBrowser ? window.location.origin : "");
|
|
1981
2087
|
this._api = createApiClient(this.basePath);
|
|
1982
2088
|
this._wireMiddlewares();
|
|
1983
2089
|
this._networkState = { step: "connected", network: config.stellarNetwork ?? "testnet" };
|
|
1984
|
-
if (!
|
|
2090
|
+
if (!isClientRuntime) {
|
|
1985
2091
|
warnServerSide("constructor");
|
|
1986
2092
|
this._initialized = Promise.resolve();
|
|
1987
2093
|
return;
|
|
@@ -2007,7 +2113,7 @@ var PollarClient = class {
|
|
|
2007
2113
|
// ─── Lifecycle ────────────────────────────────────────────────────────────
|
|
2008
2114
|
async _initialize() {
|
|
2009
2115
|
this._apiKeyHash = await hashApiKey(this.apiKey);
|
|
2010
|
-
if (
|
|
2116
|
+
if (isBrowser) {
|
|
2011
2117
|
const sessionKey = sessionStorageKey(this._apiKeyHash);
|
|
2012
2118
|
const handler = (e) => {
|
|
2013
2119
|
if (e.key === sessionKey) {
|
|
@@ -2029,7 +2135,7 @@ var PollarClient = class {
|
|
|
2029
2135
|
}
|
|
2030
2136
|
/** Detach the cross-tab storage listener and abort any in-flight login. */
|
|
2031
2137
|
destroy() {
|
|
2032
|
-
if (this._storageEventHandler &&
|
|
2138
|
+
if (this._storageEventHandler && isBrowser) {
|
|
2033
2139
|
window.removeEventListener("storage", this._storageEventHandler);
|
|
2034
2140
|
this._storageEventHandler = null;
|
|
2035
2141
|
}
|
|
@@ -2312,7 +2418,7 @@ var PollarClient = class {
|
|
|
2312
2418
|
}
|
|
2313
2419
|
// ─── Login (unified entry point) ─────────────────────────────────────────
|
|
2314
2420
|
login(options) {
|
|
2315
|
-
if (!
|
|
2421
|
+
if (!isClientRuntime) {
|
|
2316
2422
|
warnServerSide("login");
|
|
2317
2423
|
return;
|
|
2318
2424
|
}
|
|
@@ -2323,7 +2429,9 @@ var PollarClient = class {
|
|
|
2323
2429
|
loginOAuth(options.provider, {
|
|
2324
2430
|
...deps,
|
|
2325
2431
|
basePath: this.basePath,
|
|
2326
|
-
apiKey: this.apiKey
|
|
2432
|
+
apiKey: this.apiKey,
|
|
2433
|
+
openAuthUrl: this._openAuthUrl,
|
|
2434
|
+
redirectUri: this._oauthRedirectUri
|
|
2327
2435
|
}).catch((err) => this._handleFlowError(err));
|
|
2328
2436
|
} else if (options.provider === "email") {
|
|
2329
2437
|
const { email } = options;
|
|
@@ -2339,7 +2447,7 @@ var PollarClient = class {
|
|
|
2339
2447
|
}
|
|
2340
2448
|
// ─── Email OTP flow (3 steps) ─────────────────────────────────────────────
|
|
2341
2449
|
beginEmailLogin() {
|
|
2342
|
-
if (!
|
|
2450
|
+
if (!isClientRuntime) {
|
|
2343
2451
|
warnServerSide("beginEmailLogin");
|
|
2344
2452
|
return;
|
|
2345
2453
|
}
|
|
@@ -2347,7 +2455,7 @@ var PollarClient = class {
|
|
|
2347
2455
|
initEmailSession(this._flowDeps(controller.signal)).catch((err) => this._handleFlowError(err));
|
|
2348
2456
|
}
|
|
2349
2457
|
sendEmailCode(email) {
|
|
2350
|
-
if (!
|
|
2458
|
+
if (!isClientRuntime) {
|
|
2351
2459
|
warnServerSide("sendEmailCode");
|
|
2352
2460
|
return;
|
|
2353
2461
|
}
|
|
@@ -2359,7 +2467,7 @@ var PollarClient = class {
|
|
|
2359
2467
|
sendEmailCode(email, clientSessionId, this._flowDeps(signal)).catch((err) => this._handleFlowError(err));
|
|
2360
2468
|
}
|
|
2361
2469
|
verifyEmailCode(code) {
|
|
2362
|
-
if (!
|
|
2470
|
+
if (!isClientRuntime) {
|
|
2363
2471
|
warnServerSide("verifyEmailCode");
|
|
2364
2472
|
return;
|
|
2365
2473
|
}
|
|
@@ -2377,7 +2485,7 @@ var PollarClient = class {
|
|
|
2377
2485
|
}
|
|
2378
2486
|
// ─── Wallet flow (single call) ────────────────────────────────────────────
|
|
2379
2487
|
loginWallet(type) {
|
|
2380
|
-
if (!
|
|
2488
|
+
if (!isClientRuntime) {
|
|
2381
2489
|
warnServerSide("loginWallet");
|
|
2382
2490
|
return;
|
|
2383
2491
|
}
|
|
@@ -2403,7 +2511,7 @@ var PollarClient = class {
|
|
|
2403
2511
|
* across all devices.
|
|
2404
2512
|
*/
|
|
2405
2513
|
async logout(options = {}) {
|
|
2406
|
-
if (!
|
|
2514
|
+
if (!isClientRuntime) {
|
|
2407
2515
|
warnServerSide("logout");
|
|
2408
2516
|
return;
|
|
2409
2517
|
}
|
|
@@ -2433,7 +2541,7 @@ var PollarClient = class {
|
|
|
2433
2541
|
* `current` flag identifies which entry corresponds to this client.
|
|
2434
2542
|
*/
|
|
2435
2543
|
async listSessions() {
|
|
2436
|
-
if (!
|
|
2544
|
+
if (!isClientRuntime) {
|
|
2437
2545
|
warnServerSide("listSessions");
|
|
2438
2546
|
return [];
|
|
2439
2547
|
}
|
|
@@ -2452,7 +2560,7 @@ var PollarClient = class {
|
|
|
2452
2560
|
* does NOT clear local state — call `logout()` for that case.
|
|
2453
2561
|
*/
|
|
2454
2562
|
async revokeSession(familyId) {
|
|
2455
|
-
if (!
|
|
2563
|
+
if (!isClientRuntime) {
|
|
2456
2564
|
warnServerSide("revokeSession");
|
|
2457
2565
|
return;
|
|
2458
2566
|
}
|
|
@@ -2950,6 +3058,11 @@ var PollarClient = class {
|
|
|
2950
3058
|
_flowDeps(signal) {
|
|
2951
3059
|
return {
|
|
2952
3060
|
api: this._api,
|
|
3061
|
+
basePath: this.basePath,
|
|
3062
|
+
// SSE status streaming works on web; React Native's `fetch` has no
|
|
3063
|
+
// readable `response.body`, so those clients poll the non-streaming
|
|
3064
|
+
// status endpoint instead. `isBrowser` is false in RN and SSR alike.
|
|
3065
|
+
useStreaming: isBrowser,
|
|
2953
3066
|
signal,
|
|
2954
3067
|
setAuthState: this._setAuthState.bind(this),
|
|
2955
3068
|
storeSession: this._storeSession.bind(this),
|