@solvapay/server 1.0.0-preview.9 → 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 +87 -46
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/edge.d.ts +2598 -329
- package/dist/edge.js +1006 -296
- package/dist/index.cjs +3601 -2757
- package/dist/index.d.cts +2740 -382
- package/dist/index.d.ts +2740 -382
- package/dist/index.js +1063 -295
- package/dist/webapi-K5XBCEO6.js +3775 -0
- package/package.json +18 -13
- package/dist/chunk-R5U7XKVJ.js +0 -16
- package/dist/esm-5GYCIXIY.js +0 -3475
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
|
@@ -5,6 +5,7 @@ Universal server SDK for Node.js and edge runtimes. Includes API client, paywall
|
|
|
5
5
|
**Works in**: Node.js, Vercel Edge Functions, Cloudflare Workers, Deno, Supabase Edge Functions, and more.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
|
+
|
|
8
9
|
```bash
|
|
9
10
|
pnpm add @solvapay/server
|
|
10
11
|
```
|
|
@@ -16,39 +17,39 @@ pnpm add @solvapay/server
|
|
|
16
17
|
The same imports work in **Node.js and edge runtimes**. The correct implementation is automatically selected:
|
|
17
18
|
|
|
18
19
|
```ts
|
|
19
|
-
import { createSolvaPayClient, verifyWebhook } from '@solvapay/server'
|
|
20
|
+
import { createSolvaPayClient, verifyWebhook } from '@solvapay/server'
|
|
20
21
|
|
|
21
22
|
// Works in Node.js, Edge Functions, Cloudflare Workers, Deno, etc.
|
|
22
|
-
const apiClient = createSolvaPayClient({
|
|
23
|
-
apiKey: process.env.SOLVAPAY_SECRET_KEY
|
|
24
|
-
})
|
|
23
|
+
const apiClient = createSolvaPayClient({
|
|
24
|
+
apiKey: process.env.SOLVAPAY_SECRET_KEY!,
|
|
25
|
+
})
|
|
25
26
|
|
|
26
27
|
// Auto-selects Node crypto or Web Crypto based on runtime
|
|
27
|
-
const event = await verifyWebhook({
|
|
28
|
-
body,
|
|
29
|
-
signature,
|
|
30
|
-
secret: process.env.SOLVAPAY_WEBHOOK_SECRET
|
|
31
|
-
})
|
|
28
|
+
const event = await verifyWebhook({
|
|
29
|
+
body,
|
|
30
|
+
signature,
|
|
31
|
+
secret: process.env.SOLVAPAY_WEBHOOK_SECRET!,
|
|
32
|
+
})
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
**Edge Runtime Examples:**
|
|
35
36
|
|
|
36
37
|
```ts
|
|
37
38
|
// Supabase Edge Function
|
|
38
|
-
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
|
39
|
-
import { createSolvaPayClient, verifyWebhook } from 'https://esm.sh/@solvapay/server@latest'
|
|
39
|
+
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
|
40
|
+
import { createSolvaPayClient, verifyWebhook } from 'https://esm.sh/@solvapay/server@latest'
|
|
40
41
|
|
|
41
42
|
const solvapay = createSolvaPayClient({
|
|
42
43
|
apiKey: Deno.env.get('SOLVAPAY_SECRET_KEY')!,
|
|
43
|
-
})
|
|
44
|
+
})
|
|
44
45
|
|
|
45
46
|
// Vercel Edge Function
|
|
46
|
-
import { createSolvaPayClient } from '@solvapay/server'
|
|
47
|
+
import { createSolvaPayClient } from '@solvapay/server'
|
|
47
48
|
|
|
48
|
-
export const runtime = 'edge'
|
|
49
|
+
export const runtime = 'edge'
|
|
49
50
|
const solvapay = createSolvaPayClient({
|
|
50
51
|
apiKey: process.env.SOLVAPAY_SECRET_KEY!,
|
|
51
|
-
})
|
|
52
|
+
})
|
|
52
53
|
```
|
|
53
54
|
|
|
54
55
|
### Paywall Protection
|
|
@@ -59,12 +60,12 @@ Use the unified payable API to protect your endpoints and functions with usage l
|
|
|
59
60
|
import { createSolvaPay } from '@solvapay/server';
|
|
60
61
|
|
|
61
62
|
// Create SolvaPay instance with your API key
|
|
62
|
-
const solvaPay = createSolvaPay({
|
|
63
|
-
apiKey: process.env.SOLVAPAY_SECRET_KEY!
|
|
63
|
+
const solvaPay = createSolvaPay({
|
|
64
|
+
apiKey: process.env.SOLVAPAY_SECRET_KEY!
|
|
64
65
|
});
|
|
65
66
|
|
|
66
|
-
// Create a payable with your
|
|
67
|
-
const payable = solvaPay.payable({
|
|
67
|
+
// Create a payable with your product configuration
|
|
68
|
+
const payable = solvaPay.payable({ product: 'my-product' });
|
|
68
69
|
|
|
69
70
|
// Use the appropriate adapter for your context:
|
|
70
71
|
|
|
@@ -88,8 +89,8 @@ const protectedHandler = await payable.function(async (args) => {
|
|
|
88
89
|
return { result: 'success' };
|
|
89
90
|
});
|
|
90
91
|
|
|
91
|
-
const result = await protectedHandler({
|
|
92
|
-
auth: { customer_ref: 'customer_123' }
|
|
92
|
+
const result = await protectedHandler({
|
|
93
|
+
auth: { customer_ref: 'customer_123' }
|
|
93
94
|
});
|
|
94
95
|
```
|
|
95
96
|
|
|
@@ -98,30 +99,62 @@ const result = await protectedHandler({
|
|
|
98
99
|
You can integrate authentication adapters from `@solvapay/auth` with the `getCustomerRef` option:
|
|
99
100
|
|
|
100
101
|
```ts
|
|
101
|
-
import { createSolvaPay } from '@solvapay/server'
|
|
102
|
-
import { SupabaseAuthAdapter } from '@solvapay/auth/supabase'
|
|
102
|
+
import { createSolvaPay } from '@solvapay/server'
|
|
103
|
+
import { SupabaseAuthAdapter } from '@solvapay/auth/supabase'
|
|
103
104
|
|
|
104
105
|
const auth = new SupabaseAuthAdapter({
|
|
105
|
-
jwtSecret: process.env.SUPABASE_JWT_SECRET
|
|
106
|
-
})
|
|
106
|
+
jwtSecret: process.env.SUPABASE_JWT_SECRET!,
|
|
107
|
+
})
|
|
107
108
|
|
|
108
|
-
const solvaPay = createSolvaPay({ apiKey: process.env.SOLVAPAY_SECRET_KEY! })
|
|
109
|
+
const solvaPay = createSolvaPay({ apiKey: process.env.SOLVAPAY_SECRET_KEY! })
|
|
109
110
|
|
|
110
111
|
// Use with Next.js adapter
|
|
111
|
-
export const POST = solvaPay.payable({
|
|
112
|
-
async
|
|
113
|
-
return { result: 'success' }
|
|
112
|
+
export const POST = solvaPay.payable({ product: 'my-api' }).next(
|
|
113
|
+
async args => {
|
|
114
|
+
return { result: 'success' }
|
|
114
115
|
},
|
|
115
116
|
{
|
|
116
|
-
getCustomerRef: async
|
|
117
|
-
const userId = await auth.getUserIdFromRequest(req)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
getCustomerRef: async req => {
|
|
118
|
+
const userId = await auth.getUserIdFromRequest(req)
|
|
119
|
+
if (!userId) {
|
|
120
|
+
throw new Error('Unauthorized')
|
|
121
|
+
}
|
|
122
|
+
return userId
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
)
|
|
122
126
|
```
|
|
123
127
|
|
|
124
128
|
This automatically extracts the user ID from authentication tokens and uses it as the customer reference for paywall checks.
|
|
129
|
+
Fail closed on missing/invalid auth. Do not fall back to shared identities like `anonymous`.
|
|
130
|
+
|
|
131
|
+
For MCP bearer-token flows, the SDK also exports helper utilities:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
import {
|
|
135
|
+
getCustomerRefFromBearerAuthHeader,
|
|
136
|
+
McpBearerAuthError,
|
|
137
|
+
} from '@solvapay/server'
|
|
138
|
+
|
|
139
|
+
const handler = solvaPay.payable({ product: 'my-api' }).mcp(
|
|
140
|
+
async args => ({ ok: true }),
|
|
141
|
+
{
|
|
142
|
+
getCustomerRef: args => {
|
|
143
|
+
try {
|
|
144
|
+
return getCustomerRefFromBearerAuthHeader(args._authHeader as string | undefined)
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (error instanceof McpBearerAuthError) {
|
|
147
|
+
throw new Error('Unauthorized')
|
|
148
|
+
}
|
|
149
|
+
throw error
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`payable({ getCustomerRef })` is now supported as a default extractor across adapters. Adapter-level
|
|
157
|
+
`getCustomerRef` still takes precedence when both are provided.
|
|
125
158
|
|
|
126
159
|
### When to Use Each Adapter
|
|
127
160
|
|
|
@@ -175,18 +208,20 @@ This will fetch the OpenAPI spec from `http://localhost:3001/v1/openapi.json` an
|
|
|
175
208
|
### Using Generated Types
|
|
176
209
|
|
|
177
210
|
```typescript
|
|
178
|
-
import type { paths, components } from './types/generated'
|
|
211
|
+
import type { paths, components } from './types/generated'
|
|
179
212
|
|
|
180
213
|
// Use path operation types
|
|
181
|
-
type CheckLimitsRequest =
|
|
182
|
-
|
|
214
|
+
type CheckLimitsRequest =
|
|
215
|
+
paths['/v1/sdk/limits']['post']['requestBody']['content']['application/json']
|
|
216
|
+
type CheckLimitsResponse =
|
|
217
|
+
paths['/v1/sdk/limits']['post']['responses']['200']['content']['application/json']
|
|
183
218
|
|
|
184
219
|
// Use component schemas
|
|
185
|
-
type Agent = components['schemas']['Agent']
|
|
186
|
-
type Plan = components['schemas']['Plan']
|
|
220
|
+
type Agent = components['schemas']['Agent']
|
|
221
|
+
type Plan = components['schemas']['Plan']
|
|
187
222
|
```
|
|
188
223
|
|
|
189
|
-
**Note:** The generated types complement the existing hand-written types in `src/types.ts`. Run `pnpm generate:types` whenever the backend API changes to keep types in sync.
|
|
224
|
+
**Note:** The generated types complement the existing hand-written types in `src/types/client.ts`. Run `pnpm generate:types` whenever the backend API changes to keep types in sync.
|
|
190
225
|
|
|
191
226
|
## Testing
|
|
192
227
|
|
|
@@ -213,18 +248,20 @@ pnpm test:watch
|
|
|
213
248
|
|
|
214
249
|
### Unit Tests
|
|
215
250
|
|
|
216
|
-
Unit tests (`__tests__/paywall.test.ts`) use a mock API client and test:
|
|
251
|
+
Unit tests (`__tests__/paywall.unit.test.ts`, `__tests__/mcp-auth.unit.test.ts`) use a mock API client and test:
|
|
252
|
+
|
|
217
253
|
- Paywall protection logic
|
|
218
254
|
- Handler creation (HTTP, Next.js, MCP)
|
|
219
255
|
- Error handling
|
|
220
256
|
- Authentication flows
|
|
221
|
-
-
|
|
257
|
+
- Product resolution
|
|
222
258
|
|
|
223
259
|
**No backend required** - runs fast and deterministically.
|
|
224
260
|
|
|
225
261
|
### Integration Tests
|
|
226
262
|
|
|
227
263
|
Integration tests (`__tests__/backend.integration.test.ts`) connect to a real SolvaPay backend and test:
|
|
264
|
+
|
|
228
265
|
- SDK API methods with real responses
|
|
229
266
|
- Actual limit enforcement
|
|
230
267
|
- Real usage tracking
|
|
@@ -251,6 +288,7 @@ USE_REAL_BACKEND=true SOLVAPAY_SECRET_KEY=your_key pnpm test:integration
|
|
|
251
288
|
### Payment Integration Tests (Stripe)
|
|
252
289
|
|
|
253
290
|
Payment tests (`__tests__/payment-stripe.integration.test.ts`) verify the complete payment flow with Stripe:
|
|
291
|
+
|
|
254
292
|
- Creating payment intents
|
|
255
293
|
- Confirming payments with test cards
|
|
256
294
|
- Webhook processing (optional)
|
|
@@ -270,24 +308,27 @@ export SOLVAPAY_API_BASE_URL=http://localhost:3001
|
|
|
270
308
|
The E2E webhook test is skipped by default because it requires Stripe webhooks to be forwarded to your local backend. To enable webhook testing:
|
|
271
309
|
|
|
272
310
|
1. **Install Stripe CLI:**
|
|
311
|
+
|
|
273
312
|
```bash
|
|
274
313
|
# macOS
|
|
275
314
|
brew install stripe/stripe-cli/stripe
|
|
276
|
-
|
|
315
|
+
|
|
277
316
|
# Linux / Windows - see https://stripe.com/docs/stripe-cli
|
|
278
317
|
```
|
|
279
318
|
|
|
280
319
|
2. **Login to Stripe:**
|
|
320
|
+
|
|
281
321
|
```bash
|
|
282
322
|
stripe login
|
|
283
323
|
```
|
|
284
324
|
|
|
285
325
|
3. **Forward webhooks to your local backend:**
|
|
326
|
+
|
|
286
327
|
```bash
|
|
287
328
|
# Terminal 1: Start your backend
|
|
288
329
|
cd path/to/solvapay-backend
|
|
289
330
|
pnpm dev
|
|
290
|
-
|
|
331
|
+
|
|
291
332
|
# Terminal 2: Forward Stripe webhooks
|
|
292
333
|
stripe listen --forward-to localhost:3001/webhooks/stripe
|
|
293
334
|
```
|
|
@@ -354,4 +395,4 @@ By default, both are **disabled** to keep test output clean and readable. Enable
|
|
|
354
395
|
run: pnpm test:integration
|
|
355
396
|
```
|
|
356
397
|
|
|
357
|
-
More: docs/architecture.md
|
|
398
|
+
More: [docs/guides/architecture.md](../../docs/guides/architecture.md)
|