spaps 0.3.5 → 0.3.6

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 +1 -1
  2. package/src/local-server.js +104 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spaps",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
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": {
@@ -349,16 +349,111 @@ class LocalServer {
349
349
  });
350
350
  });
351
351
 
352
- // Mock admin product sync endpoint
353
- this.app.post('/api/v1/admin/products/sync', (req, res) => {
354
- res.json({
355
- success: true,
356
- message: 'Products synced successfully (local mode)',
357
- data: {
358
- synced_count: 2,
359
- products: ['Validate', 'Prototype']
352
+ // Admin product sync endpoint - REAL or MOCK based on config
353
+ this.app.post('/api/v1/admin/products/sync', async (req, res) => {
354
+ try {
355
+ if (USE_REAL_STRIPE) {
356
+ // Get local products from admin manager
357
+ const localProducts = this.adminManager.listProducts();
358
+ const syncResults = [];
359
+
360
+ for (const product of localProducts) {
361
+ try {
362
+ // Check if product already exists in Stripe
363
+ let stripeProduct;
364
+ try {
365
+ stripeProduct = await stripe.products.retrieve(product.id);
366
+ } catch (error) {
367
+ if (error.code === 'resource_missing') {
368
+ // Create new product in Stripe
369
+ stripeProduct = await stripe.products.create({
370
+ id: product.id,
371
+ name: product.name,
372
+ description: product.description,
373
+ metadata: {
374
+ spaps_managed: 'true',
375
+ created_by: 'spaps_admin'
376
+ }
377
+ });
378
+
379
+ // Create corresponding price
380
+ await stripe.prices.create({
381
+ id: product.price_id,
382
+ product: stripeProduct.id,
383
+ unit_amount: product.price,
384
+ currency: product.currency,
385
+ metadata: {
386
+ spaps_managed: 'true'
387
+ }
388
+ });
389
+
390
+ syncResults.push({
391
+ id: product.id,
392
+ name: product.name,
393
+ action: 'created',
394
+ stripe_id: stripeProduct.id
395
+ });
396
+ } else {
397
+ throw error;
398
+ }
399
+ }
400
+
401
+ if (stripeProduct && !syncResults.find(r => r.id === product.id)) {
402
+ // Update existing product
403
+ await stripe.products.update(stripeProduct.id, {
404
+ name: product.name,
405
+ description: product.description,
406
+ active: product.active
407
+ });
408
+
409
+ syncResults.push({
410
+ id: product.id,
411
+ name: product.name,
412
+ action: 'updated',
413
+ stripe_id: stripeProduct.id
414
+ });
415
+ }
416
+ } catch (productError) {
417
+ console.error(`Error syncing product ${product.id}:`, productError);
418
+ syncResults.push({
419
+ id: product.id,
420
+ name: product.name,
421
+ action: 'error',
422
+ error: productError.message
423
+ });
424
+ }
425
+ }
426
+
427
+ res.json({
428
+ success: true,
429
+ message: `Successfully synced ${syncResults.filter(r => r.action !== 'error').length} products to Stripe`,
430
+ data: {
431
+ synced_count: syncResults.filter(r => r.action !== 'error').length,
432
+ total_count: localProducts.length,
433
+ results: syncResults
434
+ }
435
+ });
436
+ } else {
437
+ // Mock response (fallback)
438
+ res.json({
439
+ success: true,
440
+ message: 'Products synced successfully (mock mode)',
441
+ data: {
442
+ synced_count: 2,
443
+ products: ['Validate', 'Prototype']
444
+ }
445
+ });
360
446
  }
361
- });
447
+ } catch (error) {
448
+ console.error('Product sync error:', error);
449
+ res.status(500).json({
450
+ success: false,
451
+ error: {
452
+ code: 'SYNC_ERROR',
453
+ message: error.message || 'Failed to sync products'
454
+ }
455
+ });
456
+ }
362
457
  });
363
458
 
364
459
  // Mock usage endpoints