spaps 0.3.5 → 0.3.7

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 +105 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spaps",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
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,112 @@ 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 by searching metadata
363
+ let stripeProduct;
364
+ const existingProducts = await stripe.products.list({
365
+ limit: 100,
366
+ expand: ['data.default_price']
367
+ });
368
+
369
+ stripeProduct = existingProducts.data.find(p =>
370
+ p.metadata && p.metadata.spaps_id === product.id
371
+ );
372
+
373
+ if (!stripeProduct) {
374
+ // Create new product in Stripe
375
+ stripeProduct = await stripe.products.create({
376
+ name: product.name,
377
+ description: product.description,
378
+ metadata: {
379
+ spaps_managed: 'true',
380
+ created_by: 'spaps_admin',
381
+ spaps_id: product.id
382
+ }
383
+ });
384
+
385
+ // Create corresponding price
386
+ await stripe.prices.create({
387
+ product: stripeProduct.id,
388
+ unit_amount: product.price,
389
+ currency: product.currency,
390
+ metadata: {
391
+ spaps_managed: 'true',
392
+ spaps_price_id: product.price_id
393
+ }
394
+ });
395
+
396
+ syncResults.push({
397
+ id: product.id,
398
+ name: product.name,
399
+ action: 'created',
400
+ stripe_id: stripeProduct.id
401
+ });
402
+ } else {
403
+ // Update existing product
404
+ await stripe.products.update(stripeProduct.id, {
405
+ name: product.name,
406
+ description: product.description,
407
+ active: product.active !== false
408
+ });
409
+
410
+ syncResults.push({
411
+ id: product.id,
412
+ name: product.name,
413
+ action: 'updated',
414
+ stripe_id: stripeProduct.id
415
+ });
416
+ }
417
+ } catch (productError) {
418
+ console.error(`Error syncing product ${product.id}:`, productError);
419
+ syncResults.push({
420
+ id: product.id,
421
+ name: product.name,
422
+ action: 'error',
423
+ error: productError.message
424
+ });
425
+ }
426
+ }
427
+
428
+ res.json({
429
+ success: true,
430
+ message: `Successfully synced ${syncResults.filter(r => r.action !== 'error').length} products to Stripe`,
431
+ data: {
432
+ synced_count: syncResults.filter(r => r.action !== 'error').length,
433
+ total_count: localProducts.length,
434
+ results: syncResults
435
+ }
436
+ });
437
+ } else {
438
+ // Mock response (fallback)
439
+ res.json({
440
+ success: true,
441
+ message: 'Products synced successfully (mock mode)',
442
+ data: {
443
+ synced_count: 2,
444
+ products: ['Validate', 'Prototype']
445
+ }
446
+ });
360
447
  }
361
- });
448
+ } catch (error) {
449
+ console.error('Product sync error:', error);
450
+ res.status(500).json({
451
+ success: false,
452
+ error: {
453
+ code: 'SYNC_ERROR',
454
+ message: error.message || 'Failed to sync products'
455
+ }
456
+ });
457
+ }
362
458
  });
363
459
 
364
460
  // Mock usage endpoints