@solvapay/server 1.0.0-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/README.md +242 -0
- package/dist/chunk-R5U7XKVJ.js +16 -0
- package/dist/edge.d.ts +845 -0
- package/dist/edge.js +847 -0
- package/dist/esm-5GYCIXIY.js +3475 -0
- package/dist/index.cjs +5093 -0
- package/dist/index.d.cts +825 -0
- package/dist/index.d.ts +825 -0
- package/dist/index.js +834 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# @solvapay/server
|
|
2
|
+
|
|
3
|
+
Universal server SDK for Node.js and edge runtimes. Includes API client, paywall protection, and webhook verification.
|
|
4
|
+
|
|
5
|
+
**Works in**: Node.js, Vercel Edge Functions, Cloudflare Workers, Deno, Supabase Edge Functions, and more.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add @solvapay/server
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
### Basic Client
|
|
15
|
+
|
|
16
|
+
The same imports work in **Node.js and edge runtimes**. The correct implementation is automatically selected:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { createSolvaPayClient, verifyWebhook } from '@solvapay/server';
|
|
20
|
+
|
|
21
|
+
// Works in Node.js, Edge Functions, Cloudflare Workers, Deno, etc.
|
|
22
|
+
const apiClient = createSolvaPayClient({
|
|
23
|
+
apiKey: process.env.SOLVAPAY_SECRET_KEY!
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// 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
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Edge Runtime Examples:**
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// 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';
|
|
40
|
+
|
|
41
|
+
const solvapay = createSolvaPayClient({
|
|
42
|
+
apiKey: Deno.env.get('SOLVAPAY_SECRET_KEY')!,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Vercel Edge Function
|
|
46
|
+
import { createSolvaPayClient } from '@solvapay/server';
|
|
47
|
+
|
|
48
|
+
export const runtime = 'edge';
|
|
49
|
+
const solvapay = createSolvaPayClient({
|
|
50
|
+
apiKey: process.env.SOLVAPAY_SECRET_KEY!,
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Paywall Protection
|
|
55
|
+
|
|
56
|
+
Use the unified payable API to protect your endpoints and functions with usage limits and metered billing:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { createSolvaPay } from '@solvapay/server';
|
|
60
|
+
|
|
61
|
+
// Create SolvaPay instance with your API key
|
|
62
|
+
const solvaPay = createSolvaPay({
|
|
63
|
+
apiKey: process.env.SOLVAPAY_SECRET_KEY!
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Create a payable with your agent configuration
|
|
67
|
+
const payable = solvaPay.payable({ agent: 'my-agent' });
|
|
68
|
+
|
|
69
|
+
// Use the appropriate adapter for your context:
|
|
70
|
+
|
|
71
|
+
// For HTTP frameworks (Express, Fastify)
|
|
72
|
+
app.post('/tasks', payable.http(async (args) => {
|
|
73
|
+
return { result: 'success' };
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
// For Next.js App Router
|
|
77
|
+
export const POST = payable.next(async (args) => {
|
|
78
|
+
return { result: 'success' };
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// For MCP servers
|
|
82
|
+
server.setRequestHandler(ListToolsRequestSchema, payable.mcp(async (args) => {
|
|
83
|
+
return { tools: [...] };
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
// For direct function protection (testing, background jobs)
|
|
87
|
+
const protectedHandler = await payable.function(async (args) => {
|
|
88
|
+
return { result: 'success' };
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const result = await protectedHandler({
|
|
92
|
+
auth: { customer_ref: 'customer_123' }
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### When to Use Each Adapter
|
|
97
|
+
|
|
98
|
+
Choose the adapter based on your context:
|
|
99
|
+
|
|
100
|
+
- **`payable.http()`** - Use with Express, Fastify, or other traditional HTTP frameworks
|
|
101
|
+
- Handles request/response objects automatically
|
|
102
|
+
- Extracts args from body, params, query
|
|
103
|
+
- Formats errors as HTTP responses
|
|
104
|
+
|
|
105
|
+
- **`payable.next()`** - Use with Next.js App Router API routes
|
|
106
|
+
- Works with Web Request/Response APIs
|
|
107
|
+
- Handles route parameters and context
|
|
108
|
+
- Returns proper Response objects
|
|
109
|
+
|
|
110
|
+
- **`payable.mcp()`** - Use with Model Context Protocol servers
|
|
111
|
+
- Wraps responses in MCP format
|
|
112
|
+
- Handles MCP-specific error reporting
|
|
113
|
+
- Provides structured content
|
|
114
|
+
|
|
115
|
+
- **`payable.function()`** - Use for direct function protection
|
|
116
|
+
- No framework overhead
|
|
117
|
+
- Perfect for testing
|
|
118
|
+
- Use in background jobs, cron tasks, or non-HTTP contexts
|
|
119
|
+
|
|
120
|
+
## API Client Methods
|
|
121
|
+
|
|
122
|
+
The `createSolvaPayClient` returns an object implementing `SolvaPayClient`:
|
|
123
|
+
|
|
124
|
+
- `checkLimits(params)` - Check if customer is within usage limits
|
|
125
|
+
- `trackUsage(params)` - Track usage for metered billing
|
|
126
|
+
- `createCustomer(params)` - Create a new customer
|
|
127
|
+
- `getCustomer(params)` - Get customer details by reference
|
|
128
|
+
|
|
129
|
+
## Type Generation
|
|
130
|
+
|
|
131
|
+
This package supports automatic TypeScript type generation from the SolvaPay backend OpenAPI specification.
|
|
132
|
+
|
|
133
|
+
### Generating Types
|
|
134
|
+
|
|
135
|
+
To generate types from your locally running backend:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Ensure your backend is running on http://localhost:3001
|
|
139
|
+
# Then run:
|
|
140
|
+
pnpm generate:types
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
This will fetch the OpenAPI spec from `http://localhost:3001/v1/openapi.json` and generate TypeScript types in `src/types/generated.ts`. Only `/v1/sdk/` routes are included in the generated types.
|
|
144
|
+
|
|
145
|
+
### Using Generated Types
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import type { paths, components } from './types/generated';
|
|
149
|
+
|
|
150
|
+
// Use path operation types
|
|
151
|
+
type CheckLimitsRequest = paths['/v1/sdk/limits']['post']['requestBody']['content']['application/json'];
|
|
152
|
+
type CheckLimitsResponse = paths['/v1/sdk/limits']['post']['responses']['200']['content']['application/json'];
|
|
153
|
+
|
|
154
|
+
// Use component schemas
|
|
155
|
+
type Agent = components['schemas']['Agent'];
|
|
156
|
+
type Plan = components['schemas']['Plan'];
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**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.
|
|
160
|
+
|
|
161
|
+
## Testing
|
|
162
|
+
|
|
163
|
+
> **📖 For detailed integration test setup**, see:
|
|
164
|
+
> - [`packages/test-utils/INTEGRATION_TESTING.md`](../test-utils/INTEGRATION_TESTING.md) - Complete setup guide
|
|
165
|
+
> - [`SDK_INTEGRATION_TESTS_IMPLEMENTATION.md`](../../SDK_INTEGRATION_TESTS_IMPLEMENTATION.md) - Implementation details
|
|
166
|
+
|
|
167
|
+
This package includes comprehensive tests for SDK functionality.
|
|
168
|
+
|
|
169
|
+
### Running Tests
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Run unit tests only (fast, uses mock backend)
|
|
173
|
+
pnpm test
|
|
174
|
+
|
|
175
|
+
# Run integration tests (requires real backend)
|
|
176
|
+
pnpm test:integration
|
|
177
|
+
|
|
178
|
+
# Run all tests
|
|
179
|
+
pnpm test:all
|
|
180
|
+
|
|
181
|
+
# Run all tests with real backend
|
|
182
|
+
pnpm test:all:integration
|
|
183
|
+
|
|
184
|
+
# Watch mode
|
|
185
|
+
pnpm test:watch
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Unit Tests
|
|
189
|
+
|
|
190
|
+
Unit tests (`__tests__/paywall.test.ts`) use a mock API client and test:
|
|
191
|
+
- Paywall protection logic
|
|
192
|
+
- Handler creation (HTTP, Next.js, MCP)
|
|
193
|
+
- Error handling
|
|
194
|
+
- Authentication flows
|
|
195
|
+
- Agent resolution
|
|
196
|
+
|
|
197
|
+
**No backend required** - runs fast and deterministically.
|
|
198
|
+
|
|
199
|
+
### Integration Tests
|
|
200
|
+
|
|
201
|
+
Integration tests (`__tests__/paywall.integration.with-fetched-defaults.test.ts`) connect to a real SolvaPay backend and test:
|
|
202
|
+
- SDK API methods with real responses
|
|
203
|
+
- Actual limit enforcement
|
|
204
|
+
- Real usage tracking
|
|
205
|
+
- Multi-framework handlers with backend
|
|
206
|
+
- Error handling with real backend responses
|
|
207
|
+
|
|
208
|
+
**Setup required:**
|
|
209
|
+
|
|
210
|
+
Set environment variables before running tests:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Option 1: Export in your shell (persists in session)
|
|
214
|
+
export USE_REAL_BACKEND=true
|
|
215
|
+
export SOLVAPAY_SECRET_KEY=your_secret_key_here
|
|
216
|
+
export SOLVAPAY_API_BASE_URL=https://api-dev.solvapay.com # optional
|
|
217
|
+
pnpm test:integration
|
|
218
|
+
|
|
219
|
+
# Option 2: Inline with command (single use)
|
|
220
|
+
USE_REAL_BACKEND=true SOLVAPAY_SECRET_KEY=your_key pnpm test:integration
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Note:** This follows the industry standard used by major SDKs (Stripe, AWS, Twilio). No `.env` file is required.
|
|
224
|
+
|
|
225
|
+
**Note:** Integration tests are automatically skipped if `USE_REAL_BACKEND` or `SOLVAPAY_SECRET_KEY` are not set. This allows CI/CD to run unit tests without backend credentials.
|
|
226
|
+
|
|
227
|
+
### CI/CD
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
# Always run unit tests
|
|
231
|
+
- name: Run unit tests
|
|
232
|
+
run: pnpm test
|
|
233
|
+
|
|
234
|
+
# Optionally run integration tests if secrets available
|
|
235
|
+
- name: Run integration tests
|
|
236
|
+
if: ${{ secrets.SOLVAPAY_SECRET_KEY != '' }}
|
|
237
|
+
env:
|
|
238
|
+
SOLVAPAY_SECRET_KEY: ${{ secrets.SOLVAPAY_SECRET_KEY }}
|
|
239
|
+
run: pnpm test:integration
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
More: docs/architecture.md
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
__require,
|
|
15
|
+
__export
|
|
16
|
+
};
|