stripe-experiment-sync 1.0.19 → 1.0.20

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/index.d.cts CHANGED
@@ -33,7 +33,7 @@ declare class PostgresClient {
33
33
  }>(entries: T[], table: string): Promise<T[]>;
34
34
  upsertManyWithTimestampProtection<T extends {
35
35
  [Key: string]: any;
36
- }>(entries: T[], table: string, accountId: string, syncTimestamp?: string, upsertOptions?: RawJsonUpsertOptions): Promise<T[]>;
36
+ }>(entries: T[], table: string, accountId: string, syncTimestamp?: string, upsertOptions?: RawJsonUpsertOptions, schemaOverride?: string): Promise<T[]>;
37
37
  private cleanseArrayField;
38
38
  findMissingEntries(table: string, ids: string[]): Promise<string[]>;
39
39
  upsertAccount(accountData: {
@@ -102,9 +102,10 @@ declare class PostgresClient {
102
102
  cancelStaleRuns(accountId: string): Promise<void>;
103
103
  /**
104
104
  * Get or create a sync run for this account.
105
- * Returns existing run if one is active, otherwise creates new one.
105
+ * Returns existing run if one is active for the given triggeredBy, otherwise creates new one.
106
106
  * Auto-cancels stale runs before checking.
107
107
  *
108
+ * @param triggeredBy - Worker type (e.g., 'worker', 'sigma-worker'). Runs are isolated per triggeredBy.
108
109
  * @returns RunKey with isNew flag, or null if constraint violation (race condition)
109
110
  */
110
111
  getOrCreateSyncRun(accountId: string, triggeredBy?: string): Promise<{
@@ -114,8 +115,9 @@ declare class PostgresClient {
114
115
  } | null>;
115
116
  /**
116
117
  * Get the active sync run for an account (if any).
118
+ * @param triggeredBy - If provided, only returns run matching this triggeredBy value
117
119
  */
118
- getActiveSyncRun(accountId: string): Promise<{
120
+ getActiveSyncRun(accountId: string, triggeredBy?: string): Promise<{
119
121
  accountId: string;
120
122
  runStartedAt: Date;
121
123
  } | null>;
@@ -129,6 +131,10 @@ declare class PostgresClient {
129
131
  maxConcurrent: number;
130
132
  closedAt: Date | null;
131
133
  } | null>;
134
+ /**
135
+ * Ensure a sync run has at least the requested max_concurrent value.
136
+ */
137
+ ensureSyncRunMaxConcurrent(accountId: string, runStartedAt: Date, maxConcurrent: number): Promise<void>;
132
138
  /**
133
139
  * Close a sync run (mark as done).
134
140
  * Status (complete/error) is derived from object run states.
@@ -179,6 +185,11 @@ declare class PostgresClient {
179
185
  * For non-numeric cursors, just sets the value directly.
180
186
  */
181
187
  updateObjectCursor(accountId: string, runStartedAt: Date, object: string, cursor: string | null): Promise<void>;
188
+ setObjectCursor(accountId: string, runStartedAt: Date, object: string, cursor: string | null): Promise<void>;
189
+ /**
190
+ * List object names for a run by status, optionally filtered to a subset.
191
+ */
192
+ listObjectsByStatus(accountId: string, runStartedAt: Date, status: string, objectFilter?: string[]): Promise<string[]>;
182
193
  /**
183
194
  * Get the highest cursor from previous syncs for an object type.
184
195
  * Uses only completed object runs.
@@ -195,6 +206,11 @@ declare class PostgresClient {
195
206
  * Get the highest cursor from previous syncs for an object type, excluding the current run.
196
207
  */
197
208
  getLastCursorBeforeRun(accountId: string, object: string, runStartedAt: Date): Promise<string | null>;
209
+ /**
210
+ * Get the most recent cursor for an object run before the given run.
211
+ * This returns the raw cursor value without interpretation.
212
+ */
213
+ getLastObjectCursorBeforeRun(accountId: string, object: string, runStartedAt: Date): Promise<string | null>;
198
214
  /**
199
215
  * Delete all sync runs and object runs for an account.
200
216
  * Useful for testing or resetting sync state.
@@ -243,6 +259,12 @@ type SigmaCursorSpec = {
243
259
  version: 1;
244
260
  columns: SigmaCursorColumnSpec[];
245
261
  };
262
+ type SigmaColumnSpec = {
263
+ name: string;
264
+ sigmaType: string;
265
+ pgType: string;
266
+ primaryKey: boolean;
267
+ };
246
268
  type SigmaIngestionConfig = {
247
269
  /**
248
270
  * The Sigma table name to query (no quoting, no schema).
@@ -258,6 +280,11 @@ type SigmaIngestionConfig = {
258
280
  * Defines the ordering and cursor semantics. The columns must form a total order (i.e. be unique together) or pagination can be incorrect.
259
281
  */
260
282
  cursor: SigmaCursorSpec;
283
+ /**
284
+ * Column metadata for the destination table.
285
+ * If provided, used to dynamically create/reconcile the table.
286
+ */
287
+ columns?: SigmaColumnSpec[];
261
288
  /** Optional additional WHERE clause appended with AND (must not include leading WHERE). */
262
289
  additionalWhere?: string;
263
290
  /** Columns to SELECT (defaults to `*`). */
@@ -286,6 +313,16 @@ type StripeSyncConfig = {
286
313
  * Default: false (opt-in, so workers don't enqueue Sigma jobs unexpectedly).
287
314
  */
288
315
  enableSigma?: boolean;
316
+ /**
317
+ * Optional override for Sigma page size (per query).
318
+ * Useful for edge function CPU limits; lower values reduce per-invocation work.
319
+ */
320
+ sigmaPageSizeOverride?: number;
321
+ /**
322
+ * Postgres schema name for Sigma tables.
323
+ * Default: "sigma"
324
+ */
325
+ sigmaSchemaName?: string;
289
326
  /** Stripe account ID. If not provided, will be retrieved from Stripe API. Used as fallback option. */
290
327
  stripeAccountId?: string;
291
328
  /** Stripe webhook signing secret for validating webhook signatures. Required if not using managed webhooks. */
@@ -340,7 +377,7 @@ type StripeSyncConfig = {
340
377
  */
341
378
  maxConcurrentCustomers?: number;
342
379
  };
343
- 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' | 'subscription_item_change_events_v2_beta' | 'exchange_rates_from_usd';
380
+ 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';
344
381
  interface Sync {
345
382
  synced: number;
346
383
  }
@@ -364,6 +401,8 @@ interface SyncBackfill {
364
401
  checkoutSessions?: Sync;
365
402
  subscriptionItemChangeEventsV2Beta?: Sync;
366
403
  exchangeRatesFromUsd?: Sync;
404
+ /** Sigma-backed results by table name (e.g. subscription_item_change_events_v2_beta). */
405
+ sigma?: Record<string, Sync>;
367
406
  }
368
407
  interface SyncParams {
369
408
  created?: {
@@ -406,6 +445,8 @@ interface ProcessNextResult {
406
445
  hasMore: boolean;
407
446
  /** The sync run this processing belongs to */
408
447
  runStartedAt: Date;
448
+ /** Sigma-only: whether this step started a new Sigma query run */
449
+ startedQuery?: boolean;
409
450
  }
410
451
  /**
411
452
  * Parameters for processNext() including optional run context
@@ -496,7 +537,12 @@ declare class StripeSync {
496
537
  private config;
497
538
  stripe: Stripe;
498
539
  postgresClient: PostgresClient;
540
+ private readonly resourceRegistry;
541
+ private get sigmaSchemaName();
499
542
  constructor(config: StripeSyncConfig);
543
+ private buildResourceRegistry;
544
+ private isSigmaResource;
545
+ private sigmaResultKey;
500
546
  /**
501
547
  * Get the Stripe account ID. Delegates to getCurrentAccount() for the actual lookup.
502
548
  */
@@ -539,7 +585,6 @@ declare class StripeSync {
539
585
  }>;
540
586
  processWebhook(payload: Buffer | string, signature: string | undefined): Promise<void>;
541
587
  private readonly eventHandlers;
542
- private readonly resourceRegistry;
543
588
  processEvent(event: Stripe.Event): Promise<void>;
544
589
  /**
545
590
  * Returns an array of all webhook event types that this sync engine can handle.
@@ -552,6 +597,13 @@ declare class StripeSync {
552
597
  * Order is determined by the `order` field in resourceRegistry.
553
598
  */
554
599
  getSupportedSyncObjects(): Exclude<SyncObject, 'all' | 'customer_with_entitlements'>[];
600
+ /**
601
+ * Get the list of Sigma-backed object types that can be synced.
602
+ * Only returns sigma objects when enableSigma is true.
603
+ *
604
+ * @returns Array of sigma object names (e.g. 'subscription_item_change_events_v2_beta')
605
+ */
606
+ getSupportedSigmaObjects(): string[];
555
607
  private handleChargeEvent;
556
608
  private handleCustomerDeletedEvent;
557
609
  private handleCustomerEvent;
@@ -645,6 +697,22 @@ declare class StripeSync {
645
697
  runKey: RunKey;
646
698
  objects: Exclude<SyncObject, 'all' | 'customer_with_entitlements'>[];
647
699
  }>;
700
+ private applySyncBackfillResult;
701
+ processUntilDoneParallel(params?: SyncParams & {
702
+ maxParallel?: number;
703
+ triggeredBy?: string;
704
+ continueOnError?: boolean;
705
+ skipInaccessibleSigmaTables?: boolean;
706
+ }): Promise<{
707
+ results: SyncBackfill;
708
+ totals: Record<string, number>;
709
+ totalSynced: number;
710
+ skipped: string[];
711
+ errors: Array<{
712
+ object: string;
713
+ message: string;
714
+ }>;
715
+ }>;
648
716
  processUntilDone(params?: SyncParams): Promise<SyncBackfill>;
649
717
  /**
650
718
  * Internal implementation of processUntilDone with an existing run.
@@ -763,6 +831,7 @@ type MigrationConfig = {
763
831
  databaseUrl: string;
764
832
  ssl?: ConnectionOptions;
765
833
  logger?: Logger;
834
+ enableSigma?: boolean;
766
835
  };
767
836
  declare function runMigrations(config: MigrationConfig): Promise<void>;
768
837
 
package/dist/index.d.ts CHANGED
@@ -33,7 +33,7 @@ declare class PostgresClient {
33
33
  }>(entries: T[], table: string): Promise<T[]>;
34
34
  upsertManyWithTimestampProtection<T extends {
35
35
  [Key: string]: any;
36
- }>(entries: T[], table: string, accountId: string, syncTimestamp?: string, upsertOptions?: RawJsonUpsertOptions): Promise<T[]>;
36
+ }>(entries: T[], table: string, accountId: string, syncTimestamp?: string, upsertOptions?: RawJsonUpsertOptions, schemaOverride?: string): Promise<T[]>;
37
37
  private cleanseArrayField;
38
38
  findMissingEntries(table: string, ids: string[]): Promise<string[]>;
39
39
  upsertAccount(accountData: {
@@ -102,9 +102,10 @@ declare class PostgresClient {
102
102
  cancelStaleRuns(accountId: string): Promise<void>;
103
103
  /**
104
104
  * Get or create a sync run for this account.
105
- * Returns existing run if one is active, otherwise creates new one.
105
+ * Returns existing run if one is active for the given triggeredBy, otherwise creates new one.
106
106
  * Auto-cancels stale runs before checking.
107
107
  *
108
+ * @param triggeredBy - Worker type (e.g., 'worker', 'sigma-worker'). Runs are isolated per triggeredBy.
108
109
  * @returns RunKey with isNew flag, or null if constraint violation (race condition)
109
110
  */
110
111
  getOrCreateSyncRun(accountId: string, triggeredBy?: string): Promise<{
@@ -114,8 +115,9 @@ declare class PostgresClient {
114
115
  } | null>;
115
116
  /**
116
117
  * Get the active sync run for an account (if any).
118
+ * @param triggeredBy - If provided, only returns run matching this triggeredBy value
117
119
  */
118
- getActiveSyncRun(accountId: string): Promise<{
120
+ getActiveSyncRun(accountId: string, triggeredBy?: string): Promise<{
119
121
  accountId: string;
120
122
  runStartedAt: Date;
121
123
  } | null>;
@@ -129,6 +131,10 @@ declare class PostgresClient {
129
131
  maxConcurrent: number;
130
132
  closedAt: Date | null;
131
133
  } | null>;
134
+ /**
135
+ * Ensure a sync run has at least the requested max_concurrent value.
136
+ */
137
+ ensureSyncRunMaxConcurrent(accountId: string, runStartedAt: Date, maxConcurrent: number): Promise<void>;
132
138
  /**
133
139
  * Close a sync run (mark as done).
134
140
  * Status (complete/error) is derived from object run states.
@@ -179,6 +185,11 @@ declare class PostgresClient {
179
185
  * For non-numeric cursors, just sets the value directly.
180
186
  */
181
187
  updateObjectCursor(accountId: string, runStartedAt: Date, object: string, cursor: string | null): Promise<void>;
188
+ setObjectCursor(accountId: string, runStartedAt: Date, object: string, cursor: string | null): Promise<void>;
189
+ /**
190
+ * List object names for a run by status, optionally filtered to a subset.
191
+ */
192
+ listObjectsByStatus(accountId: string, runStartedAt: Date, status: string, objectFilter?: string[]): Promise<string[]>;
182
193
  /**
183
194
  * Get the highest cursor from previous syncs for an object type.
184
195
  * Uses only completed object runs.
@@ -195,6 +206,11 @@ declare class PostgresClient {
195
206
  * Get the highest cursor from previous syncs for an object type, excluding the current run.
196
207
  */
197
208
  getLastCursorBeforeRun(accountId: string, object: string, runStartedAt: Date): Promise<string | null>;
209
+ /**
210
+ * Get the most recent cursor for an object run before the given run.
211
+ * This returns the raw cursor value without interpretation.
212
+ */
213
+ getLastObjectCursorBeforeRun(accountId: string, object: string, runStartedAt: Date): Promise<string | null>;
198
214
  /**
199
215
  * Delete all sync runs and object runs for an account.
200
216
  * Useful for testing or resetting sync state.
@@ -243,6 +259,12 @@ type SigmaCursorSpec = {
243
259
  version: 1;
244
260
  columns: SigmaCursorColumnSpec[];
245
261
  };
262
+ type SigmaColumnSpec = {
263
+ name: string;
264
+ sigmaType: string;
265
+ pgType: string;
266
+ primaryKey: boolean;
267
+ };
246
268
  type SigmaIngestionConfig = {
247
269
  /**
248
270
  * The Sigma table name to query (no quoting, no schema).
@@ -258,6 +280,11 @@ type SigmaIngestionConfig = {
258
280
  * Defines the ordering and cursor semantics. The columns must form a total order (i.e. be unique together) or pagination can be incorrect.
259
281
  */
260
282
  cursor: SigmaCursorSpec;
283
+ /**
284
+ * Column metadata for the destination table.
285
+ * If provided, used to dynamically create/reconcile the table.
286
+ */
287
+ columns?: SigmaColumnSpec[];
261
288
  /** Optional additional WHERE clause appended with AND (must not include leading WHERE). */
262
289
  additionalWhere?: string;
263
290
  /** Columns to SELECT (defaults to `*`). */
@@ -286,6 +313,16 @@ type StripeSyncConfig = {
286
313
  * Default: false (opt-in, so workers don't enqueue Sigma jobs unexpectedly).
287
314
  */
288
315
  enableSigma?: boolean;
316
+ /**
317
+ * Optional override for Sigma page size (per query).
318
+ * Useful for edge function CPU limits; lower values reduce per-invocation work.
319
+ */
320
+ sigmaPageSizeOverride?: number;
321
+ /**
322
+ * Postgres schema name for Sigma tables.
323
+ * Default: "sigma"
324
+ */
325
+ sigmaSchemaName?: string;
289
326
  /** Stripe account ID. If not provided, will be retrieved from Stripe API. Used as fallback option. */
290
327
  stripeAccountId?: string;
291
328
  /** Stripe webhook signing secret for validating webhook signatures. Required if not using managed webhooks. */
@@ -340,7 +377,7 @@ type StripeSyncConfig = {
340
377
  */
341
378
  maxConcurrentCustomers?: number;
342
379
  };
343
- 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' | 'subscription_item_change_events_v2_beta' | 'exchange_rates_from_usd';
380
+ 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';
344
381
  interface Sync {
345
382
  synced: number;
346
383
  }
@@ -364,6 +401,8 @@ interface SyncBackfill {
364
401
  checkoutSessions?: Sync;
365
402
  subscriptionItemChangeEventsV2Beta?: Sync;
366
403
  exchangeRatesFromUsd?: Sync;
404
+ /** Sigma-backed results by table name (e.g. subscription_item_change_events_v2_beta). */
405
+ sigma?: Record<string, Sync>;
367
406
  }
368
407
  interface SyncParams {
369
408
  created?: {
@@ -406,6 +445,8 @@ interface ProcessNextResult {
406
445
  hasMore: boolean;
407
446
  /** The sync run this processing belongs to */
408
447
  runStartedAt: Date;
448
+ /** Sigma-only: whether this step started a new Sigma query run */
449
+ startedQuery?: boolean;
409
450
  }
410
451
  /**
411
452
  * Parameters for processNext() including optional run context
@@ -496,7 +537,12 @@ declare class StripeSync {
496
537
  private config;
497
538
  stripe: Stripe;
498
539
  postgresClient: PostgresClient;
540
+ private readonly resourceRegistry;
541
+ private get sigmaSchemaName();
499
542
  constructor(config: StripeSyncConfig);
543
+ private buildResourceRegistry;
544
+ private isSigmaResource;
545
+ private sigmaResultKey;
500
546
  /**
501
547
  * Get the Stripe account ID. Delegates to getCurrentAccount() for the actual lookup.
502
548
  */
@@ -539,7 +585,6 @@ declare class StripeSync {
539
585
  }>;
540
586
  processWebhook(payload: Buffer | string, signature: string | undefined): Promise<void>;
541
587
  private readonly eventHandlers;
542
- private readonly resourceRegistry;
543
588
  processEvent(event: Stripe.Event): Promise<void>;
544
589
  /**
545
590
  * Returns an array of all webhook event types that this sync engine can handle.
@@ -552,6 +597,13 @@ declare class StripeSync {
552
597
  * Order is determined by the `order` field in resourceRegistry.
553
598
  */
554
599
  getSupportedSyncObjects(): Exclude<SyncObject, 'all' | 'customer_with_entitlements'>[];
600
+ /**
601
+ * Get the list of Sigma-backed object types that can be synced.
602
+ * Only returns sigma objects when enableSigma is true.
603
+ *
604
+ * @returns Array of sigma object names (e.g. 'subscription_item_change_events_v2_beta')
605
+ */
606
+ getSupportedSigmaObjects(): string[];
555
607
  private handleChargeEvent;
556
608
  private handleCustomerDeletedEvent;
557
609
  private handleCustomerEvent;
@@ -645,6 +697,22 @@ declare class StripeSync {
645
697
  runKey: RunKey;
646
698
  objects: Exclude<SyncObject, 'all' | 'customer_with_entitlements'>[];
647
699
  }>;
700
+ private applySyncBackfillResult;
701
+ processUntilDoneParallel(params?: SyncParams & {
702
+ maxParallel?: number;
703
+ triggeredBy?: string;
704
+ continueOnError?: boolean;
705
+ skipInaccessibleSigmaTables?: boolean;
706
+ }): Promise<{
707
+ results: SyncBackfill;
708
+ totals: Record<string, number>;
709
+ totalSynced: number;
710
+ skipped: string[];
711
+ errors: Array<{
712
+ object: string;
713
+ message: string;
714
+ }>;
715
+ }>;
648
716
  processUntilDone(params?: SyncParams): Promise<SyncBackfill>;
649
717
  /**
650
718
  * Internal implementation of processUntilDone with an existing run.
@@ -763,6 +831,7 @@ type MigrationConfig = {
763
831
  databaseUrl: string;
764
832
  ssl?: ConnectionOptions;
765
833
  logger?: Logger;
834
+ enableSigma?: boolean;
766
835
  };
767
836
  declare function runMigrations(config: MigrationConfig): Promise<void>;
768
837
 
package/dist/index.js CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  createStripeWebSocketClient,
6
6
  hashApiKey,
7
7
  runMigrations
8
- } from "./chunk-XKBCLBFT.js";
9
- import "./chunk-CMGFQCD7.js";
8
+ } from "./chunk-HHDPFCIA.js";
9
+ import "./chunk-NM6L6EPQ.js";
10
10
  export {
11
11
  PostgresClient,
12
12
  StripeSync,
@@ -0,0 +1,8 @@
1
+ -- Allow parallel sync runs per triggered_by (sigma-worker vs stripe-worker)
2
+ ALTER TABLE "stripe"."_sync_runs" DROP CONSTRAINT IF EXISTS one_active_run_per_account;
3
+ ALTER TABLE "stripe"."_sync_runs"
4
+ ADD CONSTRAINT one_active_run_per_account_triggered_by
5
+ EXCLUDE (
6
+ "_account_id" WITH =,
7
+ COALESCE(triggered_by, 'default') WITH =
8
+ ) WHERE (closed_at IS NULL);