spaps 0.3.3 → 0.3.4
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/package.json +1 -1
- package/src/local-server.js +147 -1
package/package.json
CHANGED
package/src/local-server.js
CHANGED
|
@@ -147,7 +147,23 @@ class LocalServer {
|
|
|
147
147
|
});
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
// Mock Stripe
|
|
150
|
+
// Mock Stripe checkout sessions endpoint (SDK expects this path)
|
|
151
|
+
this.app.post('/api/stripe/checkout-sessions', (req, res) => {
|
|
152
|
+
const sessionId = 'cs_local_' + Date.now();
|
|
153
|
+
res.json({
|
|
154
|
+
success: true,
|
|
155
|
+
data: {
|
|
156
|
+
sessionId,
|
|
157
|
+
url: `http://localhost:${this.port}/checkout/${sessionId}?success=${encodeURIComponent(req.body.success_url)}&cancel=${encodeURIComponent(req.body.cancel_url)}`,
|
|
158
|
+
amount_total: req.body.amount || 999,
|
|
159
|
+
currency: req.body.currency || 'usd',
|
|
160
|
+
payment_status: 'unpaid',
|
|
161
|
+
status: 'open'
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Mock Stripe endpoints (legacy)
|
|
151
167
|
this.app.post('/api/stripe/create-checkout-session', (req, res) => {
|
|
152
168
|
res.json({
|
|
153
169
|
sessionId: 'cs_test_local_' + Date.now(),
|
|
@@ -164,6 +180,80 @@ class LocalServer {
|
|
|
164
180
|
});
|
|
165
181
|
});
|
|
166
182
|
|
|
183
|
+
// Mock Stripe products endpoint
|
|
184
|
+
this.app.get('/api/stripe/products', (req, res) => {
|
|
185
|
+
res.json({
|
|
186
|
+
success: true,
|
|
187
|
+
data: [
|
|
188
|
+
{
|
|
189
|
+
id: 'prod_local_validate',
|
|
190
|
+
name: 'Validate',
|
|
191
|
+
description: 'Proof of concept validation',
|
|
192
|
+
price: 500,
|
|
193
|
+
currency: 'usd',
|
|
194
|
+
active: true
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
id: 'prod_local_prototype',
|
|
198
|
+
name: 'Prototype',
|
|
199
|
+
description: 'Build an MVP prototype',
|
|
200
|
+
price: 2500,
|
|
201
|
+
currency: 'usd',
|
|
202
|
+
active: true
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Mock auth nonce endpoint
|
|
209
|
+
this.app.post('/api/auth/nonce', (req, res) => {
|
|
210
|
+
const { wallet_address } = req.body;
|
|
211
|
+
res.json({
|
|
212
|
+
success: true,
|
|
213
|
+
data: {
|
|
214
|
+
nonce: 'local-nonce-' + Date.now(),
|
|
215
|
+
message: `Sign this message to authenticate your wallet ${wallet_address}.\n\nNonce: local-nonce-${Date.now()}`,
|
|
216
|
+
wallet_address,
|
|
217
|
+
expires_at: new Date(Date.now() + 300000).toISOString()
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Mock magic link endpoint
|
|
223
|
+
this.app.post('/api/auth/magic-link', (req, res) => {
|
|
224
|
+
const { email } = req.body;
|
|
225
|
+
res.json({
|
|
226
|
+
success: true,
|
|
227
|
+
message: 'Magic link sent successfully (simulated in local mode)',
|
|
228
|
+
data: {
|
|
229
|
+
email,
|
|
230
|
+
sent_at: new Date().toISOString()
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Mock customer portal endpoint
|
|
236
|
+
this.app.post('/api/stripe/customer-portal', (req, res) => {
|
|
237
|
+
res.json({
|
|
238
|
+
success: true,
|
|
239
|
+
data: {
|
|
240
|
+
url: `http://localhost:${this.port}/customer-portal?return=${encodeURIComponent(req.body.return_url || 'http://localhost:3000')}`
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Mock admin product sync endpoint
|
|
246
|
+
this.app.post('/api/v1/admin/products/sync', (req, res) => {
|
|
247
|
+
res.json({
|
|
248
|
+
success: true,
|
|
249
|
+
message: 'Products synced successfully (local mode)',
|
|
250
|
+
data: {
|
|
251
|
+
synced_count: 2,
|
|
252
|
+
products: ['Validate', 'Prototype']
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
167
257
|
// Mock usage endpoints
|
|
168
258
|
this.app.get('/api/usage/balance', (req, res) => {
|
|
169
259
|
res.json({
|
|
@@ -243,6 +333,62 @@ class LocalServer {
|
|
|
243
333
|
`);
|
|
244
334
|
});
|
|
245
335
|
|
|
336
|
+
// Mock customer portal page
|
|
337
|
+
this.app.get('/customer-portal', (req, res) => {
|
|
338
|
+
const { return: returnUrl } = req.query;
|
|
339
|
+
|
|
340
|
+
res.send(`
|
|
341
|
+
<!DOCTYPE html>
|
|
342
|
+
<html>
|
|
343
|
+
<head>
|
|
344
|
+
<title>SPAPS Local - Customer Portal</title>
|
|
345
|
+
<style>
|
|
346
|
+
body { font-family: system-ui; max-width: 600px; margin: 100px auto; padding: 2rem; }
|
|
347
|
+
button { width: 100%; padding: 1rem; margin: 0.5rem 0; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; }
|
|
348
|
+
.primary { background: #635bff; color: white; }
|
|
349
|
+
.primary:hover { background: #4b41e0; }
|
|
350
|
+
.secondary { background: #f5f5f5; }
|
|
351
|
+
.secondary:hover { background: #e5e5e5; }
|
|
352
|
+
.section { background: #f9f9f9; padding: 1.5rem; margin: 1rem 0; border-radius: 8px; }
|
|
353
|
+
</style>
|
|
354
|
+
</head>
|
|
355
|
+
<body>
|
|
356
|
+
<h1>🍠 Customer Portal (Local)</h1>
|
|
357
|
+
<p>Manage your subscription and billing information.</p>
|
|
358
|
+
|
|
359
|
+
<div class="section">
|
|
360
|
+
<h3>Current Subscription</h3>
|
|
361
|
+
<p><strong>Plan:</strong> Premium Plan</p>
|
|
362
|
+
<p><strong>Status:</strong> Active</p>
|
|
363
|
+
<p><strong>Next billing:</strong> ${new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toLocaleDateString()}</p>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
<div class="section">
|
|
367
|
+
<h3>Payment Method</h3>
|
|
368
|
+
<p><strong>Card:</strong> •••• •••• •••• 4242</p>
|
|
369
|
+
<p><strong>Expires:</strong> 12/2025</p>
|
|
370
|
+
<button class="secondary">Update Payment Method</button>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<div class="section">
|
|
374
|
+
<h3>Billing History</h3>
|
|
375
|
+
<p>• $25.00 - Premium Plan (${new Date().toLocaleDateString()})</p>
|
|
376
|
+
<p>• $25.00 - Premium Plan (${new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toLocaleDateString()})</p>
|
|
377
|
+
<button class="secondary">Download All Invoices</button>
|
|
378
|
+
</div>
|
|
379
|
+
|
|
380
|
+
<button class="primary" onclick="window.location='${returnUrl || 'http://localhost:3000'}'">
|
|
381
|
+
Return to Application
|
|
382
|
+
</button>
|
|
383
|
+
|
|
384
|
+
<p style="margin-top: 2rem; color: #666; font-size: 14px;">
|
|
385
|
+
This is a mock customer portal for local development.
|
|
386
|
+
</p>
|
|
387
|
+
</body>
|
|
388
|
+
</html>
|
|
389
|
+
`);
|
|
390
|
+
});
|
|
391
|
+
|
|
246
392
|
// Mock webhook endpoint
|
|
247
393
|
this.app.post('/api/stripe/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
|
|
248
394
|
// In local mode, accept all webhooks
|