@blinkdotnew/sdk 0.18.1 → 0.18.3
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 +175 -123
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +18 -17
- package/dist/index.mjs +18 -17
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -30,17 +30,21 @@ const blink = createClient({
|
|
|
30
30
|
authRequired: false // Don't force immediate auth - let users browse first
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
// Authentication
|
|
33
|
+
// Authentication - Choose your mode:
|
|
34
34
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
35
|
+
// 🎯 MANAGED MODE: Quick setup with hosted auth page
|
|
36
|
+
const blink = createClient({
|
|
37
|
+
projectId: 'your-project',
|
|
38
|
+
auth: { mode: 'managed' }
|
|
39
|
+
})
|
|
40
|
+
// Use: blink.auth.login() - redirects to blink.new auth
|
|
39
41
|
|
|
40
|
-
//
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
// 🎨 HEADLESS MODE: Custom UI with full control
|
|
43
|
+
const blink = createClient({
|
|
44
|
+
projectId: 'your-project',
|
|
45
|
+
auth: { mode: 'headless' }
|
|
46
|
+
})
|
|
47
|
+
// Use: blink.auth.signInWithEmail(), blink.auth.signInWithGoogle(), etc.
|
|
44
48
|
|
|
45
49
|
// Current user (works in both modes)
|
|
46
50
|
const user = await blink.auth.me()
|
|
@@ -193,65 +197,80 @@ blink.auth.setToken(jwtFromHeader)
|
|
|
193
197
|
|
|
194
198
|
> **⚠️ Version Requirement**: The flexible authentication system requires SDK version **0.18.0 or higher**. Version 0.17.x and below only support the legacy authentication system.
|
|
195
199
|
|
|
196
|
-
Blink provides **two authentication modes
|
|
197
|
-
|
|
198
|
-
#### Managed Mode (Default - Redirect-based)
|
|
200
|
+
Blink provides **two authentication modes**:
|
|
199
201
|
|
|
200
|
-
|
|
202
|
+
## 🎯 Managed Mode (Redirect-based)
|
|
203
|
+
**Perfect for:** Quick setup, minimal code
|
|
204
|
+
**Best for:** Websites, simple apps, MVP development
|
|
201
205
|
|
|
202
206
|
```typescript
|
|
203
|
-
// ⚠️ DEPRECATED: authRequired is legacy - use auth.mode instead
|
|
204
|
-
const blink = createClient({
|
|
205
|
-
projectId: 'your-project',
|
|
206
|
-
authRequired: false // Legacy - still works but deprecated
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
// ✅ RECOMMENDED: Use new auth configuration
|
|
210
207
|
const blink = createClient({
|
|
211
208
|
projectId: 'your-project',
|
|
212
|
-
auth: {
|
|
213
|
-
mode: 'managed', // Explicit mode configuration
|
|
214
|
-
redirectUrl: 'https://myapp.com/dashboard'
|
|
215
|
-
}
|
|
209
|
+
auth: { mode: 'managed' }
|
|
216
210
|
})
|
|
217
211
|
|
|
218
|
-
//
|
|
219
|
-
blink.auth.login() // Redirects to blink.new
|
|
212
|
+
// ONE METHOD: Redirect to hosted auth page
|
|
213
|
+
blink.auth.login() // → Redirects to blink.new/auth
|
|
220
214
|
blink.auth.logout() // Clear tokens and redirect
|
|
221
|
-
```
|
|
222
215
|
|
|
223
|
-
|
|
216
|
+
// User state (automatic after redirect)
|
|
217
|
+
const user = await blink.auth.me()
|
|
218
|
+
```
|
|
224
219
|
|
|
225
|
-
|
|
220
|
+
## 🎨 Headless Mode (Custom UI)
|
|
221
|
+
**Perfect for:** Custom branding, advanced UX, mobile apps
|
|
222
|
+
**Best for:** Production apps, branded experiences
|
|
226
223
|
|
|
227
224
|
```typescript
|
|
228
225
|
const blink = createClient({
|
|
229
226
|
projectId: 'your-project',
|
|
230
|
-
auth: {
|
|
231
|
-
mode: 'headless'
|
|
232
|
-
// Providers controlled via project settings
|
|
233
|
-
}
|
|
227
|
+
auth: { mode: 'headless' }
|
|
234
228
|
})
|
|
235
229
|
|
|
236
|
-
//
|
|
237
|
-
const user = await blink.auth.signUp({
|
|
238
|
-
|
|
239
|
-
password: 'SecurePass123!',
|
|
240
|
-
metadata: { displayName: 'John Doe' }
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
const user = await blink.auth.signInWithEmail('user@example.com', 'password')
|
|
244
|
-
|
|
245
|
-
// Social provider authentication
|
|
230
|
+
// MULTIPLE METHODS: Build your own UI
|
|
231
|
+
const user = await blink.auth.signUp({ email, password })
|
|
232
|
+
const user = await blink.auth.signInWithEmail(email, password)
|
|
246
233
|
const user = await blink.auth.signInWithGoogle()
|
|
247
234
|
const user = await blink.auth.signInWithGitHub()
|
|
248
235
|
const user = await blink.auth.signInWithApple()
|
|
249
236
|
const user = await blink.auth.signInWithMicrosoft()
|
|
250
237
|
|
|
251
238
|
// Magic links (passwordless)
|
|
252
|
-
await blink.auth.sendMagicLink(
|
|
253
|
-
|
|
239
|
+
await blink.auth.sendMagicLink(email)
|
|
240
|
+
|
|
241
|
+
// Password management
|
|
242
|
+
await blink.auth.sendPasswordResetEmail(email)
|
|
243
|
+
await blink.auth.sendPasswordResetEmail(email, {
|
|
244
|
+
redirectUrl: 'https://myapp.com/reset-password'
|
|
245
|
+
})
|
|
246
|
+
await blink.auth.changePassword(oldPass, newPass)
|
|
247
|
+
|
|
248
|
+
// Email verification
|
|
249
|
+
await blink.auth.sendEmailVerification()
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### ⚡ Quick Mode Comparison
|
|
253
|
+
|
|
254
|
+
| Feature | **Managed Mode** | **Headless Mode** |
|
|
255
|
+
|---------|------------------|-------------------|
|
|
256
|
+
| **Setup** | 1 line of code | Custom UI required |
|
|
257
|
+
| **Methods** | `login()` only | `signInWith*()` methods |
|
|
258
|
+
| **UI** | Hosted auth page | Your custom forms |
|
|
259
|
+
| **Branding** | Blink-branded | Fully customizable |
|
|
260
|
+
| **Mobile** | Web redirects | Native integration |
|
|
261
|
+
|
|
262
|
+
### 🚨 **Common Mistake**
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// ❌ WRONG: Using managed method in headless mode
|
|
266
|
+
const blink = createClient({
|
|
267
|
+
auth: { mode: 'headless' }
|
|
254
268
|
})
|
|
269
|
+
blink.auth.login() // Still redirects! Wrong method for headless
|
|
270
|
+
|
|
271
|
+
// ✅ CORRECT: Use headless methods
|
|
272
|
+
await blink.auth.signInWithEmail(email, password)
|
|
273
|
+
await blink.auth.signInWithGoogle()
|
|
255
274
|
```
|
|
256
275
|
|
|
257
276
|
#### 🔧 Provider Configuration
|
|
@@ -418,6 +437,10 @@ blink.auth.setToken(jwt, persist?)
|
|
|
418
437
|
const isAuth = blink.auth.isAuthenticated()
|
|
419
438
|
|
|
420
439
|
// Password management
|
|
440
|
+
await blink.auth.sendPasswordResetEmail('user@example.com')
|
|
441
|
+
await blink.auth.sendPasswordResetEmail('user@example.com', {
|
|
442
|
+
redirectUrl: 'https://myapp.com/reset-password' // Custom reset page
|
|
443
|
+
})
|
|
421
444
|
await blink.auth.changePassword('oldPass', 'newPass')
|
|
422
445
|
await blink.auth.confirmPasswordReset(token, newPassword)
|
|
423
446
|
|
|
@@ -1567,8 +1590,8 @@ const blink = createClient({
|
|
|
1567
1590
|
baseUrl: 'https://custom-api.example.com',
|
|
1568
1591
|
auth: {
|
|
1569
1592
|
mode: 'headless', // 'managed' | 'headless'
|
|
1570
|
-
authUrl: 'https://
|
|
1571
|
-
coreUrl: 'https://custom-core.example.com', // Custom API domain
|
|
1593
|
+
authUrl: 'https://your-auth-service.com', // Custom auth domain (for all auth endpoints)
|
|
1594
|
+
coreUrl: 'https://custom-core.example.com', // Custom API domain (for db, ai, storage)
|
|
1572
1595
|
// Providers controlled via project settings
|
|
1573
1596
|
redirectUrl: 'https://myapp.com/dashboard',
|
|
1574
1597
|
roles: {
|
|
@@ -1777,146 +1800,126 @@ function MyRealtimeComponent() {
|
|
|
1777
1800
|
|
|
1778
1801
|
### React
|
|
1779
1802
|
|
|
1780
|
-
####
|
|
1803
|
+
#### 🔑 Complete Examples by Mode
|
|
1781
1804
|
|
|
1782
|
-
|
|
1805
|
+
**🎯 Managed Mode Example:**
|
|
1783
1806
|
|
|
1784
1807
|
```typescript
|
|
1785
1808
|
import { createClient } from '@blinkdotnew/sdk'
|
|
1786
|
-
import { useState, useEffect } from 'react'
|
|
1787
1809
|
|
|
1788
|
-
// ✅ RECOMMENDED: Don't force immediate auth - let users browse first
|
|
1789
1810
|
const blink = createClient({
|
|
1790
1811
|
projectId: 'your-project',
|
|
1791
|
-
|
|
1792
|
-
auth: {
|
|
1793
|
-
mode: 'headless' // Use headless for custom UI
|
|
1794
|
-
// Providers controlled via project settings
|
|
1795
|
-
}
|
|
1812
|
+
auth: { mode: 'managed' }
|
|
1796
1813
|
})
|
|
1797
1814
|
|
|
1798
1815
|
function App() {
|
|
1799
1816
|
const [user, setUser] = useState(null)
|
|
1800
|
-
const [loading, setLoading] = useState(true)
|
|
1801
|
-
const [currentPage, setCurrentPage] = useState('home')
|
|
1802
1817
|
|
|
1803
|
-
// ✅ CRITICAL: Always use onAuthStateChanged
|
|
1804
1818
|
useEffect(() => {
|
|
1805
1819
|
const unsubscribe = blink.auth.onAuthStateChanged((state) => {
|
|
1806
1820
|
setUser(state.user)
|
|
1807
|
-
setLoading(state.isLoading)
|
|
1808
1821
|
})
|
|
1809
1822
|
return unsubscribe
|
|
1810
1823
|
}, [])
|
|
1811
1824
|
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1825
|
+
if (!user) {
|
|
1826
|
+
return (
|
|
1827
|
+
<div>
|
|
1828
|
+
<h1>Welcome to My App</h1>
|
|
1829
|
+
<button onClick={() => blink.auth.login()}>
|
|
1830
|
+
Sign In
|
|
1831
|
+
</button>
|
|
1832
|
+
</div>
|
|
1833
|
+
)
|
|
1834
|
+
}
|
|
1817
1835
|
|
|
1818
|
-
// Public pages (home, pricing, about) don't require auth
|
|
1819
|
-
if (currentPage === 'home') return <HomePage />
|
|
1820
|
-
if (currentPage === 'pricing') return <PricingPage />
|
|
1821
|
-
|
|
1822
|
-
// Protected pages require authentication
|
|
1823
1836
|
return <Dashboard user={user} />
|
|
1824
1837
|
}
|
|
1838
|
+
```
|
|
1839
|
+
|
|
1840
|
+
**🎨 Headless Mode Example:**
|
|
1841
|
+
|
|
1842
|
+
```typescript
|
|
1843
|
+
import { createClient } from '@blinkdotnew/sdk'
|
|
1844
|
+
|
|
1845
|
+
const blink = createClient({
|
|
1846
|
+
projectId: 'your-project',
|
|
1847
|
+
auth: { mode: 'headless' }
|
|
1848
|
+
})
|
|
1825
1849
|
|
|
1826
1850
|
function AuthForm() {
|
|
1827
1851
|
const [mode, setMode] = useState('signin') // 'signin' | 'signup' | 'reset'
|
|
1828
1852
|
const [email, setEmail] = useState('')
|
|
1829
1853
|
const [password, setPassword] = useState('')
|
|
1830
|
-
const [error, setError] = useState('')
|
|
1831
1854
|
const [message, setMessage] = useState('')
|
|
1832
1855
|
|
|
1833
|
-
const handleEmailAuth = async (
|
|
1834
|
-
e.preventDefault()
|
|
1835
|
-
setError('')
|
|
1836
|
-
|
|
1856
|
+
const handleEmailAuth = async () => {
|
|
1837
1857
|
try {
|
|
1838
|
-
if (mode === '
|
|
1839
|
-
const user = await blink.auth.signUp({ email, password })
|
|
1840
|
-
setMessage('Account created! Please check your email to verify.')
|
|
1841
|
-
await blink.auth.sendEmailVerification()
|
|
1842
|
-
} else if (mode === 'signin') {
|
|
1858
|
+
if (mode === 'signin') {
|
|
1843
1859
|
await blink.auth.signInWithEmail(email, password)
|
|
1844
|
-
|
|
1860
|
+
} else if (mode === 'signup') {
|
|
1861
|
+
await blink.auth.signUp({ email, password })
|
|
1862
|
+
setMessage('Account created! Check your email to verify.')
|
|
1845
1863
|
} else if (mode === 'reset') {
|
|
1846
|
-
await blink.auth.sendPasswordResetEmail(email
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
if (err.code === 'EMAIL_NOT_VERIFIED') {
|
|
1851
|
-
setError('Please verify your email first')
|
|
1852
|
-
await blink.auth.sendEmailVerification()
|
|
1853
|
-
} else {
|
|
1854
|
-
setError(err.message)
|
|
1864
|
+
await blink.auth.sendPasswordResetEmail(email, {
|
|
1865
|
+
redirectUrl: 'https://myapp.com/reset-password' // Your custom reset page
|
|
1866
|
+
})
|
|
1867
|
+
setMessage('Password reset email sent! Check your inbox.')
|
|
1855
1868
|
}
|
|
1869
|
+
} catch (error) {
|
|
1870
|
+
console.error('Auth failed:', error.message)
|
|
1856
1871
|
}
|
|
1857
1872
|
}
|
|
1858
1873
|
|
|
1859
|
-
const handleSocialAuth = async (
|
|
1874
|
+
const handleSocialAuth = async () => {
|
|
1860
1875
|
try {
|
|
1861
|
-
await blink.auth.
|
|
1862
|
-
} catch (
|
|
1863
|
-
|
|
1876
|
+
await blink.auth.signInWithGoogle()
|
|
1877
|
+
} catch (error) {
|
|
1878
|
+
console.error('Social auth failed:', error.message)
|
|
1864
1879
|
}
|
|
1865
1880
|
}
|
|
1866
1881
|
|
|
1867
1882
|
return (
|
|
1868
|
-
<div
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
{error && <div style={{ color: 'red', marginBottom: '1rem' }}>{error}</div>}
|
|
1872
|
-
{message && <div style={{ color: 'green', marginBottom: '1rem' }}>{message}</div>}
|
|
1883
|
+
<div>
|
|
1884
|
+
{message && <p style={{ color: 'green' }}>{message}</p>}
|
|
1873
1885
|
|
|
1874
|
-
<form onSubmit={handleEmailAuth}
|
|
1875
|
-
<input
|
|
1876
|
-
type="email"
|
|
1877
|
-
placeholder="Email"
|
|
1886
|
+
<form onSubmit={handleEmailAuth}>
|
|
1887
|
+
<input
|
|
1888
|
+
type="email"
|
|
1878
1889
|
value={email}
|
|
1879
1890
|
onChange={(e) => setEmail(e.target.value)}
|
|
1880
|
-
|
|
1891
|
+
placeholder="Email"
|
|
1881
1892
|
/>
|
|
1882
1893
|
|
|
1883
1894
|
{mode !== 'reset' && (
|
|
1884
|
-
<input
|
|
1885
|
-
type="password"
|
|
1886
|
-
placeholder="Password"
|
|
1895
|
+
<input
|
|
1896
|
+
type="password"
|
|
1887
1897
|
value={password}
|
|
1888
1898
|
onChange={(e) => setPassword(e.target.value)}
|
|
1889
|
-
|
|
1899
|
+
placeholder="Password"
|
|
1890
1900
|
/>
|
|
1891
1901
|
)}
|
|
1892
1902
|
|
|
1893
|
-
<button type="submit"
|
|
1894
|
-
{mode === 'signin' ? 'Sign In' : mode === 'signup' ? '
|
|
1903
|
+
<button type="submit">
|
|
1904
|
+
{mode === 'signin' ? 'Sign In' : mode === 'signup' ? 'Sign Up' : 'Send Reset Email'}
|
|
1895
1905
|
</button>
|
|
1896
1906
|
</form>
|
|
1897
1907
|
|
|
1898
1908
|
{mode !== 'reset' && (
|
|
1899
|
-
<
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
</button>
|
|
1903
|
-
<button onClick={() => handleSocialAuth('github')} style={{ flex: 1, padding: '0.5rem' }}>
|
|
1904
|
-
GitHub
|
|
1905
|
-
</button>
|
|
1906
|
-
</div>
|
|
1909
|
+
<button type="button" onClick={handleSocialAuth}>
|
|
1910
|
+
Continue with Google
|
|
1911
|
+
</button>
|
|
1907
1912
|
)}
|
|
1908
1913
|
|
|
1909
|
-
<div
|
|
1914
|
+
<div>
|
|
1910
1915
|
{mode === 'signin' && (
|
|
1911
1916
|
<>
|
|
1912
|
-
<button onClick={() => setMode('signup')}
|
|
1913
|
-
Create Account
|
|
1914
|
-
</button>
|
|
1917
|
+
<button onClick={() => setMode('signup')}>Create Account</button>
|
|
1915
1918
|
<button onClick={() => setMode('reset')}>Forgot Password?</button>
|
|
1916
1919
|
</>
|
|
1917
1920
|
)}
|
|
1918
1921
|
{mode === 'signup' && (
|
|
1919
|
-
<button onClick={() => setMode('signin')}>
|
|
1922
|
+
<button onClick={() => setMode('signin')}>Back to Sign In</button>
|
|
1920
1923
|
)}
|
|
1921
1924
|
{mode === 'reset' && (
|
|
1922
1925
|
<button onClick={() => setMode('signin')}>Back to Sign In</button>
|
|
@@ -1927,6 +1930,55 @@ function AuthForm() {
|
|
|
1927
1930
|
}
|
|
1928
1931
|
```
|
|
1929
1932
|
|
|
1933
|
+
#### 🔄 Custom Reset Page Handling
|
|
1934
|
+
|
|
1935
|
+
**When users click the reset link, handle it in your app:**
|
|
1936
|
+
|
|
1937
|
+
```typescript
|
|
1938
|
+
// /reset-password page component
|
|
1939
|
+
function ResetPasswordPage() {
|
|
1940
|
+
const [token, setToken] = useState('')
|
|
1941
|
+
const [projectId, setProjectId] = useState('')
|
|
1942
|
+
const [newPassword, setNewPassword] = useState('')
|
|
1943
|
+
const [message, setMessage] = useState('')
|
|
1944
|
+
|
|
1945
|
+
useEffect(() => {
|
|
1946
|
+
// Extract token and projectId from URL params
|
|
1947
|
+
const params = new URLSearchParams(window.location.search)
|
|
1948
|
+
setToken(params.get('token') || '')
|
|
1949
|
+
setProjectId(params.get('projectId') || '')
|
|
1950
|
+
}, [])
|
|
1951
|
+
|
|
1952
|
+
const handleReset = async (e) => {
|
|
1953
|
+
e.preventDefault()
|
|
1954
|
+
|
|
1955
|
+
try {
|
|
1956
|
+
await blink.auth.confirmPasswordReset(token, newPassword)
|
|
1957
|
+
setMessage('Password reset successfully! You can now sign in.')
|
|
1958
|
+
} catch (error) {
|
|
1959
|
+
console.error('Reset failed:', error.message)
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
if (!token) return <div>Invalid reset link</div>
|
|
1964
|
+
|
|
1965
|
+
return (
|
|
1966
|
+
<form onSubmit={handleReset}>
|
|
1967
|
+
<h1>Set New Password</h1>
|
|
1968
|
+
<input
|
|
1969
|
+
type="password"
|
|
1970
|
+
value={newPassword}
|
|
1971
|
+
onChange={(e) => setNewPassword(e.target.value)}
|
|
1972
|
+
placeholder="Enter new password"
|
|
1973
|
+
minLength={8}
|
|
1974
|
+
/>
|
|
1975
|
+
<button type="submit">Reset Password</button>
|
|
1976
|
+
{message && <p style={{ color: 'green' }}>{message}</p>}
|
|
1977
|
+
</form>
|
|
1978
|
+
)
|
|
1979
|
+
}
|
|
1980
|
+
```
|
|
1981
|
+
|
|
1930
1982
|
#### Custom Email Branding Example
|
|
1931
1983
|
|
|
1932
1984
|
**Send password reset with your own email service:**
|
package/dist/index.d.mts
CHANGED
|
@@ -914,7 +914,9 @@ declare class BlinkAuth {
|
|
|
914
914
|
/**
|
|
915
915
|
* Send password reset email (using Blink default email service)
|
|
916
916
|
*/
|
|
917
|
-
sendPasswordResetEmail(email: string
|
|
917
|
+
sendPasswordResetEmail(email: string, options?: {
|
|
918
|
+
redirectUrl?: string;
|
|
919
|
+
}): Promise<void>;
|
|
918
920
|
/**
|
|
919
921
|
* Confirm password reset with token
|
|
920
922
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -914,7 +914,9 @@ declare class BlinkAuth {
|
|
|
914
914
|
/**
|
|
915
915
|
* Send password reset email (using Blink default email service)
|
|
916
916
|
*/
|
|
917
|
-
sendPasswordResetEmail(email: string
|
|
917
|
+
sendPasswordResetEmail(email: string, options?: {
|
|
918
|
+
redirectUrl?: string;
|
|
919
|
+
}): Promise<void>;
|
|
918
920
|
/**
|
|
919
921
|
* Confirm password reset with token
|
|
920
922
|
*/
|
package/dist/index.js
CHANGED
|
@@ -925,8 +925,8 @@ var BlinkAuth = class {
|
|
|
925
925
|
};
|
|
926
926
|
this.authUrl = this.authConfig.authUrl || "https://blink.new";
|
|
927
927
|
this.coreUrl = this.authConfig.coreUrl || "https://core.blink.new";
|
|
928
|
-
if (typeof window !== "undefined" && this.
|
|
929
|
-
console.warn("\u26A0\uFE0F Using default
|
|
928
|
+
if (typeof window !== "undefined" && this.authUrl === "https://blink.new" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")) {
|
|
929
|
+
console.warn("\u26A0\uFE0F Using default authUrl in development. Set auth.authUrl to your app origin for headless auth endpoints to work.");
|
|
930
930
|
}
|
|
931
931
|
if (config.authRequired !== void 0 && !config.auth?.mode) {
|
|
932
932
|
this.authConfig.mode = config.authRequired ? "managed" : "headless";
|
|
@@ -1258,7 +1258,7 @@ var BlinkAuth = class {
|
|
|
1258
1258
|
throw new BlinkAuthError("INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */, "signUp is only available in headless mode");
|
|
1259
1259
|
}
|
|
1260
1260
|
try {
|
|
1261
|
-
const response = await fetch(`${this.
|
|
1261
|
+
const response = await fetch(`${this.authUrl}/api/auth/signup`, {
|
|
1262
1262
|
method: "POST",
|
|
1263
1263
|
headers: {
|
|
1264
1264
|
"Content-Type": "application/json"
|
|
@@ -1297,7 +1297,7 @@ var BlinkAuth = class {
|
|
|
1297
1297
|
throw new BlinkAuthError("INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */, "signInWithEmail is only available in headless mode");
|
|
1298
1298
|
}
|
|
1299
1299
|
try {
|
|
1300
|
-
const response = await fetch(`${this.
|
|
1300
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/email`, {
|
|
1301
1301
|
method: "POST",
|
|
1302
1302
|
headers: {
|
|
1303
1303
|
"Content-Type": "application/json"
|
|
@@ -1466,7 +1466,7 @@ var BlinkAuth = class {
|
|
|
1466
1466
|
*/
|
|
1467
1467
|
async generatePasswordResetToken(email) {
|
|
1468
1468
|
try {
|
|
1469
|
-
const response = await fetch(`${this.
|
|
1469
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/reset/generate`, {
|
|
1470
1470
|
method: "POST",
|
|
1471
1471
|
headers: {
|
|
1472
1472
|
"Content-Type": "application/json"
|
|
@@ -1501,16 +1501,17 @@ var BlinkAuth = class {
|
|
|
1501
1501
|
/**
|
|
1502
1502
|
* Send password reset email (using Blink default email service)
|
|
1503
1503
|
*/
|
|
1504
|
-
async sendPasswordResetEmail(email) {
|
|
1504
|
+
async sendPasswordResetEmail(email, options) {
|
|
1505
1505
|
try {
|
|
1506
|
-
const response = await fetch(`${this.
|
|
1506
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/reset`, {
|
|
1507
1507
|
method: "POST",
|
|
1508
1508
|
headers: {
|
|
1509
1509
|
"Content-Type": "application/json"
|
|
1510
1510
|
},
|
|
1511
1511
|
body: JSON.stringify({
|
|
1512
1512
|
email,
|
|
1513
|
-
projectId: this.config.projectId
|
|
1513
|
+
projectId: this.config.projectId,
|
|
1514
|
+
redirectUrl: options?.redirectUrl
|
|
1514
1515
|
})
|
|
1515
1516
|
});
|
|
1516
1517
|
if (!response.ok) {
|
|
@@ -1530,7 +1531,7 @@ var BlinkAuth = class {
|
|
|
1530
1531
|
*/
|
|
1531
1532
|
async confirmPasswordReset(token, newPassword) {
|
|
1532
1533
|
try {
|
|
1533
|
-
const response = await fetch(`${this.
|
|
1534
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/reset/confirm`, {
|
|
1534
1535
|
method: "POST",
|
|
1535
1536
|
headers: {
|
|
1536
1537
|
"Content-Type": "application/json"
|
|
@@ -1562,7 +1563,7 @@ var BlinkAuth = class {
|
|
|
1562
1563
|
throw new BlinkAuthError("TOKEN_EXPIRED" /* TOKEN_EXPIRED */, "No access token available");
|
|
1563
1564
|
}
|
|
1564
1565
|
try {
|
|
1565
|
-
const response = await fetch(`${this.
|
|
1566
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/change`, {
|
|
1566
1567
|
method: "POST",
|
|
1567
1568
|
headers: {
|
|
1568
1569
|
"Authorization": `Bearer ${token}`,
|
|
@@ -1594,7 +1595,7 @@ var BlinkAuth = class {
|
|
|
1594
1595
|
throw new BlinkAuthError("TOKEN_EXPIRED" /* TOKEN_EXPIRED */, "No access token available");
|
|
1595
1596
|
}
|
|
1596
1597
|
try {
|
|
1597
|
-
const response = await fetch(`${this.
|
|
1598
|
+
const response = await fetch(`${this.authUrl}/api/auth/email/verify/generate`, {
|
|
1598
1599
|
method: "POST",
|
|
1599
1600
|
headers: {
|
|
1600
1601
|
"Authorization": `Bearer ${token}`,
|
|
@@ -1632,7 +1633,7 @@ var BlinkAuth = class {
|
|
|
1632
1633
|
throw new BlinkAuthError("TOKEN_EXPIRED" /* TOKEN_EXPIRED */, "No access token available");
|
|
1633
1634
|
}
|
|
1634
1635
|
try {
|
|
1635
|
-
const response = await fetch(`${this.
|
|
1636
|
+
const response = await fetch(`${this.authUrl}/api/auth/email/verify/send`, {
|
|
1636
1637
|
method: "POST",
|
|
1637
1638
|
headers: {
|
|
1638
1639
|
"Authorization": `Bearer ${token}`,
|
|
@@ -1656,7 +1657,7 @@ var BlinkAuth = class {
|
|
|
1656
1657
|
*/
|
|
1657
1658
|
async verifyEmail(token) {
|
|
1658
1659
|
try {
|
|
1659
|
-
const response = await fetch(`${this.
|
|
1660
|
+
const response = await fetch(`${this.authUrl}/api/auth/email/verify`, {
|
|
1660
1661
|
method: "POST",
|
|
1661
1662
|
headers: {
|
|
1662
1663
|
"Content-Type": "application/json"
|
|
@@ -1683,7 +1684,7 @@ var BlinkAuth = class {
|
|
|
1683
1684
|
*/
|
|
1684
1685
|
async generateMagicLinkToken(email, options) {
|
|
1685
1686
|
try {
|
|
1686
|
-
const response = await fetch(`${this.
|
|
1687
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/magic/generate`, {
|
|
1687
1688
|
method: "POST",
|
|
1688
1689
|
headers: {
|
|
1689
1690
|
"Content-Type": "application/json"
|
|
@@ -1721,7 +1722,7 @@ var BlinkAuth = class {
|
|
|
1721
1722
|
*/
|
|
1722
1723
|
async sendMagicLink(email, options) {
|
|
1723
1724
|
try {
|
|
1724
|
-
const response = await fetch(`${this.
|
|
1725
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/magic`, {
|
|
1725
1726
|
method: "POST",
|
|
1726
1727
|
headers: {
|
|
1727
1728
|
"Content-Type": "application/json"
|
|
@@ -1753,7 +1754,7 @@ var BlinkAuth = class {
|
|
|
1753
1754
|
throw new BlinkAuthError("VERIFICATION_FAILED" /* VERIFICATION_FAILED */, "No magic link token found");
|
|
1754
1755
|
}
|
|
1755
1756
|
try {
|
|
1756
|
-
const response = await fetch(`${this.
|
|
1757
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/magic/verify`, {
|
|
1757
1758
|
method: "POST",
|
|
1758
1759
|
headers: {
|
|
1759
1760
|
"Content-Type": "application/json"
|
|
@@ -1789,7 +1790,7 @@ var BlinkAuth = class {
|
|
|
1789
1790
|
*/
|
|
1790
1791
|
async getAvailableProviders() {
|
|
1791
1792
|
try {
|
|
1792
|
-
const response = await fetch(`${this.
|
|
1793
|
+
const response = await fetch(`${this.authUrl}/api/auth/providers?projectId=${encodeURIComponent(this.config.projectId)}`);
|
|
1793
1794
|
if (!response.ok) {
|
|
1794
1795
|
return ["email", "google"];
|
|
1795
1796
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -923,8 +923,8 @@ var BlinkAuth = class {
|
|
|
923
923
|
};
|
|
924
924
|
this.authUrl = this.authConfig.authUrl || "https://blink.new";
|
|
925
925
|
this.coreUrl = this.authConfig.coreUrl || "https://core.blink.new";
|
|
926
|
-
if (typeof window !== "undefined" && this.
|
|
927
|
-
console.warn("\u26A0\uFE0F Using default
|
|
926
|
+
if (typeof window !== "undefined" && this.authUrl === "https://blink.new" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")) {
|
|
927
|
+
console.warn("\u26A0\uFE0F Using default authUrl in development. Set auth.authUrl to your app origin for headless auth endpoints to work.");
|
|
928
928
|
}
|
|
929
929
|
if (config.authRequired !== void 0 && !config.auth?.mode) {
|
|
930
930
|
this.authConfig.mode = config.authRequired ? "managed" : "headless";
|
|
@@ -1256,7 +1256,7 @@ var BlinkAuth = class {
|
|
|
1256
1256
|
throw new BlinkAuthError("INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */, "signUp is only available in headless mode");
|
|
1257
1257
|
}
|
|
1258
1258
|
try {
|
|
1259
|
-
const response = await fetch(`${this.
|
|
1259
|
+
const response = await fetch(`${this.authUrl}/api/auth/signup`, {
|
|
1260
1260
|
method: "POST",
|
|
1261
1261
|
headers: {
|
|
1262
1262
|
"Content-Type": "application/json"
|
|
@@ -1295,7 +1295,7 @@ var BlinkAuth = class {
|
|
|
1295
1295
|
throw new BlinkAuthError("INVALID_CREDENTIALS" /* INVALID_CREDENTIALS */, "signInWithEmail is only available in headless mode");
|
|
1296
1296
|
}
|
|
1297
1297
|
try {
|
|
1298
|
-
const response = await fetch(`${this.
|
|
1298
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/email`, {
|
|
1299
1299
|
method: "POST",
|
|
1300
1300
|
headers: {
|
|
1301
1301
|
"Content-Type": "application/json"
|
|
@@ -1464,7 +1464,7 @@ var BlinkAuth = class {
|
|
|
1464
1464
|
*/
|
|
1465
1465
|
async generatePasswordResetToken(email) {
|
|
1466
1466
|
try {
|
|
1467
|
-
const response = await fetch(`${this.
|
|
1467
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/reset/generate`, {
|
|
1468
1468
|
method: "POST",
|
|
1469
1469
|
headers: {
|
|
1470
1470
|
"Content-Type": "application/json"
|
|
@@ -1499,16 +1499,17 @@ var BlinkAuth = class {
|
|
|
1499
1499
|
/**
|
|
1500
1500
|
* Send password reset email (using Blink default email service)
|
|
1501
1501
|
*/
|
|
1502
|
-
async sendPasswordResetEmail(email) {
|
|
1502
|
+
async sendPasswordResetEmail(email, options) {
|
|
1503
1503
|
try {
|
|
1504
|
-
const response = await fetch(`${this.
|
|
1504
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/reset`, {
|
|
1505
1505
|
method: "POST",
|
|
1506
1506
|
headers: {
|
|
1507
1507
|
"Content-Type": "application/json"
|
|
1508
1508
|
},
|
|
1509
1509
|
body: JSON.stringify({
|
|
1510
1510
|
email,
|
|
1511
|
-
projectId: this.config.projectId
|
|
1511
|
+
projectId: this.config.projectId,
|
|
1512
|
+
redirectUrl: options?.redirectUrl
|
|
1512
1513
|
})
|
|
1513
1514
|
});
|
|
1514
1515
|
if (!response.ok) {
|
|
@@ -1528,7 +1529,7 @@ var BlinkAuth = class {
|
|
|
1528
1529
|
*/
|
|
1529
1530
|
async confirmPasswordReset(token, newPassword) {
|
|
1530
1531
|
try {
|
|
1531
|
-
const response = await fetch(`${this.
|
|
1532
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/reset/confirm`, {
|
|
1532
1533
|
method: "POST",
|
|
1533
1534
|
headers: {
|
|
1534
1535
|
"Content-Type": "application/json"
|
|
@@ -1560,7 +1561,7 @@ var BlinkAuth = class {
|
|
|
1560
1561
|
throw new BlinkAuthError("TOKEN_EXPIRED" /* TOKEN_EXPIRED */, "No access token available");
|
|
1561
1562
|
}
|
|
1562
1563
|
try {
|
|
1563
|
-
const response = await fetch(`${this.
|
|
1564
|
+
const response = await fetch(`${this.authUrl}/api/auth/password/change`, {
|
|
1564
1565
|
method: "POST",
|
|
1565
1566
|
headers: {
|
|
1566
1567
|
"Authorization": `Bearer ${token}`,
|
|
@@ -1592,7 +1593,7 @@ var BlinkAuth = class {
|
|
|
1592
1593
|
throw new BlinkAuthError("TOKEN_EXPIRED" /* TOKEN_EXPIRED */, "No access token available");
|
|
1593
1594
|
}
|
|
1594
1595
|
try {
|
|
1595
|
-
const response = await fetch(`${this.
|
|
1596
|
+
const response = await fetch(`${this.authUrl}/api/auth/email/verify/generate`, {
|
|
1596
1597
|
method: "POST",
|
|
1597
1598
|
headers: {
|
|
1598
1599
|
"Authorization": `Bearer ${token}`,
|
|
@@ -1630,7 +1631,7 @@ var BlinkAuth = class {
|
|
|
1630
1631
|
throw new BlinkAuthError("TOKEN_EXPIRED" /* TOKEN_EXPIRED */, "No access token available");
|
|
1631
1632
|
}
|
|
1632
1633
|
try {
|
|
1633
|
-
const response = await fetch(`${this.
|
|
1634
|
+
const response = await fetch(`${this.authUrl}/api/auth/email/verify/send`, {
|
|
1634
1635
|
method: "POST",
|
|
1635
1636
|
headers: {
|
|
1636
1637
|
"Authorization": `Bearer ${token}`,
|
|
@@ -1654,7 +1655,7 @@ var BlinkAuth = class {
|
|
|
1654
1655
|
*/
|
|
1655
1656
|
async verifyEmail(token) {
|
|
1656
1657
|
try {
|
|
1657
|
-
const response = await fetch(`${this.
|
|
1658
|
+
const response = await fetch(`${this.authUrl}/api/auth/email/verify`, {
|
|
1658
1659
|
method: "POST",
|
|
1659
1660
|
headers: {
|
|
1660
1661
|
"Content-Type": "application/json"
|
|
@@ -1681,7 +1682,7 @@ var BlinkAuth = class {
|
|
|
1681
1682
|
*/
|
|
1682
1683
|
async generateMagicLinkToken(email, options) {
|
|
1683
1684
|
try {
|
|
1684
|
-
const response = await fetch(`${this.
|
|
1685
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/magic/generate`, {
|
|
1685
1686
|
method: "POST",
|
|
1686
1687
|
headers: {
|
|
1687
1688
|
"Content-Type": "application/json"
|
|
@@ -1719,7 +1720,7 @@ var BlinkAuth = class {
|
|
|
1719
1720
|
*/
|
|
1720
1721
|
async sendMagicLink(email, options) {
|
|
1721
1722
|
try {
|
|
1722
|
-
const response = await fetch(`${this.
|
|
1723
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/magic`, {
|
|
1723
1724
|
method: "POST",
|
|
1724
1725
|
headers: {
|
|
1725
1726
|
"Content-Type": "application/json"
|
|
@@ -1751,7 +1752,7 @@ var BlinkAuth = class {
|
|
|
1751
1752
|
throw new BlinkAuthError("VERIFICATION_FAILED" /* VERIFICATION_FAILED */, "No magic link token found");
|
|
1752
1753
|
}
|
|
1753
1754
|
try {
|
|
1754
|
-
const response = await fetch(`${this.
|
|
1755
|
+
const response = await fetch(`${this.authUrl}/api/auth/signin/magic/verify`, {
|
|
1755
1756
|
method: "POST",
|
|
1756
1757
|
headers: {
|
|
1757
1758
|
"Content-Type": "application/json"
|
|
@@ -1787,7 +1788,7 @@ var BlinkAuth = class {
|
|
|
1787
1788
|
*/
|
|
1788
1789
|
async getAvailableProviders() {
|
|
1789
1790
|
try {
|
|
1790
|
-
const response = await fetch(`${this.
|
|
1791
|
+
const response = await fetch(`${this.authUrl}/api/auth/providers?projectId=${encodeURIComponent(this.config.projectId)}`);
|
|
1791
1792
|
if (!response.ok) {
|
|
1792
1793
|
return ["email", "google"];
|
|
1793
1794
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blinkdotnew/sdk",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.3",
|
|
4
4
|
"description": "Blink TypeScript SDK for client-side applications - Zero-boilerplate CRUD + auth + AI + analytics + notifications for modern SaaS/AI apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"blink",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@blink/core": "0.4.
|
|
53
|
+
"@blink/core": "0.4.1",
|
|
54
54
|
"tsup": "^8.0.0",
|
|
55
55
|
"typescript": "^5.0.0"
|
|
56
56
|
},
|