@proveanything/smartlinks-auth-ui 0.5.21 → 0.6.0
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/ACCOUNT_CACHING.md +349 -0
- package/ANDROID_NATIVE_BRIDGE.md +775 -0
- package/AUTH_STATE_MANAGEMENT.md +262 -0
- package/CAPACITOR_INTEGRATION.md +244 -0
- package/CUSTOMIZATION_GUIDE.md +411 -0
- package/README.md +73 -13
- package/SDK_DEBUGGING_GUIDE.md +217 -0
- package/SMARTLINKS_FRAME.md +302 -0
- package/SMARTLINKS_INTEGRATION.md +330 -0
- package/WHATSAPP_OTP_PLAN.md +106 -0
- package/dist/api.d.ts +15 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/components/ProviderButtons.d.ts +1 -0
- package/dist/components/ProviderButtons.d.ts.map +1 -1
- package/dist/components/SmartlinksAuthUI.d.ts.map +1 -1
- package/dist/context/AuthContext.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +386 -34
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +386 -33
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +98 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/persistentStorage.d.ts +14 -0
- package/dist/utils/persistentStorage.d.ts.map +1 -1
- package/dist/utils/tokenStorage.d.ts +7 -0
- package/dist/utils/tokenStorage.d.ts.map +1 -1
- package/package.json +15 -6
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# Smartlinks SDK Integration
|
|
2
|
+
|
|
3
|
+
The `@smartlinks/auth-ui` module now integrates with `@proveanything/smartlinks` SDK for enhanced session management and authenticated API calls.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The auth-ui package includes `@proveanything/smartlinks` as a dependency. When you install the auth-ui package, the Smartlinks SDK will be automatically included:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @smartlinks/auth-ui
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Basic Setup with Smartlinks SDK
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { AuthProvider, useAuth } from '@smartlinks/auth-ui';
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
return (
|
|
22
|
+
<AuthProvider
|
|
23
|
+
apiEndpoint="https://api.smartlinks.com"
|
|
24
|
+
clientId="your-client-id"
|
|
25
|
+
>
|
|
26
|
+
<YourApp />
|
|
27
|
+
</AuthProvider>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Access Smartlinks Client
|
|
33
|
+
|
|
34
|
+
The `useAuth` hook now provides access to the initialized Smartlinks client:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { useAuth } from '@smartlinks/auth-ui';
|
|
38
|
+
|
|
39
|
+
function Dashboard() {
|
|
40
|
+
const { user, token, smartlinks } = useAuth();
|
|
41
|
+
|
|
42
|
+
// Make authenticated API calls using Smartlinks SDK
|
|
43
|
+
const fetchData = async () => {
|
|
44
|
+
if (smartlinks) {
|
|
45
|
+
const data = await smartlinks.request('/api/data');
|
|
46
|
+
console.log('Data:', data);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div>
|
|
52
|
+
<h1>Welcome, {user?.displayName}</h1>
|
|
53
|
+
<button onClick={fetchData}>Fetch Data</button>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Smartlinks Client API
|
|
60
|
+
|
|
61
|
+
The Smartlinks client is automatically initialized and managed by the AuthProvider. It provides the following methods:
|
|
62
|
+
|
|
63
|
+
### Authentication
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
const { smartlinks } = useAuth();
|
|
67
|
+
|
|
68
|
+
// Token is automatically set on login
|
|
69
|
+
// But you can manually set it if needed
|
|
70
|
+
smartlinks?.setToken('bearer_token');
|
|
71
|
+
|
|
72
|
+
// Get current token
|
|
73
|
+
const token = smartlinks?.getToken();
|
|
74
|
+
|
|
75
|
+
// Clear token
|
|
76
|
+
smartlinks?.clearToken();
|
|
77
|
+
|
|
78
|
+
// Refresh token (automatically updates auth context)
|
|
79
|
+
await smartlinks?.refreshToken();
|
|
80
|
+
|
|
81
|
+
// Logout (calls server logout endpoint and clears local state)
|
|
82
|
+
await smartlinks?.logout();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Authenticated API Calls
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
// GET request
|
|
89
|
+
const data = await smartlinks?.request('/api/endpoint');
|
|
90
|
+
|
|
91
|
+
// POST request
|
|
92
|
+
const result = await smartlinks?.request(
|
|
93
|
+
'/api/endpoint',
|
|
94
|
+
'POST',
|
|
95
|
+
{ key: 'value' }
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// With custom headers
|
|
99
|
+
const result = await smartlinks?.request(
|
|
100
|
+
'/api/endpoint',
|
|
101
|
+
'POST',
|
|
102
|
+
{ key: 'value' },
|
|
103
|
+
{ 'X-Custom-Header': 'value' }
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### User Profile Management
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
// Get current user profile
|
|
111
|
+
const profile = await smartlinks?.getCurrentUser();
|
|
112
|
+
|
|
113
|
+
// Update user profile
|
|
114
|
+
const updated = await smartlinks?.updateProfile({
|
|
115
|
+
displayName: 'New Name',
|
|
116
|
+
photoURL: 'https://...'
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Account Data Management
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
// Get account data
|
|
124
|
+
const accountData = await smartlinks?.getAccountData();
|
|
125
|
+
|
|
126
|
+
// Update account data
|
|
127
|
+
const updated = await smartlinks?.updateAccountData({
|
|
128
|
+
plan: 'enterprise',
|
|
129
|
+
seats: 100
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Authentication Headers
|
|
134
|
+
|
|
135
|
+
The Smartlinks client automatically includes the following headers in all requests:
|
|
136
|
+
|
|
137
|
+
- `Authorization: Bearer {token}` - Bearer token from authentication
|
|
138
|
+
- `X-Client-ID: {clientId}` - Client identifier for multi-tenancy
|
|
139
|
+
- `Content-Type: application/json` - JSON content type
|
|
140
|
+
|
|
141
|
+
## Token Refresh
|
|
142
|
+
|
|
143
|
+
The SDK handles automatic token refresh:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
const { refreshToken } = useAuth();
|
|
147
|
+
|
|
148
|
+
// Manually refresh token
|
|
149
|
+
try {
|
|
150
|
+
await refreshToken();
|
|
151
|
+
console.log('Token refreshed successfully');
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error('Token refresh failed, user logged out');
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
If token refresh fails, the user is automatically logged out.
|
|
158
|
+
|
|
159
|
+
## Server-Side Logout
|
|
160
|
+
|
|
161
|
+
The `logout()` function now calls the server-side logout endpoint before clearing local state:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
const { logout } = useAuth();
|
|
165
|
+
|
|
166
|
+
// Logout (invalidates token on server)
|
|
167
|
+
await logout();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This ensures the bearer token is invalidated on the server, preventing its reuse.
|
|
171
|
+
|
|
172
|
+
## Example: Complete Authentication Flow
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import {
|
|
176
|
+
FirebaseAuthUI,
|
|
177
|
+
AuthProvider,
|
|
178
|
+
useAuth,
|
|
179
|
+
ProtectedRoute
|
|
180
|
+
} from '@smartlinks/auth-ui';
|
|
181
|
+
|
|
182
|
+
function App() {
|
|
183
|
+
return (
|
|
184
|
+
<AuthProvider
|
|
185
|
+
apiEndpoint="https://api.smartlinks.com"
|
|
186
|
+
clientId="your-client-id"
|
|
187
|
+
>
|
|
188
|
+
<Router>
|
|
189
|
+
<Routes>
|
|
190
|
+
<Route path="/login" element={<LoginPage />} />
|
|
191
|
+
<Route path="/dashboard" element={
|
|
192
|
+
<ProtectedRoute fallback={<Navigate to="/login" />}>
|
|
193
|
+
<Dashboard />
|
|
194
|
+
</ProtectedRoute>
|
|
195
|
+
} />
|
|
196
|
+
</Routes>
|
|
197
|
+
</Router>
|
|
198
|
+
</AuthProvider>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function LoginPage() {
|
|
203
|
+
const { login } = useAuth();
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<FirebaseAuthUI
|
|
207
|
+
apiEndpoint="https://api.smartlinks.com/api/v1/public/authui"
|
|
208
|
+
clientId="your-client-id"
|
|
209
|
+
accountData={{ plan: 'trial' }}
|
|
210
|
+
onAuthSuccess={(token, user, accountData) => {
|
|
211
|
+
// Auth context and Smartlinks SDK are automatically updated
|
|
212
|
+
login(token, user, accountData);
|
|
213
|
+
}}
|
|
214
|
+
enabledProviders={['email', 'google', 'phone']}
|
|
215
|
+
/>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function Dashboard() {
|
|
220
|
+
const { user, smartlinks, logout } = useAuth();
|
|
221
|
+
const [data, setData] = useState(null);
|
|
222
|
+
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
loadData();
|
|
225
|
+
}, []);
|
|
226
|
+
|
|
227
|
+
const loadData = async () => {
|
|
228
|
+
if (smartlinks) {
|
|
229
|
+
const result = await smartlinks.request('/api/dashboard');
|
|
230
|
+
setData(result);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const handleLogout = async () => {
|
|
235
|
+
await logout(); // Invalidates token on server
|
|
236
|
+
// User is redirected to login by ProtectedRoute
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<div>
|
|
241
|
+
<h1>Welcome, {user?.displayName}</h1>
|
|
242
|
+
<pre>{JSON.stringify(data, null, 2)}</pre>
|
|
243
|
+
<button onClick={handleLogout}>Logout</button>
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Backend Requirements
|
|
250
|
+
|
|
251
|
+
Your Smartlinks backend should implement these endpoints:
|
|
252
|
+
|
|
253
|
+
### POST /auth/refresh
|
|
254
|
+
```json
|
|
255
|
+
Request: { "token": "current_bearer_token" }
|
|
256
|
+
Response: { "token": "new_bearer_token" }
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### POST /auth/logout
|
|
260
|
+
```json
|
|
261
|
+
Request: Headers: Authorization: Bearer {token}
|
|
262
|
+
Response: { "success": true }
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### GET /user/me
|
|
266
|
+
```json
|
|
267
|
+
Response: { "uid": "...", "email": "...", "displayName": "..." }
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### PATCH /user/me
|
|
271
|
+
```json
|
|
272
|
+
Request: { "displayName": "New Name" }
|
|
273
|
+
Response: { "uid": "...", "email": "...", "displayName": "New Name" }
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### GET /account/me
|
|
277
|
+
```json
|
|
278
|
+
Response: { "clientId": "...", "plan": "pro", ... }
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### PATCH /account/me
|
|
282
|
+
```json
|
|
283
|
+
Request: { "plan": "enterprise" }
|
|
284
|
+
Response: { "clientId": "...", "plan": "enterprise", ... }
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## TypeScript Support
|
|
288
|
+
|
|
289
|
+
Full TypeScript definitions are included:
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import type {
|
|
293
|
+
SmartlinksClient,
|
|
294
|
+
AuthContextValue
|
|
295
|
+
} from '@smartlinks/auth-ui';
|
|
296
|
+
|
|
297
|
+
const { smartlinks }: AuthContextValue = useAuth();
|
|
298
|
+
|
|
299
|
+
// smartlinks is typed as SmartlinksClient | null
|
|
300
|
+
if (smartlinks) {
|
|
301
|
+
const data = await smartlinks.request<MyDataType>('/api/endpoint');
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Error Handling
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
const { smartlinks, logout } = useAuth();
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const data = await smartlinks?.request('/api/endpoint');
|
|
312
|
+
} catch (error) {
|
|
313
|
+
if (error.message.includes('401')) {
|
|
314
|
+
// Token expired or invalid
|
|
315
|
+
await logout();
|
|
316
|
+
} else {
|
|
317
|
+
console.error('API error:', error);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Benefits of Smartlinks SDK Integration
|
|
323
|
+
|
|
324
|
+
1. **Automatic Token Management**: Token is automatically included in all API requests
|
|
325
|
+
2. **Automatic Refresh**: Token refresh is handled seamlessly
|
|
326
|
+
3. **Server-Side Logout**: Tokens are properly invalidated on logout
|
|
327
|
+
4. **Type Safety**: Full TypeScript support for all API calls
|
|
328
|
+
5. **Multi-Tenant Support**: Client ID automatically included in headers
|
|
329
|
+
6. **Centralized Error Handling**: Consistent error handling across all requests
|
|
330
|
+
7. **Profile & Account Management**: Built-in utilities for common operations
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# WhatsApp OTP Flow — Implementation Plan
|
|
2
|
+
|
|
3
|
+
This is the **outbound** WhatsApp flow: we send the user a templated WhatsApp
|
|
4
|
+
message containing a 6-digit code, they type it back into the form. It mirrors
|
|
5
|
+
the existing SMS phone-OTP flow (`PhoneAuthForm` + `sendPhoneCode` /
|
|
6
|
+
`verifyPhoneCode`) but uses the WhatsApp Business API instead of SMS.
|
|
7
|
+
|
|
8
|
+
This complements the existing **inbound** flow (user messages us, we
|
|
9
|
+
auto-recognise their phone number and log them in) which is already shipping.
|
|
10
|
+
|
|
11
|
+
## Why both flows
|
|
12
|
+
|
|
13
|
+
| Flow | UX | Cost | When it shines |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| **Inbound** (live) | Type name → tap "Open WhatsApp" → hit send | Free (no Meta template fee) | Mobile-first, "magical" feel, opens 24h support window automatically |
|
|
16
|
+
| **Outbound OTP** (this plan) | Type phone → receive code → type code | ~$0.005–0.05 per message (Meta authentication template) | Familiar pattern, works when user can't initiate (e.g. desktop without QR scan), no need for Meta-verified business profile to receive |
|
|
17
|
+
|
|
18
|
+
Admin should be able to enable either or both. When both are enabled, the WhatsApp screen offers a toggle ("Send me a code" / "I'll message you").
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 1. Backend (you)
|
|
23
|
+
|
|
24
|
+
Two new endpoints, mirroring the phone OTP pair:
|
|
25
|
+
|
|
26
|
+
### `POST /authkit/:clientId/whatsapp-code`
|
|
27
|
+
Request body:
|
|
28
|
+
```json
|
|
29
|
+
{ "phoneNumber": "+447700900123" }
|
|
30
|
+
```
|
|
31
|
+
Response:
|
|
32
|
+
```json
|
|
33
|
+
{ "verificationId": "wa_otp_abc123", "expiresAt": "2026-05-14T12:05:00Z" }
|
|
34
|
+
```
|
|
35
|
+
Behaviour:
|
|
36
|
+
- Generate 6-digit code, hash it, store `{ verificationId, phoneHash, codeHash, expiresAt, attempts: 0 }` with 5-min TTL.
|
|
37
|
+
- Send via Meta WhatsApp Cloud API using a pre-approved **authentication** template (e.g. `auth_code_v1` with `{{1}} = code`). Use the same Meta WABA + access token as the inbound flow.
|
|
38
|
+
- Rate-limit: max 3 sends per phone per hour, max 1 send per 30s.
|
|
39
|
+
- Errors: `429` rate-limited, `400` invalid phone, `502` Meta API error.
|
|
40
|
+
|
|
41
|
+
### `POST /authkit/:clientId/whatsapp-code/verify`
|
|
42
|
+
Request body:
|
|
43
|
+
```json
|
|
44
|
+
{ "verificationId": "wa_otp_abc123", "code": "482910" }
|
|
45
|
+
```
|
|
46
|
+
Response (success):
|
|
47
|
+
```json
|
|
48
|
+
{ "uid": "...", "token": "...", "refreshToken": "...", "isNewUser": true, "phoneNumber": "+447700900123" }
|
|
49
|
+
```
|
|
50
|
+
Behaviour:
|
|
51
|
+
- Compare hashed code, decrement `attempts` (max 5), on success call existing `ensureAccount` + issue tokens (same flow as `verifyPhoneCode`).
|
|
52
|
+
- Errors: `400` invalid/expired code, `429` too many attempts.
|
|
53
|
+
|
|
54
|
+
### SDK additions (`@proveanything/smartlinks`)
|
|
55
|
+
Add to the `authKit` namespace, mirroring `sendPhoneCode` / `verifyPhoneCode`:
|
|
56
|
+
```ts
|
|
57
|
+
authKit.sendWhatsAppCode(clientId, phoneNumber): Promise<{ verificationId, expiresAt }>
|
|
58
|
+
authKit.verifyWhatsAppCode(clientId, verificationId, code): Promise<AuthResponse>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 2. Frontend (auth-module — to do once SDK ships)
|
|
64
|
+
|
|
65
|
+
### `auth-module/src/api.ts`
|
|
66
|
+
Add two methods alongside `sendPhoneCode` / `verifyPhoneCode`:
|
|
67
|
+
```ts
|
|
68
|
+
async sendWhatsAppCode(phoneNumber: string)
|
|
69
|
+
async verifyWhatsAppCode(verificationId: string, code: string)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### `WhatsAppAuthForm.tsx`
|
|
73
|
+
Extend with a `mode` prop: `'inbound' | 'otp' | 'both'`.
|
|
74
|
+
- `inbound` (current behaviour, default): auto-issues link, polls webhook.
|
|
75
|
+
- `otp`: phone input → sends code → 6-digit OTP screen (reuse `OTPInput`).
|
|
76
|
+
- `both`: top-of-form segmented toggle ("Message us" / "Get a code"), defaulting to inbound on mobile and otp on desktop without QR scanner.
|
|
77
|
+
|
|
78
|
+
### `SmartlinksAuthUI.tsx`
|
|
79
|
+
Pass the configured WhatsApp mode (from AuthKit config) into `WhatsAppAuthForm`.
|
|
80
|
+
Add a `handleWhatsAppOtp(phoneNumber, code)` callback that calls
|
|
81
|
+
`api.verifyWhatsAppCode` and feeds the result into the same login pipeline as
|
|
82
|
+
`handlePhoneAuth`.
|
|
83
|
+
|
|
84
|
+
### Admin (`AdminPage.tsx`)
|
|
85
|
+
Under the WhatsApp toggle, add a sub-radio when enabled:
|
|
86
|
+
- ○ Inbound only (zero-friction)
|
|
87
|
+
- ○ Code only (familiar)
|
|
88
|
+
- ● Both (let user choose) ← default
|
|
89
|
+
|
|
90
|
+
Persist as `whatsappMode: 'inbound' | 'otp' | 'both'` on the AuthKit config doc.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 3. Sequencing
|
|
95
|
+
|
|
96
|
+
1. **You**: implement the two backend endpoints + SDK methods, ship as e.g. `@proveanything/smartlinks@1.14.0`.
|
|
97
|
+
2. **Me**: bump SDK version, add `api.ts` methods, extend form + admin toggle, wire into `SmartlinksAuthUI`.
|
|
98
|
+
3. **Both**: end-to-end test on a real phone with a Meta-approved auth template.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 4. Open questions
|
|
103
|
+
|
|
104
|
+
- **Template approval**: do you have a Meta-approved WhatsApp authentication template ready, or do we need to submit one? (Approval takes 1–24h.)
|
|
105
|
+
- **Phone number sharing with SMS**: should the WhatsApp OTP flow fall back to SMS if the user doesn't have WhatsApp installed (no read receipt within e.g. 60s)? This is a nice-to-have but adds complexity.
|
|
106
|
+
- **Cost cap**: do you want a per-AuthKit daily budget cap on WhatsApp template sends to prevent abuse?
|
package/dist/api.d.ts
CHANGED
|
@@ -20,6 +20,21 @@ export declare class AuthAPI {
|
|
|
20
20
|
tokenType?: 'id_token' | 'access_token';
|
|
21
21
|
}): Promise<AuthResponse>;
|
|
22
22
|
loginWithGoogleCode(code: string, redirectUri: string): Promise<AuthResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Sign in with Apple via an identity token (from native "Sign in with Apple"
|
|
25
|
+
* or the web JS flow). The backend verifies the JWT against Apple's keys.
|
|
26
|
+
*
|
|
27
|
+
* Delegates to `smartlinks.authKit.appleLogin`, which on success stores the
|
|
28
|
+
* bearer token automatically and invalidates the SDK cache.
|
|
29
|
+
*/
|
|
30
|
+
loginWithApple(identityToken: string, options?: {
|
|
31
|
+
authorizationCode?: string;
|
|
32
|
+
nonce?: string;
|
|
33
|
+
appleUserInfo?: {
|
|
34
|
+
email?: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
};
|
|
37
|
+
}): Promise<AuthResponse>;
|
|
23
38
|
sendPhoneCode(phoneNumber: string): Promise<{
|
|
24
39
|
verificationId: string;
|
|
25
40
|
}>;
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIpF;;;GAGG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,GAAG,CAAyC;gBAExC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU;IAQxF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAI7D,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAWnD,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAC7C,cAAc,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACjF,SAAS,CAAC,EAAE,UAAU,GAAG,cAAc,CAAC;KACzC,GAAG,OAAO,CAAC,YAAY,CAAC;IAmBnB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ interface ProviderButtonsProps {
|
|
|
6
6
|
providerOrder?: string[];
|
|
7
7
|
onEmailLogin?: () => void;
|
|
8
8
|
onGoogleLogin: () => Promise<void>;
|
|
9
|
+
onAppleLogin?: () => Promise<void> | void;
|
|
9
10
|
onPhoneLogin: () => void;
|
|
10
11
|
onMagicLinkLogin?: () => void;
|
|
11
12
|
onWhatsAppLogin?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderButtons.d.ts","sourceRoot":"","sources":["../../src/components/ProviderButtons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,gBAAgB,CAAC;AAExB,UAAU,oBAAoB;IAC5B,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"ProviderButtons.d.ts","sourceRoot":"","sources":["../../src/components/ProviderButtons.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,gBAAgB,CAAC;AAExB,UAAU,oBAAoB;IAC5B,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+I1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAcpE,OAAO,KAAK,EAAE,qBAAqB,EAAyF,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAcpE,OAAO,KAAK,EAAE,qBAAqB,EAAyF,MAAM,UAAU,CAAC;AAwW7I,QAAA,MAAM,mBAAmB,QAAa,OAAO,CAAC,IAAI,CAqBjD,CAAC;AAqDF,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAI/B,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAu2E5D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAOnG,OAAO,KAAK,EAAqC,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGvG,eAAO,MAAM,WAAW,6CAAyD,CAAC;AAGlF,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAOnG,OAAO,KAAK,EAAqC,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGvG,eAAO,MAAM,WAAW,6CAAyD,CAAC;AAGlF,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAg1CpD,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type { SmartlinksFrameProps, IframeResizeOptions, IframeResponderOptions,
|
|
|
5
5
|
export { AuthProvider, useAuth } from './context/AuthContext';
|
|
6
6
|
export { ProtectedRoute } from './components/ProtectedRoute';
|
|
7
7
|
export { tokenStorage } from './utils/tokenStorage';
|
|
8
|
+
export { setStorageAdapter } from './utils/persistentStorage';
|
|
9
|
+
export type { PersistentStorage, StorageBackend } from './utils/persistentStorage';
|
|
8
10
|
export { AuthUIPreview } from './components/AuthUIPreview';
|
|
9
11
|
export { getDefaultAuthKitId, setDefaultAuthKitId } from './utils/defaultAuthKit';
|
|
10
12
|
export { getFriendlyErrorMessage, isConflictError, isAuthError, isRateLimitError, isServerError, getErrorStatusCode, getErrorCode } from './utils/errorHandling';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EACL,eAAe,EAEf,gBAAgB,EAChB,cAAc,EAEd,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,aAAa,GACd,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EACL,eAAe,EAEf,gBAAgB,EAChB,cAAc,EAEd,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,UAAU,EACV,aAAa,GACd,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAInF,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAG3D,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAGlF,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,YAAY,EACb,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAC3K,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAE/F,YAAY,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACpH,4CAA4C;AAC5C,YAAY,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,kCAAkC,CAAC;AACrF,mFAAmF;AACnF,YAAY,EAAE,qBAAqB,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAGxF,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,YAAY,EACZ,aAAa,GACd,MAAM,wBAAwB,CAAC;AAGhC,mBAAmB,SAAS,CAAC;AAC7B,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG5E,OAAO,EAAE,gBAAgB,IAAI,cAAc,EAAE,MAAM,+BAA+B,CAAC"}
|