@smarthivelabs-devs/auth-expo 1.6.0 → 1.6.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 +142 -16
- package/dist/index.d.ts +4 -1
- package/dist/index.js +80 -28
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -38,9 +38,9 @@ import { SmartHiveAuthProvider, buildRedirectUri } from "@smarthivelabs-devs/aut
|
|
|
38
38
|
export default function Layout() {
|
|
39
39
|
return (
|
|
40
40
|
<SmartHiveAuthProvider
|
|
41
|
-
projectId={process.env.
|
|
42
|
-
publishableKey={process.env.
|
|
43
|
-
baseUrl={process.env.
|
|
41
|
+
projectId={process.env.EXPO_PUBLIC_SMARTHIVE_AUTH_PROJECT_ID!}
|
|
42
|
+
publishableKey={process.env.EXPO_PUBLIC_SMARTHIVE_AUTH_PUBLISHABLE_KEY!}
|
|
43
|
+
baseUrl={process.env.EXPO_PUBLIC_SMARTHIVE_AUTH_BASE_URL!}
|
|
44
44
|
redirectUri={buildRedirectUri("myapp")}
|
|
45
45
|
>
|
|
46
46
|
<Stack />
|
|
@@ -51,9 +51,9 @@ export default function Layout() {
|
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
53
|
# .env
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
EXPO_PUBLIC_SMARTHIVE_AUTH_PROJECT_ID=proj_abc123
|
|
55
|
+
EXPO_PUBLIC_SMARTHIVE_AUTH_PUBLISHABLE_KEY=pk_prod_abc123
|
|
56
|
+
EXPO_PUBLIC_SMARTHIVE_AUTH_BASE_URL=https://auth.myapp.com
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
---
|
|
@@ -402,9 +402,9 @@ import { SmartHiveAuthProvider, buildRedirectUri } from "@smarthivelabs-devs/aut
|
|
|
402
402
|
export default function Layout() {
|
|
403
403
|
return (
|
|
404
404
|
<SmartHiveAuthProvider
|
|
405
|
-
projectId={process.env.
|
|
406
|
-
publishableKey={process.env.
|
|
407
|
-
baseUrl={process.env.
|
|
405
|
+
projectId={process.env.EXPO_PUBLIC_SMARTHIVE_AUTH_PROJECT_ID!}
|
|
406
|
+
publishableKey={process.env.EXPO_PUBLIC_SMARTHIVE_AUTH_PUBLISHABLE_KEY!}
|
|
407
|
+
baseUrl={process.env.EXPO_PUBLIC_SMARTHIVE_AUTH_BASE_URL!}
|
|
408
408
|
redirectUri={buildRedirectUri("myapp")}
|
|
409
409
|
>
|
|
410
410
|
<Stack />
|
|
@@ -563,7 +563,7 @@ const router = express.Router();
|
|
|
563
563
|
|
|
564
564
|
const SMARTHIVE_BASE = process.env.SMARTHIVE_AUTH_BASE_URL!; // https://authcore.smarthivelabs.dev
|
|
565
565
|
const SMARTHIVE_ENV = process.env.SMARTHIVE_AUTH_ENVIRONMENT!; // prod
|
|
566
|
-
const SMARTHIVE_PID = process.env.
|
|
566
|
+
const SMARTHIVE_PID = process.env.SMARTHIVE_AUTH_PROJECT_ID!;
|
|
567
567
|
const APP_BASE_URL = process.env.APP_BASE_URL!; // https://api.yourapp.com
|
|
568
568
|
|
|
569
569
|
// Initiation — app calls this, proxy forwards to SmartHive
|
|
@@ -618,13 +618,139 @@ That's it. `signIn.social("google")` now opens `api.yourapp.com/api/auth/social/
|
|
|
618
618
|
|
|
619
619
|
---
|
|
620
620
|
|
|
621
|
-
##
|
|
621
|
+
## Backend Integration
|
|
622
622
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
623
|
+
Most apps need a backend that the Expo app calls for data. Here is the complete flow for how the Expo SDK, the developer's backend, and the SmartHive server SDK work together.
|
|
624
|
+
|
|
625
|
+
### Architecture overview
|
|
626
|
+
|
|
627
|
+
```
|
|
628
|
+
Expo App Developer Backend SmartHive Auth
|
|
629
|
+
──────────────────────────────────────────────────────────────────────────────
|
|
630
|
+
1. signIn.email / signIn.social ──── (direct to SmartHive) ────► headless endpoint
|
|
631
|
+
◄── access_token + refresh_token
|
|
632
|
+
SecureStore ◄── tokens saved
|
|
633
|
+
|
|
634
|
+
2. authFetch("https://api.myapp.com/me") ──► requireAuth() ──► JWKS endpoint
|
|
635
|
+
(adds Authorization: Bearer <token>) verifies JWT (once per key rotation)
|
|
636
|
+
◄── req.auth.userId
|
|
637
|
+
your API logic runs
|
|
638
|
+
◄── JSON response
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
**No tokens are sent to your backend** — only the short-lived access token (JWT) in the `Authorization` header. Your backend never sees or stores the refresh token.
|
|
642
|
+
|
|
643
|
+
### Step 1 — Expo app calls your backend
|
|
644
|
+
|
|
645
|
+
Every method from `useAuthFetch()` or `authFetch` automatically adds the `Authorization: Bearer <token>` header and transparently refreshes the access token when it is near expiry.
|
|
646
|
+
|
|
647
|
+
```tsx
|
|
648
|
+
// In your Expo screen
|
|
649
|
+
import { useAuthFetch } from "@smarthivelabs-devs/auth-expo";
|
|
650
|
+
|
|
651
|
+
const authFetch = useAuthFetch();
|
|
652
|
+
|
|
653
|
+
const res = await authFetch("https://api.myapp.com/profile");
|
|
654
|
+
const data = await res.json();
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
Or using `client.fetch` directly:
|
|
658
|
+
|
|
659
|
+
```tsx
|
|
660
|
+
const { client } = useAuth();
|
|
661
|
+
const res = await client.fetch("https://api.myapp.com/orders");
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Step 2 — Backend verifies the JWT
|
|
665
|
+
|
|
666
|
+
Install the server SDK on your backend:
|
|
667
|
+
|
|
668
|
+
```bash
|
|
669
|
+
npm install @smarthivelabs-devs/auth-server
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
```ts
|
|
673
|
+
// Express — src/middleware/auth.ts
|
|
674
|
+
import { requireAuth } from "@smarthivelabs-devs/auth-server";
|
|
675
|
+
|
|
676
|
+
export const protect = requireAuth({
|
|
677
|
+
issuer: process.env.SMARTHIVE_AUTH_ISSUER!, // e.g. https://authcore.smarthivelabs.dev
|
|
678
|
+
projectId: process.env.SMARTHIVE_AUTH_PROJECT_ID!, // optional — rejects tokens from other projects
|
|
679
|
+
});
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
```env
|
|
683
|
+
SMARTHIVE_AUTH_ISSUER=https://authcore.smarthivelabs.dev
|
|
684
|
+
SMARTHIVE_AUTH_PROJECT_ID=proj_abc123
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
```ts
|
|
688
|
+
// Express — src/routes/profile.ts
|
|
689
|
+
import { protect } from "../middleware/auth";
|
|
690
|
+
|
|
691
|
+
router.get("/profile", protect, (req, res) => {
|
|
692
|
+
// req.auth is typed as AuthContext
|
|
693
|
+
res.json({ userId: req.auth!.userId, email: req.auth!.email });
|
|
694
|
+
});
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
### Step 3 — Sign-up flow
|
|
698
|
+
|
|
699
|
+
Sign-up goes directly to SmartHive Auth — your backend does not need a sign-up endpoint.
|
|
700
|
+
|
|
701
|
+
```tsx
|
|
702
|
+
// Expo — sign-up screen
|
|
703
|
+
const { signUp } = useAuth();
|
|
704
|
+
|
|
705
|
+
const result = await signUp.email({
|
|
706
|
+
email: "user@example.com",
|
|
707
|
+
password: "secret123",
|
|
708
|
+
name: "Jane Doe",
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
if (result.requiresVerification) {
|
|
712
|
+
// Show "check your inbox" screen
|
|
713
|
+
// No session yet — user must verify email before signing in
|
|
714
|
+
} else {
|
|
715
|
+
// Session saved automatically — user is now signed in
|
|
716
|
+
// Next authFetch call to your backend will include a valid token
|
|
717
|
+
}
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
Once signed in, calls to `authFetch` on your backend will immediately work — no extra step needed.
|
|
721
|
+
|
|
722
|
+
### Step 4 — Admin operations (optional)
|
|
723
|
+
|
|
724
|
+
If your backend needs to look up user details, ban a user, or list sessions, use `createAdminClient` from the server SDK with your `shai_*` key from the dashboard.
|
|
725
|
+
|
|
726
|
+
```ts
|
|
727
|
+
import { requireAuth, createAdminClient } from "@smarthivelabs-devs/auth-server";
|
|
728
|
+
|
|
729
|
+
const smarthive = createAdminClient({
|
|
730
|
+
secretKey: process.env.SMARTHIVE_AUTH_ADMIN_KEY!, // shai_*
|
|
731
|
+
baseUrl: process.env.SMARTHIVE_AUTH_ISSUER!,
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
// After verifying the JWT, look up the full user record
|
|
735
|
+
router.get("/profile", protect, async (req, res) => {
|
|
736
|
+
const { user } = await smarthive.users.get(req.auth!.userId);
|
|
737
|
+
res.json(user);
|
|
738
|
+
});
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### Full sign-in flow reference
|
|
742
|
+
|
|
743
|
+
| Step | Who | What happens |
|
|
744
|
+
|---|---|---|
|
|
745
|
+
| 1 | Expo app | `signIn.email()` or `signIn.social()` — tokens returned from SmartHive |
|
|
746
|
+
| 2 | Expo app | Tokens stored in SecureStore (never leaves the device in plaintext) |
|
|
747
|
+
| 3 | Expo app | `authFetch(backendUrl)` — sends `Authorization: Bearer <access_token>` |
|
|
748
|
+
| 4 | Backend | `requireAuth()` fetches SmartHive JWKS once, verifies JWT signature + expiry |
|
|
749
|
+
| 5 | Backend | `req.auth.userId` is available — your business logic runs |
|
|
750
|
+
| 6 | Backend | (optional) `smarthive.users.get(userId)` for full user profile |
|
|
751
|
+
| Token refresh | Expo SDK | When access token is ≤ 30 s from expiry, automatically refreshed before the next `authFetch` — your backend never sees an expired token |
|
|
752
|
+
|
|
753
|
+
---
|
|
628
754
|
|
|
629
755
|
---
|
|
630
756
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { SmartHiveAuthConfig, SmartHiveAuthClient, AuthSession, HeadlessSignInResult, SocialProvider, HeadlessSignUpResult } from '@smarthivelabs-devs/auth-sdk';
|
|
3
|
+
export { SmartHiveAuthError } from '@smarthivelabs-devs/auth-sdk';
|
|
3
4
|
|
|
4
5
|
interface SmartHiveExpoConfig extends Omit<SmartHiveAuthConfig, "storage"> {
|
|
5
6
|
/** Deep link redirect URI, e.g. "myapp://auth/callback" */
|
|
@@ -86,6 +87,8 @@ interface AuthContextValue {
|
|
|
86
87
|
}
|
|
87
88
|
interface SmartHiveAuthProviderProps extends SmartHiveExpoConfig {
|
|
88
89
|
children: React.ReactNode;
|
|
90
|
+
/** Called whenever any auth operation (sign-in, sign-up, OTP, OAuth callback) throws. Use this to show a global error toast. Errors still propagate to the caller after this. */
|
|
91
|
+
onAuthError?: (error: unknown) => void;
|
|
89
92
|
}
|
|
90
93
|
/** @deprecated Use SmartHiveAuthProviderProps */
|
|
91
94
|
type SmartHiveProviderProps = SmartHiveAuthProviderProps;
|
|
@@ -95,7 +98,7 @@ type SmartHiveProviderProps = SmartHiveAuthProviderProps;
|
|
|
95
98
|
* - OAuth 2.0 + PKCE browser redirect via `login()`
|
|
96
99
|
* - Headless direct sign-in via `signIn.*` (no browser, custom login screens)
|
|
97
100
|
*/
|
|
98
|
-
declare function SmartHiveAuthProvider({ children, ...config }: SmartHiveAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
101
|
+
declare function SmartHiveAuthProvider({ children, onAuthError, ...config }: SmartHiveAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
99
102
|
declare function useAuth(): AuthContextValue;
|
|
100
103
|
declare function useSession(): AuthSession | null;
|
|
101
104
|
declare function useUser(): {} | null;
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import * as WebBrowser from "expo-web-browser";
|
|
|
14
14
|
import * as SecureStore from "expo-secure-store";
|
|
15
15
|
import {
|
|
16
16
|
initAuth,
|
|
17
|
+
SmartHiveAuthError,
|
|
17
18
|
envFromPublishableKey
|
|
18
19
|
} from "@smarthivelabs-devs/auth-sdk";
|
|
19
20
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
@@ -80,11 +81,14 @@ function initExpoAuth(config) {
|
|
|
80
81
|
if (result.type === "success") {
|
|
81
82
|
await base.handleSocialCallback({ url: result.url });
|
|
82
83
|
}
|
|
84
|
+
},
|
|
85
|
+
async logout() {
|
|
86
|
+
await base.headless.signOut();
|
|
83
87
|
}
|
|
84
88
|
};
|
|
85
89
|
}
|
|
86
90
|
var AuthContext = createContext(null);
|
|
87
|
-
function SmartHiveAuthProvider({ children, ...config }) {
|
|
91
|
+
function SmartHiveAuthProvider({ children, onAuthError, ...config }) {
|
|
88
92
|
const configRef = useRef(config);
|
|
89
93
|
const client = useMemo(() => initExpoAuth(configRef.current), []);
|
|
90
94
|
const [session, setSession] = useState(null);
|
|
@@ -106,10 +110,12 @@ function SmartHiveAuthProvider({ children, ...config }) {
|
|
|
106
110
|
try {
|
|
107
111
|
const parsed = new URL(url);
|
|
108
112
|
if (parsed.searchParams.has("access_token") || parsed.searchParams.has("error")) {
|
|
109
|
-
client.handleSocialCallback({ url }).then((s) => setSession(s)).catch(() => {
|
|
113
|
+
client.handleSocialCallback({ url }).then((s) => setSession(s)).catch((err) => {
|
|
114
|
+
onAuthError?.(err);
|
|
110
115
|
});
|
|
111
|
-
} else {
|
|
112
|
-
client.handleCallback({ url }).then((s) => setSession(s)).catch(() => {
|
|
116
|
+
} else if (parsed.searchParams.has("code")) {
|
|
117
|
+
client.handleCallback({ url }).then((s) => setSession(s)).catch((err) => {
|
|
118
|
+
onAuthError?.(err);
|
|
113
119
|
});
|
|
114
120
|
}
|
|
115
121
|
} catch {
|
|
@@ -140,16 +146,23 @@ function SmartHiveAuthProvider({ children, ...config }) {
|
|
|
140
146
|
(input, init) => client.fetch(input, init),
|
|
141
147
|
[client]
|
|
142
148
|
);
|
|
149
|
+
const onAuthErrorRef = useRef(onAuthError);
|
|
150
|
+
onAuthErrorRef.current = onAuthError;
|
|
143
151
|
function wrapHeadlessSignIn(fn) {
|
|
144
152
|
return async (params) => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
try {
|
|
154
|
+
const result = await fn(params);
|
|
155
|
+
setSession({
|
|
156
|
+
accessToken: result.accessToken,
|
|
157
|
+
refreshToken: result.refreshToken,
|
|
158
|
+
expiresAt: result.expiresAt,
|
|
159
|
+
user: result.user
|
|
160
|
+
});
|
|
161
|
+
return result;
|
|
162
|
+
} catch (err) {
|
|
163
|
+
onAuthErrorRef.current?.(err);
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
153
166
|
};
|
|
154
167
|
}
|
|
155
168
|
const signIn = useMemo(() => {
|
|
@@ -157,20 +170,46 @@ function SmartHiveAuthProvider({ children, ...config }) {
|
|
|
157
170
|
return {
|
|
158
171
|
email: wrapHeadlessSignIn(h.signIn.email.bind(h.signIn)),
|
|
159
172
|
phone: {
|
|
160
|
-
sendOtp: (p) =>
|
|
173
|
+
sendOtp: async (p) => {
|
|
174
|
+
try {
|
|
175
|
+
await h.signIn.phone.sendOtp(p);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
onAuthErrorRef.current?.(err);
|
|
178
|
+
throw err;
|
|
179
|
+
}
|
|
180
|
+
},
|
|
161
181
|
verify: wrapHeadlessSignIn(h.signIn.phone.verify.bind(h.signIn.phone))
|
|
162
182
|
},
|
|
163
183
|
emailOtp: {
|
|
164
|
-
send: (p) =>
|
|
184
|
+
send: async (p) => {
|
|
185
|
+
try {
|
|
186
|
+
await h.signIn.emailOtp.send(p);
|
|
187
|
+
} catch (err) {
|
|
188
|
+
onAuthErrorRef.current?.(err);
|
|
189
|
+
throw err;
|
|
190
|
+
}
|
|
191
|
+
},
|
|
165
192
|
verify: wrapHeadlessSignIn(h.signIn.emailOtp.verify.bind(h.signIn.emailOtp))
|
|
166
193
|
},
|
|
167
194
|
magicLink: {
|
|
168
|
-
send: (p) =>
|
|
195
|
+
send: async (p) => {
|
|
196
|
+
try {
|
|
197
|
+
await h.signIn.magicLink.send(p);
|
|
198
|
+
} catch (err) {
|
|
199
|
+
onAuthErrorRef.current?.(err);
|
|
200
|
+
throw err;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
169
203
|
},
|
|
170
204
|
social: async (provider, options) => {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
205
|
+
try {
|
|
206
|
+
await client.loginSocial(provider, options);
|
|
207
|
+
const s = await client.getSession();
|
|
208
|
+
if (s) setSession(s);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
onAuthErrorRef.current?.(err);
|
|
211
|
+
throw err;
|
|
212
|
+
}
|
|
174
213
|
}
|
|
175
214
|
};
|
|
176
215
|
}, [client]);
|
|
@@ -178,18 +217,30 @@ function SmartHiveAuthProvider({ children, ...config }) {
|
|
|
178
217
|
const h = client.headless;
|
|
179
218
|
return {
|
|
180
219
|
email: async (params) => {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
220
|
+
try {
|
|
221
|
+
const result = await h.signUp.email(params);
|
|
222
|
+
if (!result.requiresVerification) {
|
|
223
|
+
setSession({
|
|
224
|
+
accessToken: result.accessToken,
|
|
225
|
+
refreshToken: result.refreshToken,
|
|
226
|
+
expiresAt: result.expiresAt,
|
|
227
|
+
user: result.user
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
} catch (err) {
|
|
232
|
+
onAuthErrorRef.current?.(err);
|
|
233
|
+
throw err;
|
|
189
234
|
}
|
|
190
|
-
return result;
|
|
191
235
|
},
|
|
192
|
-
resendVerificationEmail: (params) =>
|
|
236
|
+
resendVerificationEmail: async (params) => {
|
|
237
|
+
try {
|
|
238
|
+
await h.signUp.resendVerificationEmail(params);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
onAuthErrorRef.current?.(err);
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
193
244
|
};
|
|
194
245
|
}, [client]);
|
|
195
246
|
const value = useMemo(
|
|
@@ -256,6 +307,7 @@ export {
|
|
|
256
307
|
AuthLoading,
|
|
257
308
|
SignedIn,
|
|
258
309
|
SignedOut,
|
|
310
|
+
SmartHiveAuthError,
|
|
259
311
|
SmartHiveAuthProvider,
|
|
260
312
|
SmartHiveProvider,
|
|
261
313
|
buildRedirectUri,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Linking } from \"react-native\";\nimport { AuthRequest } from \"expo-auth-session\";\nimport * as WebBrowser from \"expo-web-browser\";\nimport * as SecureStore from \"expo-secure-store\";\nimport {\n initAuth,\n envFromPublishableKey,\n type AuthSession,\n type AuthStorage,\n type HeadlessClient,\n type HeadlessSignInResult,\n type HeadlessSignUpResult,\n type SmartHiveAuthClient,\n type SmartHiveAuthConfig,\n type SocialProvider,\n} from \"@smarthivelabs-devs/auth-sdk\";\n\n// ── Secure storage adapter ────────────────────────────────────────────────────\n\nconst secureStorage: AuthStorage = {\n getItem: (key) => SecureStore.getItemAsync(key),\n setItem: (key, value) => SecureStore.setItemAsync(key, value),\n removeItem: (key) => SecureStore.deleteItemAsync(key),\n};\n\nconst storageKeys = {\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\n// ── Config ────────────────────────────────────────────────────────────────────\n\nexport interface SmartHiveExpoConfig extends Omit<SmartHiveAuthConfig, \"storage\"> {\n /** Deep link redirect URI, e.g. \"myapp://auth/callback\" */\n redirectUri: string;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth routes through your domain — Google/Apple consent screens\n * show your domain instead of SmartHive's. Your backend must implement\n * GET /api/auth/social/:provider and GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\n/**\n * Build a deep link redirect URI from your Expo app scheme.\n * @example buildRedirectUri(\"myapp\") → \"myapp://auth/callback\"\n */\nexport function buildRedirectUri(scheme: string, path = \"auth/callback\"): string {\n return `${scheme}://${path}`;\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n// ── Auth client (Expo flavour) ─────────────────────────────────────────────────\n\n/**\n * Creates an auth client that uses SecureStore for token storage and\n * Linking.openURL for the OAuth redirect (instead of location.assign).\n */\nexport function initExpoAuth(config: SmartHiveExpoConfig): SmartHiveAuthClient {\n const base = initAuth({\n ...config,\n storage: secureStorage,\n temporaryStorage: secureStorage\n } as SmartHiveAuthConfig);\n\n return {\n ...base,\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri;\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const request = new AuthRequest({\n clientId: config.publishableKey,\n redirectUri,\n responseType: \"code\",\n usePKCE: true,\n state: options?.state,\n extraParams: {\n project_id: config.projectId,\n publishable_key: config.publishableKey\n }\n });\n const url = await request.makeAuthUrlAsync({\n authorizationEndpoint: `${authBase}/api/auth/oauth2/authorize`\n });\n\n if (request.codeVerifier) {\n await secureStorage.setItem(storageKeys.pkceVerifier, request.codeVerifier);\n }\n await secureStorage.setItem(storageKeys.pkceState, request.state);\n await Linking.openURL(url);\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri;\n let socialUrl: URL;\n\n if (config.socialProxyUrl) {\n // Route through the app's own backend — Google/Apple show the app's domain\n socialUrl = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n socialUrl.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n // Direct SmartHive route\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const env = envFromPublishableKey(config.publishableKey);\n socialUrl = new URL(`${authBase}/${env}/api/auth/social/${provider}`);\n socialUrl.searchParams.set(\"project_id\", config.projectId);\n socialUrl.searchParams.set(\"redirect_uri\", redirectUri);\n }\n\n // In-app browser sheet — auto-closes when redirectUri fires\n const result = await WebBrowser.openAuthSessionAsync(socialUrl.toString(), redirectUri);\n if (result.type === \"success\") {\n await base.handleSocialCallback({ url: result.url });\n }\n },\n };\n}\n\n// ── Context ────────────────────────────────────────────────────────────────────\n\ninterface AuthContextValue {\n client: SmartHiveAuthClient;\n session: AuthSession | null;\n isLoaded: boolean;\n isSignedIn: boolean;\n /** OAuth 2.0 + PKCE browser redirect sign-in (unchanged). */\n login(options?: { redirectUri?: string }): Promise<void>;\n logout(): Promise<void>;\n refreshSession(): Promise<void>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n authFetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n /**\n * Headless (no browser) sign-in methods for custom login screens.\n * Tokens are stored in SecureStore automatically on success.\n */\n signIn: {\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n phone: {\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n emailOtp: {\n send(params: { email: string }): Promise<void>;\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n magicLink: {\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n /** Initiate a social OAuth flow — opens an in-app browser sheet (expo-web-browser). Auto-closes on redirect and updates session state. */\n social(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n };\n signUp: {\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n resendVerificationEmail(params: { email: string }): Promise<void>;\n };\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n// ── Provider ───────────────────────────────────────────────────────────────────\n\nexport interface SmartHiveAuthProviderProps extends SmartHiveExpoConfig {\n children: React.ReactNode;\n}\n\n/** @deprecated Use SmartHiveAuthProviderProps */\nexport type SmartHiveProviderProps = SmartHiveAuthProviderProps;\n\n/**\n * Wraps your Expo app and provides auth state to all child components.\n * Tokens are stored in SecureStore. Supports both:\n * - OAuth 2.0 + PKCE browser redirect via `login()`\n * - Headless direct sign-in via `signIn.*` (no browser, custom login screens)\n */\nexport function SmartHiveAuthProvider({ children, ...config }: SmartHiveAuthProviderProps) {\n const configRef = useRef(config);\n const client = useMemo(() => initExpoAuth(configRef.current), []);\n\n const [session, setSession] = useState<AuthSession | null>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n\n // Initial session load from SecureStore\n useEffect(() => {\n let cancelled = false;\n client\n .initialize()\n .then(() => client.getSession())\n .then((s) => { if (!cancelled) setSession(s); })\n .catch(() => {})\n .finally(() => { if (!cancelled) setIsLoaded(true); });\n return () => { cancelled = true; };\n }, [client]);\n\n // Deep link listener — catches both PKCE and social OAuth callbacks\n useEffect(() => {\n function handleUrl({ url }: { url: string }) {\n try {\n const parsed = new URL(url);\n if (parsed.searchParams.has(\"access_token\") || parsed.searchParams.has(\"error\")) {\n // Social auth callback — tokens already in URL params\n client\n .handleSocialCallback({ url })\n .then((s) => setSession(s))\n .catch(() => {});\n } else {\n // PKCE OAuth callback — exchange code for tokens\n client\n .handleCallback({ url })\n .then((s) => setSession(s))\n .catch(() => {});\n }\n } catch {\n // Unparseable URL — ignore\n }\n }\n\n const sub = Linking.addEventListener(\"url\", handleUrl);\n\n // Handle cold-start: app opened directly from the OAuth redirect URL\n Linking.getInitialURL().then((url) => {\n if (url) handleUrl({ url });\n });\n\n return () => sub.remove();\n }, [client]);\n\n const login = useCallback(\n (options?: { redirectUri?: string }) => client.login(options),\n [client]\n );\n\n const logout = useCallback(async () => {\n await client.logout();\n setSession(null);\n }, [client]);\n\n const refreshSession = useCallback(async () => {\n setSession(await client.refreshSession());\n }, [client]);\n\n const getAuthorizationHeader = useCallback(\n () => client.getAuthorizationHeader(),\n [client]\n );\n\n const authFetch = useCallback(\n (input: string | URL | Request, init?: RequestInit) => client.fetch(input, init),\n [client]\n );\n\n // ── Headless sign-in wrappers — save session + update state ──────────────────\n\n function wrapHeadlessSignIn(\n fn: (p: never) => Promise<HeadlessSignInResult>\n ) {\n return async (params: never) => {\n const result = await fn(params);\n setSession({\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: result.expiresAt,\n user: result.user,\n });\n return result;\n };\n }\n\n const signIn = useMemo<AuthContextValue[\"signIn\"]>(() => {\n const h: HeadlessClient = client.headless;\n return {\n email: wrapHeadlessSignIn(h.signIn.email.bind(h.signIn) as never),\n phone: {\n sendOtp: (p) => h.signIn.phone.sendOtp(p),\n verify: wrapHeadlessSignIn(h.signIn.phone.verify.bind(h.signIn.phone) as never),\n },\n emailOtp: {\n send: (p) => h.signIn.emailOtp.send(p),\n verify: wrapHeadlessSignIn(h.signIn.emailOtp.verify.bind(h.signIn.emailOtp) as never),\n },\n magicLink: {\n send: (p) => h.signIn.magicLink.send(p),\n },\n social: async (provider, options) => {\n await client.loginSocial(provider, options);\n // loginSocial used openAuthSessionAsync + handleSocialCallback — session is now in SecureStore\n const s = await client.getSession();\n if (s) setSession(s);\n },\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client]);\n\n const signUp = useMemo<AuthContextValue[\"signUp\"]>(() => {\n const h: HeadlessClient = client.headless;\n return {\n email: async (params) => {\n const result = await h.signUp.email(params);\n if (!result.requiresVerification) {\n setSession({\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: result.expiresAt,\n user: result.user,\n });\n }\n return result;\n },\n resendVerificationEmail: (params) => h.signUp.resendVerificationEmail(params),\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client]);\n\n const value = useMemo<AuthContextValue>(\n () => ({\n client,\n session,\n isLoaded,\n isSignedIn: !!session,\n login,\n logout,\n refreshSession,\n getAuthorizationHeader,\n authFetch,\n signIn,\n signUp,\n }),\n [client, session, isLoaded, login, logout, refreshSession, getAuthorizationHeader, authFetch, signIn, signUp]\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n// ── Hooks ──────────────────────────────────────────────────────────────────────\n\nfunction useAuthContext(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) throw new Error(\"useAuth must be used inside <SmartHiveAuthProvider>.\");\n return ctx;\n}\n\nexport function useAuth() { return useAuthContext(); }\nexport function useSession() { return useAuthContext().session; }\nexport function useUser() { return useAuthContext().session?.user ?? null; }\nexport function useIsLoaded() { return useAuthContext().isLoaded; }\n\nexport function useIsSignedIn() {\n const { isLoaded, isSignedIn } = useAuthContext();\n return isLoaded ? isSignedIn : null;\n}\n\nexport function useAuthFetch() {\n return useAuthContext().authFetch;\n}\n\nexport function useAuthorizationHeader() {\n return useAuthContext().getAuthorizationHeader;\n}\n\n/** @deprecated Use SmartHiveAuthProvider */\nexport const SmartHiveProvider = SmartHiveAuthProvider;\n\n// ── Render helpers ─────────────────────────────────────────────────────────────\n\nexport function SignedIn({ children }: { children: React.ReactNode }) {\n const { isLoaded, isSignedIn } = useAuthContext();\n if (!isLoaded || !isSignedIn) return null;\n return <>{children}</>;\n}\n\nexport function SignedOut({ children }: { children: React.ReactNode }) {\n const { isLoaded, isSignedIn } = useAuthContext();\n if (!isLoaded || isSignedIn) return null;\n return <>{children}</>;\n}\n\nexport function AuthLoading({ children }: { children: React.ReactNode }) {\n const { isLoaded } = useAuthContext();\n return isLoaded ? null : <>{children}</>;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Linking } from \"react-native\";\nimport { AuthRequest } from \"expo-auth-session\";\nimport * as WebBrowser from \"expo-web-browser\";\nimport * as SecureStore from \"expo-secure-store\";\nimport {\n initAuth,\n SmartHiveAuthError,\n envFromPublishableKey,\n type AuthSession,\n type AuthStorage,\n type HeadlessClient,\n type HeadlessSignInResult,\n type HeadlessSignUpResult,\n type SmartHiveAuthClient,\n type SmartHiveAuthConfig,\n type SocialProvider,\n} from \"@smarthivelabs-devs/auth-sdk\";\n\nexport { SmartHiveAuthError };\n\n// ── Secure storage adapter ────────────────────────────────────────────────────\n\nconst secureStorage: AuthStorage = {\n getItem: (key) => SecureStore.getItemAsync(key),\n setItem: (key, value) => SecureStore.setItemAsync(key, value),\n removeItem: (key) => SecureStore.deleteItemAsync(key),\n};\n\nconst storageKeys = {\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\n// ── Config ────────────────────────────────────────────────────────────────────\n\nexport interface SmartHiveExpoConfig extends Omit<SmartHiveAuthConfig, \"storage\"> {\n /** Deep link redirect URI, e.g. \"myapp://auth/callback\" */\n redirectUri: string;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth routes through your domain — Google/Apple consent screens\n * show your domain instead of SmartHive's. Your backend must implement\n * GET /api/auth/social/:provider and GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\n/**\n * Build a deep link redirect URI from your Expo app scheme.\n * @example buildRedirectUri(\"myapp\") → \"myapp://auth/callback\"\n */\nexport function buildRedirectUri(scheme: string, path = \"auth/callback\"): string {\n return `${scheme}://${path}`;\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n// ── Auth client (Expo flavour) ─────────────────────────────────────────────────\n\n/**\n * Creates an auth client that uses SecureStore for token storage and\n * Linking.openURL for the OAuth redirect (instead of location.assign).\n */\nexport function initExpoAuth(config: SmartHiveExpoConfig): SmartHiveAuthClient {\n const base = initAuth({\n ...config,\n storage: secureStorage,\n temporaryStorage: secureStorage\n } as SmartHiveAuthConfig);\n\n return {\n ...base,\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri;\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const request = new AuthRequest({\n clientId: config.publishableKey,\n redirectUri,\n responseType: \"code\",\n usePKCE: true,\n state: options?.state,\n extraParams: {\n project_id: config.projectId,\n publishable_key: config.publishableKey\n }\n });\n const url = await request.makeAuthUrlAsync({\n authorizationEndpoint: `${authBase}/api/auth/oauth2/authorize`\n });\n\n if (request.codeVerifier) {\n await secureStorage.setItem(storageKeys.pkceVerifier, request.codeVerifier);\n }\n await secureStorage.setItem(storageKeys.pkceState, request.state);\n await Linking.openURL(url);\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri;\n let socialUrl: URL;\n\n if (config.socialProxyUrl) {\n // Route through the app's own backend — Google/Apple show the app's domain\n socialUrl = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n socialUrl.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n // Direct SmartHive route\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const env = envFromPublishableKey(config.publishableKey);\n socialUrl = new URL(`${authBase}/${env}/api/auth/social/${provider}`);\n socialUrl.searchParams.set(\"project_id\", config.projectId);\n socialUrl.searchParams.set(\"redirect_uri\", redirectUri);\n }\n\n // In-app browser sheet — auto-closes when redirectUri fires\n const result = await WebBrowser.openAuthSessionAsync(socialUrl.toString(), redirectUri);\n if (result.type === \"success\") {\n await base.handleSocialCallback({ url: result.url });\n }\n },\n\n async logout() {\n // React Native has no cookie jar, so the base SDK's credentials:\"include\" sign-out\n // endpoint never reaches the session. Use the headless signOut which sends the\n // refresh_token in the request body so the server can revoke the session.\n await base.headless.signOut();\n },\n };\n}\n\n// ── Context ────────────────────────────────────────────────────────────────────\n\ninterface AuthContextValue {\n client: SmartHiveAuthClient;\n session: AuthSession | null;\n isLoaded: boolean;\n isSignedIn: boolean;\n /** OAuth 2.0 + PKCE browser redirect sign-in (unchanged). */\n login(options?: { redirectUri?: string }): Promise<void>;\n logout(): Promise<void>;\n refreshSession(): Promise<void>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n authFetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n /**\n * Headless (no browser) sign-in methods for custom login screens.\n * Tokens are stored in SecureStore automatically on success.\n */\n signIn: {\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n phone: {\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n emailOtp: {\n send(params: { email: string }): Promise<void>;\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n magicLink: {\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n /** Initiate a social OAuth flow — opens an in-app browser sheet (expo-web-browser). Auto-closes on redirect and updates session state. */\n social(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n };\n signUp: {\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n resendVerificationEmail(params: { email: string }): Promise<void>;\n };\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\n// ── Provider ───────────────────────────────────────────────────────────────────\n\nexport interface SmartHiveAuthProviderProps extends SmartHiveExpoConfig {\n children: React.ReactNode;\n /** Called whenever any auth operation (sign-in, sign-up, OTP, OAuth callback) throws. Use this to show a global error toast. Errors still propagate to the caller after this. */\n onAuthError?: (error: unknown) => void;\n}\n\n/** @deprecated Use SmartHiveAuthProviderProps */\nexport type SmartHiveProviderProps = SmartHiveAuthProviderProps;\n\n/**\n * Wraps your Expo app and provides auth state to all child components.\n * Tokens are stored in SecureStore. Supports both:\n * - OAuth 2.0 + PKCE browser redirect via `login()`\n * - Headless direct sign-in via `signIn.*` (no browser, custom login screens)\n */\nexport function SmartHiveAuthProvider({ children, onAuthError, ...config }: SmartHiveAuthProviderProps) {\n const configRef = useRef(config);\n const client = useMemo(() => initExpoAuth(configRef.current), []);\n\n const [session, setSession] = useState<AuthSession | null>(null);\n const [isLoaded, setIsLoaded] = useState(false);\n\n // Initial session load from SecureStore\n useEffect(() => {\n let cancelled = false;\n client\n .initialize()\n .then(() => client.getSession())\n .then((s) => { if (!cancelled) setSession(s); })\n .catch(() => {})\n .finally(() => { if (!cancelled) setIsLoaded(true); });\n return () => { cancelled = true; };\n }, [client]);\n\n // Deep link listener — catches both PKCE and social OAuth callbacks\n useEffect(() => {\n function handleUrl({ url }: { url: string }) {\n try {\n const parsed = new URL(url);\n if (parsed.searchParams.has(\"access_token\") || parsed.searchParams.has(\"error\")) {\n // Social auth callback — tokens already in URL params\n client\n .handleSocialCallback({ url })\n .then((s) => setSession(s))\n .catch((err) => { onAuthError?.(err); });\n } else if (parsed.searchParams.has(\"code\")) {\n // PKCE OAuth callback — exchange code for tokens\n client\n .handleCallback({ url })\n .then((s) => setSession(s))\n .catch((err) => { onAuthError?.(err); });\n }\n } catch {\n // Unparseable URL — ignore\n }\n }\n\n const sub = Linking.addEventListener(\"url\", handleUrl);\n\n // Handle cold-start: app opened directly from the OAuth redirect URL\n Linking.getInitialURL().then((url) => {\n if (url) handleUrl({ url });\n });\n\n return () => sub.remove();\n }, [client]);\n\n const login = useCallback(\n (options?: { redirectUri?: string }) => client.login(options),\n [client]\n );\n\n const logout = useCallback(async () => {\n await client.logout();\n setSession(null);\n }, [client]);\n\n const refreshSession = useCallback(async () => {\n setSession(await client.refreshSession());\n }, [client]);\n\n const getAuthorizationHeader = useCallback(\n () => client.getAuthorizationHeader(),\n [client]\n );\n\n const authFetch = useCallback(\n (input: string | URL | Request, init?: RequestInit) => client.fetch(input, init),\n [client]\n );\n\n // ── Headless sign-in wrappers — save session + update state ──────────────────\n\n const onAuthErrorRef = useRef(onAuthError);\n onAuthErrorRef.current = onAuthError;\n\n function wrapHeadlessSignIn(fn: (p: never) => Promise<HeadlessSignInResult>) {\n return async (params: never) => {\n try {\n const result = await fn(params);\n setSession({\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: result.expiresAt,\n user: result.user,\n });\n return result;\n } catch (err) {\n onAuthErrorRef.current?.(err);\n throw err;\n }\n };\n }\n\n const signIn = useMemo<AuthContextValue[\"signIn\"]>(() => {\n const h: HeadlessClient = client.headless;\n return {\n email: wrapHeadlessSignIn(h.signIn.email.bind(h.signIn) as never),\n phone: {\n sendOtp: async (p) => { try { await h.signIn.phone.sendOtp(p); } catch (err) { onAuthErrorRef.current?.(err); throw err; } },\n verify: wrapHeadlessSignIn(h.signIn.phone.verify.bind(h.signIn.phone) as never),\n },\n emailOtp: {\n send: async (p) => { try { await h.signIn.emailOtp.send(p); } catch (err) { onAuthErrorRef.current?.(err); throw err; } },\n verify: wrapHeadlessSignIn(h.signIn.emailOtp.verify.bind(h.signIn.emailOtp) as never),\n },\n magicLink: {\n send: async (p) => { try { await h.signIn.magicLink.send(p); } catch (err) { onAuthErrorRef.current?.(err); throw err; } },\n },\n social: async (provider, options) => {\n try {\n await client.loginSocial(provider, options);\n const s = await client.getSession();\n if (s) setSession(s);\n } catch (err) {\n onAuthErrorRef.current?.(err);\n throw err;\n }\n },\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client]);\n\n const signUp = useMemo<AuthContextValue[\"signUp\"]>(() => {\n const h: HeadlessClient = client.headless;\n return {\n email: async (params) => {\n try {\n const result = await h.signUp.email(params);\n if (!result.requiresVerification) {\n setSession({\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt: result.expiresAt,\n user: result.user,\n });\n }\n return result;\n } catch (err) {\n onAuthErrorRef.current?.(err);\n throw err;\n }\n },\n resendVerificationEmail: async (params) => {\n try {\n await h.signUp.resendVerificationEmail(params);\n } catch (err) {\n onAuthErrorRef.current?.(err);\n throw err;\n }\n },\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client]);\n\n const value = useMemo<AuthContextValue>(\n () => ({\n client,\n session,\n isLoaded,\n isSignedIn: !!session,\n login,\n logout,\n refreshSession,\n getAuthorizationHeader,\n authFetch,\n signIn,\n signUp,\n }),\n [client, session, isLoaded, login, logout, refreshSession, getAuthorizationHeader, authFetch, signIn, signUp]\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n\n// ── Hooks ──────────────────────────────────────────────────────────────────────\n\nfunction useAuthContext(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (!ctx) throw new Error(\"useAuth must be used inside <SmartHiveAuthProvider>.\");\n return ctx;\n}\n\nexport function useAuth() { return useAuthContext(); }\nexport function useSession() { return useAuthContext().session; }\nexport function useUser() { return useAuthContext().session?.user ?? null; }\nexport function useIsLoaded() { return useAuthContext().isLoaded; }\n\nexport function useIsSignedIn() {\n const { isLoaded, isSignedIn } = useAuthContext();\n return isLoaded ? isSignedIn : null;\n}\n\nexport function useAuthFetch() {\n return useAuthContext().authFetch;\n}\n\nexport function useAuthorizationHeader() {\n return useAuthContext().getAuthorizationHeader;\n}\n\n/** @deprecated Use SmartHiveAuthProvider */\nexport const SmartHiveProvider = SmartHiveAuthProvider;\n\n// ── Render helpers ─────────────────────────────────────────────────────────────\n\nexport function SignedIn({ children }: { children: React.ReactNode }) {\n const { isLoaded, isSignedIn } = useAuthContext();\n if (!isLoaded || !isSignedIn) return null;\n return <>{children}</>;\n}\n\nexport function SignedOut({ children }: { children: React.ReactNode }) {\n const { isLoaded, isSignedIn } = useAuthContext();\n if (!isLoaded || isSignedIn) return null;\n return <>{children}</>;\n}\n\nexport function AuthLoading({ children }: { children: React.ReactNode }) {\n const { isLoaded } = useAuthContext();\n return isLoaded ? null : <>{children}</>;\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,YAAY,gBAAgB;AAC5B,YAAY,iBAAiB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OASK;AAgWE,SAqCA,UArCA;AA1VT,IAAM,gBAA6B;AAAA,EACjC,SAAS,CAAC,QAAoB,yBAAa,GAAG;AAAA,EAC9C,SAAS,CAAC,KAAK,UAAsB,yBAAa,KAAK,KAAK;AAAA,EAC5D,YAAY,CAAC,QAAoB,4BAAgB,GAAG;AACtD;AAEA,IAAM,cAAc;AAAA,EAClB,cAAc;AAAA,EACd,WAAW;AACb;AAoBO,SAAS,iBAAiB,QAAgB,OAAO,iBAAyB;AAC/E,SAAO,GAAG,MAAM,MAAM,IAAI;AAC5B;AAEA,SAAS,iBAAiB,SAAiB;AACzC,SAAO,QAAQ,QAAQ,OAAO,EAAE;AAClC;AAQO,SAAS,aAAa,QAAkD;AAC7E,QAAM,OAAO,SAAS;AAAA,IACpB,GAAG;AAAA,IACH,SAAS;AAAA,IACT,kBAAkB;AAAA,EACpB,CAAwB;AAExB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,MAAM,SAAS;AACnB,YAAM,cAAc,SAAS,eAAe,OAAO;AACnD,YAAM,WAAW,iBAAiB,OAAO,cAAc,OAAO,OAAO;AACrE,YAAM,UAAU,IAAI,YAAY;AAAA,QAC9B,UAAU,OAAO;AAAA,QACjB;AAAA,QACA,cAAc;AAAA,QACd,SAAS;AAAA,QACT,OAAO,SAAS;AAAA,QAChB,aAAa;AAAA,UACX,YAAY,OAAO;AAAA,UACnB,iBAAiB,OAAO;AAAA,QAC1B;AAAA,MACF,CAAC;AACD,YAAM,MAAM,MAAM,QAAQ,iBAAiB;AAAA,QACzC,uBAAuB,GAAG,QAAQ;AAAA,MACpC,CAAC;AAED,UAAI,QAAQ,cAAc;AACxB,cAAM,cAAc,QAAQ,YAAY,cAAc,QAAQ,YAAY;AAAA,MAC5E;AACA,YAAM,cAAc,QAAQ,YAAY,WAAW,QAAQ,KAAK;AAChE,YAAM,QAAQ,QAAQ,GAAG;AAAA,IAC3B;AAAA,IAEA,MAAM,YAAY,UAAU,SAAS;AACnC,YAAM,cAAc,SAAS,eAAe,OAAO;AACnD,UAAI;AAEJ,UAAI,OAAO,gBAAgB;AAEzB,oBAAY,IAAI,IAAI,GAAG,iBAAiB,OAAO,cAAc,CAAC,oBAAoB,QAAQ,EAAE;AAC5F,kBAAU,aAAa,IAAI,gBAAgB,WAAW;AAAA,MAExD,OAAO;AAEL,cAAM,WAAW,iBAAiB,OAAO,cAAc,OAAO,OAAO;AACrE,cAAM,MAAM,sBAAsB,OAAO,cAAc;AACvD,oBAAY,IAAI,IAAI,GAAG,QAAQ,IAAI,GAAG,oBAAoB,QAAQ,EAAE;AACpE,kBAAU,aAAa,IAAI,cAAc,OAAO,SAAS;AACzD,kBAAU,aAAa,IAAI,gBAAgB,WAAW;AAAA,MACxD;AAGA,YAAM,SAAS,MAAiB,gCAAqB,UAAU,SAAS,GAAG,WAAW;AACtF,UAAI,OAAO,SAAS,WAAW;AAC7B,cAAM,KAAK,qBAAqB,EAAE,KAAK,OAAO,IAAI,CAAC;AAAA,MACrD;AAAA,IACF;AAAA,IAEA,MAAM,SAAS;AAIb,YAAM,KAAK,SAAS,QAAQ;AAAA,IAC9B;AAAA,EACF;AACF;AAyCA,IAAM,cAAc,cAAuC,IAAI;AAmBxD,SAAS,sBAAsB,EAAE,UAAU,aAAa,GAAG,OAAO,GAA+B;AACtG,QAAM,YAAY,OAAO,MAAM;AAC/B,QAAM,SAAS,QAAQ,MAAM,aAAa,UAAU,OAAO,GAAG,CAAC,CAAC;AAEhE,QAAM,CAAC,SAAS,UAAU,IAAI,SAA6B,IAAI;AAC/D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAG9C,YAAU,MAAM;AACd,QAAI,YAAY;AAChB,WACG,WAAW,EACX,KAAK,MAAM,OAAO,WAAW,CAAC,EAC9B,KAAK,CAAC,MAAM;AAAE,UAAI,CAAC,UAAW,YAAW,CAAC;AAAA,IAAG,CAAC,EAC9C,MAAM,MAAM;AAAA,IAAC,CAAC,EACd,QAAQ,MAAM;AAAE,UAAI,CAAC,UAAW,aAAY,IAAI;AAAA,IAAG,CAAC;AACvD,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAM;AAAA,EACnC,GAAG,CAAC,MAAM,CAAC;AAGX,YAAU,MAAM;AACd,aAAS,UAAU,EAAE,IAAI,GAAoB;AAC3C,UAAI;AACF,cAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,YAAI,OAAO,aAAa,IAAI,cAAc,KAAK,OAAO,aAAa,IAAI,OAAO,GAAG;AAE/E,iBACG,qBAAqB,EAAE,IAAI,CAAC,EAC5B,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC,EACzB,MAAM,CAAC,QAAQ;AAAE,0BAAc,GAAG;AAAA,UAAG,CAAC;AAAA,QAC3C,WAAW,OAAO,aAAa,IAAI,MAAM,GAAG;AAE1C,iBACG,eAAe,EAAE,IAAI,CAAC,EACtB,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC,EACzB,MAAM,CAAC,QAAQ;AAAE,0BAAc,GAAG;AAAA,UAAG,CAAC;AAAA,QAC3C;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,MAAM,QAAQ,iBAAiB,OAAO,SAAS;AAGrD,YAAQ,cAAc,EAAE,KAAK,CAAC,QAAQ;AACpC,UAAI,IAAK,WAAU,EAAE,IAAI,CAAC;AAAA,IAC5B,CAAC;AAED,WAAO,MAAM,IAAI,OAAO;AAAA,EAC1B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,QAAQ;AAAA,IACZ,CAAC,YAAuC,OAAO,MAAM,OAAO;AAAA,IAC5D,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,SAAS,YAAY,YAAY;AACrC,UAAM,OAAO,OAAO;AACpB,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,iBAAiB,YAAY,YAAY;AAC7C,eAAW,MAAM,OAAO,eAAe,CAAC;AAAA,EAC1C,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,yBAAyB;AAAA,IAC7B,MAAM,OAAO,uBAAuB;AAAA,IACpC,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,YAAY;AAAA,IAChB,CAAC,OAA+B,SAAuB,OAAO,MAAM,OAAO,IAAI;AAAA,IAC/E,CAAC,MAAM;AAAA,EACT;AAIA,QAAM,iBAAiB,OAAO,WAAW;AACzC,iBAAe,UAAU;AAEzB,WAAS,mBAAmB,IAAiD;AAC3E,WAAO,OAAO,WAAkB;AAC9B,UAAI;AACF,cAAM,SAAS,MAAM,GAAG,MAAM;AAC9B,mBAAW;AAAA,UACT,aAAa,OAAO;AAAA,UACpB,cAAc,OAAO;AAAA,UACrB,WAAW,OAAO;AAAA,UAClB,MAAM,OAAO;AAAA,QACf,CAAC;AACD,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,uBAAe,UAAU,GAAG;AAC5B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,QAAoC,MAAM;AACvD,UAAM,IAAoB,OAAO;AACjC,WAAO;AAAA,MACL,OAAO,mBAAmB,EAAE,OAAO,MAAM,KAAK,EAAE,MAAM,CAAU;AAAA,MAChE,OAAO;AAAA,QACL,SAAS,OAAO,MAAM;AAAE,cAAI;AAAE,kBAAM,EAAE,OAAO,MAAM,QAAQ,CAAC;AAAA,UAAG,SAAS,KAAK;AAAE,2BAAe,UAAU,GAAG;AAAG,kBAAM;AAAA,UAAK;AAAA,QAAE;AAAA,QAC3H,QAAQ,mBAAmB,EAAE,OAAO,MAAM,OAAO,KAAK,EAAE,OAAO,KAAK,CAAU;AAAA,MAChF;AAAA,MACA,UAAU;AAAA,QACR,MAAM,OAAO,MAAM;AAAE,cAAI;AAAE,kBAAM,EAAE,OAAO,SAAS,KAAK,CAAC;AAAA,UAAG,SAAS,KAAK;AAAE,2BAAe,UAAU,GAAG;AAAG,kBAAM;AAAA,UAAK;AAAA,QAAE;AAAA,QACxH,QAAQ,mBAAmB,EAAE,OAAO,SAAS,OAAO,KAAK,EAAE,OAAO,QAAQ,CAAU;AAAA,MACtF;AAAA,MACA,WAAW;AAAA,QACT,MAAM,OAAO,MAAM;AAAE,cAAI;AAAE,kBAAM,EAAE,OAAO,UAAU,KAAK,CAAC;AAAA,UAAG,SAAS,KAAK;AAAE,2BAAe,UAAU,GAAG;AAAG,kBAAM;AAAA,UAAK;AAAA,QAAE;AAAA,MAC3H;AAAA,MACA,QAAQ,OAAO,UAAU,YAAY;AACnC,YAAI;AACF,gBAAM,OAAO,YAAY,UAAU,OAAO;AAC1C,gBAAM,IAAI,MAAM,OAAO,WAAW;AAClC,cAAI,EAAG,YAAW,CAAC;AAAA,QACrB,SAAS,KAAK;AACZ,yBAAe,UAAU,GAAG;AAC5B,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EAEF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,SAAS,QAAoC,MAAM;AACvD,UAAM,IAAoB,OAAO;AACjC,WAAO;AAAA,MACL,OAAO,OAAO,WAAW;AACvB,YAAI;AACF,gBAAM,SAAS,MAAM,EAAE,OAAO,MAAM,MAAM;AAC1C,cAAI,CAAC,OAAO,sBAAsB;AAChC,uBAAW;AAAA,cACT,aAAa,OAAO;AAAA,cACpB,cAAc,OAAO;AAAA,cACrB,WAAW,OAAO;AAAA,cAClB,MAAM,OAAO;AAAA,YACf,CAAC;AAAA,UACH;AACA,iBAAO;AAAA,QACT,SAAS,KAAK;AACZ,yBAAe,UAAU,GAAG;AAC5B,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA,yBAAyB,OAAO,WAAW;AACzC,YAAI;AACF,gBAAM,EAAE,OAAO,wBAAwB,MAAM;AAAA,QAC/C,SAAS,KAAK;AACZ,yBAAe,UAAU,GAAG;AAC5B,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EAEF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,CAAC,CAAC;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,SAAS,UAAU,OAAO,QAAQ,gBAAgB,wBAAwB,WAAW,QAAQ,MAAM;AAAA,EAC9G;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,UAAS;AACvD;AAIA,SAAS,iBAAmC;AAC1C,QAAM,MAAM,WAAW,WAAW;AAClC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sDAAsD;AAChF,SAAO;AACT;AAEO,SAAS,UAAU;AAAE,SAAO,eAAe;AAAG;AAC9C,SAAS,aAAa;AAAE,SAAO,eAAe,EAAE;AAAS;AACzD,SAAS,UAAU;AAAE,SAAO,eAAe,EAAE,SAAS,QAAQ;AAAM;AACpE,SAAS,cAAc;AAAE,SAAO,eAAe,EAAE;AAAU;AAE3D,SAAS,gBAAgB;AAC9B,QAAM,EAAE,UAAU,WAAW,IAAI,eAAe;AAChD,SAAO,WAAW,aAAa;AACjC;AAEO,SAAS,eAAe;AAC7B,SAAO,eAAe,EAAE;AAC1B;AAEO,SAAS,yBAAyB;AACvC,SAAO,eAAe,EAAE;AAC1B;AAGO,IAAM,oBAAoB;AAI1B,SAAS,SAAS,EAAE,SAAS,GAAkC;AACpE,QAAM,EAAE,UAAU,WAAW,IAAI,eAAe;AAChD,MAAI,CAAC,YAAY,CAAC,WAAY,QAAO;AACrC,SAAO,gCAAG,UAAS;AACrB;AAEO,SAAS,UAAU,EAAE,SAAS,GAAkC;AACrE,QAAM,EAAE,UAAU,WAAW,IAAI,eAAe;AAChD,MAAI,CAAC,YAAY,WAAY,QAAO;AACpC,SAAO,gCAAG,UAAS;AACrB;AAEO,SAAS,YAAY,EAAE,SAAS,GAAkC;AACvE,QAAM,EAAE,SAAS,IAAI,eAAe;AACpC,SAAO,WAAW,OAAO,gCAAG,UAAS;AACvC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smarthivelabs-devs/auth-expo",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "SmartHive Auth provider, hooks, and SecureStore integration for React Native / Expo",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,9 +37,11 @@
|
|
|
37
37
|
"expo-auth-session": "^55.0.15",
|
|
38
38
|
"expo-secure-store": "^55.0.13",
|
|
39
39
|
"expo-web-browser": "^55.0.15",
|
|
40
|
+
"react": "^18.3.1",
|
|
41
|
+
"react-native": "^0.79.0",
|
|
40
42
|
"tsup": "^8.5.1",
|
|
41
43
|
"typescript": "^6.0.3",
|
|
42
|
-
"@smarthivelabs-devs/auth-sdk": "^1.5.
|
|
44
|
+
"@smarthivelabs-devs/auth-sdk": "^1.5.2"
|
|
43
45
|
},
|
|
44
46
|
"scripts": {
|
|
45
47
|
"build": "tsup",
|