Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions packages/cli/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Stripe API Key (get from https://dashboard.stripe.com/apikeys)
STRIPE_API_KEY=sk_test_your_stripe_api_key_here

# Stripe Project Name (for CLI testing)
STRIPE_PROJECT_NAME=your_project_name

# PostgreSQL Database URL
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/app_db

# ngrok Auth Token (get from https://dashboard.ngrok.com/signup)
NGROK_AUTH_TOKEN=your_ngrok_auth_token_here

# Optional: Database Schema (defaults to 'stripe')
# SCHEMA=stripe

# Optional: Stripe API Version (defaults to '2020-08-27')
# STRIPE_API_VERSION=2020-08-27

# Optional: Auto-expand lists (defaults to 'true')
# AUTO_EXPAND_LISTS=true

# Optional: Backfill related entities (defaults to 'true')
# BACKFILL_RELATED_ENTITIES=true
181 changes: 181 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# @supabase/stripe-sync-cli

CLI tool for syncing Stripe data to PostgreSQL with real-time webhook streaming.

## Features

- 🔄 Real-time Stripe webhook streaming to PostgreSQL
- 🚀 Automatic table creation and migrations
- 🌐 Built-in ngrok tunnel for local development
- 🔐 Secure webhook signature verification
- 🧹 Automatic cleanup on exit

## Installation

```bash
npm install -g @supabase/stripe-sync-cli
```

## Usage

### Basic Command

```bash
stripe-sync --database-url postgresql://user:password@localhost:5432/mydb
```

You'll be prompted for:
- Stripe API key (or set `STRIPE_API_KEY` env var)
- ngrok auth token (or set `NGROK_AUTH_TOKEN` env var)
- Postgres DATABASE_URL (or pass via `--database-url` flag)

### Example Output

```
$ stripe-sync postgresql://user:password@localhost:5432/mydb
Creating tables............ ✓
Populating tables.......... ✓
Streaming live changes..... ● [press Ctrl-C to abort]
```

### Command Options

```bash
stripe-sync [options]

Options:
--stripe-key <key> Stripe API key (or STRIPE_API_KEY env)
--ngrok-token <token> ngrok auth token (or NGROK_AUTH_TOKEN env)
--database-url <url> Postgres DATABASE_URL (or DATABASE_URL env)
-h, --help Display help
-V, --version Display version
```

### Environment Variables

Create a `.env` file in your project (copy from `.env.example`):

```env
STRIPE_API_KEY=sk_test_...
STRIPE_PROJECT_NAME=your_project_name
NGROK_AUTH_TOKEN=your_ngrok_token
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
```

Then run:

```bash
stripe-sync
```

### Testing with Stripe Events

Trigger test Stripe events using the built-in script:

```bash
pnpm stripe:trigger payment_intent.succeeded
pnpm stripe:trigger customer.created
pnpm stripe:trigger subscription.created
```

This uses the Stripe CLI (via Docker) to send test webhook events to your running server.

## How It Works

1. **Creates Tables**: Runs database migrations to create Stripe schema tables
2. **Sets Up Tunnel**: Creates an ngrok tunnel to expose your local server
3. **Registers Webhook**: Creates a Stripe webhook endpoint listening to all events (`*`)
4. **Streams Changes**: Real-time syncing of all Stripe events to PostgreSQL

The CLI automatically:
- Starts a Docker container running `supabase/stripe-sync-engine:latest`
- Creates an ngrok tunnel for webhook delivery
- Registers a Stripe webhook with all events enabled
- Cleans up webhook, container, and tunnel on exit (Ctrl-C)

## Prerequisites

- Docker to run the sync engine container
- Node.js >= 22.0.0
- PostgreSQL database
- Stripe API key ([Get one here](https://dashboard.stripe.com/apikeys))
- ngrok auth token ([Sign up here](https://dashboard.ngrok.com/signup))

## What Gets Synced

The CLI syncs all Stripe objects supported by `@supabase/stripe-sync-engine`:

- Customers
- Subscriptions & Subscription Schedules
- Invoices & Invoice Items
- Products & Prices
- Payment Intents & Payment Methods
- Charges & Refunds
- Disputes & Reviews
- And 20+ more object types

## Next Steps / Roadmap

### Backfill Command

Backfill historical Stripe data for a specific time period:

```bash
# Proposed usage (not yet implemented)
stripe-sync backfill --days 1 # Last 24 hours
stripe-sync backfill --days 7 # Last week
stripe-sync backfill --days 30 # Last month
```

This would:
1. Start the server
2. Call the `/sync` endpoint with date range filters
3. Display sync progress and results
4. Shut down after completion

## Troubleshooting

### "Docker is not running" or "Failed to start Docker container"

Make sure Docker is installed and running:
- Install Docker Desktop from [docker.com](https://www.docker.com/products/docker-desktop/)
- Verify Docker is running: `docker ps`
- The CLI requires Docker to run the `supabase/stripe-sync-engine:latest` container

### "Database configuration is required"

Make sure you have set `DATABASE_URL` either via:
- Command flag: `--database-url postgresql://...`
- Environment variable: `DATABASE_URL=postgresql://...`
- Interactive prompt will ask if not provided
- Start a local postgres instance with URL `postgresql://postgres:postgres@localhost:5432/app_db` using Docker by running the following command:

```bash
docker run --name local-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=app_db \
-p 5432:5432 \
-d postgres:16
```
Feel free to query it manually using `docker exec -it local-postgres psql -U postgres -d app_db`


### "Failed to create ngrok tunnel"

- Verify your ngrok auth token is valid
- Check if ngrok is blocked by your firewall
- Try running `ngrok config add-authtoken <token>` manually or go to the

### "Stripe API key should start with 'sk_'"

Make sure you're using a Secret Key (starts with `sk_`), not a Publishable Key (starts with `pk_`).

## Related Packages

- [`@supabase/stripe-sync-engine`](../sync-engine) - Core sync library
- [`@supabase/stripe-sync-fastify`](../fastify-app) - Fastify server for webhooks

## License

Apache-2.0
58 changes: 58 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@supabase/stripe-sync-cli",
"version": "0.0.0",
"description": "CLI to sync your stripe data to postgres",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"bin": {
"stripe-sync": "./dist/index.js"
},
"files": [
"dist"
],
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
"dev": "tsx src/index.ts",
"lint": "eslint src",
"format": "prettier --check .",
"format:fix": "prettier --write .",
"stripe:trigger": "./scripts/stripe-trigger.sh"
},
"keywords": [
"stripe",
"webhook",
"cli",
"development",
"ngrok",
"sync"
],
"dependencies": {
"@ngrok/ngrok": "^1.4.1",
"@supabase/stripe-sync-engine": "workspace:",
"@supabase/stripe-sync-fastify": "workspace:",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"dockerode": "^4.0.9",
"dotenv": "^16.4.7",
"inquirer": "^12.3.0"
},
"devDependencies": {
"@types/dockerode": "^3.3.45",
"@types/inquirer": "^9.0.7",
"@types/node": "^22.10.2",
"fastify": "^5.6.2",
"stripe": "^17.7.0",
"tsx": "^4.19.2"
},
"engines": {
"node": ">=22.0.0"
}
}
43 changes: 43 additions & 0 deletions packages/cli/scripts/stripe-trigger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash

# Load environment variables from .env file
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
fi

# Check if STRIPE_API_KEY is set
if [ -z "$STRIPE_API_KEY" ]; then
echo "Error: STRIPE_API_KEY not found in .env file"
exit 1
fi

# Check if STRIPE_PROJECT_NAME is set
if [ -z "$STRIPE_PROJECT_NAME" ]; then
echo "Error: STRIPE_PROJECT_NAME not found in .env file"
exit 1
fi

# Check if an event type was provided
if [ -z "$1" ]; then
echo "Usage: ./stripe-trigger.sh <event-type>"
echo ""
echo "Examples:"
echo " ./stripe-trigger.sh payment_intent.succeeded"
echo " ./stripe-trigger.sh customer.created"
echo " ./stripe-trigger.sh subscription.created"
echo ""
echo "Available events:"
docker run --rm \
-e STRIPE_API_KEY \
stripe/stripe-cli:latest \
trigger --help
exit 1
fi

# Run Stripe CLI trigger with Docker using API key and project name
docker run --rm \
-e STRIPE_API_KEY \
stripe/stripe-cli:latest \
--project-name "$STRIPE_PROJECT_NAME" \
trigger "$@" \
--api-key "$STRIPE_API_KEY"
Loading