Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Set your webhook endpoint in the Stripe dashboard to point to your server’s `/
| `AUTO_EXPAND_LISTS` | Fetch all list items from Stripe (default: false) | No |
| `BACKFILL_RELATED_ENTITIES` | Backfill related entities for foreign key integrity (default: true) | No |
| `MAX_POSTGRES_CONNECTIONS` | Max Postgres connection pool size (default: 10) | No |
| `REVALIDATE_ENTITY_VIA_STRIPE_API` | Always fetch latest entity from Stripe (default: false) | No |
| `REVALIDATE_OBJECTS_VIA_STRIPE_API` | Always fetch latest entity from Stripe (default: false) | No |

## Endpoints

Expand Down
24 changes: 12 additions & 12 deletions docs/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,18 @@ await sync.processWebhook(payload, signature)

## Configuration

| Option | Type | Description |
| ------------------------------ | ------- | -------------------------------------------------------------------------- |
| `databaseUrl` | string | Postgres connection string |
| `schema` | string | Database schema name (default: `stripe`) |
| `stripeSecretKey` | string | Stripe secret key |
| `stripeWebhookSecret` | string | Stripe webhook signing secret |
| `stripeApiVersion` | string | Stripe API version (default: `2020-08-27`) |
| `autoExpandLists` | boolean | Fetch all list items from Stripe (not just the default 10) |
| `backfillRelatedEntities` | boolean | Ensure related entities are present for foreign key integrity |
| `revalidateEntityViaStripeApi` | boolean | Always fetch latest entity from Stripe instead of trusting webhook payload |
| `maxPostgresConnections` | number | Maximum Postgres connections |
| `logger` | Logger | Logger instance (pino) |
| Option | Type | Description |
| ------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `databaseUrl` | string | Postgres connection string |
| `schema` | string | Database schema name (default: `stripe`) |
| `stripeSecretKey` | string | Stripe secret key |
| `stripeWebhookSecret` | string | Stripe webhook signing secret |
| `stripeApiVersion` | string | Stripe API version (default: `2020-08-27`) |
| `autoExpandLists` | boolean | Fetch all list items from Stripe (not just the default 10) |
| `backfillRelatedEntities` | boolean | Ensure related entities are present for foreign key integrity |
| `revalidateObjectsViaStripeApi` | Array | Always fetch latest entity from Stripe instead of trusting webhook payload, possible values: charge, credit_note, customer, dispute, invoice, payment_intent, payment_method, plan, price, product, refund, review, radar.early_fraud_warning, setup_intent, subscription, subscription_schedule, tax_id |
| `maxPostgresConnections` | number | Maximum Postgres connections |
| `logger` | Logger | Logger instance (pino) |

## Database Schema

Expand Down
4 changes: 2 additions & 2 deletions packages/fastify-app/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ BACKFILL_RELATED_ENTITIES=true
MAX_POSTGRES_CONNECTIONS=20

# If true, the webhook data is not used and instead the webhook is just a trigger to fetch the entity from Stripe again. This ensures that a race condition with failed webhooks can never accidentally overwrite the data with an older state.
# Default: false
REVALIDATE_ENTITY_VIA_STRIPE_API=false
# Default:
REVALIDATE_OBJECTS_VIA_STRIPE_API=payment_intent,invoice,customer,subscription
26 changes: 13 additions & 13 deletions packages/fastify-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ Set your webhook endpoint in the Stripe dashboard to point to your server’s `/

## Environment Variables

| Variable | Description | Required |
| ---------------------------------- | ------------------------------------------------------------------- | -------- |
| `DATABASE_URL` | Postgres connection string (with `search_path=stripe`) | Yes |
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret | Yes |
| `API_KEY` | API key for admin endpoints (backfilling, etc.) | Yes |
| `SCHEMA` | Database schema name (default: `stripe`) | No |
| `STRIPE_SECRET_KEY` | Stripe secret key (needed for active sync/backfill) | No |
| `PORT` | Port to run the server on (default: 8080) | No |
| `STRIPE_API_VERSION` | Stripe API version (default: `2020-08-27`) | No |
| `AUTO_EXPAND_LISTS` | Fetch all list items from Stripe (default: false) | No |
| `BACKFILL_RELATED_ENTITIES` | Backfill related entities for foreign key integrity (default: true) | No |
| `MAX_POSTGRES_CONNECTIONS` | Max Postgres connection pool size (default: 10) | No |
| `REVALIDATE_ENTITY_VIA_STRIPE_API` | Always fetch latest entity from Stripe (default: false) | No |
| Variable | Description | Required |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `DATABASE_URL` | Postgres connection string (with `search_path=stripe`) | Yes |
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook signing secret | Yes |
| `API_KEY` | API key for admin endpoints (backfilling, etc.) | Yes |
| `SCHEMA` | Database schema name (default: `stripe`) | No |
| `STRIPE_SECRET_KEY` | Stripe secret key (needed for active sync/backfill) | No |
| `PORT` | Port to run the server on (default: 8080) | No |
| `STRIPE_API_VERSION` | Stripe API version (default: `2020-08-27`) | No |
| `AUTO_EXPAND_LISTS` | Fetch all list items from Stripe (default: false) | No |
| `BACKFILL_RELATED_ENTITIES` | Backfill related entities for foreign key integrity (default: true) | No |
| `MAX_POSTGRES_CONNECTIONS` | Max Postgres connection pool size (default: 10) | No |
| `REVALIDATE_OBJECTS_VIA_STRIPE_API` | Always fetch latest entity from Stripe instead of trusting webhook payload, possible values: charge, credit_note, customer, dispute, invoice, payment_intent, payment_method, plan, price, product, refund, review, radar.early_fraud_warning, setup_intent, subscription, subscription_schedule, tax_id | No |

## Endpoints

Expand Down
39 changes: 39 additions & 0 deletions packages/fastify-app/src/test/revalidate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { StripeSync } from '@supabase/stripe-sync-engine'
import { vitest, beforeAll, describe, test, expect } from 'vitest'
import { runMigrations } from '@supabase/stripe-sync-engine'
import { getConfig } from '../utils/config'
import { mockStripe } from './helpers/mockStripe'
import { logger } from '../logger'
import type Stripe from 'stripe'

let stripeSync: StripeSync

beforeAll(async () => {
process.env.REVALIDATE_OBJECTS_VIA_STRIPE_API = 'invoice'

const config = getConfig()
await runMigrations({
databaseUrl: config.databaseUrl,
schema: config.schema,
logger,
})

stripeSync = new StripeSync(config)
const stripe = Object.assign(stripeSync.stripe, mockStripe)
vitest.spyOn(stripeSync, 'stripe', 'get').mockReturnValue(stripe)
})

describe('invoices', () => {
test('should revalidate entity if enabled', async () => {
const eventBody = await import(`./stripe/invoice_paid.json`).then(
({ default: myData }) => myData
)

await stripeSync.processEvent(eventBody as unknown as Stripe.Event)

const result = await stripeSync.postgresClient.query(
`select customer from stripe.invoices where id = 'in_1KJqKBJDPojXS6LNJbvLUgEy' limit 1`
)
expect(result.rows[0].customer).toEqual('cus_J7Mkgr8mvbl1eK') // from stripe mock
})
})
9 changes: 6 additions & 3 deletions packages/fastify-app/src/utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { RevalidateEntity } from '@supabase/stripe-sync-engine'
import { config } from 'dotenv'

function getConfigFromEnv(key: string, defaultValue?: string): string {
Expand Down Expand Up @@ -41,7 +42,7 @@ export type StripeSyncServerConfig = {

maxPostgresConnections?: number

revalidateEntityViaStripeApi: boolean
revalidateObjectsViaStripeApi: Array<RevalidateEntity>

port: number
}
Expand All @@ -60,7 +61,9 @@ export function getConfig(): StripeSyncServerConfig {
autoExpandLists: getConfigFromEnv('AUTO_EXPAND_LISTS', 'false') === 'true',
backfillRelatedEntities: getConfigFromEnv('BACKFILL_RELATED_ENTITIES', 'true') === 'true',
maxPostgresConnections: Number(getConfigFromEnv('MAX_POSTGRES_CONNECTIONS', '10')),
revalidateEntityViaStripeApi:
getConfigFromEnv('REVALIDATE_ENTITY_VIA_STRIPE_API', 'false') === 'true',
revalidateObjectsViaStripeApi: getConfigFromEnv('REVALIDATE_OBJECTS_VIA_STRIPE_API', '')
.split(',')
.map((it) => it.trim())
.filter((it) => it.length > 0) as Array<RevalidateEntity>,
}
}
Loading