@solvapay/react 1.0.0-preview.8 → 1.0.1-preview.1
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/LICENSE.md +21 -0
- package/README.md +214 -57
- package/dist/adapters/auth.cjs +49 -0
- package/dist/adapters/auth.d.cts +44 -0
- package/dist/adapters/auth.d.ts +44 -0
- package/dist/adapters/auth.js +6 -0
- package/dist/chunk-OUSEQRCT.js +25 -0
- package/dist/index.cjs +870 -454
- package/dist/index.d.cts +555 -186
- package/dist/index.d.ts +555 -186
- package/dist/index.js +842 -448
- package/package.json +34 -11
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 SolvaPay Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -15,31 +15,93 @@ pnpm add @solvapay/react
|
|
|
15
15
|
|
|
16
16
|
## Quick Start
|
|
17
17
|
|
|
18
|
+
### Zero-Config Usage (Recommended)
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { SolvaPayProvider, PaymentForm, usePurchase } from '@solvapay/react'
|
|
22
|
+
|
|
23
|
+
export default function App() {
|
|
24
|
+
return (
|
|
25
|
+
<SolvaPayProvider>
|
|
26
|
+
<CheckoutPage />
|
|
27
|
+
</SolvaPayProvider>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
By default, `SolvaPayProvider` uses:
|
|
33
|
+
|
|
34
|
+
- `/api/check-purchase` for purchase checks
|
|
35
|
+
- `/api/create-payment-intent` for payment creation
|
|
36
|
+
- `/api/process-payment` for payment processing
|
|
37
|
+
|
|
38
|
+
### Custom API Routes
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { SolvaPayProvider, PaymentForm } from '@solvapay/react'
|
|
42
|
+
|
|
43
|
+
export default function App() {
|
|
44
|
+
return (
|
|
45
|
+
<SolvaPayProvider
|
|
46
|
+
config={{
|
|
47
|
+
api: {
|
|
48
|
+
checkPurchase: '/api/custom/purchase',
|
|
49
|
+
createPayment: '/api/custom/payment',
|
|
50
|
+
processPayment: '/api/custom/process',
|
|
51
|
+
},
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
<CheckoutPage />
|
|
55
|
+
</SolvaPayProvider>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### With Supabase Authentication
|
|
61
|
+
|
|
18
62
|
```tsx
|
|
19
|
-
import { SolvaPayProvider
|
|
63
|
+
import { SolvaPayProvider } from '@solvapay/react'
|
|
64
|
+
import { createSupabaseAuthAdapter } from '@solvapay/react-supabase'
|
|
65
|
+
|
|
66
|
+
export default function App() {
|
|
67
|
+
const adapter = createSupabaseAuthAdapter({
|
|
68
|
+
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
69
|
+
supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<SolvaPayProvider config={{ auth: { adapter } }}>
|
|
74
|
+
<CheckoutPage />
|
|
75
|
+
</SolvaPayProvider>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Fully Custom Implementation
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { SolvaPayProvider } from '@solvapay/react'
|
|
20
84
|
|
|
21
85
|
export default function App() {
|
|
22
86
|
return (
|
|
23
87
|
<SolvaPayProvider
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const res = await fetch('/api/payments/create', {
|
|
88
|
+
createPayment={async ({ planRef, productRef }) => {
|
|
89
|
+
const res = await fetch('/api/custom/payment', {
|
|
27
90
|
method: 'POST',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return res.json();
|
|
91
|
+
body: JSON.stringify({ planRef, productRef }),
|
|
92
|
+
})
|
|
93
|
+
if (!res.ok) throw new Error('Failed to create payment')
|
|
94
|
+
return res.json()
|
|
33
95
|
}}
|
|
34
|
-
|
|
35
|
-
const res = await fetch(`/api/
|
|
36
|
-
if (!res.ok) throw new Error('Failed to check
|
|
37
|
-
return res.json()
|
|
96
|
+
checkPurchase={async customerRef => {
|
|
97
|
+
const res = await fetch(`/api/custom/purchase?customerRef=${customerRef}`)
|
|
98
|
+
if (!res.ok) throw new Error('Failed to check purchase')
|
|
99
|
+
return res.json()
|
|
38
100
|
}}
|
|
39
101
|
>
|
|
40
102
|
<CheckoutPage />
|
|
41
103
|
</SolvaPayProvider>
|
|
42
|
-
)
|
|
104
|
+
)
|
|
43
105
|
}
|
|
44
106
|
```
|
|
45
107
|
|
|
@@ -47,95 +109,183 @@ export default function App() {
|
|
|
47
109
|
|
|
48
110
|
### SolvaPayProvider
|
|
49
111
|
|
|
50
|
-
Headless context provider that manages
|
|
112
|
+
Headless context provider that manages purchase state, payment methods, and customer references.
|
|
113
|
+
|
|
114
|
+
**Features:**
|
|
115
|
+
|
|
116
|
+
- Zero-config with sensible defaults
|
|
117
|
+
- Auto-fetches purchases on mount
|
|
118
|
+
- Built-in localStorage caching with user validation
|
|
119
|
+
- Supports auth adapters for extracting user IDs and tokens
|
|
120
|
+
- Customizable API routes via config
|
|
51
121
|
|
|
52
122
|
**Props:**
|
|
53
|
-
|
|
54
|
-
- `
|
|
55
|
-
- `
|
|
56
|
-
- `
|
|
123
|
+
|
|
124
|
+
- `config?: SolvaPayConfig` - Configuration object (optional)
|
|
125
|
+
- `config.api?` - Custom API route paths
|
|
126
|
+
- `config.auth?` - Auth adapter configuration
|
|
127
|
+
- `createPayment?: (params: { planRef: string; productRef?: string }) => Promise<PaymentIntentResult>` - Custom payment creation function (optional, overrides config)
|
|
128
|
+
- `checkPurchase?: (customerRef: string) => Promise<CustomerPurchaseData>` - Custom purchase check function (optional, overrides config)
|
|
129
|
+
- `processPayment?: (params: { paymentIntentId: string; productRef: string; planRef?: string }) => Promise<ProcessPaymentResult>` - Custom payment processing function (optional)
|
|
57
130
|
- `children: React.ReactNode` - Child components
|
|
58
131
|
|
|
59
|
-
|
|
132
|
+
**Config Options:**
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
interface SolvaPayConfig {
|
|
136
|
+
api?: {
|
|
137
|
+
checkPurchase?: string // Default: '/api/check-purchase'
|
|
138
|
+
createPayment?: string // Default: '/api/create-payment-intent'
|
|
139
|
+
processPayment?: string // Default: '/api/process-payment'
|
|
140
|
+
}
|
|
141
|
+
auth?: {
|
|
142
|
+
adapter?: AuthAdapter // Auth adapter for extracting user ID/token
|
|
143
|
+
getToken?: () => Promise<string | null> // Deprecated: use adapter
|
|
144
|
+
getUserId?: () => Promise<string | null> // Deprecated: use adapter
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### PricingSelector
|
|
60
150
|
|
|
61
|
-
|
|
151
|
+
Component for selecting and displaying available pricing options.
|
|
62
152
|
|
|
63
153
|
**Props:**
|
|
64
|
-
|
|
65
|
-
- `
|
|
66
|
-
- `
|
|
67
|
-
- `
|
|
68
|
-
- `
|
|
69
|
-
- `
|
|
70
|
-
- `cancelButtonClassName?: string` - Optional className for cancel button
|
|
154
|
+
|
|
155
|
+
- `productRef?: string` - Product reference to filter pricing options
|
|
156
|
+
- `fetcher?: (productRef: string) => Promise<Plan[]>` - Custom fetcher function
|
|
157
|
+
- `onPlanSelect?: (plan: Plan) => void` - Callback when option is selected
|
|
158
|
+
- `renderPlan?: (plan: Plan) => React.ReactNode` - Custom option renderer
|
|
159
|
+
- `className?: string` - Container className
|
|
71
160
|
|
|
72
161
|
**Example:**
|
|
162
|
+
|
|
73
163
|
```tsx
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
</
|
|
164
|
+
import { PricingSelector, usePlans } from '@solvapay/react'
|
|
165
|
+
|
|
166
|
+
function PricingPage() {
|
|
167
|
+
const { plans, loading } = usePlans({ productRef: 'my-product' })
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<div>
|
|
171
|
+
{loading ? 'Loading...' : plans.map(plan => <div key={plan.reference}>{plan.price}/{plan.interval}</div>)}
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
}
|
|
82
175
|
```
|
|
83
176
|
|
|
84
177
|
### PaymentForm
|
|
85
178
|
|
|
86
|
-
Payment form component using Stripe PaymentElement.
|
|
179
|
+
Payment form component using Stripe PaymentElement. Automatically handles Stripe Elements provider setup.
|
|
87
180
|
|
|
88
181
|
**Props:**
|
|
182
|
+
|
|
183
|
+
- `planRef: string` - Plan reference for the payment
|
|
184
|
+
- `productRef?: string` - Optional product reference
|
|
89
185
|
- `onSuccess?: (paymentIntent: PaymentIntent) => void` - Callback on successful payment
|
|
90
186
|
- `onError?: (error: Error) => void` - Callback on payment error
|
|
91
187
|
- `returnUrl?: string` - Return URL after payment
|
|
92
188
|
- `submitButtonText?: string` - Submit button text (default: "Pay Now")
|
|
93
|
-
- `className?: string` - Form className (legacy, use formClassName)
|
|
94
189
|
- `formClassName?: string` - Form element className
|
|
95
190
|
- `messageClassName?: string` - Message container className
|
|
96
191
|
- `buttonClassName?: string` - Submit button className
|
|
97
192
|
|
|
98
|
-
|
|
193
|
+
**Example:**
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
import { PaymentForm } from '@solvapay/react'
|
|
197
|
+
|
|
198
|
+
function CheckoutPage() {
|
|
199
|
+
return (
|
|
200
|
+
<PaymentForm
|
|
201
|
+
planRef="pln_YOUR_PLAN"
|
|
202
|
+
productRef="prd_YOUR_PRODUCT"
|
|
203
|
+
onSuccess={() => console.log('Payment successful!')}
|
|
204
|
+
/>
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### ProductBadge
|
|
99
210
|
|
|
100
|
-
Displays current subscription
|
|
211
|
+
Displays current product subscription with render props or className pattern.
|
|
101
212
|
|
|
102
213
|
**Props:**
|
|
214
|
+
|
|
103
215
|
- `children?: (props) => React.ReactNode` - Render prop function
|
|
104
216
|
- `as?: React.ElementType` - Component to render (default: "div")
|
|
105
217
|
- `className?: string | ((props) => string)` - ClassName or function
|
|
106
218
|
|
|
107
219
|
**Example:**
|
|
220
|
+
|
|
108
221
|
```tsx
|
|
109
|
-
<
|
|
222
|
+
<ProductBadge className="badge badge-primary" />
|
|
110
223
|
```
|
|
111
224
|
|
|
112
|
-
###
|
|
225
|
+
### PurchaseGate
|
|
113
226
|
|
|
114
|
-
Controls access to content based on
|
|
227
|
+
Controls access to content based on purchase status.
|
|
115
228
|
|
|
116
229
|
**Props:**
|
|
117
|
-
|
|
230
|
+
|
|
231
|
+
- `requireProduct?: string` - Optional product name to check for an active purchase
|
|
118
232
|
- `children: (props) => React.ReactNode` - Render prop function
|
|
119
233
|
|
|
120
234
|
**Example:**
|
|
235
|
+
|
|
121
236
|
```tsx
|
|
122
|
-
<
|
|
123
|
-
{({ hasAccess, loading,
|
|
124
|
-
if (loading) return <Loading
|
|
125
|
-
if (!hasAccess) return <Paywall
|
|
126
|
-
return <PremiumContent
|
|
237
|
+
<PurchaseGate requireProduct="Pro Plan">
|
|
238
|
+
{({ hasAccess, loading, purchases }) => {
|
|
239
|
+
if (loading) return <Loading />
|
|
240
|
+
if (!hasAccess) return <Paywall />
|
|
241
|
+
return <PremiumContent />
|
|
127
242
|
}}
|
|
128
|
-
</
|
|
243
|
+
</PurchaseGate>
|
|
129
244
|
```
|
|
130
245
|
|
|
131
246
|
## Hooks
|
|
132
247
|
|
|
133
|
-
###
|
|
248
|
+
### usePurchase
|
|
249
|
+
|
|
250
|
+
Access purchase status, active purchases, and helper functions.
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
const {
|
|
254
|
+
purchases, // Array of all purchases
|
|
255
|
+
loading, // Loading state
|
|
256
|
+
hasPaidPurchase, // Boolean: has any paid purchase
|
|
257
|
+
activePurchase, // Most recent active purchase
|
|
258
|
+
refetch, // Function to refetch purchases
|
|
259
|
+
} = usePurchase()
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### usePlans
|
|
263
|
+
|
|
264
|
+
Fetch and manage available plans.
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
const {
|
|
268
|
+
plans, // Array of available plans
|
|
269
|
+
loading, // Loading state
|
|
270
|
+
error, // Error object if fetch failed
|
|
271
|
+
refetch, // Function to refetch plans
|
|
272
|
+
} = usePlans({
|
|
273
|
+
productRef: 'my-product', // Optional product reference
|
|
274
|
+
fetcher: customFetcher, // Optional custom fetcher function
|
|
275
|
+
})
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### usePurchaseStatus
|
|
134
279
|
|
|
135
|
-
|
|
280
|
+
Advanced purchase status helpers.
|
|
136
281
|
|
|
137
282
|
```tsx
|
|
138
|
-
const {
|
|
283
|
+
const {
|
|
284
|
+
cancelledPurchase, // Most recent cancelled purchase
|
|
285
|
+
shouldShowCancelledNotice, // Boolean: should show cancellation notice
|
|
286
|
+
formatDate, // Helper to format dates
|
|
287
|
+
getDaysUntilExpiration, // Helper to get days until expiration
|
|
288
|
+
} = usePurchaseStatus()
|
|
139
289
|
```
|
|
140
290
|
|
|
141
291
|
### useCheckout
|
|
@@ -143,7 +293,7 @@ const { subscriptions, loading, hasActiveSubscription, hasPlan, refetch } = useS
|
|
|
143
293
|
Manage checkout flow for a specific plan.
|
|
144
294
|
|
|
145
295
|
```tsx
|
|
146
|
-
const { loading, error, startCheckout, reset } = useCheckout('plan_ref')
|
|
296
|
+
const { loading, error, startCheckout, reset } = useCheckout('plan_ref')
|
|
147
297
|
```
|
|
148
298
|
|
|
149
299
|
### useSolvaPay
|
|
@@ -151,7 +301,14 @@ const { loading, error, startCheckout, reset } = useCheckout('plan_ref');
|
|
|
151
301
|
Access SolvaPay context directly.
|
|
152
302
|
|
|
153
303
|
```tsx
|
|
154
|
-
const {
|
|
304
|
+
const {
|
|
305
|
+
purchaseData, // Full purchase data
|
|
306
|
+
loading, // Loading state
|
|
307
|
+
createPayment, // Payment creation function
|
|
308
|
+
processPayment, // Payment processing function
|
|
309
|
+
customerRef, // Current customer reference
|
|
310
|
+
updateCustomerRef, // Function to update customer reference
|
|
311
|
+
} = useSolvaPay()
|
|
155
312
|
```
|
|
156
313
|
|
|
157
314
|
## TypeScript
|
|
@@ -159,9 +316,9 @@ const { subscription, createPayment, customerRef } = useSolvaPay();
|
|
|
159
316
|
All components and hooks are fully typed. Import types as needed:
|
|
160
317
|
|
|
161
318
|
```tsx
|
|
162
|
-
import type { PaymentFormProps,
|
|
319
|
+
import type { PaymentFormProps, PurchaseStatus, PaymentIntentResult } from '@solvapay/react'
|
|
163
320
|
```
|
|
164
321
|
|
|
165
322
|
## More Information
|
|
166
323
|
|
|
167
|
-
See `docs/architecture.md` for detailed architecture documentation.
|
|
324
|
+
See [`docs/guides/architecture.md`](../../docs/guides/architecture.md) for detailed architecture documentation.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/adapters/auth.ts
|
|
21
|
+
var auth_exports = {};
|
|
22
|
+
__export(auth_exports, {
|
|
23
|
+
defaultAuthAdapter: () => defaultAuthAdapter
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(auth_exports);
|
|
26
|
+
var defaultAuthAdapter = {
|
|
27
|
+
async getToken() {
|
|
28
|
+
if (typeof window === "undefined") return null;
|
|
29
|
+
const token = localStorage.getItem("auth_token");
|
|
30
|
+
return token || null;
|
|
31
|
+
},
|
|
32
|
+
async getUserId() {
|
|
33
|
+
const token = await this.getToken();
|
|
34
|
+
if (!token) return null;
|
|
35
|
+
try {
|
|
36
|
+
const parts = token.split(".");
|
|
37
|
+
if (parts.length === 3) {
|
|
38
|
+
const payload = JSON.parse(atob(parts[1]));
|
|
39
|
+
return payload.sub || payload.user_id || null;
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
defaultAuthAdapter
|
|
49
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Adapter Interface for Client-Side Authentication
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for authentication adapters used by SolvaPayProvider.
|
|
5
|
+
* Adapters handle token retrieval and user ID extraction in the browser.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Auth adapter interface for client-side authentication
|
|
9
|
+
*
|
|
10
|
+
* Used by SolvaPayProvider to get auth tokens and user IDs.
|
|
11
|
+
* Adapters should handle their own error cases and return null when
|
|
12
|
+
* authentication is not available or fails.
|
|
13
|
+
*/
|
|
14
|
+
interface AuthAdapter {
|
|
15
|
+
/**
|
|
16
|
+
* Get the authentication token
|
|
17
|
+
*
|
|
18
|
+
* @returns The auth token string if available, null otherwise
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* This method should never throw. If authentication fails or is missing,
|
|
22
|
+
* return null and let the caller decide how to handle unauthenticated requests.
|
|
23
|
+
*/
|
|
24
|
+
getToken: () => Promise<string | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the authenticated user ID
|
|
27
|
+
*
|
|
28
|
+
* @returns The user ID string if authenticated, null otherwise
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* This method should never throw. If authentication fails or is missing,
|
|
32
|
+
* return null and let the caller decide how to handle unauthenticated requests.
|
|
33
|
+
*/
|
|
34
|
+
getUserId: () => Promise<string | null>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Default auth adapter that only checks localStorage
|
|
38
|
+
*
|
|
39
|
+
* This is a fallback adapter that doesn't depend on any specific auth provider.
|
|
40
|
+
* It checks for a token in localStorage under the 'auth_token' key.
|
|
41
|
+
*/
|
|
42
|
+
declare const defaultAuthAdapter: AuthAdapter;
|
|
43
|
+
|
|
44
|
+
export { type AuthAdapter, defaultAuthAdapter };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Adapter Interface for Client-Side Authentication
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for authentication adapters used by SolvaPayProvider.
|
|
5
|
+
* Adapters handle token retrieval and user ID extraction in the browser.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Auth adapter interface for client-side authentication
|
|
9
|
+
*
|
|
10
|
+
* Used by SolvaPayProvider to get auth tokens and user IDs.
|
|
11
|
+
* Adapters should handle their own error cases and return null when
|
|
12
|
+
* authentication is not available or fails.
|
|
13
|
+
*/
|
|
14
|
+
interface AuthAdapter {
|
|
15
|
+
/**
|
|
16
|
+
* Get the authentication token
|
|
17
|
+
*
|
|
18
|
+
* @returns The auth token string if available, null otherwise
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* This method should never throw. If authentication fails or is missing,
|
|
22
|
+
* return null and let the caller decide how to handle unauthenticated requests.
|
|
23
|
+
*/
|
|
24
|
+
getToken: () => Promise<string | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the authenticated user ID
|
|
27
|
+
*
|
|
28
|
+
* @returns The user ID string if authenticated, null otherwise
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* This method should never throw. If authentication fails or is missing,
|
|
32
|
+
* return null and let the caller decide how to handle unauthenticated requests.
|
|
33
|
+
*/
|
|
34
|
+
getUserId: () => Promise<string | null>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Default auth adapter that only checks localStorage
|
|
38
|
+
*
|
|
39
|
+
* This is a fallback adapter that doesn't depend on any specific auth provider.
|
|
40
|
+
* It checks for a token in localStorage under the 'auth_token' key.
|
|
41
|
+
*/
|
|
42
|
+
declare const defaultAuthAdapter: AuthAdapter;
|
|
43
|
+
|
|
44
|
+
export { type AuthAdapter, defaultAuthAdapter };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/adapters/auth.ts
|
|
2
|
+
var defaultAuthAdapter = {
|
|
3
|
+
async getToken() {
|
|
4
|
+
if (typeof window === "undefined") return null;
|
|
5
|
+
const token = localStorage.getItem("auth_token");
|
|
6
|
+
return token || null;
|
|
7
|
+
},
|
|
8
|
+
async getUserId() {
|
|
9
|
+
const token = await this.getToken();
|
|
10
|
+
if (!token) return null;
|
|
11
|
+
try {
|
|
12
|
+
const parts = token.split(".");
|
|
13
|
+
if (parts.length === 3) {
|
|
14
|
+
const payload = JSON.parse(atob(parts[1]));
|
|
15
|
+
return payload.sub || payload.user_id || null;
|
|
16
|
+
}
|
|
17
|
+
} catch {
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
defaultAuthAdapter
|
|
25
|
+
};
|