stripe-experiment-sync 0.0.5 → 1.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.
@@ -0,0 +1,49 @@
1
+ -- Add _account_id column to all tables to track which Stripe account each record belongs to
2
+ -- Column is nullable for backward compatibility with existing data
3
+
4
+ ALTER TABLE "stripe"."active_entitlements" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
5
+
6
+ ALTER TABLE "stripe"."charges" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
7
+
8
+ ALTER TABLE "stripe"."checkout_session_line_items" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
9
+
10
+ ALTER TABLE "stripe"."checkout_sessions" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
11
+
12
+ ALTER TABLE "stripe"."credit_notes" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
13
+
14
+ ALTER TABLE "stripe"."customers" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
15
+
16
+ ALTER TABLE "stripe"."disputes" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
17
+
18
+ ALTER TABLE "stripe"."early_fraud_warnings" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
19
+
20
+ ALTER TABLE "stripe"."features" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
21
+
22
+ ALTER TABLE "stripe"."invoices" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
23
+
24
+ ALTER TABLE "stripe"."_managed_webhooks" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
25
+
26
+ ALTER TABLE "stripe"."payment_intents" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
27
+
28
+ ALTER TABLE "stripe"."payment_methods" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
29
+
30
+ ALTER TABLE "stripe"."plans" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
31
+
32
+ ALTER TABLE "stripe"."prices" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
33
+
34
+ ALTER TABLE "stripe"."products" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
35
+
36
+ ALTER TABLE "stripe"."refunds" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
37
+
38
+ ALTER TABLE "stripe"."reviews" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
39
+
40
+ ALTER TABLE "stripe"."setup_intents" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
41
+
42
+ ALTER TABLE "stripe"."subscription_items" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
43
+
44
+ ALTER TABLE "stripe"."subscription_schedules" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
45
+
46
+ ALTER TABLE "stripe"."subscriptions" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
47
+
48
+ ALTER TABLE "stripe"."tax_ids" ADD COLUMN IF NOT EXISTS "_account_id" TEXT;
49
+
@@ -0,0 +1,54 @@
1
+ -- Make _account_id required by:
2
+ -- 1. Deleting all rows where _account_id IS NULL
3
+ -- 2. Setting _account_id to NOT NULL
4
+
5
+ -- Delete rows with null _account_id
6
+ DELETE FROM "stripe"."active_entitlements" WHERE "_account_id" IS NULL;
7
+ DELETE FROM "stripe"."charges" WHERE "_account_id" IS NULL;
8
+ DELETE FROM "stripe"."checkout_session_line_items" WHERE "_account_id" IS NULL;
9
+ DELETE FROM "stripe"."checkout_sessions" WHERE "_account_id" IS NULL;
10
+ DELETE FROM "stripe"."credit_notes" WHERE "_account_id" IS NULL;
11
+ DELETE FROM "stripe"."customers" WHERE "_account_id" IS NULL;
12
+ DELETE FROM "stripe"."disputes" WHERE "_account_id" IS NULL;
13
+ DELETE FROM "stripe"."early_fraud_warnings" WHERE "_account_id" IS NULL;
14
+ DELETE FROM "stripe"."features" WHERE "_account_id" IS NULL;
15
+ DELETE FROM "stripe"."invoices" WHERE "_account_id" IS NULL;
16
+ DELETE FROM "stripe"."_managed_webhooks" WHERE "_account_id" IS NULL;
17
+ DELETE FROM "stripe"."payment_intents" WHERE "_account_id" IS NULL;
18
+ DELETE FROM "stripe"."payment_methods" WHERE "_account_id" IS NULL;
19
+ DELETE FROM "stripe"."plans" WHERE "_account_id" IS NULL;
20
+ DELETE FROM "stripe"."prices" WHERE "_account_id" IS NULL;
21
+ DELETE FROM "stripe"."products" WHERE "_account_id" IS NULL;
22
+ DELETE FROM "stripe"."refunds" WHERE "_account_id" IS NULL;
23
+ DELETE FROM "stripe"."reviews" WHERE "_account_id" IS NULL;
24
+ DELETE FROM "stripe"."setup_intents" WHERE "_account_id" IS NULL;
25
+ DELETE FROM "stripe"."subscription_items" WHERE "_account_id" IS NULL;
26
+ DELETE FROM "stripe"."subscription_schedules" WHERE "_account_id" IS NULL;
27
+ DELETE FROM "stripe"."subscriptions" WHERE "_account_id" IS NULL;
28
+ DELETE FROM "stripe"."tax_ids" WHERE "_account_id" IS NULL;
29
+
30
+ -- Make _account_id NOT NULL
31
+ ALTER TABLE "stripe"."active_entitlements" ALTER COLUMN "_account_id" SET NOT NULL;
32
+ ALTER TABLE "stripe"."charges" ALTER COLUMN "_account_id" SET NOT NULL;
33
+ ALTER TABLE "stripe"."checkout_session_line_items" ALTER COLUMN "_account_id" SET NOT NULL;
34
+ ALTER TABLE "stripe"."checkout_sessions" ALTER COLUMN "_account_id" SET NOT NULL;
35
+ ALTER TABLE "stripe"."credit_notes" ALTER COLUMN "_account_id" SET NOT NULL;
36
+ ALTER TABLE "stripe"."customers" ALTER COLUMN "_account_id" SET NOT NULL;
37
+ ALTER TABLE "stripe"."disputes" ALTER COLUMN "_account_id" SET NOT NULL;
38
+ ALTER TABLE "stripe"."early_fraud_warnings" ALTER COLUMN "_account_id" SET NOT NULL;
39
+ ALTER TABLE "stripe"."features" ALTER COLUMN "_account_id" SET NOT NULL;
40
+ ALTER TABLE "stripe"."invoices" ALTER COLUMN "_account_id" SET NOT NULL;
41
+ ALTER TABLE "stripe"."_managed_webhooks" ALTER COLUMN "_account_id" SET NOT NULL;
42
+ ALTER TABLE "stripe"."payment_intents" ALTER COLUMN "_account_id" SET NOT NULL;
43
+ ALTER TABLE "stripe"."payment_methods" ALTER COLUMN "_account_id" SET NOT NULL;
44
+ ALTER TABLE "stripe"."plans" ALTER COLUMN "_account_id" SET NOT NULL;
45
+ ALTER TABLE "stripe"."prices" ALTER COLUMN "_account_id" SET NOT NULL;
46
+ ALTER TABLE "stripe"."products" ALTER COLUMN "_account_id" SET NOT NULL;
47
+ ALTER TABLE "stripe"."refunds" ALTER COLUMN "_account_id" SET NOT NULL;
48
+ ALTER TABLE "stripe"."reviews" ALTER COLUMN "_account_id" SET NOT NULL;
49
+ ALTER TABLE "stripe"."setup_intents" ALTER COLUMN "_account_id" SET NOT NULL;
50
+ ALTER TABLE "stripe"."subscription_items" ALTER COLUMN "_account_id" SET NOT NULL;
51
+ ALTER TABLE "stripe"."subscription_schedules" ALTER COLUMN "_account_id" SET NOT NULL;
52
+ ALTER TABLE "stripe"."subscriptions" ALTER COLUMN "_account_id" SET NOT NULL;
53
+ ALTER TABLE "stripe"."tax_ids" ALTER COLUMN "_account_id" SET NOT NULL;
54
+
@@ -0,0 +1,18 @@
1
+ -- Create _sync_status metadata table for tracking incremental sync cursors
2
+ -- This table tracks the state and progress of each resource's synchronization
3
+
4
+ CREATE TABLE IF NOT EXISTS "stripe"."_sync_status" (
5
+ id serial PRIMARY KEY,
6
+ resource text UNIQUE NOT NULL,
7
+ status text CHECK (status IN ('idle', 'running', 'complete', 'error')) DEFAULT 'idle',
8
+ last_synced_at timestamptz DEFAULT now(),
9
+ last_incremental_cursor timestamptz,
10
+ error_message text,
11
+ updated_at timestamptz DEFAULT now()
12
+ );
13
+
14
+ -- Use existing set_updated_at() function created in migration 0012
15
+ CREATE TRIGGER handle_updated_at
16
+ BEFORE UPDATE ON "stripe"."_sync_status"
17
+ FOR EACH ROW
18
+ EXECUTE PROCEDURE set_updated_at();
@@ -0,0 +1,91 @@
1
+ -- Add _account_id to _sync_status table to track sync cursors per account
2
+ -- This enables proper cursor isolation when syncing multiple Stripe accounts
3
+ --
4
+ -- Breaking change: All existing cursor data will be deleted (clean slate)
5
+ -- Next sync will perform a full backfill for each account
6
+
7
+ -- Step 1: Delete all existing cursor data
8
+ DELETE FROM "stripe"."_sync_status";
9
+
10
+ -- Step 2: Add _account_id column
11
+ ALTER TABLE "stripe"."_sync_status" ADD COLUMN "_account_id" TEXT NOT NULL;
12
+
13
+ -- Step 3: Drop existing unique constraint on resource
14
+ ALTER TABLE "stripe"."_sync_status" DROP CONSTRAINT IF EXISTS _sync_status_resource_key;
15
+
16
+ -- Step 4: Add new composite unique constraint on (resource, _account_id)
17
+ ALTER TABLE "stripe"."_sync_status"
18
+ ADD CONSTRAINT _sync_status_resource_account_key
19
+ UNIQUE (resource, "_account_id");
20
+
21
+ -- Step 5: Add index for efficient lookups
22
+ CREATE INDEX IF NOT EXISTS idx_sync_status_resource_account
23
+ ON "stripe"."_sync_status" (resource, "_account_id");
24
+
25
+ -- Step 6: Create accounts table to track Stripe accounts (JSONB with generated columns)
26
+ CREATE TABLE IF NOT EXISTS "stripe"."accounts" (
27
+ id TEXT PRIMARY KEY,
28
+ raw_data JSONB NOT NULL,
29
+ first_synced_at TIMESTAMPTZ NOT NULL DEFAULT now(),
30
+ last_synced_at TIMESTAMPTZ NOT NULL DEFAULT now(),
31
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
32
+ -- Generated columns extracted from raw_data
33
+ business_name TEXT GENERATED ALWAYS AS ((raw_data->'business_profile'->>'name')::text) STORED,
34
+ email TEXT GENERATED ALWAYS AS ((raw_data->>'email')::text) STORED,
35
+ type TEXT GENERATED ALWAYS AS ((raw_data->>'type')::text) STORED,
36
+ charges_enabled BOOLEAN GENERATED ALWAYS AS ((raw_data->>'charges_enabled')::boolean) STORED,
37
+ payouts_enabled BOOLEAN GENERATED ALWAYS AS ((raw_data->>'payouts_enabled')::boolean) STORED,
38
+ details_submitted BOOLEAN GENERATED ALWAYS AS ((raw_data->>'details_submitted')::boolean) STORED,
39
+ country TEXT GENERATED ALWAYS AS ((raw_data->>'country')::text) STORED,
40
+ default_currency TEXT GENERATED ALWAYS AS ((raw_data->>'default_currency')::text) STORED,
41
+ created INTEGER GENERATED ALWAYS AS ((raw_data->>'created')::integer) STORED
42
+ );
43
+
44
+ -- Step 7: Add index for account name lookups
45
+ CREATE INDEX IF NOT EXISTS idx_accounts_business_name
46
+ ON "stripe"."accounts" (business_name);
47
+
48
+ -- Step 8: Add updated_at trigger for accounts
49
+ CREATE TRIGGER handle_updated_at
50
+ BEFORE UPDATE ON "stripe"."accounts"
51
+ FOR EACH ROW
52
+ EXECUTE PROCEDURE set_updated_at();
53
+
54
+ -- Step 9: Backfill accounts from existing data tables
55
+ INSERT INTO "stripe"."accounts" (id, raw_data, first_synced_at, last_synced_at)
56
+ SELECT DISTINCT
57
+ "_account_id" as id,
58
+ jsonb_build_object('id', "_account_id", 'type', 'unknown') as raw_data,
59
+ now() as first_synced_at,
60
+ now() as last_synced_at
61
+ FROM "stripe"."products"
62
+ WHERE "_account_id" IS NOT NULL
63
+ ON CONFLICT (id) DO NOTHING;
64
+
65
+ -- Step 10: Add foreign key constraints from data tables to accounts
66
+ ALTER TABLE "stripe"."active_entitlements" ADD CONSTRAINT fk_active_entitlements_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
67
+ ALTER TABLE "stripe"."charges" ADD CONSTRAINT fk_charges_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
68
+ ALTER TABLE "stripe"."checkout_session_line_items" ADD CONSTRAINT fk_checkout_session_line_items_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
69
+ ALTER TABLE "stripe"."checkout_sessions" ADD CONSTRAINT fk_checkout_sessions_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
70
+ ALTER TABLE "stripe"."credit_notes" ADD CONSTRAINT fk_credit_notes_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
71
+ ALTER TABLE "stripe"."customers" ADD CONSTRAINT fk_customers_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
72
+ ALTER TABLE "stripe"."disputes" ADD CONSTRAINT fk_disputes_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
73
+ ALTER TABLE "stripe"."early_fraud_warnings" ADD CONSTRAINT fk_early_fraud_warnings_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
74
+ ALTER TABLE "stripe"."features" ADD CONSTRAINT fk_features_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
75
+ ALTER TABLE "stripe"."invoices" ADD CONSTRAINT fk_invoices_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
76
+ ALTER TABLE "stripe"."_managed_webhooks" ADD CONSTRAINT fk_managed_webhooks_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
77
+ ALTER TABLE "stripe"."payment_intents" ADD CONSTRAINT fk_payment_intents_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
78
+ ALTER TABLE "stripe"."payment_methods" ADD CONSTRAINT fk_payment_methods_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
79
+ ALTER TABLE "stripe"."plans" ADD CONSTRAINT fk_plans_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
80
+ ALTER TABLE "stripe"."prices" ADD CONSTRAINT fk_prices_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
81
+ ALTER TABLE "stripe"."products" ADD CONSTRAINT fk_products_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
82
+ ALTER TABLE "stripe"."refunds" ADD CONSTRAINT fk_refunds_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
83
+ ALTER TABLE "stripe"."reviews" ADD CONSTRAINT fk_reviews_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
84
+ ALTER TABLE "stripe"."setup_intents" ADD CONSTRAINT fk_setup_intents_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
85
+ ALTER TABLE "stripe"."subscription_items" ADD CONSTRAINT fk_subscription_items_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
86
+ ALTER TABLE "stripe"."subscription_schedules" ADD CONSTRAINT fk_subscription_schedules_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
87
+ ALTER TABLE "stripe"."subscriptions" ADD CONSTRAINT fk_subscriptions_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
88
+ ALTER TABLE "stripe"."tax_ids" ADD CONSTRAINT fk_tax_ids_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
89
+
90
+ -- Step 11: Add foreign key from _sync_status to accounts
91
+ ALTER TABLE "stripe"."_sync_status" ADD CONSTRAINT fk_sync_status_account FOREIGN KEY ("_account_id") REFERENCES "stripe"."accounts" (id);
@@ -0,0 +1,12 @@
1
+ -- Add api_key_hashes array column to accounts table
2
+ -- This stores SHA-256 hashes of Stripe API keys for fast account lookups
3
+ -- Enables lookup of account ID by API key hash without making Stripe API calls
4
+ -- Supports multiple API keys per account (test/live keys, rotated keys, etc.)
5
+
6
+ -- Step 1: Add api_key_hashes column as TEXT array
7
+ ALTER TABLE "stripe"."accounts" ADD COLUMN "api_key_hashes" TEXT[] DEFAULT '{}';
8
+
9
+ -- Step 2: Create GIN index for fast array containment lookups
10
+ -- This enables efficient queries like: WHERE 'hash_value' = ANY(api_key_hashes)
11
+ CREATE INDEX IF NOT EXISTS idx_accounts_api_key_hashes
12
+ ON "stripe"."accounts" USING GIN (api_key_hashes);