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