@paymentsdb/sync-engine 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +310 -0
- package/dist/chunk-3OQVG44L.js +4196 -0
- package/dist/chunk-CMGFQCD7.js +87 -0
- package/dist/chunk-J6VKHOSX.js +641 -0
- package/dist/chunk-TYAHH7EW.js +406 -0
- package/dist/cli/index.cjs +5371 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +72 -0
- package/dist/cli/lib.cjs +5337 -0
- package/dist/cli/lib.d.cts +73 -0
- package/dist/cli/lib.d.ts +73 -0
- package/dist/cli/lib.js +21 -0
- package/dist/index.cjs +4321 -0
- package/dist/index.d.cts +815 -0
- package/dist/index.d.ts +815 -0
- package/dist/index.js +17 -0
- package/dist/migrations/0000_initial_migration.sql +1 -0
- package/dist/migrations/0001_products.sql +17 -0
- package/dist/migrations/0002_customers.sql +23 -0
- package/dist/migrations/0003_prices.sql +34 -0
- package/dist/migrations/0004_subscriptions.sql +56 -0
- package/dist/migrations/0005_invoices.sql +77 -0
- package/dist/migrations/0006_charges.sql +43 -0
- package/dist/migrations/0007_coupons.sql +19 -0
- package/dist/migrations/0008_disputes.sql +17 -0
- package/dist/migrations/0009_events.sql +12 -0
- package/dist/migrations/0010_payouts.sql +30 -0
- package/dist/migrations/0011_plans.sql +25 -0
- package/dist/migrations/0012_add_updated_at.sql +108 -0
- package/dist/migrations/0013_add_subscription_items.sql +12 -0
- package/dist/migrations/0014_migrate_subscription_items.sql +26 -0
- package/dist/migrations/0015_add_customer_deleted.sql +2 -0
- package/dist/migrations/0016_add_invoice_indexes.sql +2 -0
- package/dist/migrations/0017_drop_charges_unavailable_columns.sql +6 -0
- package/dist/migrations/0018_setup_intents.sql +17 -0
- package/dist/migrations/0019_payment_methods.sql +12 -0
- package/dist/migrations/0020_disputes_payment_intent_created_idx.sql +3 -0
- package/dist/migrations/0021_payment_intent.sql +42 -0
- package/dist/migrations/0022_adjust_plans.sql +5 -0
- package/dist/migrations/0023_invoice_deleted.sql +1 -0
- package/dist/migrations/0024_subscription_schedules.sql +29 -0
- package/dist/migrations/0025_tax_ids.sql +14 -0
- package/dist/migrations/0026_credit_notes.sql +36 -0
- package/dist/migrations/0027_add_marketing_features_to_products.sql +2 -0
- package/dist/migrations/0028_early_fraud_warning.sql +22 -0
- package/dist/migrations/0029_reviews.sql +28 -0
- package/dist/migrations/0030_refunds.sql +29 -0
- package/dist/migrations/0031_add_default_price.sql +2 -0
- package/dist/migrations/0032_update_subscription_items.sql +3 -0
- package/dist/migrations/0033_add_last_synced_at.sql +85 -0
- package/dist/migrations/0034_remove_foreign_keys.sql +13 -0
- package/dist/migrations/0035_checkout_sessions.sql +77 -0
- package/dist/migrations/0036_checkout_session_line_items.sql +24 -0
- package/dist/migrations/0037_add_features.sql +18 -0
- package/dist/migrations/0038_active_entitlement.sql +20 -0
- package/dist/migrations/0039_add_paused_to_subscription_status.sql +1 -0
- package/dist/migrations/0040_managed_webhooks.sql +28 -0
- package/dist/migrations/0041_rename_managed_webhooks.sql +2 -0
- package/dist/migrations/0042_convert_to_jsonb_generated_columns.sql +1821 -0
- package/dist/migrations/0043_add_account_id.sql +49 -0
- package/dist/migrations/0044_make_account_id_required.sql +54 -0
- package/dist/migrations/0045_sync_status.sql +18 -0
- package/dist/migrations/0046_sync_status_per_account.sql +91 -0
- package/dist/migrations/0047_api_key_hashes.sql +12 -0
- package/dist/migrations/0048_rename_reserved_columns.sql +1253 -0
- package/dist/migrations/0049_remove_redundant_underscores_from_metadata_tables.sql +68 -0
- package/dist/migrations/0050_rename_id_to_match_stripe_api.sql +239 -0
- package/dist/migrations/0051_remove_webhook_uuid.sql +7 -0
- package/dist/migrations/0052_webhook_url_uniqueness.sql +7 -0
- package/dist/migrations/0053_sync_observability.sql +104 -0
- package/dist/migrations/0054_drop_sync_status.sql +5 -0
- package/dist/migrations/0055_bigint_money_columns.sql +72 -0
- package/dist/migrations/0056_sync_run_closed_at.sql +53 -0
- package/dist/migrations/0057_rename_sync_tables.sql +57 -0
- package/dist/migrations/0058_improve_sync_runs_status.sql +36 -0
- package/dist/migrations/0059_sigma_subscription_item_change_events_v2_beta.sql +61 -0
- package/dist/migrations/0060_sigma_exchange_rates_from_usd.sql +38 -0
- package/dist/migrations/0061_add_page_cursor.sql +3 -0
- package/dist/migrations/0062_balance_transactions.sql +42 -0
- package/dist/supabase/index.cjs +523 -0
- package/dist/supabase/index.d.cts +121 -0
- package/dist/supabase/index.d.ts +121 -0
- package/dist/supabase/index.js +26 -0
- package/package.json +83 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,815 @@
|
|
|
1
|
+
import Stripe from 'stripe';
|
|
2
|
+
import pg, { PoolConfig, QueryResult } from 'pg';
|
|
3
|
+
import { ConnectionOptions } from 'node:tls';
|
|
4
|
+
|
|
5
|
+
type PostgresConfig = {
|
|
6
|
+
schema: string;
|
|
7
|
+
poolConfig: PoolConfig;
|
|
8
|
+
};
|
|
9
|
+
type RawJsonUpsertOptions = {
|
|
10
|
+
/**
|
|
11
|
+
* Columns to use as the ON CONFLICT target.
|
|
12
|
+
* Example: ['id'] for standard Stripe objects, or a composite key for Sigma tables.
|
|
13
|
+
*/
|
|
14
|
+
conflictTarget: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Additional typed columns to insert alongside `_raw_data` (for tables that don't have `id` keys).
|
|
17
|
+
* Values are read from `entry[entryKey]` and cast to `pgType` in SQL.
|
|
18
|
+
*/
|
|
19
|
+
extraColumns?: Array<{
|
|
20
|
+
column: string;
|
|
21
|
+
pgType: string;
|
|
22
|
+
entryKey: string;
|
|
23
|
+
}>;
|
|
24
|
+
};
|
|
25
|
+
declare class PostgresClient {
|
|
26
|
+
private config;
|
|
27
|
+
pool: pg.Pool;
|
|
28
|
+
constructor(config: PostgresConfig);
|
|
29
|
+
delete(table: string, id: string): Promise<boolean>;
|
|
30
|
+
query(text: string, params?: any[]): Promise<QueryResult>;
|
|
31
|
+
upsertMany<T extends {
|
|
32
|
+
[Key: string]: any;
|
|
33
|
+
}>(entries: T[], table: string): Promise<T[]>;
|
|
34
|
+
upsertManyWithTimestampProtection<T extends {
|
|
35
|
+
[Key: string]: any;
|
|
36
|
+
}>(entries: T[], table: string, accountId: string, syncTimestamp?: string, upsertOptions?: RawJsonUpsertOptions): Promise<T[]>;
|
|
37
|
+
private cleanseArrayField;
|
|
38
|
+
findMissingEntries(table: string, ids: string[]): Promise<string[]>;
|
|
39
|
+
upsertAccount(accountData: {
|
|
40
|
+
id: string;
|
|
41
|
+
raw_data: any;
|
|
42
|
+
}, apiKeyHash: string): Promise<void>;
|
|
43
|
+
getAllAccounts(): Promise<any[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Looks up an account ID by API key hash
|
|
46
|
+
* Uses the GIN index on api_key_hashes for fast lookups
|
|
47
|
+
* @param apiKeyHash - SHA-256 hash of the Stripe API key
|
|
48
|
+
* @returns Account ID if found, null otherwise
|
|
49
|
+
*/
|
|
50
|
+
getAccountIdByApiKeyHash(apiKeyHash: string): Promise<string | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Looks up full account data by API key hash
|
|
53
|
+
* @param apiKeyHash - SHA-256 hash of the Stripe API key
|
|
54
|
+
* @returns Account raw data if found, null otherwise
|
|
55
|
+
*/
|
|
56
|
+
getAccountByApiKeyHash(apiKeyHash: string): Promise<any | null>;
|
|
57
|
+
private getAccountIdColumn;
|
|
58
|
+
getAccountRecordCounts(accountId: string): Promise<{
|
|
59
|
+
[tableName: string]: number;
|
|
60
|
+
}>;
|
|
61
|
+
deleteAccountWithCascade(accountId: string, useTransaction: boolean): Promise<{
|
|
62
|
+
[tableName: string]: number;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Hash a string to a 32-bit integer for use with PostgreSQL advisory locks.
|
|
66
|
+
* Uses a simple hash algorithm that produces consistent results.
|
|
67
|
+
*/
|
|
68
|
+
private hashToInt32;
|
|
69
|
+
/**
|
|
70
|
+
* Acquire a PostgreSQL advisory lock for the given key.
|
|
71
|
+
* This lock is automatically released when the connection is closed or explicitly released.
|
|
72
|
+
* Advisory locks are session-level and will block until the lock is available.
|
|
73
|
+
*
|
|
74
|
+
* @param key - A string key to lock on (will be hashed to an integer)
|
|
75
|
+
*/
|
|
76
|
+
acquireAdvisoryLock(key: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Release a PostgreSQL advisory lock for the given key.
|
|
79
|
+
*
|
|
80
|
+
* @param key - The same string key used to acquire the lock
|
|
81
|
+
*/
|
|
82
|
+
releaseAdvisoryLock(key: string): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Execute a function while holding an advisory lock.
|
|
85
|
+
* The lock is automatically released after the function completes (success or error).
|
|
86
|
+
*
|
|
87
|
+
* IMPORTANT: This acquires a dedicated connection from the pool and holds it for the
|
|
88
|
+
* duration of the function execution. PostgreSQL advisory locks are session-level,
|
|
89
|
+
* so we must use the same connection for lock acquisition, operations, and release.
|
|
90
|
+
*
|
|
91
|
+
* @param key - A string key to lock on (will be hashed to an integer)
|
|
92
|
+
* @param fn - The function to execute while holding the lock
|
|
93
|
+
* @returns The result of the function
|
|
94
|
+
*/
|
|
95
|
+
withAdvisoryLock<T>(key: string, fn: () => Promise<T>): Promise<T>;
|
|
96
|
+
/**
|
|
97
|
+
* Cancel stale runs (running but no object updated in 5 minutes).
|
|
98
|
+
* Called before creating a new run to clean up crashed syncs.
|
|
99
|
+
* Only cancels runs that have objects AND none have recent activity.
|
|
100
|
+
* Runs without objects yet (just created) are not considered stale.
|
|
101
|
+
*/
|
|
102
|
+
cancelStaleRuns(accountId: string): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Get or create a sync run for this account.
|
|
105
|
+
* Returns existing run if one is active, otherwise creates new one.
|
|
106
|
+
* Auto-cancels stale runs before checking.
|
|
107
|
+
*
|
|
108
|
+
* @returns RunKey with isNew flag, or null if constraint violation (race condition)
|
|
109
|
+
*/
|
|
110
|
+
getOrCreateSyncRun(accountId: string, triggeredBy?: string): Promise<{
|
|
111
|
+
accountId: string;
|
|
112
|
+
runStartedAt: Date;
|
|
113
|
+
isNew: boolean;
|
|
114
|
+
} | null>;
|
|
115
|
+
/**
|
|
116
|
+
* Get the active sync run for an account (if any).
|
|
117
|
+
*/
|
|
118
|
+
getActiveSyncRun(accountId: string): Promise<{
|
|
119
|
+
accountId: string;
|
|
120
|
+
runStartedAt: Date;
|
|
121
|
+
} | null>;
|
|
122
|
+
/**
|
|
123
|
+
* Get sync run config (for concurrency control).
|
|
124
|
+
* Status is derived from sync_runs view.
|
|
125
|
+
*/
|
|
126
|
+
getSyncRun(accountId: string, runStartedAt: Date): Promise<{
|
|
127
|
+
accountId: string;
|
|
128
|
+
runStartedAt: Date;
|
|
129
|
+
maxConcurrent: number;
|
|
130
|
+
closedAt: Date | null;
|
|
131
|
+
} | null>;
|
|
132
|
+
/**
|
|
133
|
+
* Close a sync run (mark as done).
|
|
134
|
+
* Status (complete/error) is derived from object run states.
|
|
135
|
+
*/
|
|
136
|
+
closeSyncRun(accountId: string, runStartedAt: Date): Promise<void>;
|
|
137
|
+
/**
|
|
138
|
+
* Create object run entries for a sync run.
|
|
139
|
+
* All objects start as 'pending'.
|
|
140
|
+
*
|
|
141
|
+
* @param resourceNames - Database resource names (e.g. 'products', 'customers', NOT 'product', 'customer')
|
|
142
|
+
*/
|
|
143
|
+
createObjectRuns(accountId: string, runStartedAt: Date, resourceNames: string[]): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Try to start an object sync (respects max_concurrent).
|
|
146
|
+
* Returns true if claimed, false if already running or at concurrency limit.
|
|
147
|
+
*
|
|
148
|
+
* Note: There's a small race window where concurrent calls could result in
|
|
149
|
+
* max_concurrent + 1 objects running. This is acceptable behavior.
|
|
150
|
+
*/
|
|
151
|
+
tryStartObjectSync(accountId: string, runStartedAt: Date, object: string): Promise<boolean>;
|
|
152
|
+
/**
|
|
153
|
+
* Get object run details.
|
|
154
|
+
*/
|
|
155
|
+
getObjectRun(accountId: string, runStartedAt: Date, object: string): Promise<{
|
|
156
|
+
object: string;
|
|
157
|
+
status: string;
|
|
158
|
+
processedCount: number;
|
|
159
|
+
cursor: string | null;
|
|
160
|
+
pageCursor: string | null;
|
|
161
|
+
} | null>;
|
|
162
|
+
/**
|
|
163
|
+
* Update progress for an object sync.
|
|
164
|
+
* Also touches updated_at for stale detection.
|
|
165
|
+
*/
|
|
166
|
+
incrementObjectProgress(accountId: string, runStartedAt: Date, object: string, count: number): Promise<void>;
|
|
167
|
+
/**
|
|
168
|
+
* Update the pagination page_cursor used for backfills using Stripe list calls.
|
|
169
|
+
*/
|
|
170
|
+
updateObjectPageCursor(accountId: string, runStartedAt: Date, object: string, pageCursor: string | null): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Clear the pagination page_cursor for an object sync.
|
|
173
|
+
*/
|
|
174
|
+
clearObjectPageCursor(accountId: string, runStartedAt: Date, object: string): Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Update the cursor for an object sync.
|
|
177
|
+
* Only updates if the new cursor is higher than the existing one (cursors should never decrease).
|
|
178
|
+
* For numeric cursors (timestamps), uses GREATEST to ensure monotonic increase.
|
|
179
|
+
* For non-numeric cursors, just sets the value directly.
|
|
180
|
+
*/
|
|
181
|
+
updateObjectCursor(accountId: string, runStartedAt: Date, object: string, cursor: string | null): Promise<void>;
|
|
182
|
+
/**
|
|
183
|
+
* Get the highest cursor from previous syncs for an object type.
|
|
184
|
+
* Uses only completed object runs.
|
|
185
|
+
* - During the initial backfill we page through history, but we also update the cursor as we go.
|
|
186
|
+
* If we crash mid-backfill and reuse that cursor, we can accidentally switch into incremental mode
|
|
187
|
+
* too early and only ever fetch the newest page (breaking the historical backfill).
|
|
188
|
+
*
|
|
189
|
+
* Handles two cursor formats:
|
|
190
|
+
* - Numeric: compared as bigint for correct ordering
|
|
191
|
+
* - Composite cursors: compared as strings with COLLATE "C"
|
|
192
|
+
*/
|
|
193
|
+
getLastCompletedCursor(accountId: string, object: string): Promise<string | null>;
|
|
194
|
+
/**
|
|
195
|
+
* Get the highest cursor from previous syncs for an object type, excluding the current run.
|
|
196
|
+
*/
|
|
197
|
+
getLastCursorBeforeRun(accountId: string, object: string, runStartedAt: Date): Promise<string | null>;
|
|
198
|
+
/**
|
|
199
|
+
* Delete all sync runs and object runs for an account.
|
|
200
|
+
* Useful for testing or resetting sync state.
|
|
201
|
+
*/
|
|
202
|
+
deleteSyncRuns(accountId: string): Promise<void>;
|
|
203
|
+
/**
|
|
204
|
+
* Mark an object sync as complete.
|
|
205
|
+
* Auto-closes the run when all objects are done.
|
|
206
|
+
*/
|
|
207
|
+
completeObjectSync(accountId: string, runStartedAt: Date, object: string): Promise<void>;
|
|
208
|
+
/**
|
|
209
|
+
* Mark an object sync as failed.
|
|
210
|
+
* Auto-closes the run when all objects are done.
|
|
211
|
+
*/
|
|
212
|
+
failObjectSync(accountId: string, runStartedAt: Date, object: string, errorMessage: string): Promise<void>;
|
|
213
|
+
/**
|
|
214
|
+
* Check if any object in a run has errored.
|
|
215
|
+
*/
|
|
216
|
+
hasAnyObjectErrors(accountId: string, runStartedAt: Date): Promise<boolean>;
|
|
217
|
+
/**
|
|
218
|
+
* Count running objects in a run.
|
|
219
|
+
*/
|
|
220
|
+
countRunningObjects(accountId: string, runStartedAt: Date): Promise<number>;
|
|
221
|
+
/**
|
|
222
|
+
* Get the next pending object to process.
|
|
223
|
+
* Returns null if no pending objects or at concurrency limit.
|
|
224
|
+
*/
|
|
225
|
+
getNextPendingObject(accountId: string, runStartedAt: Date): Promise<string | null>;
|
|
226
|
+
/**
|
|
227
|
+
* Check if all objects in a run are complete (or error).
|
|
228
|
+
*/
|
|
229
|
+
areAllObjectsComplete(accountId: string, runStartedAt: Date): Promise<boolean>;
|
|
230
|
+
/**
|
|
231
|
+
* Closes the database connection pool and cleans up resources.
|
|
232
|
+
* Call this when you're done using the PostgresClient instance.
|
|
233
|
+
*/
|
|
234
|
+
close(): Promise<void>;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
type SigmaCursorColumnType = 'timestamp' | 'string' | 'number';
|
|
238
|
+
type SigmaCursorColumnSpec = {
|
|
239
|
+
column: string;
|
|
240
|
+
type: SigmaCursorColumnType;
|
|
241
|
+
};
|
|
242
|
+
type SigmaCursorSpec = {
|
|
243
|
+
version: 1;
|
|
244
|
+
columns: SigmaCursorColumnSpec[];
|
|
245
|
+
};
|
|
246
|
+
type SigmaIngestionConfig = {
|
|
247
|
+
/**
|
|
248
|
+
* The Sigma table name to query (no quoting, no schema).
|
|
249
|
+
*/
|
|
250
|
+
sigmaTable: string;
|
|
251
|
+
/**
|
|
252
|
+
* Destination Postgres table name (in the `stripe` schema by convention).
|
|
253
|
+
*/
|
|
254
|
+
destinationTable: string;
|
|
255
|
+
/** Limit for each Sigma query page. */
|
|
256
|
+
pageSize: number;
|
|
257
|
+
/**
|
|
258
|
+
* Defines the ordering and cursor semantics. The columns must form a total order (i.e. be unique together) or pagination can be incorrect.
|
|
259
|
+
*/
|
|
260
|
+
cursor: SigmaCursorSpec;
|
|
261
|
+
/** Optional additional WHERE clause appended with AND (must not include leading WHERE). */
|
|
262
|
+
additionalWhere?: string;
|
|
263
|
+
/** Columns to SELECT (defaults to `*`). */
|
|
264
|
+
select?: '*' | string[];
|
|
265
|
+
/** Postgres upsert behavior for this table (conflict target and typed columns). */
|
|
266
|
+
upsert: RawJsonUpsertOptions;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Simple logger interface compatible with both pino and console
|
|
271
|
+
*/
|
|
272
|
+
interface Logger {
|
|
273
|
+
info(message?: unknown, ...optionalParams: unknown[]): void;
|
|
274
|
+
warn(message?: unknown, ...optionalParams: unknown[]): void;
|
|
275
|
+
error(message?: unknown, ...optionalParams: unknown[]): void;
|
|
276
|
+
}
|
|
277
|
+
type RevalidateEntity = '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' | 'entitlements';
|
|
278
|
+
type StripeSyncConfig = {
|
|
279
|
+
/** @deprecated Use `poolConfig` with a connection string instead. */
|
|
280
|
+
databaseUrl?: string;
|
|
281
|
+
/** Stripe secret key used to authenticate requests to the Stripe API. Defaults to empty string */
|
|
282
|
+
stripeSecretKey: string;
|
|
283
|
+
/**
|
|
284
|
+
* Enables syncing Stripe Sigma (reporting) tables via the Sigma API.
|
|
285
|
+
*
|
|
286
|
+
* Default: false (opt-in, so workers don't enqueue Sigma jobs unexpectedly).
|
|
287
|
+
*/
|
|
288
|
+
enableSigma?: boolean;
|
|
289
|
+
/** Stripe account ID. If not provided, will be retrieved from Stripe API. Used as fallback option. */
|
|
290
|
+
stripeAccountId?: string;
|
|
291
|
+
/** Stripe webhook signing secret for validating webhook signatures. Required if not using managed webhooks. */
|
|
292
|
+
stripeWebhookSecret?: string;
|
|
293
|
+
/** Stripe API version for the webhooks, defaults to 2020-08-27 */
|
|
294
|
+
stripeApiVersion?: string;
|
|
295
|
+
/**
|
|
296
|
+
* Stripe limits related lists like invoice items in an invoice to 10 by default.
|
|
297
|
+
* By enabling this, sync-engine automatically fetches the remaining elements before saving
|
|
298
|
+
* */
|
|
299
|
+
autoExpandLists?: boolean;
|
|
300
|
+
/**
|
|
301
|
+
* If true, the sync engine will backfill related entities, i.e. when a invoice webhook comes in, it ensures that the customer is present and synced.
|
|
302
|
+
* This ensures foreign key integrity, but comes at the cost of additional queries to the database (and added latency for Stripe calls if the entity is actually missing).
|
|
303
|
+
*/
|
|
304
|
+
backfillRelatedEntities?: boolean;
|
|
305
|
+
/**
|
|
306
|
+
* 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.
|
|
307
|
+
*
|
|
308
|
+
* Default: false
|
|
309
|
+
*/
|
|
310
|
+
revalidateObjectsViaStripeApi?: Array<RevalidateEntity>;
|
|
311
|
+
/** @deprecated Use `poolConfig` instead. */
|
|
312
|
+
maxPostgresConnections?: number;
|
|
313
|
+
poolConfig: PoolConfig;
|
|
314
|
+
logger?: Logger;
|
|
315
|
+
/**
|
|
316
|
+
* Maximum number of retry attempts for 429 rate limit errors.
|
|
317
|
+
* Default: 5
|
|
318
|
+
*/
|
|
319
|
+
maxRetries?: number;
|
|
320
|
+
/**
|
|
321
|
+
* Initial delay in milliseconds before first retry attempt.
|
|
322
|
+
* Delay increases exponentially: 1s, 2s, 4s, 8s, 16s, etc.
|
|
323
|
+
* Default: 1000 (1 second)
|
|
324
|
+
*/
|
|
325
|
+
initialRetryDelayMs?: number;
|
|
326
|
+
/**
|
|
327
|
+
* Maximum delay in milliseconds between retry attempts.
|
|
328
|
+
* Default: 60000 (60 seconds)
|
|
329
|
+
*/
|
|
330
|
+
maxRetryDelayMs?: number;
|
|
331
|
+
/**
|
|
332
|
+
* Random jitter in milliseconds added to retry delays to prevent thundering herd.
|
|
333
|
+
* Default: 500
|
|
334
|
+
*/
|
|
335
|
+
retryJitterMs?: number;
|
|
336
|
+
/**
|
|
337
|
+
* Maximum number of customers to process concurrently when syncing payment methods.
|
|
338
|
+
* Lower values reduce API load but increase sync time.
|
|
339
|
+
* Default: 10
|
|
340
|
+
*/
|
|
341
|
+
maxConcurrentCustomers?: number;
|
|
342
|
+
};
|
|
343
|
+
type SyncObject = 'all' | 'customer' | 'customer_with_entitlements' | 'invoice' | 'price' | 'product' | 'subscription' | 'subscription_schedules' | 'setup_intent' | 'payment_method' | 'dispute' | 'charge' | 'balance_transaction' | 'payment_intent' | 'plan' | 'tax_id' | 'credit_note' | 'early_fraud_warning' | 'refund' | 'checkout_sessions' | 'subscription_item_change_events_v2_beta' | 'exchange_rates_from_usd';
|
|
344
|
+
interface Sync {
|
|
345
|
+
synced: number;
|
|
346
|
+
}
|
|
347
|
+
interface SyncBackfill {
|
|
348
|
+
products?: Sync;
|
|
349
|
+
prices?: Sync;
|
|
350
|
+
plans?: Sync;
|
|
351
|
+
customers?: Sync;
|
|
352
|
+
subscriptions?: Sync;
|
|
353
|
+
subscriptionSchedules?: Sync;
|
|
354
|
+
invoices?: Sync;
|
|
355
|
+
setupIntents?: Sync;
|
|
356
|
+
paymentIntents?: Sync;
|
|
357
|
+
paymentMethods?: Sync;
|
|
358
|
+
disputes?: Sync;
|
|
359
|
+
charges?: Sync;
|
|
360
|
+
balanceTransactions?: Sync;
|
|
361
|
+
taxIds?: Sync;
|
|
362
|
+
creditNotes?: Sync;
|
|
363
|
+
earlyFraudWarnings?: Sync;
|
|
364
|
+
refunds?: Sync;
|
|
365
|
+
checkoutSessions?: Sync;
|
|
366
|
+
subscriptionItemChangeEventsV2Beta?: Sync;
|
|
367
|
+
exchangeRatesFromUsd?: Sync;
|
|
368
|
+
}
|
|
369
|
+
interface SyncParams {
|
|
370
|
+
created?: {
|
|
371
|
+
/**
|
|
372
|
+
* Minimum value to filter by (exclusive)
|
|
373
|
+
*/
|
|
374
|
+
gt?: number;
|
|
375
|
+
/**
|
|
376
|
+
* Minimum value to filter by (inclusive)
|
|
377
|
+
*/
|
|
378
|
+
gte?: number;
|
|
379
|
+
/**
|
|
380
|
+
* Maximum value to filter by (exclusive)
|
|
381
|
+
*/
|
|
382
|
+
lt?: number;
|
|
383
|
+
/**
|
|
384
|
+
* Maximum value to filter by (inclusive)
|
|
385
|
+
*/
|
|
386
|
+
lte?: number;
|
|
387
|
+
};
|
|
388
|
+
object?: SyncObject;
|
|
389
|
+
backfillRelatedEntities?: boolean;
|
|
390
|
+
}
|
|
391
|
+
interface SyncEntitlementsParams {
|
|
392
|
+
object: 'entitlements';
|
|
393
|
+
customerId: string;
|
|
394
|
+
pagination?: Pick<Stripe.PaginationParams, 'starting_after' | 'ending_before'>;
|
|
395
|
+
}
|
|
396
|
+
interface SyncFeaturesParams {
|
|
397
|
+
object: 'features';
|
|
398
|
+
pagination?: Pick<Stripe.PaginationParams, 'starting_after' | 'ending_before'>;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Result of processing a single page of items via processNext()
|
|
402
|
+
*/
|
|
403
|
+
interface ProcessNextResult {
|
|
404
|
+
/** Number of items processed in this page */
|
|
405
|
+
processed: number;
|
|
406
|
+
/** Whether there are more items to process */
|
|
407
|
+
hasMore: boolean;
|
|
408
|
+
/** The sync run this processing belongs to */
|
|
409
|
+
runStartedAt: Date;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Parameters for processNext() including optional run context
|
|
413
|
+
*/
|
|
414
|
+
interface ProcessNextParams extends SyncParams {
|
|
415
|
+
/** Join an existing sync run instead of creating a new one */
|
|
416
|
+
runStartedAt?: Date;
|
|
417
|
+
/** Who/what triggered this sync (for observability) */
|
|
418
|
+
triggeredBy?: string;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Syncable resource configuration
|
|
422
|
+
*/
|
|
423
|
+
type BaseResourceConfig = {
|
|
424
|
+
/** Backfill order: lower numbers sync first; parents before children for FK dependencies */
|
|
425
|
+
order: number;
|
|
426
|
+
/** Whether this resource supports incremental sync via 'created' filter or cursor */
|
|
427
|
+
supportsCreatedFilter: boolean;
|
|
428
|
+
};
|
|
429
|
+
type StripeListResourceConfig = BaseResourceConfig & {
|
|
430
|
+
/** Function to list items from Stripe API */
|
|
431
|
+
listFn: (params: Stripe.PaginationParams & {
|
|
432
|
+
created?: Stripe.RangeQueryParam;
|
|
433
|
+
}) => Promise<{
|
|
434
|
+
data: unknown[];
|
|
435
|
+
has_more: boolean;
|
|
436
|
+
}>;
|
|
437
|
+
/** Function to upsert items to database */
|
|
438
|
+
upsertFn: (items: unknown[], accountId: string, backfillRelated?: boolean) => Promise<unknown[] | void>;
|
|
439
|
+
/** discriminator */
|
|
440
|
+
sigma?: undefined;
|
|
441
|
+
};
|
|
442
|
+
/**
|
|
443
|
+
* Configuration for Sigma query-backed resources.
|
|
444
|
+
* Uses Stripe Sigma SQL queries with composite cursor pagination.
|
|
445
|
+
*/
|
|
446
|
+
type SigmaResourceConfig = BaseResourceConfig & {
|
|
447
|
+
/** Sigma uses composite cursors, not created filter */
|
|
448
|
+
supportsCreatedFilter: false;
|
|
449
|
+
/** Sigma ingestion configuration (query, cursor spec, upsert options) */
|
|
450
|
+
sigma: SigmaIngestionConfig;
|
|
451
|
+
/** discriminator */
|
|
452
|
+
listFn?: undefined;
|
|
453
|
+
/** discriminator */
|
|
454
|
+
upsertFn?: undefined;
|
|
455
|
+
};
|
|
456
|
+
/** Union of all resource configuration types */
|
|
457
|
+
type ResourceConfig = StripeListResourceConfig | SigmaResourceConfig;
|
|
458
|
+
/**
|
|
459
|
+
* Installation status of the stripe-sync package
|
|
460
|
+
*/
|
|
461
|
+
type InstallationStatus = 'not_installed' | 'installing' | 'installed' | 'error';
|
|
462
|
+
/**
|
|
463
|
+
* Sync status for a single account (from sync_runs view)
|
|
464
|
+
*/
|
|
465
|
+
interface StripeSyncAccountState {
|
|
466
|
+
account_id: string;
|
|
467
|
+
started_at: string;
|
|
468
|
+
closed_at: string | null;
|
|
469
|
+
status: 'pending' | 'running' | 'complete' | 'error';
|
|
470
|
+
error_message: string | null;
|
|
471
|
+
total_processed: number;
|
|
472
|
+
total_objects: number;
|
|
473
|
+
complete_count: number;
|
|
474
|
+
error_count: number;
|
|
475
|
+
running_count: number;
|
|
476
|
+
pending_count: number;
|
|
477
|
+
triggered_by: string;
|
|
478
|
+
max_concurrent: number;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Response schema for the sync status endpoint
|
|
482
|
+
*/
|
|
483
|
+
interface StripeSyncState {
|
|
484
|
+
package_version: string;
|
|
485
|
+
installation_status: InstallationStatus;
|
|
486
|
+
sync_status: StripeSyncAccountState[];
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Identifies a specific sync run.
|
|
491
|
+
*/
|
|
492
|
+
type RunKey = {
|
|
493
|
+
accountId: string;
|
|
494
|
+
runStartedAt: Date;
|
|
495
|
+
};
|
|
496
|
+
declare class StripeSync {
|
|
497
|
+
private config;
|
|
498
|
+
stripe: Stripe;
|
|
499
|
+
postgresClient: PostgresClient;
|
|
500
|
+
constructor(config: StripeSyncConfig);
|
|
501
|
+
/**
|
|
502
|
+
* Get the Stripe account ID. Delegates to getCurrentAccount() for the actual lookup.
|
|
503
|
+
*/
|
|
504
|
+
getAccountId(objectAccountId?: string): Promise<string>;
|
|
505
|
+
/**
|
|
506
|
+
* Upsert Stripe account information to the database
|
|
507
|
+
* @param account - Stripe account object
|
|
508
|
+
* @param apiKeyHash - SHA-256 hash of API key to store for fast lookups
|
|
509
|
+
*/
|
|
510
|
+
private upsertAccount;
|
|
511
|
+
/**
|
|
512
|
+
* Get the current account being synced. Uses database lookup by API key hash,
|
|
513
|
+
* with fallback to Stripe API if not found (first-time setup or new API key).
|
|
514
|
+
* @param objectAccountId - Optional account ID from event data (Connect scenarios)
|
|
515
|
+
*/
|
|
516
|
+
getCurrentAccount(objectAccountId?: string): Promise<Stripe.Account | null>;
|
|
517
|
+
/**
|
|
518
|
+
* Get all accounts that have been synced to the database
|
|
519
|
+
*/
|
|
520
|
+
getAllSyncedAccounts(): Promise<Stripe.Account[]>;
|
|
521
|
+
/**
|
|
522
|
+
* DANGEROUS: Delete an account and all associated data from the database
|
|
523
|
+
* This operation cannot be undone!
|
|
524
|
+
*
|
|
525
|
+
* @param accountId - The Stripe account ID to delete
|
|
526
|
+
* @param options - Options for deletion behavior
|
|
527
|
+
* @param options.dryRun - If true, only count records without deleting (default: false)
|
|
528
|
+
* @param options.useTransaction - If true, use transaction for atomic deletion (default: true)
|
|
529
|
+
* @returns Deletion summary with counts and warnings
|
|
530
|
+
*/
|
|
531
|
+
dangerouslyDeleteSyncedAccountData(accountId: string, options?: {
|
|
532
|
+
dryRun?: boolean;
|
|
533
|
+
useTransaction?: boolean;
|
|
534
|
+
}): Promise<{
|
|
535
|
+
deletedAccountId: string;
|
|
536
|
+
deletedRecordCounts: {
|
|
537
|
+
[tableName: string]: number;
|
|
538
|
+
};
|
|
539
|
+
warnings: string[];
|
|
540
|
+
}>;
|
|
541
|
+
processWebhook(payload: Buffer | string, signature: string | undefined): Promise<void>;
|
|
542
|
+
private readonly eventHandlers;
|
|
543
|
+
private readonly resourceRegistry;
|
|
544
|
+
processEvent(event: Stripe.Event): Promise<void>;
|
|
545
|
+
/**
|
|
546
|
+
* Returns an array of all webhook event types that this sync engine can handle.
|
|
547
|
+
* Useful for configuring webhook endpoints with specific event subscriptions.
|
|
548
|
+
*/
|
|
549
|
+
getSupportedEventTypes(): Stripe.WebhookEndpointCreateParams.EnabledEvent[];
|
|
550
|
+
/**
|
|
551
|
+
* Returns an array of all object types that can be synced via processNext/processUntilDone.
|
|
552
|
+
* Ordered for backfill: parents before children (products before prices, customers before subscriptions).
|
|
553
|
+
* Order is determined by the `order` field in resourceRegistry.
|
|
554
|
+
*/
|
|
555
|
+
getSupportedSyncObjects(): Exclude<SyncObject, 'all' | 'customer_with_entitlements'>[];
|
|
556
|
+
private handleChargeEvent;
|
|
557
|
+
private handleCustomerDeletedEvent;
|
|
558
|
+
private handleCustomerEvent;
|
|
559
|
+
private handleCheckoutSessionEvent;
|
|
560
|
+
private handleSubscriptionEvent;
|
|
561
|
+
private handleTaxIdEvent;
|
|
562
|
+
private handleTaxIdDeletedEvent;
|
|
563
|
+
private handleInvoiceEvent;
|
|
564
|
+
private handleProductEvent;
|
|
565
|
+
private handleProductDeletedEvent;
|
|
566
|
+
private handlePriceEvent;
|
|
567
|
+
private handlePriceDeletedEvent;
|
|
568
|
+
private handlePlanEvent;
|
|
569
|
+
private handlePlanDeletedEvent;
|
|
570
|
+
private handleSetupIntentEvent;
|
|
571
|
+
private handleSubscriptionScheduleEvent;
|
|
572
|
+
private handlePaymentMethodEvent;
|
|
573
|
+
private handleDisputeEvent;
|
|
574
|
+
private handlePaymentIntentEvent;
|
|
575
|
+
private handleCreditNoteEvent;
|
|
576
|
+
private handleEarlyFraudWarningEvent;
|
|
577
|
+
private handleRefundEvent;
|
|
578
|
+
private handleReviewEvent;
|
|
579
|
+
private handleEntitlementSummaryEvent;
|
|
580
|
+
private getSyncTimestamp;
|
|
581
|
+
private shouldRefetchEntity;
|
|
582
|
+
private fetchOrUseWebhookData;
|
|
583
|
+
syncSingleEntity(stripeId: string): Promise<Stripe.Product[] | Stripe.Price[] | (Stripe.Customer | Stripe.DeletedCustomer)[] | Stripe.Subscription[] | Stripe.Invoice[] | Stripe.Charge[] | Stripe.SetupIntent[] | Stripe.PaymentMethod[] | Stripe.PaymentIntent[] | Stripe.TaxId[] | Stripe.CreditNote[] | Stripe.Dispute[] | Stripe.Radar.EarlyFraudWarning[] | Stripe.Refund[] | Stripe.Checkout.Session[] | Stripe.Review[] | Stripe.Entitlements.Feature[] | undefined>;
|
|
584
|
+
/**
|
|
585
|
+
* Process one page of items for the specified object type.
|
|
586
|
+
* Returns the number of items processed and whether there are more pages.
|
|
587
|
+
*
|
|
588
|
+
* This method is designed for queue-based consumption where each page
|
|
589
|
+
* is processed as a separate job. Uses the observable sync system for tracking.
|
|
590
|
+
*
|
|
591
|
+
* @param object - The Stripe object type to sync (e.g., 'customer', 'product')
|
|
592
|
+
* @param params - Optional parameters for filtering and run context
|
|
593
|
+
* @returns ProcessNextResult with processed count, hasMore flag, and runStartedAt
|
|
594
|
+
*
|
|
595
|
+
* @example
|
|
596
|
+
* ```typescript
|
|
597
|
+
* // Queue worker
|
|
598
|
+
* const { hasMore, runStartedAt } = await stripeSync.processNext('customer')
|
|
599
|
+
* if (hasMore) {
|
|
600
|
+
* await queue.send({ object: 'customer', runStartedAt })
|
|
601
|
+
* }
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
processNext(object: Exclude<SyncObject, 'all' | 'customer_with_entitlements'>, params?: ProcessNextParams): Promise<ProcessNextResult>;
|
|
605
|
+
private appendMigrationHint;
|
|
606
|
+
/**
|
|
607
|
+
* Get the database resource name for a SyncObject type
|
|
608
|
+
*/
|
|
609
|
+
private getResourceName;
|
|
610
|
+
/**
|
|
611
|
+
* Fetch one page of items from Stripe and upsert to database.
|
|
612
|
+
* Uses resourceRegistry for DRY list/upsert operations.
|
|
613
|
+
* Uses the observable sync system for tracking progress.
|
|
614
|
+
*/
|
|
615
|
+
private fetchOnePage;
|
|
616
|
+
private getSigmaFallbackCursorFromDestination;
|
|
617
|
+
private fetchOneSigmaPage;
|
|
618
|
+
/**
|
|
619
|
+
* Process all pages for all (or specified) object types until complete.
|
|
620
|
+
*
|
|
621
|
+
* @param params - Optional parameters for filtering and specifying object types
|
|
622
|
+
* @returns SyncBackfill with counts for each synced resource type
|
|
623
|
+
*/
|
|
624
|
+
/**
|
|
625
|
+
* Process all pages for a single object type until complete.
|
|
626
|
+
* Loops processNext() internally until hasMore is false.
|
|
627
|
+
*
|
|
628
|
+
* @param object - The object type to sync
|
|
629
|
+
* @param runStartedAt - The sync run to use (for sharing across objects)
|
|
630
|
+
* @param params - Optional sync parameters
|
|
631
|
+
* @returns Sync result with count of synced items
|
|
632
|
+
*/
|
|
633
|
+
private processObjectUntilDone;
|
|
634
|
+
/**
|
|
635
|
+
* Join existing sync run or create a new one.
|
|
636
|
+
* Returns sync run key and list of supported objects to sync.
|
|
637
|
+
*
|
|
638
|
+
* Cooperative behavior: If a sync run already exists, joins it instead of failing.
|
|
639
|
+
* This is used by workers and background processes that should cooperate.
|
|
640
|
+
*
|
|
641
|
+
* @param triggeredBy - What triggered this sync (for observability)
|
|
642
|
+
* @param objectFilter - Optional specific object to sync (e.g. 'payment_intent'). If 'all' or undefined, syncs all objects.
|
|
643
|
+
* @returns Run key and list of objects to sync
|
|
644
|
+
*/
|
|
645
|
+
joinOrCreateSyncRun(triggeredBy?: string, objectFilter?: SyncObject): Promise<{
|
|
646
|
+
runKey: RunKey;
|
|
647
|
+
objects: Exclude<SyncObject, 'all' | 'customer_with_entitlements'>[];
|
|
648
|
+
}>;
|
|
649
|
+
processUntilDone(params?: SyncParams): Promise<SyncBackfill>;
|
|
650
|
+
/**
|
|
651
|
+
* Internal implementation of processUntilDone with an existing run.
|
|
652
|
+
*/
|
|
653
|
+
private processUntilDoneWithRun;
|
|
654
|
+
/**
|
|
655
|
+
* Sync payment methods with an existing run (special case - iterates customers)
|
|
656
|
+
*/
|
|
657
|
+
private syncPaymentMethodsWithRun;
|
|
658
|
+
syncProducts(syncParams?: SyncParams): Promise<Sync>;
|
|
659
|
+
syncPrices(syncParams?: SyncParams): Promise<Sync>;
|
|
660
|
+
syncPlans(syncParams?: SyncParams): Promise<Sync>;
|
|
661
|
+
syncCustomers(syncParams?: SyncParams): Promise<Sync>;
|
|
662
|
+
syncSubscriptions(syncParams?: SyncParams): Promise<Sync>;
|
|
663
|
+
syncSubscriptionSchedules(syncParams?: SyncParams): Promise<Sync>;
|
|
664
|
+
syncInvoices(syncParams?: SyncParams): Promise<Sync>;
|
|
665
|
+
syncBalanceTransactions(syncParams?: SyncParams): Promise<Sync>;
|
|
666
|
+
syncCharges(syncParams?: SyncParams): Promise<Sync>;
|
|
667
|
+
syncSetupIntents(syncParams?: SyncParams): Promise<Sync>;
|
|
668
|
+
syncPaymentIntents(syncParams?: SyncParams): Promise<Sync>;
|
|
669
|
+
syncTaxIds(syncParams?: SyncParams): Promise<Sync>;
|
|
670
|
+
syncPaymentMethods(syncParams?: SyncParams): Promise<Sync>;
|
|
671
|
+
syncDisputes(syncParams?: SyncParams): Promise<Sync>;
|
|
672
|
+
syncEarlyFraudWarnings(syncParams?: SyncParams): Promise<Sync>;
|
|
673
|
+
syncRefunds(syncParams?: SyncParams): Promise<Sync>;
|
|
674
|
+
syncCreditNotes(syncParams?: SyncParams): Promise<Sync>;
|
|
675
|
+
syncFeatures(syncParams?: SyncFeaturesParams): Promise<Sync>;
|
|
676
|
+
syncEntitlements(customerId: string, syncParams?: SyncEntitlementsParams): Promise<Sync>;
|
|
677
|
+
syncCheckoutSessions(syncParams?: SyncParams): Promise<Sync>;
|
|
678
|
+
/**
|
|
679
|
+
* Helper to wrap a sync operation in the observable sync system.
|
|
680
|
+
* Creates/gets a sync run, sets up the object run, gets cursor, and handles completion.
|
|
681
|
+
*
|
|
682
|
+
* @param resourceName - The resource being synced (e.g., 'products', 'customers')
|
|
683
|
+
* @param triggeredBy - What triggered this sync (for observability)
|
|
684
|
+
* @param fn - The sync function to execute, receives cursor and runStartedAt
|
|
685
|
+
* @returns The result of the sync function
|
|
686
|
+
*/
|
|
687
|
+
private withSyncRun;
|
|
688
|
+
private fetchAndUpsert;
|
|
689
|
+
private upsertBalanceTransactions;
|
|
690
|
+
private upsertCharges;
|
|
691
|
+
private backfillCharges;
|
|
692
|
+
private backfillPaymentIntents;
|
|
693
|
+
private upsertCreditNotes;
|
|
694
|
+
upsertCheckoutSessions(checkoutSessions: Stripe.Checkout.Session[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Checkout.Session[]>;
|
|
695
|
+
upsertEarlyFraudWarning(earlyFraudWarnings: Stripe.Radar.EarlyFraudWarning[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Radar.EarlyFraudWarning[]>;
|
|
696
|
+
upsertRefunds(refunds: Stripe.Refund[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Refund[]>;
|
|
697
|
+
upsertReviews(reviews: Stripe.Review[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Review[]>;
|
|
698
|
+
upsertCustomers(customers: (Stripe.Customer | Stripe.DeletedCustomer)[], accountId: string, syncTimestamp?: string): Promise<(Stripe.Customer | Stripe.DeletedCustomer)[]>;
|
|
699
|
+
backfillCustomers(customerIds: string[], accountId: string): Promise<void>;
|
|
700
|
+
upsertDisputes(disputes: Stripe.Dispute[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Dispute[]>;
|
|
701
|
+
upsertInvoices(invoices: Stripe.Invoice[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Invoice[]>;
|
|
702
|
+
backfillInvoices: (invoiceIds: string[], accountId: string) => Promise<void>;
|
|
703
|
+
backfillPrices: (priceIds: string[], accountId: string) => Promise<void>;
|
|
704
|
+
upsertPlans(plans: Stripe.Plan[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Plan[]>;
|
|
705
|
+
deletePlan(id: string): Promise<boolean>;
|
|
706
|
+
upsertPrices(prices: Stripe.Price[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Price[]>;
|
|
707
|
+
deletePrice(id: string): Promise<boolean>;
|
|
708
|
+
upsertProducts(products: Stripe.Product[], accountId: string, syncTimestamp?: string): Promise<Stripe.Product[]>;
|
|
709
|
+
deleteProduct(id: string): Promise<boolean>;
|
|
710
|
+
backfillProducts(productIds: string[], accountId: string): Promise<void>;
|
|
711
|
+
upsertPaymentIntents(paymentIntents: Stripe.PaymentIntent[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.PaymentIntent[]>;
|
|
712
|
+
upsertPaymentMethods(paymentMethods: Stripe.PaymentMethod[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.PaymentMethod[]>;
|
|
713
|
+
upsertSetupIntents(setupIntents: Stripe.SetupIntent[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.SetupIntent[]>;
|
|
714
|
+
upsertTaxIds(taxIds: Stripe.TaxId[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.TaxId[]>;
|
|
715
|
+
deleteTaxId(id: string): Promise<boolean>;
|
|
716
|
+
upsertSubscriptionItems(subscriptionItems: Stripe.SubscriptionItem[], accountId: string, syncTimestamp?: string): Promise<void>;
|
|
717
|
+
fillCheckoutSessionsLineItems(checkoutSessionIds: string[], accountId: string, syncTimestamp?: string): Promise<void>;
|
|
718
|
+
upsertCheckoutSessionLineItems(lineItems: Stripe.LineItem[], checkoutSessionId: string, accountId: string, syncTimestamp?: string): Promise<void>;
|
|
719
|
+
markDeletedSubscriptionItems(subscriptionId: string, currentSubItemIds: string[]): Promise<{
|
|
720
|
+
rowCount: number;
|
|
721
|
+
}>;
|
|
722
|
+
upsertSubscriptionSchedules(subscriptionSchedules: Stripe.SubscriptionSchedule[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.SubscriptionSchedule[]>;
|
|
723
|
+
upsertSubscriptions(subscriptions: Stripe.Subscription[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<Stripe.Subscription[]>;
|
|
724
|
+
deleteRemovedActiveEntitlements(customerId: string, currentActiveEntitlementIds: string[]): Promise<{
|
|
725
|
+
rowCount: number;
|
|
726
|
+
}>;
|
|
727
|
+
upsertFeatures(features: Stripe.Entitlements.Feature[], accountId: string, syncTimestamp?: string): Promise<Stripe.Entitlements.Feature[]>;
|
|
728
|
+
backfillFeatures(featureIds: string[], accountId: string): Promise<void>;
|
|
729
|
+
upsertActiveEntitlements(customerId: string, activeEntitlements: Stripe.Entitlements.ActiveEntitlement[], accountId: string, backfillRelatedEntities?: boolean, syncTimestamp?: string): Promise<{
|
|
730
|
+
id: string;
|
|
731
|
+
object: "entitlements.active_entitlement";
|
|
732
|
+
feature: string;
|
|
733
|
+
customer: string;
|
|
734
|
+
livemode: boolean;
|
|
735
|
+
lookup_key: string;
|
|
736
|
+
}[]>;
|
|
737
|
+
findOrCreateManagedWebhook(url: string, params?: Omit<Stripe.WebhookEndpointCreateParams, 'url'>): Promise<Stripe.WebhookEndpoint>;
|
|
738
|
+
getManagedWebhook(id: string): Promise<Stripe.WebhookEndpoint | null>;
|
|
739
|
+
/**
|
|
740
|
+
* Get a managed webhook by URL and account ID.
|
|
741
|
+
* Used for race condition recovery: when createManagedWebhook hits a unique constraint
|
|
742
|
+
* violation (another instance created the webhook), we need to fetch the existing webhook
|
|
743
|
+
* by URL since we only know the URL, not the ID of the webhook that won the race.
|
|
744
|
+
*/
|
|
745
|
+
getManagedWebhookByUrl(url: string): Promise<Stripe.WebhookEndpoint | null>;
|
|
746
|
+
listManagedWebhooks(): Promise<Array<Stripe.WebhookEndpoint>>;
|
|
747
|
+
updateManagedWebhook(id: string, params: Stripe.WebhookEndpointUpdateParams): Promise<Stripe.WebhookEndpoint>;
|
|
748
|
+
deleteManagedWebhook(id: string): Promise<boolean>;
|
|
749
|
+
upsertManagedWebhooks(webhooks: Array<Stripe.WebhookEndpoint>, accountId: string, syncTimestamp?: string): Promise<Array<Stripe.WebhookEndpoint>>;
|
|
750
|
+
backfillSubscriptions(subscriptionIds: string[], accountId: string): Promise<void>;
|
|
751
|
+
backfillSubscriptionSchedules: (subscriptionIds: string[], accountId: string) => Promise<void>;
|
|
752
|
+
/**
|
|
753
|
+
* Stripe only sends the first 10 entries by default, the option will actively fetch all entries.
|
|
754
|
+
* Uses manual pagination - each fetch() gets automatic retry protection.
|
|
755
|
+
*/
|
|
756
|
+
private expandEntity;
|
|
757
|
+
private fetchMissingEntities;
|
|
758
|
+
/**
|
|
759
|
+
* Closes the database connection pool and cleans up resources.
|
|
760
|
+
* Call this when you're done using the StripeSync instance.
|
|
761
|
+
*/
|
|
762
|
+
close(): Promise<void>;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
type MigrationConfig = {
|
|
766
|
+
databaseUrl: string;
|
|
767
|
+
ssl?: ConnectionOptions;
|
|
768
|
+
logger?: Logger;
|
|
769
|
+
};
|
|
770
|
+
declare function runMigrations(config: MigrationConfig): Promise<void>;
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Hashes a Stripe API key using SHA-256
|
|
774
|
+
* Used to store API key hashes in the database for fast account lookups
|
|
775
|
+
* without storing the actual API key or making Stripe API calls
|
|
776
|
+
*
|
|
777
|
+
* @param apiKey - The Stripe API key (e.g., sk_test_... or sk_live_...)
|
|
778
|
+
* @returns SHA-256 hash of the API key as a hex string
|
|
779
|
+
*/
|
|
780
|
+
declare function hashApiKey(apiKey: string): string;
|
|
781
|
+
|
|
782
|
+
interface WebhookProcessingResult {
|
|
783
|
+
status: number;
|
|
784
|
+
databaseUrl: string;
|
|
785
|
+
event_type?: string;
|
|
786
|
+
event_id?: string;
|
|
787
|
+
error?: string;
|
|
788
|
+
}
|
|
789
|
+
interface StripeWebSocketOptions {
|
|
790
|
+
stripeApiKey: string;
|
|
791
|
+
onEvent: (event: StripeWebhookEvent) => Promise<WebhookProcessingResult | void> | WebhookProcessingResult | void;
|
|
792
|
+
onReady?: (secret: string) => void;
|
|
793
|
+
onError?: (error: Error) => void;
|
|
794
|
+
onClose?: (code: number, reason: string) => void;
|
|
795
|
+
}
|
|
796
|
+
interface StripeWebSocketClient {
|
|
797
|
+
close: () => void;
|
|
798
|
+
isConnected: () => boolean;
|
|
799
|
+
}
|
|
800
|
+
interface StripeWebhookEvent {
|
|
801
|
+
type: string;
|
|
802
|
+
webhook_id: string;
|
|
803
|
+
webhook_conversation_id: string;
|
|
804
|
+
event_payload: string;
|
|
805
|
+
http_headers: Record<string, string>;
|
|
806
|
+
endpoint: {
|
|
807
|
+
url: string;
|
|
808
|
+
status: string;
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
declare function createStripeWebSocketClient(options: StripeWebSocketOptions): Promise<StripeWebSocketClient>;
|
|
812
|
+
|
|
813
|
+
declare const VERSION: string;
|
|
814
|
+
|
|
815
|
+
export { type BaseResourceConfig, type InstallationStatus, type Logger, PostgresClient, type ProcessNextParams, type ProcessNextResult, type ResourceConfig, type RevalidateEntity, type SigmaResourceConfig, type StripeListResourceConfig, StripeSync, type StripeSyncAccountState, type StripeSyncConfig, type StripeSyncState, type StripeWebSocketClient, type StripeWebSocketOptions, type StripeWebhookEvent, type Sync, type SyncBackfill, type SyncEntitlementsParams, type SyncFeaturesParams, type SyncObject, type SyncParams, VERSION, type WebhookProcessingResult, createStripeWebSocketClient, hashApiKey, runMigrations };
|