-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdirect-postgres-migration.js
More file actions
165 lines (142 loc) · 5.54 KB
/
Copy pathdirect-postgres-migration.js
File metadata and controls
165 lines (142 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/env node
/**
* Direct PostgreSQL Migration Script
* Works directly with PostgreSQL without Prisma schema conflicts
*/
const pg = require('pg');
const DATABASE_URL = process.argv[2] || "postgresql://neurodecor_user:586qMnRlWWvWajAzX75qSSr9FASQ02wu@dpg-d2c5ulbuibrs7385h9rg-a.oregon-postgres.render.com/neurodecor";
console.log('🚀 Direct PostgreSQL Migration');
console.log('==============================\n');
async function executeMigration() {
const client = new pg.Client({
connectionString: DATABASE_URL,
ssl: {
rejectUnauthorized: false // Required for Render PostgreSQL
}
});
try {
console.log('📊 Connecting to PostgreSQL database...');
await client.connect();
console.log('✅ Connected successfully!\n');
// Test connection
const versionResult = await client.query('SELECT version()');
console.log('📊 Database version:', versionResult.rows[0].version.split(' ')[1]);
console.log('');
// Check current columns
console.log('🔍 Checking existing columns...');
const checkQuery = `
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'colibrrri_subscriptions'
AND column_name IN ('isRecurring', 'recurringToken', 'recurringMode', 'nextPaymentDate', 'lastPaymentDate', 'failedPaymentAttempts', 'maxFailedAttempts')
`;
const existingColumns = await client.query(checkQuery);
console.log(`Found ${existingColumns.rows.length}/7 recurring payment columns\n`);
if (existingColumns.rows.length === 7) {
console.log('✅ All columns already exist! No migration needed.');
return;
}
// Execute migration
console.log('🚀 Executing migration...');
const migrationSQL = `
ALTER TABLE "colibrrri_subscriptions"
ADD COLUMN IF NOT EXISTS "isRecurring" BOOLEAN DEFAULT false,
ADD COLUMN IF NOT EXISTS "recurringToken" TEXT,
ADD COLUMN IF NOT EXISTS "recurringMode" TEXT,
ADD COLUMN IF NOT EXISTS "nextPaymentDate" TIMESTAMP(3),
ADD COLUMN IF NOT EXISTS "lastPaymentDate" TIMESTAMP(3),
ADD COLUMN IF NOT EXISTS "failedPaymentAttempts" INTEGER DEFAULT 0,
ADD COLUMN IF NOT EXISTS "maxFailedAttempts" INTEGER DEFAULT 3;
`;
await client.query(migrationSQL);
console.log('✅ Migration SQL executed successfully!\n');
// Verify migration
console.log('🔍 Verifying migration...');
const verifyQuery = `
SELECT column_name, data_type, column_default
FROM information_schema.columns
WHERE table_name = 'colibrrri_subscriptions'
AND column_name IN ('isRecurring', 'recurringToken', 'recurringMode', 'nextPaymentDate', 'lastPaymentDate', 'failedPaymentAttempts', 'maxFailedAttempts')
ORDER BY column_name;
`;
const verifyResult = await client.query(verifyQuery);
console.log('✅ Successfully added columns:');
verifyResult.rows.forEach(col => {
console.log(` - ${col.column_name} (${col.data_type})`);
});
// Test query
console.log('\n🔍 Testing with actual query...');
const testQuery = `
SELECT id, plan, status, "isRecurring", "recurringToken", "failedPaymentAttempts"
FROM "colibrrri_subscriptions"
LIMIT 1;
`;
try {
const testResult = await client.query(testQuery);
if (testResult.rows.length > 0) {
console.log('✅ Test query successful!');
console.log('Sample data:', {
plan: testResult.rows[0].plan,
status: testResult.rows[0].status,
isRecurring: testResult.rows[0].isRecurring,
failedPaymentAttempts: testResult.rows[0].failedpaymentattempts
});
} else {
console.log('⚠️ No subscriptions found (empty table)');
}
} catch (e) {
console.log('⚠️ Test query failed:', e.message);
}
console.log('\n' + '='.repeat(50));
console.log('🎉 MIGRATION COMPLETED SUCCESSFULLY!');
console.log('='.repeat(50));
console.log('\n✅ Production database now supports recurring payments');
console.log('✅ The 500 errors should be resolved');
console.log('✅ Payment callbacks will save recToken');
console.log('✅ Automatic renewals are enabled');
} catch (error) {
console.error('\n❌ Migration failed!');
console.error('Error:', error.message);
if (error.message.includes('does not exist')) {
console.error('\n⚠️ Table colibrrri_subscriptions not found.');
console.error('Checking for alternative table names...');
// Try to find the correct table
const tablesQuery = `
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE '%subscription%';
`;
try {
const tables = await client.query(tablesQuery);
if (tables.rows.length > 0) {
console.log('Found subscription tables:', tables.rows.map(t => t.table_name).join(', '));
}
} catch (e) {
console.log('Could not list tables');
}
}
throw error;
} finally {
await client.end();
console.log('\n📊 Database connection closed.');
}
}
// Install pg if not available
const { execSync } = require('child_process');
try {
require.resolve('pg');
} catch(e) {
console.log('📦 Installing pg package...');
execSync('npm install pg', { stdio: 'inherit' });
}
// Run migration
executeMigration()
.then(() => {
console.log('\n✨ Process completed successfully!');
process.exit(0);
})
.catch((error) => {
console.error('\n💥 Fatal error:', error.message);
process.exit(1);
});