spaps 0.3.2 → 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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/local-server.js +148 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spaps",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Sweet Potato Authentication & Payment Service CLI - Zero-config local development and project scaffolding",
5
5
  "main": "bin/spaps.js",
6
6
  "bin": {
@@ -54,4 +54,4 @@
54
54
  "client.js",
55
55
  "README.md"
56
56
  ]
57
- }
57
+ }
@@ -32,7 +32,7 @@ class LocalServer {
32
32
  origin: true,
33
33
  credentials: true,
34
34
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
35
- allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key', 'X-Test-User'],
35
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key', 'X-Test-User', 'x-local-mode'],
36
36
  }));
37
37
 
38
38
  // Body parsing
@@ -147,7 +147,23 @@ class LocalServer {
147
147
  });
148
148
  });
149
149
 
150
- // Mock Stripe endpoints
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