@erikey/react 0.3.3 → 0.3.5
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/index.d.mts +8 -6
- package/dist/index.mjs +27 -125
- package/dist/index.mjs.map +1 -1
- package/dist/ui/index.mjs +2 -2
- package/dist/ui/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -2190,8 +2190,10 @@ type DashboardClient = ReturnType<typeof createDashboardClient>;
|
|
|
2190
2190
|
* - Bearer token auth for cross-origin iframes (Sandpack)
|
|
2191
2191
|
* - localStorage token storage when cookies are blocked
|
|
2192
2192
|
*
|
|
2193
|
-
*
|
|
2194
|
-
*
|
|
2193
|
+
* Architecture:
|
|
2194
|
+
* - Uses better-auth's native reactivity (nanostores + useSyncExternalStore)
|
|
2195
|
+
* - Hooks into fetchOptions.onSuccess to store tokens for cross-origin
|
|
2196
|
+
* - No Proxy wrapper - uses better-auth's useSession directly
|
|
2195
2197
|
*/
|
|
2196
2198
|
interface AuthClientConfig {
|
|
2197
2199
|
/**
|
|
@@ -2208,9 +2210,9 @@ interface AuthClientConfig {
|
|
|
2208
2210
|
/**
|
|
2209
2211
|
* Create an auth client for end-user authentication
|
|
2210
2212
|
*
|
|
2211
|
-
*
|
|
2212
|
-
* Automatically detects cross-origin
|
|
2213
|
-
* Bearer tokens instead of cookies.
|
|
2213
|
+
* Uses better-auth/react with Erikey-specific configuration.
|
|
2214
|
+
* Automatically detects cross-origin contexts (Sandpack, deployed sites)
|
|
2215
|
+
* and uses Bearer tokens instead of cookies.
|
|
2214
2216
|
*
|
|
2215
2217
|
* @example Basic usage
|
|
2216
2218
|
* ```tsx
|
|
@@ -2227,7 +2229,7 @@ interface AuthClientConfig {
|
|
|
2227
2229
|
* // Social OAuth
|
|
2228
2230
|
* await auth.signIn.social({ provider: 'google' });
|
|
2229
2231
|
*
|
|
2230
|
-
* // Reactive session hook (React)
|
|
2232
|
+
* // Reactive session hook (React) - uses better-auth's nanostores
|
|
2231
2233
|
* const { data: session, isPending } = auth.useSession();
|
|
2232
2234
|
*
|
|
2233
2235
|
* // Sign out
|
package/dist/index.mjs
CHANGED
|
@@ -1611,9 +1611,6 @@ function createDashboardClient(config) {
|
|
|
1611
1611
|
});
|
|
1612
1612
|
}
|
|
1613
1613
|
|
|
1614
|
-
// src/auth-client.ts
|
|
1615
|
-
import { useState, useEffect, useCallback as useCallback2 } from "react";
|
|
1616
|
-
|
|
1617
1614
|
// src/lib/cross-origin-auth.ts
|
|
1618
1615
|
function shouldUseBearerAuth(authApiUrl) {
|
|
1619
1616
|
if (typeof window === "undefined") {
|
|
@@ -1662,10 +1659,6 @@ function clearToken(projectId) {
|
|
|
1662
1659
|
function createAuthClient2(config) {
|
|
1663
1660
|
const { projectId, baseUrl = "https://auth.erikey.com" } = config;
|
|
1664
1661
|
const useBearerAuth = shouldUseBearerAuth(baseUrl);
|
|
1665
|
-
const sessionListeners = /* @__PURE__ */ new Set();
|
|
1666
|
-
const notifySessionChange = () => {
|
|
1667
|
-
sessionListeners.forEach((listener) => listener());
|
|
1668
|
-
};
|
|
1669
1662
|
const fetchOptions = {
|
|
1670
1663
|
// Always send project ID header for multi-tenant routing
|
|
1671
1664
|
headers: {
|
|
@@ -1677,131 +1670,40 @@ function createAuthClient2(config) {
|
|
|
1677
1670
|
type: "Bearer",
|
|
1678
1671
|
token: () => getStoredToken(projectId) || ""
|
|
1679
1672
|
}
|
|
1673
|
+
},
|
|
1674
|
+
// Hook into successful responses to handle token storage
|
|
1675
|
+
onSuccess: async (context) => {
|
|
1676
|
+
if (!useBearerAuth) return;
|
|
1677
|
+
const url = context.response?.url || "";
|
|
1678
|
+
const path = new URL(url, baseUrl).pathname;
|
|
1679
|
+
const token = context.data?.token;
|
|
1680
|
+
if (token && (path.includes("/sign-in") || path.includes("/sign-up"))) {
|
|
1681
|
+
const session = {
|
|
1682
|
+
id: context.data?.session?.id || "session",
|
|
1683
|
+
token,
|
|
1684
|
+
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3).toISOString()
|
|
1685
|
+
};
|
|
1686
|
+
storeToken(projectId, session);
|
|
1687
|
+
}
|
|
1688
|
+
if (path.includes("/sign-out")) {
|
|
1689
|
+
clearToken(projectId);
|
|
1690
|
+
}
|
|
1691
|
+
},
|
|
1692
|
+
// Handle errors - clear token on auth errors
|
|
1693
|
+
onError: async (context) => {
|
|
1694
|
+
if (!useBearerAuth) return;
|
|
1695
|
+
if (context.response?.status === 401) {
|
|
1696
|
+
clearToken(projectId);
|
|
1697
|
+
}
|
|
1680
1698
|
}
|
|
1681
1699
|
};
|
|
1682
1700
|
const client = createAuthClient({
|
|
1683
1701
|
baseURL: baseUrl,
|
|
1684
1702
|
fetchOptions,
|
|
1685
|
-
// For same-origin, include cookies
|
|
1703
|
+
// For same-origin, include cookies (cross-origin uses Bearer from fetchOptions.auth)
|
|
1686
1704
|
...!useBearerAuth && { credentials: "include" }
|
|
1687
1705
|
});
|
|
1688
|
-
|
|
1689
|
-
return client;
|
|
1690
|
-
}
|
|
1691
|
-
return new Proxy({}, {
|
|
1692
|
-
get(_target, prop) {
|
|
1693
|
-
if (typeof prop === "symbol") {
|
|
1694
|
-
return client[prop];
|
|
1695
|
-
}
|
|
1696
|
-
const mergeHeaders = (args) => {
|
|
1697
|
-
const [data, ...rest] = args;
|
|
1698
|
-
if (!data || typeof data !== "object") return args;
|
|
1699
|
-
const existingHeaders = data.fetchOptions?.headers || {};
|
|
1700
|
-
const mergedData = {
|
|
1701
|
-
...data,
|
|
1702
|
-
fetchOptions: {
|
|
1703
|
-
...data.fetchOptions,
|
|
1704
|
-
headers: {
|
|
1705
|
-
"X-Project-Id": projectId,
|
|
1706
|
-
...existingHeaders
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1709
|
-
};
|
|
1710
|
-
return [mergedData, ...rest];
|
|
1711
|
-
};
|
|
1712
|
-
if (prop === "signIn") {
|
|
1713
|
-
return new Proxy(client.signIn, {
|
|
1714
|
-
get(_signInTarget, signInProp) {
|
|
1715
|
-
if (signInProp === "email") {
|
|
1716
|
-
return async (...args) => {
|
|
1717
|
-
const mergedArgs = mergeHeaders(args);
|
|
1718
|
-
const result = await client.signIn.email(...mergedArgs);
|
|
1719
|
-
const token = result.data?.token;
|
|
1720
|
-
if (token) {
|
|
1721
|
-
const session = {
|
|
1722
|
-
id: result.data?.session?.id || "session",
|
|
1723
|
-
token,
|
|
1724
|
-
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3).toISOString()
|
|
1725
|
-
};
|
|
1726
|
-
storeToken(projectId, session);
|
|
1727
|
-
notifySessionChange();
|
|
1728
|
-
}
|
|
1729
|
-
return result;
|
|
1730
|
-
};
|
|
1731
|
-
}
|
|
1732
|
-
return client.signIn[signInProp];
|
|
1733
|
-
}
|
|
1734
|
-
});
|
|
1735
|
-
}
|
|
1736
|
-
if (prop === "signUp") {
|
|
1737
|
-
return new Proxy(client.signUp, {
|
|
1738
|
-
get(_signUpTarget, signUpProp) {
|
|
1739
|
-
if (signUpProp === "email") {
|
|
1740
|
-
return async (...args) => {
|
|
1741
|
-
const mergedArgs = mergeHeaders(args);
|
|
1742
|
-
const result = await client.signUp.email(...mergedArgs);
|
|
1743
|
-
const token = result.data?.token;
|
|
1744
|
-
if (token) {
|
|
1745
|
-
const session = {
|
|
1746
|
-
id: result.data?.session?.id || "session",
|
|
1747
|
-
token,
|
|
1748
|
-
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1e3).toISOString()
|
|
1749
|
-
};
|
|
1750
|
-
storeToken(projectId, session);
|
|
1751
|
-
notifySessionChange();
|
|
1752
|
-
}
|
|
1753
|
-
return result;
|
|
1754
|
-
};
|
|
1755
|
-
}
|
|
1756
|
-
return client.signUp[signUpProp];
|
|
1757
|
-
}
|
|
1758
|
-
});
|
|
1759
|
-
}
|
|
1760
|
-
if (prop === "signOut") {
|
|
1761
|
-
return async (...args) => {
|
|
1762
|
-
clearToken(projectId);
|
|
1763
|
-
const result = await client.signOut(...args);
|
|
1764
|
-
notifySessionChange();
|
|
1765
|
-
return result;
|
|
1766
|
-
};
|
|
1767
|
-
}
|
|
1768
|
-
if (prop === "useSession") {
|
|
1769
|
-
return function useSession() {
|
|
1770
|
-
const [data, setData] = useState(null);
|
|
1771
|
-
const [isPending, setIsPending] = useState(true);
|
|
1772
|
-
const [error, setError] = useState(null);
|
|
1773
|
-
const refetch = useCallback2(async () => {
|
|
1774
|
-
setIsPending(true);
|
|
1775
|
-
try {
|
|
1776
|
-
const result = await client.getSession();
|
|
1777
|
-
if (result.error) {
|
|
1778
|
-
setError(result.error);
|
|
1779
|
-
setData(null);
|
|
1780
|
-
} else {
|
|
1781
|
-
setData(result.data);
|
|
1782
|
-
setError(null);
|
|
1783
|
-
}
|
|
1784
|
-
} catch (e) {
|
|
1785
|
-
setError(e);
|
|
1786
|
-
setData(null);
|
|
1787
|
-
}
|
|
1788
|
-
setIsPending(false);
|
|
1789
|
-
}, []);
|
|
1790
|
-
useEffect(() => {
|
|
1791
|
-
refetch();
|
|
1792
|
-
}, [refetch]);
|
|
1793
|
-
useEffect(() => {
|
|
1794
|
-
sessionListeners.add(refetch);
|
|
1795
|
-
return () => {
|
|
1796
|
-
sessionListeners.delete(refetch);
|
|
1797
|
-
};
|
|
1798
|
-
}, [refetch]);
|
|
1799
|
-
return { data, isPending, error, refetch };
|
|
1800
|
-
};
|
|
1801
|
-
}
|
|
1802
|
-
return client[prop];
|
|
1803
|
-
}
|
|
1804
|
-
});
|
|
1706
|
+
return client;
|
|
1805
1707
|
}
|
|
1806
1708
|
|
|
1807
1709
|
// src/kv-client.ts
|