rebours/scripts/stripe-purge.mjs

156 lines
4.4 KiB
JavaScript

#!/usr/bin/env node
/**
* stripe-purge.mjs
* ─────────────────
* Supprime TOUS les produits (et leurs prix) du compte Stripe.
*
* Usage :
* node scripts/stripe-purge.mjs # mode dry-run (affiche sans supprimer)
* node scripts/stripe-purge.mjs --confirm # suppression réelle
*
* ⚠️ IRRÉVERSIBLE — utiliser avec précaution
*/
import 'dotenv/config'
import Stripe from 'stripe'
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY
if (!STRIPE_SECRET_KEY) {
console.error('❌ STRIPE_SECRET_KEY manquant dans .env')
process.exit(1)
}
const stripe = new Stripe(STRIPE_SECRET_KEY)
const dryRun = !process.argv.includes('--confirm')
if (dryRun) {
console.log('🔍 MODE DRY-RUN — aucun produit ne sera supprimé')
console.log(' Ajouter --confirm pour supprimer réellement\n')
}
async function archivePrices(productId) {
let hasMore = true
let startingAfter = undefined
let count = 0
while (hasMore) {
const params = { product: productId, active: true, limit: 100 }
if (startingAfter) params.starting_after = startingAfter
const prices = await stripe.prices.list(params)
for (const price of prices.data) {
if (dryRun) {
console.log(` 📌 Prix ${price.id}${price.unit_amount / 100} ${price.currency.toUpperCase()} (serait archivé)`)
} else {
await stripe.prices.update(price.id, { active: false })
console.log(` ✓ Prix archivé: ${price.id}`)
}
count++
}
hasMore = prices.has_more
if (prices.data.length > 0) {
startingAfter = prices.data[prices.data.length - 1].id
}
}
return count
}
async function main() {
let hasMore = true
let startingAfter = undefined
let totalProducts = 0
let totalPrices = 0
console.log('🗑️ Récupération des produits Stripe...\n')
while (hasMore) {
const params = { limit: 100, active: true }
if (startingAfter) params.starting_after = startingAfter
const products = await stripe.products.list(params)
for (const product of products.data) {
console.log(`📦 ${product.name || product.id}`)
// 1. Archiver les prix (obligatoire avant suppression)
const priceCount = await archivePrices(product.id)
totalPrices += priceCount
// 2. Archiver puis supprimer le produit
if (dryRun) {
console.log(` 🗑️ Produit serait supprimé\n`)
} else {
// D'abord archiver (désactiver)
await stripe.products.update(product.id, { active: false })
// Puis supprimer (possible uniquement si aucune facture liée)
try {
await stripe.products.del(product.id)
console.log(` ✓ Produit supprimé\n`)
} catch (err) {
// Si le produit a des factures, on ne peut que l'archiver
console.log(` ⚠️ Produit archivé (suppression impossible: ${err.message})\n`)
}
}
totalProducts++
}
hasMore = products.has_more
if (products.data.length > 0) {
startingAfter = products.data[products.data.length - 1].id
}
}
// Aussi traiter les produits déjà archivés
hasMore = true
startingAfter = undefined
while (hasMore) {
const params = { limit: 100, active: false }
if (startingAfter) params.starting_after = startingAfter
const products = await stripe.products.list(params)
for (const product of products.data) {
console.log(`📦 (archivé) ${product.name || product.id}`)
const priceCount = await archivePrices(product.id)
totalPrices += priceCount
if (dryRun) {
console.log(` 🗑️ Produit serait supprimé\n`)
} else {
try {
await stripe.products.del(product.id)
console.log(` ✓ Produit supprimé\n`)
} catch (err) {
console.log(` ⚠️ Non supprimable: ${err.message}\n`)
}
}
totalProducts++
}
hasMore = products.has_more
if (products.data.length > 0) {
startingAfter = products.data[products.data.length - 1].id
}
}
console.log('─'.repeat(50))
if (dryRun) {
console.log(`📊 ${totalProducts} produits et ${totalPrices} prix SERAIENT supprimés`)
console.log('\n👉 Relancer avec --confirm pour exécuter')
} else {
console.log(`${totalProducts} produits et ${totalPrices} prix traités`)
}
}
main().catch(err => {
console.error('❌ Erreur:', err.message)
process.exit(1)
})