payment-kit 1.27.1 → 1.28.0
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/__blocklet__.js +37 -0
- package/api/ocap-1.30-subpath-shims.d.ts +35 -0
- package/api/src/crons/index.ts +10 -0
- package/api/src/crons/metering-subscription-detection.ts +12 -14
- package/api/src/crons/overdue-detection.ts +51 -74
- package/api/src/integrations/arcblock/nft.ts +6 -2
- package/api/src/integrations/arcblock/stake.ts +3 -2
- package/api/src/integrations/arcblock/token.ts +4 -4
- package/api/src/integrations/blocklet/notification.ts +1 -1
- package/api/src/integrations/ethereum/tx.ts +29 -0
- package/api/src/integrations/stripe/handlers/invoice.ts +70 -53
- package/api/src/integrations/stripe/handlers/payment-intent.ts +8 -1
- package/api/src/integrations/stripe/resource.ts +8 -0
- package/api/src/libs/audit.ts +32 -16
- package/api/src/libs/auth.ts +49 -2
- package/api/src/libs/chain-error.ts +31 -0
- package/api/src/libs/error.ts +15 -0
- package/api/src/libs/event.ts +42 -1
- package/api/src/libs/invoice.ts +69 -34
- package/api/src/libs/notification/template/customer-auto-recharge-daily-limit-exceeded.ts +1 -3
- package/api/src/libs/notification/template/customer-auto-recharge-failed.ts +1 -3
- package/api/src/libs/notification/template/customer-credit-grant-granted.ts +1 -3
- package/api/src/libs/notification/template/customer-credit-insufficient.ts +1 -3
- package/api/src/libs/notification/template/customer-credit-low-balance.ts +1 -3
- package/api/src/libs/notification/template/customer-revenue-succeeded.ts +1 -3
- package/api/src/libs/notification/template/customer-reward-succeeded.ts +1 -3
- package/api/src/libs/notification/template/one-time-payment-refund-succeeded.ts +1 -3
- package/api/src/libs/notification/template/one-time-payment-succeeded.ts +1 -3
- package/api/src/libs/notification/template/subscription-renew-failed.ts +1 -3
- package/api/src/libs/notification/template/subscription-slippage-exceeded.ts +1 -3
- package/api/src/libs/notification/template/subscription-slippage-warning.ts +1 -3
- package/api/src/libs/notification/template/subscription-succeeded.ts +1 -1
- package/api/src/libs/pagination.ts +14 -9
- package/api/src/libs/payment.ts +25 -10
- package/api/src/libs/session.ts +1 -1
- package/api/src/libs/timing.ts +35 -0
- package/api/src/libs/util.ts +16 -15
- package/api/src/libs/wallet-migration.ts +72 -53
- package/api/src/queues/auto-recharge.ts +1 -1
- package/api/src/queues/credit-consume.ts +94 -12
- package/api/src/queues/credit-grant.ts +4 -0
- package/api/src/queues/event.ts +14 -2
- package/api/src/queues/invoice.ts +1 -0
- package/api/src/queues/payment.ts +83 -15
- package/api/src/queues/refund.ts +84 -71
- package/api/src/queues/subscription.ts +1 -0
- package/api/src/routes/checkout-sessions.ts +82 -43
- package/api/src/routes/connect/change-payment.ts +2 -0
- package/api/src/routes/connect/change-plan.ts +2 -0
- package/api/src/routes/connect/pay.ts +12 -3
- package/api/src/routes/connect/setup.ts +3 -1
- package/api/src/routes/connect/shared.ts +52 -39
- package/api/src/routes/connect/subscribe.ts +4 -1
- package/api/src/routes/credit-grants.ts +25 -17
- package/api/src/routes/donations.ts +2 -2
- package/api/src/routes/meter-events.ts +16 -6
- package/api/src/routes/payment-links.ts +1 -1
- package/api/src/routes/payment-methods.ts +1 -1
- package/api/src/routes/settings.ts +1 -1
- package/api/src/routes/tax-rates.ts +1 -1
- package/api/src/store/models/customer.ts +23 -1
- package/api/src/store/models/payment-method.ts +4 -0
- package/api/src/store/models/price.ts +23 -14
- package/api/tests/libs/wallet-migration.spec.ts +4 -4
- package/api/tests/queues/credit-consume-batch.spec.ts +5 -2
- package/api/tests/queues/credit-consume.spec.ts +8 -4
- package/api/tests/routes/credit-grants.spec.ts +1 -0
- package/blocklet.yml +1 -1
- package/cloudflare/MIGRATION-CHALLENGES.md +676 -0
- package/cloudflare/MIGRATION-RUNBOOK.md +777 -0
- package/cloudflare/README.md +499 -0
- package/cloudflare/STAGING-MIGRATION-GUIDE.md +602 -0
- package/cloudflare/build.ts +151 -0
- package/cloudflare/did-connect-auth.ts +527 -0
- package/cloudflare/docs/2026-04-22-sdk-1.30.9-upgrade-retro.md +324 -0
- package/cloudflare/docs/2026-04-24-queue-ops-followup.md +218 -0
- package/cloudflare/docs/cf-queues-ops-alert-analysis.md +663 -0
- package/cloudflare/docs/cf-workers-local-dev-and-fixes.md +284 -0
- package/cloudflare/docs/cleanup-tasks-2026-05.md +62 -0
- package/cloudflare/docs/payment-kit-platform-analysis-2026-04-20.md +354 -0
- package/cloudflare/frontend-shims/buffer-polyfill.ts +9 -0
- package/cloudflare/frontend-shims/js-sdk.ts +43 -0
- package/cloudflare/frontend-shims/mime-types.ts +46 -0
- package/cloudflare/frontend-shims/session.ts +24 -0
- package/cloudflare/frontend-shims/vite-plugin-noop.ts +6 -0
- package/cloudflare/index.html +40 -0
- package/cloudflare/migrate-to-d1.js +252 -0
- package/cloudflare/migrations/0001_initial_schema.sql +82 -0
- package/cloudflare/migrations/0002_indexes.sql +75 -0
- package/cloudflare/migrations/0003_locks_and_constraints.sql +18 -0
- package/cloudflare/run-build.js +390 -0
- package/cloudflare/scripts/test-decrypt.js +102 -0
- package/cloudflare/shims/arcblock-ws.ts +20 -0
- package/cloudflare/shims/axios-http-adapter.ts +4 -0
- package/cloudflare/shims/axios-lite.ts +117 -0
- package/cloudflare/shims/blocklet-sdk/auth-service.ts +33 -0
- package/cloudflare/shims/blocklet-sdk/cdn.ts +3 -0
- package/cloudflare/shims/blocklet-sdk/component-api.ts +35 -0
- package/cloudflare/shims/blocklet-sdk/component.ts +18 -0
- package/cloudflare/shims/blocklet-sdk/config.ts +8 -0
- package/cloudflare/shims/blocklet-sdk/did.ts +14 -0
- package/cloudflare/shims/blocklet-sdk/env.ts +12 -0
- package/cloudflare/shims/blocklet-sdk/eventbus.ts +3 -0
- package/cloudflare/shims/blocklet-sdk/fallback.ts +3 -0
- package/cloudflare/shims/blocklet-sdk/index.ts +11 -0
- package/cloudflare/shims/blocklet-sdk/logger.ts +11 -0
- package/cloudflare/shims/blocklet-sdk/middlewares.ts +15 -0
- package/cloudflare/shims/blocklet-sdk/notification.ts +11 -0
- package/cloudflare/shims/blocklet-sdk/security.ts +53 -0
- package/cloudflare/shims/blocklet-sdk/session.ts +8 -0
- package/cloudflare/shims/blocklet-sdk/verify-sign.ts +38 -0
- package/cloudflare/shims/blocklet-sdk/wallet-authenticator.ts +3 -0
- package/cloudflare/shims/blocklet-sdk/wallet-handler.ts +6 -0
- package/cloudflare/shims/blocklet-sdk/wallet.ts +103 -0
- package/cloudflare/shims/cookie-parser.ts +3 -0
- package/cloudflare/shims/cors.ts +21 -0
- package/cloudflare/shims/cron.ts +189 -0
- package/cloudflare/shims/crypto-js-warn.ts +7 -0
- package/cloudflare/shims/did-space-js.ts +17 -0
- package/cloudflare/shims/did-space.ts +11 -0
- package/cloudflare/shims/error.ts +18 -0
- package/cloudflare/shims/express-compat/index.ts +80 -0
- package/cloudflare/shims/express-compat/types.ts +41 -0
- package/cloudflare/shims/fastq.ts +105 -0
- package/cloudflare/shims/lock.ts +115 -0
- package/cloudflare/shims/mime-types.ts +56 -0
- package/cloudflare/shims/nedb-storage.ts +9 -0
- package/cloudflare/shims/node-child-process.ts +9 -0
- package/cloudflare/shims/node-fs.ts +20 -0
- package/cloudflare/shims/node-http.ts +13 -0
- package/cloudflare/shims/node-https.ts +4 -0
- package/cloudflare/shims/node-misc.ts +15 -0
- package/cloudflare/shims/node-net.ts +8 -0
- package/cloudflare/shims/node-os.ts +14 -0
- package/cloudflare/shims/node-tty.ts +8 -0
- package/cloudflare/shims/node-zlib.ts +17 -0
- package/cloudflare/shims/noop.ts +26 -0
- package/cloudflare/shims/payment-vendor.ts +14 -0
- package/cloudflare/shims/querystring.ts +12 -0
- package/cloudflare/shims/queue.ts +585 -0
- package/cloudflare/shims/rolldown-runtime.ts +43 -0
- package/cloudflare/shims/sequelize-d1/datatypes.ts +24 -0
- package/cloudflare/shims/sequelize-d1/helpers.ts +46 -0
- package/cloudflare/shims/sequelize-d1/index.ts +34 -0
- package/cloudflare/shims/sequelize-d1/model.ts +1157 -0
- package/cloudflare/shims/sequelize-d1/operators.ts +293 -0
- package/cloudflare/shims/sequelize-d1/retry.ts +85 -0
- package/cloudflare/shims/sequelize-d1/sequelize-class.ts +119 -0
- package/cloudflare/shims/sequelize-d1/timing.ts +81 -0
- package/cloudflare/shims/sequelize-d1/types.ts +35 -0
- package/cloudflare/shims/stripe-cf.ts +29 -0
- package/cloudflare/shims/ws-lite.ts +103 -0
- package/cloudflare/shims/xss.ts +3 -0
- package/cloudflare/tests/shims/cron.spec.ts +210 -0
- package/cloudflare/tests/shims/queue-scheduled.spec.ts +186 -0
- package/cloudflare/vite.config.ts +162 -0
- package/cloudflare/worker.ts +1553 -0
- package/cloudflare/wrangler.json +63 -0
- package/cloudflare/wrangler.jsonc +69 -0
- package/cloudflare/wrangler.staging.json +66 -0
- package/cloudflare/wrangler.toml +28 -0
- package/jest.config.js +4 -12
- package/package.json +26 -22
- package/src/app.tsx +62 -4
- package/src/components/customer/link.tsx +9 -13
- package/src/components/customer/notification-preference.tsx +3 -2
- package/src/components/filter-toolbar.tsx +4 -0
- package/src/components/invoice/list.tsx +9 -1
- package/src/components/invoice-pdf/utils.ts +2 -1
- package/src/components/layout/admin.tsx +39 -5
- package/src/components/layout/user-cf.tsx +77 -0
- package/src/components/payment-intent/actions.tsx +23 -3
- package/src/components/safe-did-address.tsx +75 -0
- package/src/libs/patch-user-card.ts +25 -0
- package/src/libs/util.ts +5 -7
- package/src/pages/admin/billing/meter-events/index.tsx +4 -0
- package/src/pages/admin/customers/customers/detail.tsx +2 -2
- package/src/pages/admin/customers/customers/index.tsx +2 -2
- package/src/pages/admin/overview.tsx +3 -1
- package/src/pages/customer/subscription/detail.tsx +4 -4
- package/tsconfig.api.json +1 -6
- package/tsconfig.json +3 -4
- package/tsconfig.types.json +2 -1
- package/vite.config.ts +6 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SQLite → D1 data migration script for Payment Kit
|
|
4
|
+
*
|
|
5
|
+
* Reads from the local blocklet-server SQLite database and generates
|
|
6
|
+
* SQL files that can be imported into D1 via `wrangler d1 execute`.
|
|
7
|
+
*
|
|
8
|
+
* Uses sqlite3 CLI (no npm dependencies needed).
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* node cloudflare/migrate-to-d1.js [--dry-run] [--table <name>] [--skip-events]
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const { execSync } = require('child_process');
|
|
17
|
+
|
|
18
|
+
// Parse args
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const flags = {
|
|
21
|
+
dryRun: args.includes('--dry-run'),
|
|
22
|
+
skipEvents: args.includes('--skip-events'),
|
|
23
|
+
batchSize: 50,
|
|
24
|
+
tables: [],
|
|
25
|
+
dbPath: path.join(
|
|
26
|
+
process.env.HOME,
|
|
27
|
+
'blocklet-server-data/.blocklet-server/data',
|
|
28
|
+
'zNKuN3XwXN7xq2NsJQjjfwujyqCxx26DhwgV',
|
|
29
|
+
'z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk',
|
|
30
|
+
'payment-kit.db'
|
|
31
|
+
),
|
|
32
|
+
outputDir: path.resolve(__dirname, 'migration-sql'),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < args.length; i++) {
|
|
36
|
+
if (args[i] === '--batch-size' && args[i + 1]) flags.batchSize = parseInt(args[++i], 10);
|
|
37
|
+
if (args[i] === '--table' && args[i + 1]) flags.tables.push(args[++i]);
|
|
38
|
+
if (args[i] === '--db-path' && args[i + 1]) flags.dbPath = args[++i];
|
|
39
|
+
if (args[i] === '--output-dir' && args[i + 1]) flags.outputDir = args[++i];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Tables to skip
|
|
43
|
+
const SKIP_TABLES = ['customers_backup', 'payment_currencies_tmp', 'SequelizeMeta'];
|
|
44
|
+
|
|
45
|
+
function sqlite3(dbPath, query) {
|
|
46
|
+
try {
|
|
47
|
+
return execSync(`sqlite3 "${dbPath}" "${query}"`, {
|
|
48
|
+
encoding: 'utf-8',
|
|
49
|
+
maxBuffer: 100 * 1024 * 1024, // 100MB buffer
|
|
50
|
+
}).trim();
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error(`sqlite3 error: ${err.message}`);
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function sqlite3Json(dbPath, query) {
|
|
58
|
+
try {
|
|
59
|
+
const result = execSync(`sqlite3 -json "${dbPath}" "${query}"`, {
|
|
60
|
+
encoding: 'utf-8',
|
|
61
|
+
maxBuffer: 100 * 1024 * 1024,
|
|
62
|
+
}).trim();
|
|
63
|
+
return result ? JSON.parse(result) : [];
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error(`sqlite3 json error for query: ${query.slice(0, 100)}`);
|
|
66
|
+
console.error(err.message.slice(0, 200));
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function escapeSQL(value) {
|
|
72
|
+
if (value === null || value === undefined) return 'NULL';
|
|
73
|
+
if (typeof value === 'number') return String(value);
|
|
74
|
+
if (typeof value === 'boolean') return value ? '1' : '0';
|
|
75
|
+
const str = String(value).replace(/'/g, "''");
|
|
76
|
+
return `'${str}'`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function main() {
|
|
80
|
+
console.log('=== Payment Kit SQLite → D1 Migration ===');
|
|
81
|
+
console.log(`Source: ${flags.dbPath}`);
|
|
82
|
+
console.log(`Output: ${flags.outputDir}`);
|
|
83
|
+
console.log(`Dry run: ${flags.dryRun}`);
|
|
84
|
+
console.log();
|
|
85
|
+
|
|
86
|
+
if (!fs.existsSync(flags.dbPath)) {
|
|
87
|
+
console.error(`ERROR: Source database not found: ${flags.dbPath}`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Get all tables
|
|
92
|
+
const tablesRaw = sqlite3(flags.dbPath, '.tables');
|
|
93
|
+
const allTables = tablesRaw.split(/\s+/).filter(Boolean).sort();
|
|
94
|
+
|
|
95
|
+
const tables = flags.tables.length > 0
|
|
96
|
+
? flags.tables.filter(t => allTables.includes(t))
|
|
97
|
+
: allTables.filter(t => !SKIP_TABLES.includes(t));
|
|
98
|
+
|
|
99
|
+
if (flags.skipEvents) {
|
|
100
|
+
const idx = tables.indexOf('events');
|
|
101
|
+
if (idx > -1) tables.splice(idx, 1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log(`Tables to migrate: ${tables.length}`);
|
|
105
|
+
console.log();
|
|
106
|
+
|
|
107
|
+
// Create output directory
|
|
108
|
+
fs.mkdirSync(flags.outputDir, { recursive: true });
|
|
109
|
+
|
|
110
|
+
// Phase 1: Generate schema SQL
|
|
111
|
+
const schemaFile = path.join(flags.outputDir, '000-schema.sql');
|
|
112
|
+
const schemaLines = [];
|
|
113
|
+
|
|
114
|
+
for (const table of tables) {
|
|
115
|
+
const createSQL = sqlite3(flags.dbPath,
|
|
116
|
+
`SELECT sql FROM sqlite_master WHERE type='table' AND name='${table}';`
|
|
117
|
+
);
|
|
118
|
+
if (createSQL) {
|
|
119
|
+
const sql = createSQL.replace(
|
|
120
|
+
/CREATE TABLE\s+/i,
|
|
121
|
+
'CREATE TABLE IF NOT EXISTS '
|
|
122
|
+
);
|
|
123
|
+
schemaLines.push(sql + ';');
|
|
124
|
+
schemaLines.push('');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Indexes
|
|
129
|
+
const indexSQL = sqlite3(flags.dbPath,
|
|
130
|
+
"SELECT sql FROM sqlite_master WHERE type='index' AND sql IS NOT NULL ORDER BY name;"
|
|
131
|
+
);
|
|
132
|
+
if (indexSQL) {
|
|
133
|
+
schemaLines.push('-- Indexes');
|
|
134
|
+
for (const line of indexSQL.split('\n').filter(Boolean)) {
|
|
135
|
+
const sql = line
|
|
136
|
+
.replace(/CREATE INDEX\s+/i, 'CREATE INDEX IF NOT EXISTS ')
|
|
137
|
+
.replace(/CREATE UNIQUE INDEX\s+/i, 'CREATE UNIQUE INDEX IF NOT EXISTS ');
|
|
138
|
+
schemaLines.push(sql + ';');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
fs.writeFileSync(schemaFile, schemaLines.join('\n'));
|
|
143
|
+
console.log(`Schema written: ${schemaFile}`);
|
|
144
|
+
|
|
145
|
+
// Phase 2: Generate data SQL files per table
|
|
146
|
+
let totalRows = 0;
|
|
147
|
+
let fileIndex = 1;
|
|
148
|
+
|
|
149
|
+
for (const table of tables) {
|
|
150
|
+
const countStr = sqlite3(flags.dbPath, `SELECT COUNT(*) FROM "${table}";`);
|
|
151
|
+
const count = parseInt(countStr, 10) || 0;
|
|
152
|
+
|
|
153
|
+
if (count === 0) {
|
|
154
|
+
console.log(` ${table}: 0 rows (skip)`);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log(` ${table}: ${count} rows — exporting...`);
|
|
159
|
+
|
|
160
|
+
// Get column names
|
|
161
|
+
const colInfoRaw = sqlite3(flags.dbPath, `PRAGMA table_info("${table}");`);
|
|
162
|
+
const colNames = colInfoRaw.split('\n').filter(Boolean).map(line => {
|
|
163
|
+
const parts = line.split('|');
|
|
164
|
+
return parts[1]; // column name is the second field
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Export in pages to avoid memory issues
|
|
168
|
+
const pageSize = 500;
|
|
169
|
+
let offset = 0;
|
|
170
|
+
let partIndex = 0;
|
|
171
|
+
const paddedIdx = String(fileIndex).padStart(3, '0');
|
|
172
|
+
|
|
173
|
+
while (offset < count) {
|
|
174
|
+
const rows = sqlite3Json(flags.dbPath,
|
|
175
|
+
`SELECT * FROM "${table}" LIMIT ${pageSize} OFFSET ${offset};`
|
|
176
|
+
);
|
|
177
|
+
if (!rows || rows.length === 0) break;
|
|
178
|
+
|
|
179
|
+
const sqlLines = [];
|
|
180
|
+
sqlLines.push(`-- Table: ${table} (rows ${offset + 1}-${offset + rows.length} of ${count})`);
|
|
181
|
+
|
|
182
|
+
// Generate INSERT statements in batches
|
|
183
|
+
for (let i = 0; i < rows.length; i += flags.batchSize) {
|
|
184
|
+
const batch = rows.slice(i, i + flags.batchSize);
|
|
185
|
+
const values = batch.map(row => {
|
|
186
|
+
const vals = colNames.map(col => escapeSQL(row[col]));
|
|
187
|
+
return `(${vals.join(', ')})`;
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
sqlLines.push(
|
|
191
|
+
`INSERT OR IGNORE INTO "${table}" (${colNames.map(c => `"${c}"`).join(', ')}) VALUES`
|
|
192
|
+
);
|
|
193
|
+
sqlLines.push(values.join(',\n') + ';');
|
|
194
|
+
sqlLines.push('');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const partSuffix = partIndex > 0 ? `-part${partIndex}` : '';
|
|
198
|
+
const dataFile = path.join(flags.outputDir, `${paddedIdx}-${table}${partSuffix}.sql`);
|
|
199
|
+
fs.writeFileSync(dataFile, sqlLines.join('\n'));
|
|
200
|
+
|
|
201
|
+
partIndex++;
|
|
202
|
+
offset += rows.length;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
totalRows += count;
|
|
206
|
+
fileIndex++;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
console.log();
|
|
210
|
+
console.log(`Total: ${totalRows} rows across ${tables.length} tables`);
|
|
211
|
+
console.log(`SQL files generated in: ${flags.outputDir}`);
|
|
212
|
+
|
|
213
|
+
if (flags.dryRun) {
|
|
214
|
+
console.log('\nDry run — skipping D1 import.');
|
|
215
|
+
console.log('To import, run:');
|
|
216
|
+
console.log(` for f in ${flags.outputDir}/*.sql; do`);
|
|
217
|
+
console.log(' echo "Importing $f..."');
|
|
218
|
+
console.log(` npx wrangler d1 execute payment-kit-dev --local --file="$f" --config=cloudflare/wrangler.jsonc`);
|
|
219
|
+
console.log(' done');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Phase 3: Execute SQL files against D1
|
|
224
|
+
console.log('\n=== Importing into D1 ===');
|
|
225
|
+
const sqlFiles = fs.readdirSync(flags.outputDir)
|
|
226
|
+
.filter(f => f.endsWith('.sql'))
|
|
227
|
+
.sort();
|
|
228
|
+
|
|
229
|
+
const cwd = path.resolve(__dirname, '..');
|
|
230
|
+
for (const file of sqlFiles) {
|
|
231
|
+
const filePath = path.join(flags.outputDir, file);
|
|
232
|
+
const stat = fs.statSync(filePath);
|
|
233
|
+
const sizeMB = (stat.size / 1024 / 1024).toFixed(2);
|
|
234
|
+
|
|
235
|
+
process.stdout.write(` ${file} (${sizeMB}MB)... `);
|
|
236
|
+
try {
|
|
237
|
+
execSync(
|
|
238
|
+
`npx wrangler d1 execute payment-kit-dev --local --file="${filePath}" --config=cloudflare/wrangler.jsonc`,
|
|
239
|
+
{ cwd, stdio: 'pipe', timeout: 120000 }
|
|
240
|
+
);
|
|
241
|
+
console.log('OK');
|
|
242
|
+
} catch (err) {
|
|
243
|
+
const errMsg = err.stderr?.toString()?.slice(0, 300) || err.message;
|
|
244
|
+
console.log('FAILED');
|
|
245
|
+
console.error(` ${errMsg}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
console.log('\nMigration complete!');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
main();
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
-- Payment Kit: Complete D1 schema
|
|
2
|
+
-- All statements use IF NOT EXISTS for idempotency.
|
|
3
|
+
|
|
4
|
+
CREATE TABLE IF NOT EXISTS `archive_locks` (`id` VARCHAR(40) NOT NULL PRIMARY KEY, `locked_by` VARCHAR(64), `locked_at` INTEGER, `expires_at` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS `archive_metadata` (`id` VARCHAR(40) NOT NULL PRIMARY KEY, `archive_file` VARCHAR(128) NOT NULL, `date_range_start` INTEGER NOT NULL, `date_range_end` INTEGER NOT NULL, `tables` JSON NOT NULL DEFAULT '{}', `total_records` INTEGER NOT NULL DEFAULT 0, `checksum` VARCHAR(128), `file_size` INTEGER, `duration_ms` INTEGER, `triggered_by` TEXT NOT NULL, `triggered_by_user_id` VARCHAR(64), `status` TEXT NOT NULL, `error` TEXT, `query_count` INTEGER NOT NULL DEFAULT 0, `query_actor_ids` JSON DEFAULT '[]', `last_queried_at` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS `auto_recharge_configs` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `customer_id` VARCHAR(18) NOT NULL REFERENCES `customers` (`id`), `livemode` TINYINT(1) NOT NULL, `enabled` TINYINT(1) NOT NULL DEFAULT 0, `threshold` VARCHAR(32) NOT NULL, `payment_method_id` VARCHAR(15), `currency_id` VARCHAR(15) NOT NULL, `recharge_currency_id` VARCHAR(15), `price_id` VARCHAR(32) NOT NULL, `quantity` INTEGER NOT NULL DEFAULT 1, `payment_settings` JSON DEFAULT '{"payment_method_types":[],"payment_method_options":{}}', `payment_details` JSON, `daily_limits` JSON DEFAULT '{"max_attempts":0,"max_amount":"0"}', `last_recharge_date` VARCHAR(10), `daily_stats` JSON NOT NULL DEFAULT '{"attempt_count":0,"total_amount":"0"}', `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `slippage_config` JSON);
|
|
9
|
+
|
|
10
|
+
CREATE TABLE IF NOT EXISTS `checkout_sessions` (`id` VARCHAR(64) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `client_reference_id` VARCHAR(128), `currency_id` VARCHAR(15) NOT NULL, `invoice_id` VARCHAR(30), `customer_id` VARCHAR(30), `customer_did` VARCHAR(40), `payment_link_id` VARCHAR(30), `subscription_id` VARCHAR(30), `recovered_from` VARCHAR(30), `payment_intent_id` VARCHAR(30), `mode` TEXT NOT NULL, `status` TEXT NOT NULL, `payment_status` TEXT NOT NULL, `line_items` JSON NOT NULL, `amount_subtotal` VARCHAR(32) NOT NULL, `amount_total` VARCHAR(32) NOT NULL, `total_details` JSON NOT NULL, `url` VARCHAR(512), `cancel_url` VARCHAR(512), `success_url` VARCHAR(512), `currency_conversion` JSON, `after_expiration` JSON, `allow_promotion_codes` TINYINT(1) DEFAULT 0, `consent_collection` JSON, `consent` JSON, `custom_fields` JSON DEFAULT '[]', `custom_text` JSON, `customer_creation` TEXT NOT NULL, `customer_update` JSON DEFAULT '{"address":"never","name":"never","shipping":"never"}', `expires_at` INTEGER, `invoice_creation` JSON, `payment_method_types` JSON DEFAULT '[]', `phone_number_collection` JSON, `billing_address_collection` TEXT NOT NULL DEFAULT 'auto', `submit_type` TEXT NOT NULL, `subscription_data` JSON, `payment_details` JSON, `metadata` JSON, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `nft_mint_settings` JSON, `payment_intent_data` JSON, `nft_mint_details` JSON, `nft_mint_status` TEXT NOT NULL DEFAULT 'disabled', `cross_sell_behavior` TEXT DEFAULT 'auto', `setup_intent_id` VARCHAR(30), `enable_subscription_grouping` TINYINT(1) DEFAULT 0, `subscription_groups` JSON, `success_subscription_count` INTEGER DEFAULT 0, "discounts" JSON, `fulfillment_status` VARCHAR(255), `vendor_info` JSON, `slippage_percent` DECIMAL(5,2) NOT NULL DEFAULT 0.5);
|
|
11
|
+
|
|
12
|
+
CREATE TABLE IF NOT EXISTS `coupons` (`id` VARCHAR(15) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `amount_off` VARCHAR(32) DEFAULT '0', `percent_off` INTEGER DEFAULT '0', `currency_id` VARCHAR(15) NOT NULL, `duration` TEXT, `duration_in_months` INTEGER NOT NULL, `name` VARCHAR(64) NOT NULL, `applies_to` JSON, `currency_options` JSON DEFAULT '{}', `max_redemptions` INTEGER, `times_redeemed` INTEGER DEFAULT '0', `valid` TINYINT(1) DEFAULT 0, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `created_via` TEXT, `locked` TINYINT(1) NOT NULL DEFAULT 0, `redeem_by` INTEGER, `redeem_by_new` INTEGER, `description` TEXT);
|
|
13
|
+
|
|
14
|
+
CREATE TABLE IF NOT EXISTS `credit_grants` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `object` VARCHAR(32) NOT NULL DEFAULT 'credit_grant', `amount` VARCHAR(32) NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `applicability_config` JSON, `category` TEXT NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `effective_at` INTEGER, `expires_at` INTEGER, `livemode` TINYINT(1) NOT NULL, `metadata` JSON, `name` VARCHAR(255), `priority` INTEGER NOT NULL DEFAULT 50, `test_clock` VARCHAR(32), `voided_at` INTEGER, `status` TEXT NOT NULL DEFAULT 'granted', `remaining_amount` VARCHAR(32) NOT NULL, `created_by` VARCHAR(40), `updated_by` VARCHAR(40), `created_via` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `chain_status` TEXT, `chain_detail` JSON);
|
|
15
|
+
|
|
16
|
+
CREATE TABLE IF NOT EXISTS `credit_transactions` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `quantity` VARCHAR(32) NOT NULL, `credit_amount` VARCHAR(32) NOT NULL, `remaining_balance` VARCHAR(32) NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `credit_grant_id` VARCHAR(18) NOT NULL, `meter_id` VARCHAR(18), `subscription_id` VARCHAR(18), `source` VARCHAR(255), `meter_event_name` VARCHAR(128) NOT NULL, `meter_unit` VARCHAR(32) NOT NULL, `description` TEXT, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `transfer_status` TEXT, `transfer_hash` VARCHAR(255));
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS `customers` (`id` VARCHAR(18) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `did` VARCHAR(40) NOT NULL, `address` JSON, `description` VARCHAR(512), `name` VARCHAR(64), `email` VARCHAR(128), `phone` VARCHAR(32), `shipping` JSON, `balance` VARCHAR(32) DEFAULT '0', `currency_id` VARCHAR(15), `delinquent` TINYINT(1) NOT NULL, `discount_id` VARCHAR(32), `metadata` JSON, `invoice_credit_balance` JSON, `invoice_prefix` VARCHAR(30), `invoice_settings` JSON, `next_invoice_sequence` NUMBER DEFAULT '1', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `token_balance` JSON DEFAULT '"{}"', `last_sync_at` INTEGER, `preference` JSON DEFAULT '"{\"notification\":{\"frequency\":\"monthly\",\"schedule\":{\"time\":\"10:00\",\"date\":1}}}"');
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS `discounts` (`id` VARCHAR(15) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `coupon_id` VARCHAR(30) NOT NULL, `customer_id` VARCHAR(30) NOT NULL, `promotion_code_id` VARCHAR(30), `subscription_id` VARCHAR(30), `checkout_session_id` VARCHAR(30), `invoice_id` VARCHAR(30), `invoice_item_id` VARCHAR(30), `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `verification_method` VARCHAR(50), `verification_data` JSON, `start` INTEGER NOT NULL, `end` INTEGER, `confirmed` TINYINT(1) NOT NULL DEFAULT 1);
|
|
21
|
+
|
|
22
|
+
CREATE TABLE IF NOT EXISTS `events` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `type` VARCHAR(128) NOT NULL, `object_type` VARCHAR(64) NOT NULL, `object_id` VARCHAR(64) NOT NULL, `data` JSON NOT NULL, `request` JSON, `pending_webhooks` INTEGER NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
23
|
+
|
|
24
|
+
CREATE TABLE IF NOT EXISTS `exchange_rate_providers` (`id` VARCHAR(32) NOT NULL PRIMARY KEY, `name` VARCHAR(64) NOT NULL UNIQUE, `enabled` TINYINT(1) NOT NULL DEFAULT 1, `priority` INTEGER NOT NULL DEFAULT 1, `status` TEXT NOT NULL DEFAULT 'active', `paused_reason` VARCHAR(512), `config` JSON, `last_success_at` DATETIME, `last_failure_at` DATETIME, `failure_count` INTEGER NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `type` VARCHAR(32) NOT NULL DEFAULT 'token-data');
|
|
25
|
+
|
|
26
|
+
CREATE TABLE IF NOT EXISTS `invoice_items` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `amount` VARCHAR(32) NOT NULL, `quantity` INTEGER NOT NULL, `description` VARCHAR(256) NOT NULL, `period` JSON, `customer_id` VARCHAR(18) NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `price_id` VARCHAR(30) NOT NULL, `invoice_id` VARCHAR(30) NOT NULL, `subscription_id` VARCHAR(30), `subscription_item_id` VARCHAR(30), `discountable` TINYINT(1) NOT NULL, `discount_amounts` JSON DEFAULT '[]', `discounts` JSON DEFAULT '[]', `proration` TINYINT(1) DEFAULT 0, `proration_details` JSON, `metadata` JSON DEFAULT '{}', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `tax_rate_id` VARCHAR(30));
|
|
27
|
+
|
|
28
|
+
CREATE TABLE IF NOT EXISTS `invoices` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `auto_advance` TINYINT(1) NOT NULL, `account_country` VARCHAR(64), `account_name` VARCHAR(64), `charge_id` VARCHAR(30), `collection_method` TEXT NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `description` VARCHAR(512), `hosted_invoice_url` VARCHAR(512), `payment_intent_id` VARCHAR(30), `period_end` INTEGER DEFAULT 0, `period_start` INTEGER DEFAULT 0, `status` TEXT NOT NULL, `checkout_session_id` VARCHAR(64), `subscription_id` VARCHAR(30), `subscription_details` JSON DEFAULT '{}', `subscription_proration_date` INTEGER, `total` VARCHAR(32) NOT NULL, `subtotal` VARCHAR(32) NOT NULL, `subtotal_excluding_tax` VARCHAR(32) NOT NULL, `tax` VARCHAR(32) DEFAULT '0', `amount_due` VARCHAR(32) NOT NULL, `amount_paid` VARCHAR(32) DEFAULT '0', `amount_remaining` VARCHAR(32) NOT NULL, `amount_shipping` VARCHAR(32) DEFAULT '0', `attempt_count` INTEGER DEFAULT 0, `attempted` TINYINT(1) DEFAULT 0, `next_payment_attempt` INTEGER, `billing_reason` TEXT, `custom_fields` JSON DEFAULT '[]', `customer_address` JSON, `customer_name` VARCHAR(64), `customer_email` VARCHAR(128), `customer_phone` VARCHAR(32), `customer_shipping` JSON, `default_payment_method_id` VARCHAR(30), `discounts` JSON DEFAULT '[]', `due_date` INTEGER, `effective_at` INTEGER, `ending_balance` VARCHAR(32) DEFAULT '0', `footer` VARCHAR(512), `from_invoice_id` VARCHAR(30), `invoice_pdf` VARCHAR(512), `last_finalization_error` JSON, `latest_revision` VARCHAR(30), `number` VARCHAR(64), `paid` TINYINT(1) DEFAULT 0, `paid_out_of_band` TINYINT(1) DEFAULT 0, `payment_settings` JSON, `post_payment_credit_notes_amount` VARCHAR(32) DEFAULT '0', `pre_payment_credit_notes_amount` VARCHAR(32) DEFAULT '0', `quote_id` VARCHAR(30), `receipt_number` VARCHAR(64), `days_until_due` NUMBER, `rendering_options` JSON, `starting_balance` VARCHAR(32) DEFAULT '0', `statement_descriptor` VARCHAR(64), `status_transitions` JSON DEFAULT '{}', `test_clock_id` VARCHAR(30), `threshold_reason` JSON, `total_discount_amounts` JSON DEFAULT '[]', `webhooks_delivered_at` INTEGER, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `starting_token_balance` JSON DEFAULT '"{}"', `ending_token_balance` JSON DEFAULT '"{}"');
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS `jobs` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `queue` VARCHAR(32) NOT NULL, `job` JSON NOT NULL, `retry_count` INTEGER DEFAULT 0, `delay` INTEGER DEFAULT -1, `will_run_at` INTEGER DEFAULT -1, `cancelled` TINYINT(1) DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
31
|
+
|
|
32
|
+
CREATE TABLE IF NOT EXISTS `locks` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `lock_at` INTEGER DEFAULT 0, `release_at` INTEGER DEFAULT -1, `reason` VARCHAR(255), `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
33
|
+
|
|
34
|
+
CREATE TABLE IF NOT EXISTS `meter_events` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `event_name` VARCHAR(128) NOT NULL, `timestamp` INTEGER NOT NULL, `payload` JSON NOT NULL, `identifier` VARCHAR(255) NOT NULL UNIQUE, `livemode` TINYINT(1) NOT NULL, `status` TEXT NOT NULL DEFAULT 'pending', `attempt_count` INTEGER NOT NULL DEFAULT 0, `next_attempt` INTEGER, `processed_at` INTEGER, `credit_consumed` VARCHAR(40) NOT NULL DEFAULT '0', `credit_pending` VARCHAR(40) NOT NULL DEFAULT '0', `metadata` JSON, `created_by` VARCHAR(40), `created_via` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `source_data` JSON);
|
|
35
|
+
|
|
36
|
+
CREATE TABLE IF NOT EXISTS `meters` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `object` VARCHAR(32) NOT NULL DEFAULT 'meter', `name` VARCHAR(255) NOT NULL, `event_name` VARCHAR(128) NOT NULL UNIQUE, `aggregation_method` TEXT NOT NULL DEFAULT 'sum', `status` TEXT NOT NULL DEFAULT 'active', `unit` VARCHAR(32) NOT NULL, `description` TEXT, `component_did` VARCHAR(40), `currency_id` VARCHAR(40), `livemode` TINYINT(1) NOT NULL, `metadata` JSON, `created_by` VARCHAR(40), `updated_by` VARCHAR(40), `created_via` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
37
|
+
|
|
38
|
+
CREATE TABLE IF NOT EXISTS `payment_currencies` (`id` VARCHAR(15) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `is_base_currency` TINYINT(1) DEFAULT 0, `payment_method_id` VARCHAR(30) NOT NULL, `name` VARCHAR(64) NOT NULL, `description` VARCHAR(512), `logo` VARCHAR(512) NOT NULL, `symbol` VARCHAR(16) NOT NULL, `decimal` NUMBER DEFAULT 2, `maximum_precision` NUMBER DEFAULT 6, `minimum_payment_amount` VARCHAR(32) DEFAULT '0', `maximum_payment_amount` VARCHAR(32) DEFAULT '0', `contract` VARCHAR(256), `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `vault_config` JSON, `type` TEXT NOT NULL DEFAULT 'standard', `recharge_config` JSON, `token_config` JSON);
|
|
39
|
+
|
|
40
|
+
CREATE TABLE IF NOT EXISTS `payment_intents` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `amount` VARCHAR(32) NOT NULL, `amount_received` VARCHAR(32), `amount_capturable` VARCHAR(32), `amount_details` JSON, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `description` VARCHAR(512), `last_payment_error` JSON, `last_charge` VARCHAR(30), `metadata` JSON, `invoice_id` VARCHAR(30), `payment_method_id` VARCHAR(30) NOT NULL, `receipt_email` VARCHAR(255), `statement_descriptor` VARCHAR(32), `statement_descriptor_suffix` VARCHAR(32), `status` TEXT NOT NULL, `canceled_at` DATETIME, `cancellation_reason` TEXT, `capture_method` TEXT NOT NULL, `confirmation_method` TEXT NOT NULL, `payment_method_types` JSON DEFAULT '[]', `review` VARCHAR(30), `payment_details` JSON, `setup_future_usage` TEXT, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `beneficiaries` JSON, `quote_locked_at` DATETIME);
|
|
41
|
+
|
|
42
|
+
CREATE TABLE IF NOT EXISTS `payment_links` (`id` VARCHAR(40) NOT NULL UNIQUE PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `line_items` JSON DEFAULT '[]', `name` VARCHAR(255), `currency_id` VARCHAR(16), `after_completion` JSON DEFAULT '{"type":"hosted_confirmation"}', `allow_promotion_codes` TINYINT(1) DEFAULT 0, `consent_collection` JSON, `custom_fields` JSON DEFAULT '[]', `custom_text` JSON, `customer_creation` TEXT NOT NULL, `invoice_creation` JSON, `payment_method_types` JSON DEFAULT '[]', `phone_number_collection` JSON, `billing_address_collection` TEXT NOT NULL DEFAULT 'auto', `submit_type` TEXT NOT NULL, `subscription_data` JSON, `metadata` JSON, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `nft_mint_settings` JSON, `cross_sell_behavior` TEXT DEFAULT 'auto', `donation_settings` JSON, `beneficiaries` JSON, `enable_subscription_grouping` TINYINT(1) DEFAULT 0, `lookup_key` VARCHAR(128));
|
|
43
|
+
|
|
44
|
+
CREATE TABLE IF NOT EXISTS `payment_methods` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `type` TEXT, `name` VARCHAR(64), `description` VARCHAR(512), `logo` VARCHAR(512), `default_currency_id` VARCHAR(15), `confirmation` JSON NOT NULL, `settings` JSON NOT NULL, `features` JSON NOT NULL, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
45
|
+
|
|
46
|
+
CREATE TABLE IF NOT EXISTS `payment_stats` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `timestamp` INTEGER DEFAULT 0, `currency_id` VARCHAR(16) NOT NULL, `amount_paid` VARCHAR(64) DEFAULT '0', `amount_payout` VARCHAR(64) DEFAULT '0', `amount_refund` VARCHAR(64) DEFAULT '0', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
47
|
+
|
|
48
|
+
CREATE TABLE IF NOT EXISTS `payouts` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `automatic` TINYINT(1) NOT NULL, `description` VARCHAR(512), `amount` VARCHAR(32) NOT NULL, `destination` VARCHAR(512) NOT NULL, `payment_details` JSON, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `payment_intent_id` VARCHAR(16) NOT NULL, `payment_method_id` VARCHAR(30), `metadata` JSON, `status` TEXT NOT NULL, `failure_message` VARCHAR(256), `failure_code` TEXT, `attempt_count` INTEGER DEFAULT 0, `attempted` TINYINT(1) DEFAULT 0, `next_attempt` INTEGER, `last_attempt_error` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `vendor_info` JSON);
|
|
49
|
+
|
|
50
|
+
CREATE TABLE IF NOT EXISTS `price_quotes` (`id` VARCHAR(32) NOT NULL PRIMARY KEY, `price_id` VARCHAR(32) NOT NULL, `session_id` VARCHAR(32), `invoice_id` VARCHAR(32), `idempotency_key` VARCHAR(128) NOT NULL UNIQUE, `base_currency` VARCHAR(8) NOT NULL DEFAULT 'USD', `base_amount` VARCHAR(32) NOT NULL, `target_currency_id` VARCHAR(16) NOT NULL, `rate_currency_symbol` VARCHAR(16) NOT NULL, `exchange_rate` VARCHAR(32) NOT NULL, `quoted_amount` VARCHAR(64) NOT NULL, `rate_provider_id` VARCHAR(32) NOT NULL, `rate_provider_name` VARCHAR(64) NOT NULL, `rate_timestamp_ms` BIGINT NOT NULL, `expires_at` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'active', `metadata` JSON, `created_at` DATETIME NOT NULL, `slippage_percent` DECIMAL(5,2), `max_payable_token` VARCHAR(64), `min_acceptable_rate` VARCHAR(32), `slippage_derived_at_ms` BIGINT);
|
|
51
|
+
|
|
52
|
+
CREATE TABLE IF NOT EXISTS `prices` (`id` VARCHAR(32) NOT NULL PRIMARY KEY, `product_id` VARCHAR(32) NOT NULL, `nickname` VARCHAR(512), `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `type` TEXT NOT NULL, `billing_scheme` TEXT NOT NULL, `unit_amount` VARCHAR(32) NOT NULL, `recurring` JSON, `tiers_mode` TEXT, `tiers` JSON, `custom_unit_amount` JSON, `lookup_key` VARCHAR(128), `metadata` JSON, `transform_quantity` JSON, `currency_id` VARCHAR(16), `currency_options` JSON DEFAULT '[]', `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `upsell` JSON, `quantity_available` INTEGER NOT NULL DEFAULT 0, `quantity_sold` INTEGER NOT NULL DEFAULT 0, `quantity_limit_per_checkout` INTEGER NOT NULL DEFAULT 0, `tax_behavior` TEXT NOT NULL DEFAULT 'inclusive', `pricing_type` TEXT NOT NULL DEFAULT 'fixed', `base_currency` VARCHAR(8), `base_amount` VARCHAR(32), `dynamic_pricing_config` JSON);
|
|
53
|
+
|
|
54
|
+
CREATE TABLE IF NOT EXISTS `pricing_tables` (`id` VARCHAR(42) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) NOT NULL, `name` VARCHAR(255), `items` JSON DEFAULT '[]', `branding_settings` JSON NOT NULL, `metadata` JSON, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL);
|
|
55
|
+
|
|
56
|
+
CREATE TABLE IF NOT EXISTS `product_vendors` (`id` STRING NOT NULL UNIQUE PRIMARY KEY, `vendor_key` STRING NOT NULL, `name` STRING NOT NULL, `description` TEXT, `app_url` STRING NOT NULL, `app_pid` STRING NOT NULL, `app_logo` STRING, `status` STRING NOT NULL DEFAULT 'active', `metadata` JSON DEFAULT '{}', `created_by` STRING, `created_at` DATE NOT NULL DEFAULT 'CURRENT_TIMESTAMP', `updated_at` DATE NOT NULL DEFAULT 'CURRENT_TIMESTAMP', `vendor_type` STRING NOT NULL DEFAULT 'launcher', `vendor_did` STRING, `extends` JSON);
|
|
57
|
+
|
|
58
|
+
CREATE TABLE IF NOT EXISTS `products` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `type` TEXT, `name` VARCHAR(512), `description` VARCHAR(2048), `images` JSON DEFAULT '[]', `features` JSON DEFAULT '[]', `unit_label` VARCHAR(32), `default_price_id` VARCHAR(32), `metadata` JSON, `statement_descriptor` VARCHAR(32), `nft_factory` VARCHAR(40), `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `cross_sell` JSON, `vendor_config` JSON, `tax_code` VARCHAR(20));
|
|
59
|
+
|
|
60
|
+
CREATE TABLE IF NOT EXISTS `promotion_codes` (`id` VARCHAR(30) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `active` TINYINT(1) DEFAULT 1, `code` VARCHAR(16) NOT NULL, `coupon_id` VARCHAR(30), `max_redemptions` INTEGER, `restrictions` JSON DEFAULT '{}', `customer_id` VARCHAR(30), `times_redeemed` INTEGER DEFAULT '0', `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `verification_type` TEXT NOT NULL DEFAULT 'code', `nft_config` JSON, `vc_config` JSON, `customer_dids` JSON, `created_via` TEXT, `locked` TINYINT(1) NOT NULL DEFAULT 0, `expires_at` INTEGER, `expires_at_new` INTEGER, `description` TEXT);
|
|
61
|
+
|
|
62
|
+
CREATE TABLE IF NOT EXISTS `refunds` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `description` VARCHAR(512), `livemode` TINYINT(1) NOT NULL, `amount` VARCHAR(32) NOT NULL, `payment_details` JSON, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `payment_intent_id` VARCHAR(16) NOT NULL, `invoice_id` VARCHAR(30), `subscription_id` VARCHAR(30), `metadata` JSON, `status` TEXT NOT NULL, `reason` TEXT, `failure_reason` TEXT, `attempt_count` INTEGER DEFAULT 0, `attempted` TINYINT(1) DEFAULT 0, `next_attempt` INTEGER, `last_attempt_error` JSON, `starting_balance` VARCHAR(32) DEFAULT '0', `ending_balance` VARCHAR(32) DEFAULT '0', `starting_token_balance` JSON DEFAULT '{}', `ending_token_balance` JSON DEFAULT '{}', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `payment_method_id` VARCHAR(30), `type` TEXT DEFAULT 'refund');
|
|
63
|
+
|
|
64
|
+
CREATE TABLE IF NOT EXISTS `revenue_snapshots` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `currency_id` VARCHAR(16) NOT NULL, `timestamp` INTEGER NOT NULL, `period_type` TEXT NOT NULL DEFAULT 'monthly', `total_revenue` VARCHAR(64) DEFAULT '0', `refund_amount` VARCHAR(64) DEFAULT '0', `promotion_cost` VARCHAR(64) DEFAULT '0', `credit_grant_cost` VARCHAR(64) DEFAULT '0', `vendor_cost` VARCHAR(64) DEFAULT '0', `taxed_revenue` VARCHAR(64) DEFAULT '0', `net_revenue` VARCHAR(64) DEFAULT '0', `archive_metadata_id` VARCHAR(40), `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
65
|
+
|
|
66
|
+
CREATE TABLE IF NOT EXISTS `settings` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `active` TINYINT(1) NOT NULL DEFAULT 1, `type` VARCHAR(64) NOT NULL, `mount_location` VARCHAR(255) NOT NULL, `component_did` VARCHAR(255), `description` VARCHAR(255) NOT NULL, `settings` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
67
|
+
|
|
68
|
+
CREATE TABLE IF NOT EXISTS `setup_intents` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `description` VARCHAR(512), `last_setup_error` JSON, `last_attempt` VARCHAR(30), `metadata` JSON, `status` TEXT NOT NULL, `usage` TEXT NOT NULL, `canceled_at` INTEGER, `cancellation_reason` TEXT, `flow_directions` JSON DEFAULT '["inbound","outbound"]', `payment_method_types` JSON DEFAULT '[]', `payment_method_options` JSON, `payment_method_id` VARCHAR(30) NOT NULL, `setup_details` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
69
|
+
|
|
70
|
+
CREATE TABLE IF NOT EXISTS `subscription_items` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `subscription_id` VARCHAR(30) NOT NULL, `price_id` VARCHAR(30) NOT NULL, `quantity` INTEGER, `metadata` JSON, `billing_threshold` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
71
|
+
|
|
72
|
+
CREATE TABLE IF NOT EXISTS `subscription_schedules` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `current_phase` JSON NOT NULL, `customer_id` VARCHAR(30) NOT NULL, `subscription_id` VARCHAR(30) NOT NULL, `released_subscription_id` VARCHAR(30), `status` TEXT NOT NULL, `default_settings` JSON, `end_behavior` TEXT NOT NULL, `test_clock_id` VARCHAR(30), `metadata` JSON, `canceled_at` INTEGER, `completed_at` INTEGER, `released_at` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
73
|
+
|
|
74
|
+
CREATE TABLE IF NOT EXISTS `subscriptions` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `cancel_at_period_end` TINYINT(1) NOT NULL, `current_period_end` INTEGER NOT NULL, `current_period_start` INTEGER NOT NULL, `default_payment_method_id` VARCHAR(30), `description` VARCHAR(512), `latest_invoice_id` VARCHAR(30), `pending_setup_intent` VARCHAR(30), `pending_update` JSON, `status` TEXT NOT NULL, `cancel_at` INTEGER, `canceled_at` INTEGER, `cancelation_details` JSON, `billing_cycle_anchor` INTEGER NOT NULL, `billing_thresholds` JSON, `collection_method` TEXT NOT NULL, `days_until_due` NUMBER, `discount_id` VARCHAR(30), `next_pending_invoice_item_invoice_id` VARCHAR(30), `pause_collection` JSON, `payment_settings` JSON, `pending_invoice_item_interval` JSON NOT NULL, `schedule_id` VARCHAR(30), `end_at` INTEGER, `start_date` INTEGER NOT NULL, `payment_details` JSON, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `proration_behavior` TEXT DEFAULT 'none', `payment_behavior` TEXT DEFAULT 'default_incomplete', `days_until_cancel` NUMBER, `service_actions` JSON DEFAULT '"[]"', `trial_start` INTEGER, `trial_end` INTEGER, `trial_settings` JSON, `recovered_from` VARCHAR(40), `overdraft_protection` JSON DEFAULT '"{\"enabled\":false,\"payment_method_id\":null,\"payment_details\":null}"', `credit_schedule_state` JSON DEFAULT NULL, `slippage_config` JSON);
|
|
75
|
+
|
|
76
|
+
CREATE TABLE IF NOT EXISTS `tax_rates` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `active` TINYINT(1) DEFAULT 1, `country` VARCHAR(2) NOT NULL, `state` VARCHAR(50), `postal_code` VARCHAR(20), `tax_code` VARCHAR(20), `percentage` DECIMAL(5,4) NOT NULL, `display_name` VARCHAR(100) NOT NULL, `description` VARCHAR(500), `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
77
|
+
|
|
78
|
+
CREATE TABLE IF NOT EXISTS `usage_records` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `timestamp` INTEGER NOT NULL, `quantity` BIGINT NOT NULL, `subscription_item_id` VARCHAR(30) NOT NULL, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `billed` TINYINT(1) DEFAULT 0);
|
|
79
|
+
|
|
80
|
+
CREATE TABLE IF NOT EXISTS `webhook_attempts` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `event_id` VARCHAR(30) NOT NULL, `webhook_endpoint_id` VARCHAR(30) NOT NULL, `status` TEXT NOT NULL, `response_status` INTEGER NOT NULL, `response_body` JSON NOT NULL, `retry_count` INTEGER DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);
|
|
81
|
+
|
|
82
|
+
CREATE TABLE IF NOT EXISTS `webhook_endpoints` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `api_version` VARCHAR(16) NOT NULL, `url` VARCHAR(512) NOT NULL, `description` VARCHAR(512), `enabled_events` JSON NOT NULL, `metadata` JSON, `status` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
-- Payment Kit: All indexes
|
|
2
|
+
-- Matches the indexes from the original Sequelize migrations.
|
|
3
|
+
|
|
4
|
+
CREATE INDEX IF NOT EXISTS `idx_auto_recharge_configs_currency_id` ON `auto_recharge_configs` (`currency_id`);
|
|
5
|
+
CREATE INDEX IF NOT EXISTS `idx_auto_recharge_configs_customer_id` ON `auto_recharge_configs` (`customer_id`);
|
|
6
|
+
CREATE INDEX IF NOT EXISTS `idx_checkout_sessions_fulfillment_status` ON `checkout_sessions` (`fulfillment_status`);
|
|
7
|
+
CREATE INDEX IF NOT EXISTS `idx_checkout_sessions_payment_intent` ON `checkout_sessions` (`payment_intent_id`);
|
|
8
|
+
CREATE INDEX IF NOT EXISTS `idx_checkout_sessions_payment_link_status_livemode` ON `checkout_sessions` (`payment_link_id`, `status`, `livemode`);
|
|
9
|
+
CREATE INDEX IF NOT EXISTS `idx_checkout_sessions_status` ON `checkout_sessions` (`status`);
|
|
10
|
+
CREATE INDEX IF NOT EXISTS `idx_checkout_sessions_subscription` ON `checkout_sessions` (`subscription_id`);
|
|
11
|
+
CREATE INDEX IF NOT EXISTS idx_credit_grant_stats_by_grantor ON credit_grants(json_extract(metadata, '$.granted_by'), currency_id, created_at) WHERE json_extract(metadata, '$.granted_by') IS NOT NULL;
|
|
12
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_grants_chain_status` ON `credit_grants` (`chain_status`);
|
|
13
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_grants_currency` ON `credit_grants` (`currency_id`);
|
|
14
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_grants_customer` ON `credit_grants` (`customer_id`);
|
|
15
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_grants_customer_currency_status` ON `credit_grants` (`customer_id`, `currency_id`, `status`);
|
|
16
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_grants_status` ON `credit_grants` (`status`);
|
|
17
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_transactions_created` ON `credit_transactions` (`created_at`);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_transactions_customer_created` ON `credit_transactions` (`customer_id`, `created_at`);
|
|
19
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_transactions_event_created` ON `credit_transactions` (`meter_event_name`, `created_at`);
|
|
20
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_transactions_meter_created` ON `credit_transactions` (`meter_id`, `created_at`);
|
|
21
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_transactions_subscription_created` ON `credit_transactions` (`subscription_id`, `created_at`);
|
|
22
|
+
CREATE INDEX IF NOT EXISTS `idx_credit_transactions_transfer_status` ON `credit_transactions` (`transfer_status`);
|
|
23
|
+
CREATE INDEX IF NOT EXISTS `idx_customers_did` ON `customers` (`did`);
|
|
24
|
+
CREATE INDEX IF NOT EXISTS `idx_erp_enabled_priority` ON `exchange_rate_providers` (`enabled`, `priority`);
|
|
25
|
+
CREATE UNIQUE INDEX IF NOT EXISTS `idx_erp_name` ON `exchange_rate_providers` (`name`);
|
|
26
|
+
CREATE INDEX IF NOT EXISTS `idx_events_object_id_created` ON `events` (`object_id`, `created_at`);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS `idx_events_object_type_id_created` ON `events` (`object_type`, `object_id`, `created_at`);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS `idx_events_type_created` ON `events` (`type`, `created_at`);
|
|
29
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_currency_id` ON `invoices` (`currency_id`);
|
|
30
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_customer_id` ON `invoices` (`customer_id`);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_customer_total` ON `invoices` (`customer_id`, `total`);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_items_invoice_id` ON `invoice_items` (`invoice_id`);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_items_tax_rate_id_invoice_id` ON `invoice_items` (`tax_rate_id`, `invoice_id`);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_status_collection` ON `invoices` (`status`, `collection_method`);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_status_total` ON `invoices` (`status`, `total`);
|
|
36
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_subscription_id` ON `invoices` (`subscription_id`);
|
|
37
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_subtotal` ON `invoices` (`subtotal`);
|
|
38
|
+
CREATE INDEX IF NOT EXISTS `idx_invoice_total` ON `invoices` (`total`);
|
|
39
|
+
CREATE INDEX IF NOT EXISTS `idx_invoices_created_at` ON `invoices` (`created_at`);
|
|
40
|
+
CREATE INDEX IF NOT EXISTS `idx_invoices_status` ON `invoices` (`status`);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS `idx_jobs_cancelled_run_at` ON `jobs` (`cancelled`, `will_run_at`);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS `idx_jobs_queue_cancelled_run_at_delay` ON `jobs` (`queue`, `cancelled`, `will_run_at`, `delay`);
|
|
43
|
+
CREATE INDEX IF NOT EXISTS `idx_jobs_queue_id` ON `jobs` (`queue`, `id`);
|
|
44
|
+
CREATE INDEX IF NOT EXISTS `idx_jobs_queue_run_at` ON `jobs` (`queue`, `will_run_at`);
|
|
45
|
+
CREATE INDEX IF NOT EXISTS idx_meter_events_customer_status ON meter_events(json_extract(payload, '$.customer_id'), status, livemode, created_at);
|
|
46
|
+
CREATE INDEX IF NOT EXISTS `idx_meter_events_event_livemode_created` ON `meter_events` (`event_name`, `livemode`, `created_at`);
|
|
47
|
+
CREATE INDEX IF NOT EXISTS `idx_meter_events_livemode_event_timestamp` ON `meter_events` (`livemode`, `event_name`, `timestamp`);
|
|
48
|
+
CREATE INDEX IF NOT EXISTS `idx_meter_events_status_created` ON `meter_events` (`status`, `created_at`);
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_meter_events_subscription_status ON meter_events(json_extract(payload, '$.subscription_id'), status, livemode, created_at);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS `idx_meters_livemode_status` ON `meters` (`livemode`, `status`);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS `idx_payment_currencies_base_livemode` ON `payment_currencies` (`is_base_currency`, `livemode`);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS `idx_payment_intent_currency_id` ON `payment_intents` (`currency_id`);
|
|
53
|
+
CREATE INDEX IF NOT EXISTS `idx_payment_intent_customer_id` ON `payment_intents` (`customer_id`);
|
|
54
|
+
CREATE INDEX IF NOT EXISTS `idx_payment_intent_invoice_id` ON `payment_intents` (`invoice_id`);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS `idx_payment_intent_status_updated_at` ON `payment_intents` (`status`, `updated_at`);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS `idx_payment_stats_timestamp_currency_id` ON `payment_stats` (`timestamp`, `currency_id`);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS `idx_payouts_updated_at_status` ON `payouts` (`updated_at`, `status`);
|
|
58
|
+
CREATE INDEX IF NOT EXISTS `idx_pq_created` ON `price_quotes` (`created_at`);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS `idx_pq_currency_created` ON `price_quotes` (`rate_currency_symbol`, `created_at`);
|
|
60
|
+
CREATE UNIQUE INDEX IF NOT EXISTS `idx_pq_idempotency` ON `price_quotes` (`idempotency_key`);
|
|
61
|
+
CREATE INDEX IF NOT EXISTS `idx_pq_invoice_status` ON `price_quotes` (`invoice_id`, `status`);
|
|
62
|
+
CREATE INDEX IF NOT EXISTS `idx_pq_session_status_expires` ON `price_quotes` (`session_id`, `status`, `expires_at`);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS `idx_refunds_payment_intent_id_type` ON `refunds` (`payment_intent_id`, `type`);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS `idx_refunds_status_type_updated_at` ON `refunds` (`status`, `type`, `updated_at`);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS `idx_refunds_subscription_id_type` ON `refunds` (`subscription_id`, `type`);
|
|
66
|
+
CREATE UNIQUE INDEX IF NOT EXISTS `idx_revenue_snapshots_unique` ON `revenue_snapshots` (`timestamp`, `currency_id`, `livemode`, `period_type`);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS `idx_subscription_item_subscription_id_price_id` ON `subscription_items` (`subscription_id`, `price_id`);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS `idx_subscription_period` ON `subscriptions` (`current_period_start`, `current_period_end`);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS `idx_subscription_status` ON `subscriptions` (`status`);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS `idx_subscriptions_customer_id` ON `subscriptions` (`customer_id`);
|
|
71
|
+
CREATE INDEX IF NOT EXISTS `idx_usage_records_subscription_item_id_timestamp` ON `usage_records` (`subscription_item_id`, `timestamp`);
|
|
72
|
+
CREATE INDEX IF NOT EXISTS `idx_webhook_attempts_event_id` ON `webhook_attempts` (`event_id`);
|
|
73
|
+
CREATE INDEX IF NOT EXISTS `idx_webhook_attempts_webhook_endpoint_id` ON `webhook_attempts` (`webhook_endpoint_id`);
|
|
74
|
+
CREATE INDEX IF NOT EXISTS `idx_webhook_endpoint_status_livemode` ON `webhook_endpoints` (`status`, `livemode`);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS `tax_rates_query_index` ON `tax_rates` (`country`, `state`, `postal_code`, `tax_code`);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Distributed locks table for D1-based locking across CF Worker isolates
|
|
2
|
+
CREATE TABLE IF NOT EXISTS _locks (
|
|
3
|
+
name TEXT PRIMARY KEY,
|
|
4
|
+
owner TEXT NOT NULL,
|
|
5
|
+
expires_at INTEGER NOT NULL
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
-- Unique index on Stripe invoice ID to prevent duplicate mirroring
|
|
9
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_invoices_stripe_id
|
|
10
|
+
ON invoices(json_extract(metadata, '$.stripe_id'))
|
|
11
|
+
WHERE json_extract(metadata, '$.stripe_id') IS NOT NULL;
|
|
12
|
+
|
|
13
|
+
-- DID Connect token storage (D1 for strong consistency instead of KV)
|
|
14
|
+
CREATE TABLE IF NOT EXISTS _did_connect_tokens (
|
|
15
|
+
token TEXT PRIMARY KEY,
|
|
16
|
+
data TEXT NOT NULL,
|
|
17
|
+
expires_at INTEGER NOT NULL
|
|
18
|
+
);
|