156 lines
4.4 KiB
JavaScript
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)
|
|
})
|