a tool for shared writing and social publishing
at main 62 lines 1.9 kB view raw
1import Stripe from "stripe"; 2import { PRODUCT_DEF_ID, PRODUCT_DEFINITION, PRICE_DEFINITIONS } from "./products"; 3 4const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, { 5 apiVersion: "2026-02-25.clover", 6}); 7 8async function sync() { 9 console.log("Syncing Stripe products and prices..."); 10 11 // Find or create product 12 let product: Stripe.Product | undefined; 13 const existing = await stripe.products.search({ 14 query: `metadata["product_def_id"]:"${PRODUCT_DEF_ID}"`, 15 }); 16 17 if (existing.data.length > 0) { 18 product = existing.data[0]; 19 console.log(`Found existing product: ${product.id}`); 20 // Update if name or metadata changed 21 product = await stripe.products.update(product.id, { 22 name: PRODUCT_DEFINITION.name, 23 metadata: PRODUCT_DEFINITION.metadata, 24 }); 25 console.log(`Updated product: ${product.id}`); 26 } else { 27 product = await stripe.products.create({ 28 name: PRODUCT_DEFINITION.name, 29 metadata: PRODUCT_DEFINITION.metadata, 30 }); 31 console.log(`Created product: ${product.id}`); 32 } 33 34 // Sync prices by lookup_key 35 for (const [cadence, def] of Object.entries(PRICE_DEFINITIONS)) { 36 const existingPrices = await stripe.prices.list({ 37 lookup_keys: [def.lookup_key], 38 }); 39 40 if (existingPrices.data.length > 0) { 41 console.log( 42 `Price "${def.lookup_key}" already exists: ${existingPrices.data[0].id}`, 43 ); 44 } else { 45 const price = await stripe.prices.create({ 46 product: product.id, 47 unit_amount: def.unit_amount, 48 currency: def.currency, 49 recurring: def.recurring, 50 lookup_key: def.lookup_key, 51 }); 52 console.log(`Created price "${def.lookup_key}": ${price.id}`); 53 } 54 } 55 56 console.log("Sync complete."); 57} 58 59sync().catch((err) => { 60 console.error("Sync failed:", err); 61 process.exit(1); 62});