stripe-experiment-sync 1.0.9-beta.1765909347 → 1.0.10
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/dist/{chunk-2CYYWBTD.js → chunk-62FKHVHJ.js} +27 -486
- package/dist/{chunk-SI3VFP3M.js → chunk-AHNO3EMD.js} +36 -9
- package/dist/{chunk-DBJCCGXP.js → chunk-FZQ4B7VZ.js} +12 -29
- package/dist/{chunk-3W3CERIG.js → chunk-VEEV6P4R.js} +1 -3
- package/dist/cli/index.cjs +82 -527
- package/dist/cli/index.js +12 -8
- package/dist/cli/lib.cjs +74 -523
- package/dist/cli/lib.d.cts +1 -2
- package/dist/cli/lib.d.ts +1 -2
- package/dist/cli/lib.js +4 -4
- package/dist/index.cjs +27 -490
- package/dist/index.d.cts +4 -107
- package/dist/index.d.ts +4 -107
- package/dist/index.js +2 -6
- package/dist/supabase/index.cjs +36 -11
- package/dist/supabase/index.d.cts +4 -2
- package/dist/supabase/index.d.ts +4 -2
- package/dist/supabase/index.js +2 -2
- package/package.json +1 -3
- package/dist/migrations/0059_sigma_subscription_item_change_events_v2_beta.sql +0 -61
- package/dist/migrations/0060_sigma_exchange_rates_from_usd.sql +0 -38
package/dist/index.d.cts
CHANGED
|
@@ -6,22 +6,6 @@ type PostgresConfig = {
|
|
|
6
6
|
schema: string;
|
|
7
7
|
poolConfig: PoolConfig;
|
|
8
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
9
|
declare class PostgresClient {
|
|
26
10
|
private config;
|
|
27
11
|
pool: pg.Pool;
|
|
@@ -33,7 +17,7 @@ declare class PostgresClient {
|
|
|
33
17
|
}>(entries: T[], table: string): Promise<T[]>;
|
|
34
18
|
upsertManyWithTimestampProtection<T extends {
|
|
35
19
|
[Key: string]: any;
|
|
36
|
-
}>(entries: T[], table: string, accountId: string, syncTimestamp?: string
|
|
20
|
+
}>(entries: T[], table: string, accountId: string, syncTimestamp?: string): Promise<T[]>;
|
|
37
21
|
private cleanseArrayField;
|
|
38
22
|
findMissingEntries(table: string, ids: string[]): Promise<string[]>;
|
|
39
23
|
upsertAccount(accountData: {
|
|
@@ -173,10 +157,6 @@ declare class PostgresClient {
|
|
|
173
157
|
* This considers completed, error, AND running runs to ensure recovery syncs
|
|
174
158
|
* don't re-process data that was already synced before a crash.
|
|
175
159
|
* A 'running' status with a cursor means the process was killed mid-sync.
|
|
176
|
-
*
|
|
177
|
-
* Handles two cursor formats:
|
|
178
|
-
* - Numeric: compared as bigint for correct ordering
|
|
179
|
-
* - Composite cursors: compared as strings with COLLATE "C"
|
|
180
160
|
*/
|
|
181
161
|
getLastCompletedCursor(accountId: string, object: string): Promise<string | null>;
|
|
182
162
|
/**
|
|
@@ -218,38 +198,6 @@ declare class PostgresClient {
|
|
|
218
198
|
close(): Promise<void>;
|
|
219
199
|
}
|
|
220
200
|
|
|
221
|
-
type SigmaCursorColumnType = 'timestamp' | 'string' | 'number';
|
|
222
|
-
type SigmaCursorColumnSpec = {
|
|
223
|
-
column: string;
|
|
224
|
-
type: SigmaCursorColumnType;
|
|
225
|
-
};
|
|
226
|
-
type SigmaCursorSpec = {
|
|
227
|
-
version: 1;
|
|
228
|
-
columns: SigmaCursorColumnSpec[];
|
|
229
|
-
};
|
|
230
|
-
type SigmaIngestionConfig = {
|
|
231
|
-
/**
|
|
232
|
-
* The Sigma table name to query (no quoting, no schema).
|
|
233
|
-
*/
|
|
234
|
-
sigmaTable: string;
|
|
235
|
-
/**
|
|
236
|
-
* Destination Postgres table name (in the `stripe` schema by convention).
|
|
237
|
-
*/
|
|
238
|
-
destinationTable: string;
|
|
239
|
-
/** Limit for each Sigma query page. */
|
|
240
|
-
pageSize: number;
|
|
241
|
-
/**
|
|
242
|
-
* Defines the ordering and cursor semantics. The columns must form a total order (i.e. be unique together) or pagination can be incorrect.
|
|
243
|
-
*/
|
|
244
|
-
cursor: SigmaCursorSpec;
|
|
245
|
-
/** Optional additional WHERE clause appended with AND (must not include leading WHERE). */
|
|
246
|
-
additionalWhere?: string;
|
|
247
|
-
/** Columns to SELECT (defaults to `*`). */
|
|
248
|
-
select?: '*' | string[];
|
|
249
|
-
/** Postgres upsert behavior for this table (conflict target and typed columns). */
|
|
250
|
-
upsert: RawJsonUpsertOptions;
|
|
251
|
-
};
|
|
252
|
-
|
|
253
201
|
/**
|
|
254
202
|
* Simple logger interface compatible with both pino and console
|
|
255
203
|
*/
|
|
@@ -264,12 +212,6 @@ type StripeSyncConfig = {
|
|
|
264
212
|
databaseUrl?: string;
|
|
265
213
|
/** Stripe secret key used to authenticate requests to the Stripe API. Defaults to empty string */
|
|
266
214
|
stripeSecretKey: string;
|
|
267
|
-
/**
|
|
268
|
-
* Enables syncing Stripe Sigma (reporting) tables via the Sigma API.
|
|
269
|
-
*
|
|
270
|
-
* Default: false (opt-in, so workers don't enqueue Sigma jobs unexpectedly).
|
|
271
|
-
*/
|
|
272
|
-
enableSigmaSync?: boolean;
|
|
273
215
|
/** Stripe account ID. If not provided, will be retrieved from Stripe API. Used as fallback option. */
|
|
274
216
|
stripeAccountId?: string;
|
|
275
217
|
/** Stripe webhook signing secret for validating webhook signatures. Required if not using managed webhooks. */
|
|
@@ -294,7 +236,7 @@ type StripeSyncConfig = {
|
|
|
294
236
|
revalidateObjectsViaStripeApi?: Array<RevalidateEntity>;
|
|
295
237
|
/** @deprecated Use `poolConfig` instead. */
|
|
296
238
|
maxPostgresConnections?: number;
|
|
297
|
-
poolConfig
|
|
239
|
+
poolConfig: PoolConfig;
|
|
298
240
|
logger?: Logger;
|
|
299
241
|
/**
|
|
300
242
|
* Maximum number of retry attempts for 429 rate limit errors.
|
|
@@ -318,7 +260,7 @@ type StripeSyncConfig = {
|
|
|
318
260
|
*/
|
|
319
261
|
retryJitterMs?: number;
|
|
320
262
|
};
|
|
321
|
-
type SyncObject = 'all' | 'customer' | 'customer_with_entitlements' | 'invoice' | 'price' | 'product' | 'subscription' | 'subscription_schedules' | 'setup_intent' | 'payment_method' | 'dispute' | 'charge' | 'payment_intent' | 'plan' | 'tax_id' | 'credit_note' | 'early_fraud_warning' | 'refund' | 'checkout_sessions'
|
|
263
|
+
type SyncObject = 'all' | 'customer' | 'customer_with_entitlements' | 'invoice' | 'price' | 'product' | 'subscription' | 'subscription_schedules' | 'setup_intent' | 'payment_method' | 'dispute' | 'charge' | 'payment_intent' | 'plan' | 'tax_id' | 'credit_note' | 'early_fraud_warning' | 'refund' | 'checkout_sessions';
|
|
322
264
|
interface Sync {
|
|
323
265
|
synced: number;
|
|
324
266
|
}
|
|
@@ -340,8 +282,6 @@ interface SyncBackfill {
|
|
|
340
282
|
earlyFraudWarnings?: Sync;
|
|
341
283
|
refunds?: Sync;
|
|
342
284
|
checkoutSessions?: Sync;
|
|
343
|
-
subscriptionItemChangeEventsV2Beta?: Sync;
|
|
344
|
-
exchangeRatesFromUsd?: Sync;
|
|
345
285
|
}
|
|
346
286
|
interface SyncParams {
|
|
347
287
|
created?: {
|
|
@@ -394,44 +334,6 @@ interface ProcessNextParams extends SyncParams {
|
|
|
394
334
|
/** Who/what triggered this sync (for observability) */
|
|
395
335
|
triggeredBy?: string;
|
|
396
336
|
}
|
|
397
|
-
/**
|
|
398
|
-
* Syncable resource configuration
|
|
399
|
-
*/
|
|
400
|
-
type BaseResourceConfig = {
|
|
401
|
-
/** Backfill order: lower numbers sync first; parents before children for FK dependencies */
|
|
402
|
-
order: number;
|
|
403
|
-
/** Whether this resource supports incremental sync via 'created' filter or cursor */
|
|
404
|
-
supportsCreatedFilter: boolean;
|
|
405
|
-
};
|
|
406
|
-
type StripeListResourceConfig = BaseResourceConfig & {
|
|
407
|
-
/** Function to list items from Stripe API */
|
|
408
|
-
listFn: (params: Stripe.PaginationParams & {
|
|
409
|
-
created?: Stripe.RangeQueryParam;
|
|
410
|
-
}) => Promise<{
|
|
411
|
-
data: unknown[];
|
|
412
|
-
has_more: boolean;
|
|
413
|
-
}>;
|
|
414
|
-
/** Function to upsert items to database */
|
|
415
|
-
upsertFn: (items: unknown[], accountId: string, backfillRelated?: boolean) => Promise<unknown[] | void>;
|
|
416
|
-
/** discriminator */
|
|
417
|
-
sigma?: undefined;
|
|
418
|
-
};
|
|
419
|
-
/**
|
|
420
|
-
* Configuration for Sigma query-backed resources.
|
|
421
|
-
* Uses Stripe Sigma SQL queries with composite cursor pagination.
|
|
422
|
-
*/
|
|
423
|
-
type SigmaResourceConfig = BaseResourceConfig & {
|
|
424
|
-
/** Sigma uses composite cursors, not created filter */
|
|
425
|
-
supportsCreatedFilter: false;
|
|
426
|
-
/** Sigma ingestion configuration (query, cursor spec, upsert options) */
|
|
427
|
-
sigma: SigmaIngestionConfig;
|
|
428
|
-
/** discriminator */
|
|
429
|
-
listFn?: undefined;
|
|
430
|
-
/** discriminator */
|
|
431
|
-
upsertFn?: undefined;
|
|
432
|
-
};
|
|
433
|
-
/** Union of all resource configuration types */
|
|
434
|
-
type ResourceConfig = StripeListResourceConfig | SigmaResourceConfig;
|
|
435
337
|
|
|
436
338
|
/**
|
|
437
339
|
* Identifies a specific sync run.
|
|
@@ -559,8 +461,6 @@ declare class StripeSync {
|
|
|
559
461
|
* Uses the observable sync system for tracking progress.
|
|
560
462
|
*/
|
|
561
463
|
private fetchOnePage;
|
|
562
|
-
private getSigmaFallbackCursorFromDestination;
|
|
563
|
-
private fetchOneSigmaPage;
|
|
564
464
|
/**
|
|
565
465
|
* Process all pages for all (or specified) object types until complete.
|
|
566
466
|
*
|
|
@@ -752,9 +652,6 @@ interface StripeWebhookEvent {
|
|
|
752
652
|
}
|
|
753
653
|
declare function createStripeWebSocketClient(options: StripeWebSocketOptions): Promise<StripeWebSocketClient>;
|
|
754
654
|
|
|
755
|
-
declare function parseCsvObjects(csv: string): Array<Record<string, string | null>>;
|
|
756
|
-
declare function normalizeSigmaTimestampToIso(value: string): string | null;
|
|
757
|
-
|
|
758
655
|
declare const VERSION: string;
|
|
759
656
|
|
|
760
|
-
export { type
|
|
657
|
+
export { type Logger, PostgresClient, type ProcessNextParams, type ProcessNextResult, type RevalidateEntity, StripeSync, type StripeSyncConfig, type StripeWebSocketClient, type StripeWebSocketOptions, type StripeWebhookEvent, type Sync, type SyncBackfill, type SyncEntitlementsParams, type SyncFeaturesParams, type SyncObject, type SyncParams, VERSION, type WebhookProcessingResult, createStripeWebSocketClient, hashApiKey, runMigrations };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,22 +6,6 @@ type PostgresConfig = {
|
|
|
6
6
|
schema: string;
|
|
7
7
|
poolConfig: PoolConfig;
|
|
8
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
9
|
declare class PostgresClient {
|
|
26
10
|
private config;
|
|
27
11
|
pool: pg.Pool;
|
|
@@ -33,7 +17,7 @@ declare class PostgresClient {
|
|
|
33
17
|
}>(entries: T[], table: string): Promise<T[]>;
|
|
34
18
|
upsertManyWithTimestampProtection<T extends {
|
|
35
19
|
[Key: string]: any;
|
|
36
|
-
}>(entries: T[], table: string, accountId: string, syncTimestamp?: string
|
|
20
|
+
}>(entries: T[], table: string, accountId: string, syncTimestamp?: string): Promise<T[]>;
|
|
37
21
|
private cleanseArrayField;
|
|
38
22
|
findMissingEntries(table: string, ids: string[]): Promise<string[]>;
|
|
39
23
|
upsertAccount(accountData: {
|
|
@@ -173,10 +157,6 @@ declare class PostgresClient {
|
|
|
173
157
|
* This considers completed, error, AND running runs to ensure recovery syncs
|
|
174
158
|
* don't re-process data that was already synced before a crash.
|
|
175
159
|
* A 'running' status with a cursor means the process was killed mid-sync.
|
|
176
|
-
*
|
|
177
|
-
* Handles two cursor formats:
|
|
178
|
-
* - Numeric: compared as bigint for correct ordering
|
|
179
|
-
* - Composite cursors: compared as strings with COLLATE "C"
|
|
180
160
|
*/
|
|
181
161
|
getLastCompletedCursor(accountId: string, object: string): Promise<string | null>;
|
|
182
162
|
/**
|
|
@@ -218,38 +198,6 @@ declare class PostgresClient {
|
|
|
218
198
|
close(): Promise<void>;
|
|
219
199
|
}
|
|
220
200
|
|
|
221
|
-
type SigmaCursorColumnType = 'timestamp' | 'string' | 'number';
|
|
222
|
-
type SigmaCursorColumnSpec = {
|
|
223
|
-
column: string;
|
|
224
|
-
type: SigmaCursorColumnType;
|
|
225
|
-
};
|
|
226
|
-
type SigmaCursorSpec = {
|
|
227
|
-
version: 1;
|
|
228
|
-
columns: SigmaCursorColumnSpec[];
|
|
229
|
-
};
|
|
230
|
-
type SigmaIngestionConfig = {
|
|
231
|
-
/**
|
|
232
|
-
* The Sigma table name to query (no quoting, no schema).
|
|
233
|
-
*/
|
|
234
|
-
sigmaTable: string;
|
|
235
|
-
/**
|
|
236
|
-
* Destination Postgres table name (in the `stripe` schema by convention).
|
|
237
|
-
*/
|
|
238
|
-
destinationTable: string;
|
|
239
|
-
/** Limit for each Sigma query page. */
|
|
240
|
-
pageSize: number;
|
|
241
|
-
/**
|
|
242
|
-
* Defines the ordering and cursor semantics. The columns must form a total order (i.e. be unique together) or pagination can be incorrect.
|
|
243
|
-
*/
|
|
244
|
-
cursor: SigmaCursorSpec;
|
|
245
|
-
/** Optional additional WHERE clause appended with AND (must not include leading WHERE). */
|
|
246
|
-
additionalWhere?: string;
|
|
247
|
-
/** Columns to SELECT (defaults to `*`). */
|
|
248
|
-
select?: '*' | string[];
|
|
249
|
-
/** Postgres upsert behavior for this table (conflict target and typed columns). */
|
|
250
|
-
upsert: RawJsonUpsertOptions;
|
|
251
|
-
};
|
|
252
|
-
|
|
253
201
|
/**
|
|
254
202
|
* Simple logger interface compatible with both pino and console
|
|
255
203
|
*/
|
|
@@ -264,12 +212,6 @@ type StripeSyncConfig = {
|
|
|
264
212
|
databaseUrl?: string;
|
|
265
213
|
/** Stripe secret key used to authenticate requests to the Stripe API. Defaults to empty string */
|
|
266
214
|
stripeSecretKey: string;
|
|
267
|
-
/**
|
|
268
|
-
* Enables syncing Stripe Sigma (reporting) tables via the Sigma API.
|
|
269
|
-
*
|
|
270
|
-
* Default: false (opt-in, so workers don't enqueue Sigma jobs unexpectedly).
|
|
271
|
-
*/
|
|
272
|
-
enableSigmaSync?: boolean;
|
|
273
215
|
/** Stripe account ID. If not provided, will be retrieved from Stripe API. Used as fallback option. */
|
|
274
216
|
stripeAccountId?: string;
|
|
275
217
|
/** Stripe webhook signing secret for validating webhook signatures. Required if not using managed webhooks. */
|
|
@@ -294,7 +236,7 @@ type StripeSyncConfig = {
|
|
|
294
236
|
revalidateObjectsViaStripeApi?: Array<RevalidateEntity>;
|
|
295
237
|
/** @deprecated Use `poolConfig` instead. */
|
|
296
238
|
maxPostgresConnections?: number;
|
|
297
|
-
poolConfig
|
|
239
|
+
poolConfig: PoolConfig;
|
|
298
240
|
logger?: Logger;
|
|
299
241
|
/**
|
|
300
242
|
* Maximum number of retry attempts for 429 rate limit errors.
|
|
@@ -318,7 +260,7 @@ type StripeSyncConfig = {
|
|
|
318
260
|
*/
|
|
319
261
|
retryJitterMs?: number;
|
|
320
262
|
};
|
|
321
|
-
type SyncObject = 'all' | 'customer' | 'customer_with_entitlements' | 'invoice' | 'price' | 'product' | 'subscription' | 'subscription_schedules' | 'setup_intent' | 'payment_method' | 'dispute' | 'charge' | 'payment_intent' | 'plan' | 'tax_id' | 'credit_note' | 'early_fraud_warning' | 'refund' | 'checkout_sessions'
|
|
263
|
+
type SyncObject = 'all' | 'customer' | 'customer_with_entitlements' | 'invoice' | 'price' | 'product' | 'subscription' | 'subscription_schedules' | 'setup_intent' | 'payment_method' | 'dispute' | 'charge' | 'payment_intent' | 'plan' | 'tax_id' | 'credit_note' | 'early_fraud_warning' | 'refund' | 'checkout_sessions';
|
|
322
264
|
interface Sync {
|
|
323
265
|
synced: number;
|
|
324
266
|
}
|
|
@@ -340,8 +282,6 @@ interface SyncBackfill {
|
|
|
340
282
|
earlyFraudWarnings?: Sync;
|
|
341
283
|
refunds?: Sync;
|
|
342
284
|
checkoutSessions?: Sync;
|
|
343
|
-
subscriptionItemChangeEventsV2Beta?: Sync;
|
|
344
|
-
exchangeRatesFromUsd?: Sync;
|
|
345
285
|
}
|
|
346
286
|
interface SyncParams {
|
|
347
287
|
created?: {
|
|
@@ -394,44 +334,6 @@ interface ProcessNextParams extends SyncParams {
|
|
|
394
334
|
/** Who/what triggered this sync (for observability) */
|
|
395
335
|
triggeredBy?: string;
|
|
396
336
|
}
|
|
397
|
-
/**
|
|
398
|
-
* Syncable resource configuration
|
|
399
|
-
*/
|
|
400
|
-
type BaseResourceConfig = {
|
|
401
|
-
/** Backfill order: lower numbers sync first; parents before children for FK dependencies */
|
|
402
|
-
order: number;
|
|
403
|
-
/** Whether this resource supports incremental sync via 'created' filter or cursor */
|
|
404
|
-
supportsCreatedFilter: boolean;
|
|
405
|
-
};
|
|
406
|
-
type StripeListResourceConfig = BaseResourceConfig & {
|
|
407
|
-
/** Function to list items from Stripe API */
|
|
408
|
-
listFn: (params: Stripe.PaginationParams & {
|
|
409
|
-
created?: Stripe.RangeQueryParam;
|
|
410
|
-
}) => Promise<{
|
|
411
|
-
data: unknown[];
|
|
412
|
-
has_more: boolean;
|
|
413
|
-
}>;
|
|
414
|
-
/** Function to upsert items to database */
|
|
415
|
-
upsertFn: (items: unknown[], accountId: string, backfillRelated?: boolean) => Promise<unknown[] | void>;
|
|
416
|
-
/** discriminator */
|
|
417
|
-
sigma?: undefined;
|
|
418
|
-
};
|
|
419
|
-
/**
|
|
420
|
-
* Configuration for Sigma query-backed resources.
|
|
421
|
-
* Uses Stripe Sigma SQL queries with composite cursor pagination.
|
|
422
|
-
*/
|
|
423
|
-
type SigmaResourceConfig = BaseResourceConfig & {
|
|
424
|
-
/** Sigma uses composite cursors, not created filter */
|
|
425
|
-
supportsCreatedFilter: false;
|
|
426
|
-
/** Sigma ingestion configuration (query, cursor spec, upsert options) */
|
|
427
|
-
sigma: SigmaIngestionConfig;
|
|
428
|
-
/** discriminator */
|
|
429
|
-
listFn?: undefined;
|
|
430
|
-
/** discriminator */
|
|
431
|
-
upsertFn?: undefined;
|
|
432
|
-
};
|
|
433
|
-
/** Union of all resource configuration types */
|
|
434
|
-
type ResourceConfig = StripeListResourceConfig | SigmaResourceConfig;
|
|
435
337
|
|
|
436
338
|
/**
|
|
437
339
|
* Identifies a specific sync run.
|
|
@@ -559,8 +461,6 @@ declare class StripeSync {
|
|
|
559
461
|
* Uses the observable sync system for tracking progress.
|
|
560
462
|
*/
|
|
561
463
|
private fetchOnePage;
|
|
562
|
-
private getSigmaFallbackCursorFromDestination;
|
|
563
|
-
private fetchOneSigmaPage;
|
|
564
464
|
/**
|
|
565
465
|
* Process all pages for all (or specified) object types until complete.
|
|
566
466
|
*
|
|
@@ -752,9 +652,6 @@ interface StripeWebhookEvent {
|
|
|
752
652
|
}
|
|
753
653
|
declare function createStripeWebSocketClient(options: StripeWebSocketOptions): Promise<StripeWebSocketClient>;
|
|
754
654
|
|
|
755
|
-
declare function parseCsvObjects(csv: string): Array<Record<string, string | null>>;
|
|
756
|
-
declare function normalizeSigmaTimestampToIso(value: string): string | null;
|
|
757
|
-
|
|
758
655
|
declare const VERSION: string;
|
|
759
656
|
|
|
760
|
-
export { type
|
|
657
|
+
export { type Logger, PostgresClient, type ProcessNextParams, type ProcessNextResult, type RevalidateEntity, StripeSync, type StripeSyncConfig, type StripeWebSocketClient, type StripeWebSocketOptions, type StripeWebhookEvent, type Sync, type SyncBackfill, type SyncEntitlementsParams, type SyncFeaturesParams, type SyncObject, type SyncParams, VERSION, type WebhookProcessingResult, createStripeWebSocketClient, hashApiKey, runMigrations };
|
package/dist/index.js
CHANGED
|
@@ -4,18 +4,14 @@ import {
|
|
|
4
4
|
VERSION,
|
|
5
5
|
createStripeWebSocketClient,
|
|
6
6
|
hashApiKey,
|
|
7
|
-
normalizeSigmaTimestampToIso,
|
|
8
|
-
parseCsvObjects,
|
|
9
7
|
runMigrations
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-62FKHVHJ.js";
|
|
9
|
+
import "./chunk-VEEV6P4R.js";
|
|
12
10
|
export {
|
|
13
11
|
PostgresClient,
|
|
14
12
|
StripeSync,
|
|
15
13
|
VERSION,
|
|
16
14
|
createStripeWebSocketClient,
|
|
17
15
|
hashApiKey,
|
|
18
|
-
normalizeSigmaTimestampToIso,
|
|
19
|
-
parseCsvObjects,
|
|
20
16
|
runMigrations
|
|
21
17
|
};
|
package/dist/supabase/index.cjs
CHANGED
|
@@ -54,7 +54,7 @@ var stripe_setup_default = "import { StripeSync, runMigrations } from 'npm:strip
|
|
|
54
54
|
var stripe_webhook_default = "import { StripeSync } from 'npm:stripe-experiment-sync'\n\nDeno.serve(async (req) => {\n if (req.method !== 'POST') {\n return new Response('Method not allowed', { status: 405 })\n }\n\n const sig = req.headers.get('stripe-signature')\n if (!sig) {\n return new Response('Missing stripe-signature header', { status: 400 })\n }\n\n const rawDbUrl = Deno.env.get('SUPABASE_DB_URL')\n if (!rawDbUrl) {\n return new Response(JSON.stringify({ error: 'SUPABASE_DB_URL not set' }), { status: 500 })\n }\n const dbUrl = rawDbUrl.replace(/[?&]sslmode=[^&]*/g, '').replace(/[?&]$/, '')\n\n const stripeSync = new StripeSync({\n poolConfig: { connectionString: dbUrl, max: 1 },\n stripeSecretKey: Deno.env.get('STRIPE_SECRET_KEY')!,\n })\n\n try {\n const rawBody = new Uint8Array(await req.arrayBuffer())\n await stripeSync.processWebhook(rawBody, sig)\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n })\n } catch (error) {\n console.error('Webhook processing error:', error)\n const isSignatureError =\n error.message?.includes('signature') || error.type === 'StripeSignatureVerificationError'\n const status = isSignatureError ? 400 : 500\n return new Response(JSON.stringify({ error: error.message }), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n } finally {\n await stripeSync.postgresClient.pool.end()\n }\n})\n";
|
|
55
55
|
|
|
56
56
|
// raw-ts:/home/runner/work/sync-engine/sync-engine/packages/sync-engine/src/supabase/edge-functions/stripe-worker.ts
|
|
57
|
-
var stripe_worker_default = "/**\n * Stripe Sync Worker\n *\n * Triggered by pg_cron
|
|
57
|
+
var stripe_worker_default = "/**\n * Stripe Sync Worker\n *\n * Triggered by pg_cron at a configurable interval (default: 60 seconds). Uses pgmq for durable work queue.\n *\n * Flow:\n * 1. Read batch of messages from pgmq (qty=10, vt=60s)\n * 2. If queue empty: enqueue all objects (continuous sync)\n * 3. Process messages in parallel (Promise.all):\n * - processNext(object)\n * - Delete message on success\n * - Re-enqueue if hasMore\n * 4. Return results summary\n *\n * Concurrency:\n * - Multiple workers can run concurrently via overlapping pg_cron triggers.\n * - Each worker processes its batch of messages in parallel (Promise.all).\n * - pgmq visibility timeout prevents duplicate message reads across workers.\n * - processNext() is idempotent (uses internal cursor tracking), so duplicate\n * processing on timeout/crash is safe.\n */\n\nimport { StripeSync } from 'npm:stripe-experiment-sync'\nimport postgres from 'npm:postgres'\n\nconst QUEUE_NAME = 'stripe_sync_work'\nconst VISIBILITY_TIMEOUT = 60 // seconds\nconst BATCH_SIZE = 10\n\nDeno.serve(async (req) => {\n const authHeader = req.headers.get('Authorization')\n if (!authHeader?.startsWith('Bearer ')) {\n return new Response('Unauthorized', { status: 401 })\n }\n\n const rawDbUrl = Deno.env.get('SUPABASE_DB_URL')\n if (!rawDbUrl) {\n return new Response(JSON.stringify({ error: 'SUPABASE_DB_URL not set' }), { status: 500 })\n }\n const dbUrl = rawDbUrl.replace(/[?&]sslmode=[^&]*/g, '').replace(/[?&]$/, '')\n\n let sql\n let stripeSync\n\n try {\n sql = postgres(dbUrl, { max: 1, prepare: false })\n } catch (error) {\n return new Response(\n JSON.stringify({\n error: 'Failed to create postgres connection',\n details: error.message,\n stack: error.stack,\n }),\n { status: 500, headers: { 'Content-Type': 'application/json' } }\n )\n }\n\n try {\n stripeSync = new StripeSync({\n poolConfig: { connectionString: dbUrl, max: 1 },\n stripeSecretKey: Deno.env.get('STRIPE_SECRET_KEY')!,\n })\n } catch (error) {\n await sql.end()\n return new Response(\n JSON.stringify({\n error: 'Failed to create StripeSync',\n details: error.message,\n stack: error.stack,\n }),\n { status: 500, headers: { 'Content-Type': 'application/json' } }\n )\n }\n\n try {\n // Read batch of messages from queue\n const messages = await sql`\n SELECT * FROM pgmq.read(${QUEUE_NAME}::text, ${VISIBILITY_TIMEOUT}::int, ${BATCH_SIZE}::int)\n `\n\n // If queue empty, enqueue all objects for continuous sync\n if (messages.length === 0) {\n // Create sync run to make enqueued work visible (status='pending')\n const { objects } = await stripeSync.joinOrCreateSyncRun('worker')\n const msgs = objects.map((object) => JSON.stringify({ object }))\n\n await sql`\n SELECT pgmq.send_batch(\n ${QUEUE_NAME}::text,\n ${sql.array(msgs)}::jsonb[]\n )\n `\n\n return new Response(JSON.stringify({ enqueued: objects.length, objects }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n\n // Process messages in parallel\n const results = await Promise.all(\n messages.map(async (msg) => {\n const { object } = msg.message as { object: string }\n\n try {\n const result = await stripeSync.processNext(object)\n\n // Delete message on success (cast to bigint to disambiguate overloaded function)\n await sql`SELECT pgmq.delete(${QUEUE_NAME}::text, ${msg.msg_id}::bigint)`\n\n // Re-enqueue if more pages\n if (result.hasMore) {\n await sql`SELECT pgmq.send(${QUEUE_NAME}::text, ${sql.json({ object })}::jsonb)`\n }\n\n return { object, ...result }\n } catch (error) {\n // Log error but continue to next message\n // Message will become visible again after visibility timeout\n console.error(`Error processing ${object}:`, error)\n return {\n object,\n processed: 0,\n hasMore: false,\n error: error.message,\n stack: error.stack,\n }\n }\n })\n )\n\n return new Response(JSON.stringify({ results }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n })\n } catch (error) {\n console.error('Worker error:', error)\n return new Response(JSON.stringify({ error: error.message, stack: error.stack }), {\n status: 500,\n headers: { 'Content-Type': 'application/json' },\n })\n } finally {\n if (sql) await sql.end()\n if (stripeSync) await stripeSync.postgresClient.pool.end()\n }\n})\n";
|
|
58
58
|
|
|
59
59
|
// src/supabase/edge-function-code.ts
|
|
60
60
|
var setupFunctionCode = stripe_setup_default;
|
|
@@ -64,7 +64,7 @@ var workerFunctionCode = stripe_worker_default;
|
|
|
64
64
|
// package.json
|
|
65
65
|
var package_default = {
|
|
66
66
|
name: "stripe-experiment-sync",
|
|
67
|
-
version: "1.0.
|
|
67
|
+
version: "1.0.10",
|
|
68
68
|
private: false,
|
|
69
69
|
description: "Stripe Sync Engine to sync Stripe data to Postgres",
|
|
70
70
|
type: "module",
|
|
@@ -104,7 +104,6 @@ var package_default = {
|
|
|
104
104
|
dotenv: "^16.4.7",
|
|
105
105
|
express: "^4.18.2",
|
|
106
106
|
inquirer: "^12.3.0",
|
|
107
|
-
papaparse: "5.4.1",
|
|
108
107
|
pg: "^8.16.3",
|
|
109
108
|
"pg-node-migrations": "0.0.8",
|
|
110
109
|
stripe: "^17.7.0",
|
|
@@ -116,7 +115,6 @@ var package_default = {
|
|
|
116
115
|
"@types/express": "^4.17.21",
|
|
117
116
|
"@types/inquirer": "^9.0.7",
|
|
118
117
|
"@types/node": "^24.10.1",
|
|
119
|
-
"@types/papaparse": "5.3.16",
|
|
120
118
|
"@types/pg": "^8.15.5",
|
|
121
119
|
"@types/ws": "^8.5.13",
|
|
122
120
|
"@types/yesql": "^4.1.4",
|
|
@@ -212,8 +210,29 @@ var SupabaseSetupClient = class {
|
|
|
212
210
|
}
|
|
213
211
|
/**
|
|
214
212
|
* Setup pg_cron job to invoke worker function
|
|
213
|
+
* @param intervalSeconds - How often to run the worker (default: 60 seconds)
|
|
215
214
|
*/
|
|
216
|
-
async setupPgCronJob() {
|
|
215
|
+
async setupPgCronJob(intervalSeconds = 60) {
|
|
216
|
+
if (!Number.isInteger(intervalSeconds) || intervalSeconds < 1) {
|
|
217
|
+
throw new Error(`Invalid interval: ${intervalSeconds}. Must be a positive integer.`);
|
|
218
|
+
}
|
|
219
|
+
let schedule;
|
|
220
|
+
if (intervalSeconds < 60) {
|
|
221
|
+
schedule = `${intervalSeconds} seconds`;
|
|
222
|
+
} else if (intervalSeconds % 60 === 0) {
|
|
223
|
+
const minutes = intervalSeconds / 60;
|
|
224
|
+
if (minutes < 60) {
|
|
225
|
+
schedule = `*/${minutes} * * * *`;
|
|
226
|
+
} else {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Invalid interval: ${intervalSeconds}. Intervals >= 3600 seconds (1 hour) are not supported. Use a value between 1-3599 seconds.`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
throw new Error(
|
|
233
|
+
`Invalid interval: ${intervalSeconds}. Must be either 1-59 seconds or a multiple of 60 (e.g., 60, 120, 180).`
|
|
234
|
+
);
|
|
235
|
+
}
|
|
217
236
|
const serviceRoleKey = await this.getServiceRoleKey();
|
|
218
237
|
const escapedServiceRoleKey = serviceRoleKey.replace(/'/g, "''");
|
|
219
238
|
const sql = `
|
|
@@ -241,11 +260,11 @@ var SupabaseSetupClient = class {
|
|
|
241
260
|
SELECT 1 FROM cron.job WHERE jobname = 'stripe-sync-scheduler'
|
|
242
261
|
);
|
|
243
262
|
|
|
244
|
-
-- Create job to invoke worker
|
|
263
|
+
-- Create job to invoke worker at configured interval
|
|
245
264
|
-- Worker reads from pgmq, enqueues objects if empty, and processes sync work
|
|
246
265
|
SELECT cron.schedule(
|
|
247
266
|
'stripe-sync-worker',
|
|
248
|
-
'
|
|
267
|
+
'${schedule}',
|
|
249
268
|
$$
|
|
250
269
|
SELECT net.http_post(
|
|
251
270
|
url := 'https://${this.projectRef}.${this.projectBaseUrl}/functions/v1/stripe-worker',
|
|
@@ -473,7 +492,7 @@ var SupabaseSetupClient = class {
|
|
|
473
492
|
`from 'npm:stripe-experiment-sync@${version}'`
|
|
474
493
|
);
|
|
475
494
|
}
|
|
476
|
-
async install(stripeKey, packageVersion) {
|
|
495
|
+
async install(stripeKey, packageVersion, workerIntervalSeconds) {
|
|
477
496
|
const trimmedStripeKey = stripeKey.trim();
|
|
478
497
|
if (!trimmedStripeKey.startsWith("sk_") && !trimmedStripeKey.startsWith("rk_")) {
|
|
479
498
|
throw new Error('Stripe key should start with "sk_" or "rk_"');
|
|
@@ -497,7 +516,7 @@ var SupabaseSetupClient = class {
|
|
|
497
516
|
if (!setupResult.success) {
|
|
498
517
|
throw new Error(`Setup failed: ${setupResult.error}`);
|
|
499
518
|
}
|
|
500
|
-
await this.setupPgCronJob();
|
|
519
|
+
await this.setupPgCronJob(workerIntervalSeconds);
|
|
501
520
|
await this.updateInstallationComment(
|
|
502
521
|
`${STRIPE_SCHEMA_COMMENT_PREFIX} v${package_default.version} ${INSTALLATION_INSTALLED_SUFFIX}`
|
|
503
522
|
);
|
|
@@ -510,14 +529,20 @@ var SupabaseSetupClient = class {
|
|
|
510
529
|
}
|
|
511
530
|
};
|
|
512
531
|
async function install(params) {
|
|
513
|
-
const {
|
|
532
|
+
const {
|
|
533
|
+
supabaseAccessToken,
|
|
534
|
+
supabaseProjectRef,
|
|
535
|
+
stripeKey,
|
|
536
|
+
packageVersion,
|
|
537
|
+
workerIntervalSeconds
|
|
538
|
+
} = params;
|
|
514
539
|
const client = new SupabaseSetupClient({
|
|
515
540
|
accessToken: supabaseAccessToken,
|
|
516
541
|
projectRef: supabaseProjectRef,
|
|
517
542
|
projectBaseUrl: params.baseProjectUrl,
|
|
518
543
|
managementApiBaseUrl: params.baseManagementApiUrl
|
|
519
544
|
});
|
|
520
|
-
await client.install(stripeKey, packageVersion);
|
|
545
|
+
await client.install(stripeKey, packageVersion, workerIntervalSeconds);
|
|
521
546
|
}
|
|
522
547
|
async function uninstall(params) {
|
|
523
548
|
const { supabaseAccessToken, supabaseProjectRef, stripeKey } = params;
|
|
@@ -39,8 +39,9 @@ declare class SupabaseSetupClient {
|
|
|
39
39
|
runSQL(sql: string): Promise<unknown>;
|
|
40
40
|
/**
|
|
41
41
|
* Setup pg_cron job to invoke worker function
|
|
42
|
+
* @param intervalSeconds - How often to run the worker (default: 60 seconds)
|
|
42
43
|
*/
|
|
43
|
-
setupPgCronJob(): Promise<void>;
|
|
44
|
+
setupPgCronJob(intervalSeconds?: number): Promise<void>;
|
|
44
45
|
/**
|
|
45
46
|
* Get the webhook URL for this project
|
|
46
47
|
*/
|
|
@@ -97,13 +98,14 @@ declare class SupabaseSetupClient {
|
|
|
97
98
|
* Inject package version into Edge Function code
|
|
98
99
|
*/
|
|
99
100
|
private injectPackageVersion;
|
|
100
|
-
install(stripeKey: string, packageVersion?: string): Promise<void>;
|
|
101
|
+
install(stripeKey: string, packageVersion?: string, workerIntervalSeconds?: number): Promise<void>;
|
|
101
102
|
}
|
|
102
103
|
declare function install(params: {
|
|
103
104
|
supabaseAccessToken: string;
|
|
104
105
|
supabaseProjectRef: string;
|
|
105
106
|
stripeKey: string;
|
|
106
107
|
packageVersion?: string;
|
|
108
|
+
workerIntervalSeconds?: number;
|
|
107
109
|
baseProjectUrl?: string;
|
|
108
110
|
baseManagementApiUrl?: string;
|
|
109
111
|
}): Promise<void>;
|
package/dist/supabase/index.d.ts
CHANGED
|
@@ -39,8 +39,9 @@ declare class SupabaseSetupClient {
|
|
|
39
39
|
runSQL(sql: string): Promise<unknown>;
|
|
40
40
|
/**
|
|
41
41
|
* Setup pg_cron job to invoke worker function
|
|
42
|
+
* @param intervalSeconds - How often to run the worker (default: 60 seconds)
|
|
42
43
|
*/
|
|
43
|
-
setupPgCronJob(): Promise<void>;
|
|
44
|
+
setupPgCronJob(intervalSeconds?: number): Promise<void>;
|
|
44
45
|
/**
|
|
45
46
|
* Get the webhook URL for this project
|
|
46
47
|
*/
|
|
@@ -97,13 +98,14 @@ declare class SupabaseSetupClient {
|
|
|
97
98
|
* Inject package version into Edge Function code
|
|
98
99
|
*/
|
|
99
100
|
private injectPackageVersion;
|
|
100
|
-
install(stripeKey: string, packageVersion?: string): Promise<void>;
|
|
101
|
+
install(stripeKey: string, packageVersion?: string, workerIntervalSeconds?: number): Promise<void>;
|
|
101
102
|
}
|
|
102
103
|
declare function install(params: {
|
|
103
104
|
supabaseAccessToken: string;
|
|
104
105
|
supabaseProjectRef: string;
|
|
105
106
|
stripeKey: string;
|
|
106
107
|
packageVersion?: string;
|
|
108
|
+
workerIntervalSeconds?: number;
|
|
107
109
|
baseProjectUrl?: string;
|
|
108
110
|
baseManagementApiUrl?: string;
|
|
109
111
|
}): Promise<void>;
|
package/dist/supabase/index.js
CHANGED
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
uninstall,
|
|
10
10
|
webhookFunctionCode,
|
|
11
11
|
workerFunctionCode
|
|
12
|
-
} from "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
} from "../chunk-AHNO3EMD.js";
|
|
13
|
+
import "../chunk-VEEV6P4R.js";
|
|
14
14
|
export {
|
|
15
15
|
INSTALLATION_ERROR_SUFFIX,
|
|
16
16
|
INSTALLATION_INSTALLED_SUFFIX,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stripe-experiment-sync",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Stripe Sync Engine to sync Stripe data to Postgres",
|
|
6
6
|
"type": "module",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"dotenv": "^16.4.7",
|
|
41
41
|
"express": "^4.18.2",
|
|
42
42
|
"inquirer": "^12.3.0",
|
|
43
|
-
"papaparse": "5.4.1",
|
|
44
43
|
"pg": "^8.16.3",
|
|
45
44
|
"pg-node-migrations": "0.0.8",
|
|
46
45
|
"stripe": "^17.7.0",
|
|
@@ -52,7 +51,6 @@
|
|
|
52
51
|
"@types/express": "^4.17.21",
|
|
53
52
|
"@types/inquirer": "^9.0.7",
|
|
54
53
|
"@types/node": "^24.10.1",
|
|
55
|
-
"@types/papaparse": "5.3.16",
|
|
56
54
|
"@types/pg": "^8.15.5",
|
|
57
55
|
"@types/ws": "^8.5.13",
|
|
58
56
|
"@types/yesql": "^4.1.4",
|