Fix build issues and update dependencies
🔧 Build Fixes: - Update Node.js version from 18.x to 22.x (required by Vercel) - Remove debug endpoints to get under 12 function limit for Hobby plan - Downgrade React from 19.x to 18.x for better compatibility - Update react-router-dom to v6.28.0 (compatible with Node 22) - Update TypeScript to v5.7.3 - Update React types to match React version Functions count: 12/12 (at limit for Hobby plan) Core API endpoints: ✅ auth/login.js, auth/register.js ✅ collections/index.js, collections/add-card.js ✅ cards/find-or-create.js ✅ admin/users.js, admin/promote-user.js ✅ setup-auth.js, simple.js ✅ Legacy: migrate.ts, v1/cards/[id].ts, v1/cards/index.ts
This commit is contained in:
parent
e4b00ea227
commit
7dc8718512
5 changed files with 7 additions and 245 deletions
18
api/debug.js
18
api/debug.js
|
|
@ -1,18 +0,0 @@
|
||||||
export default function handler(req, res) {
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Debug endpoint - latest version',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
method: req.method,
|
|
||||||
environment: process.env.NODE_ENV || 'unknown',
|
|
||||||
vercel_env: process.env.VERCEL_ENV || 'unknown',
|
|
||||||
has_database_url: !!process.env.DATABASE_URL,
|
|
||||||
has_jwt_secret: !!process.env.JWT_SECRET,
|
|
||||||
database_url_length: process.env.DATABASE_URL ? process.env.DATABASE_URL.length : 0,
|
|
||||||
database_url_starts_with: process.env.DATABASE_URL ?
|
|
||||||
process.env.DATABASE_URL.substring(0, 20) + '...' : 'not set',
|
|
||||||
all_env_keys: Object.keys(process.env).filter(key =>
|
|
||||||
key.includes('DATABASE') || key.includes('JWT') || key.includes('NEON')
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
const { Pool } = require('pg');
|
|
||||||
|
|
||||||
export default async function handler(req, res) {
|
|
||||||
try {
|
|
||||||
const pool = new Pool({
|
|
||||||
connectionString: process.env.DATABASE_URL,
|
|
||||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const client = await pool.connect();
|
|
||||||
|
|
||||||
// Simple promotion - just add user 1 to admin role
|
|
||||||
const result = await client.query(`
|
|
||||||
INSERT INTO user_roles (user_id, role_id)
|
|
||||||
SELECT 1, id FROM roles WHERE name = 'admin'
|
|
||||||
ON CONFLICT DO NOTHING
|
|
||||||
RETURNING *
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Check current roles
|
|
||||||
const userRoles = await client.query(`
|
|
||||||
SELECT
|
|
||||||
u.username,
|
|
||||||
ARRAY_AGG(r.name) as roles
|
|
||||||
FROM users u
|
|
||||||
LEFT JOIN user_roles ur ON u.id = ur.user_id
|
|
||||||
LEFT JOIN roles r ON ur.role_id = r.id
|
|
||||||
WHERE u.id = 1
|
|
||||||
GROUP BY u.username
|
|
||||||
`);
|
|
||||||
|
|
||||||
client.release();
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Admin promotion complete',
|
|
||||||
inserted: result.rows.length > 0,
|
|
||||||
user: userRoles.rows[0] || null,
|
|
||||||
timestamp: new Date().toISOString()
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({
|
|
||||||
success: false,
|
|
||||||
error: error.message,
|
|
||||||
timestamp: new Date().toISOString()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
const { Pool } = require('pg');
|
|
||||||
|
|
||||||
const pool = new Pool({
|
|
||||||
connectionString: process.env.DATABASE_URL,
|
|
||||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default async function handler(req, res) {
|
|
||||||
if (req.method !== 'POST') {
|
|
||||||
return res.status(405).json({ error: 'Method not allowed' });
|
|
||||||
}
|
|
||||||
|
|
||||||
const client = await pool.connect();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Get the test user (ID 1)
|
|
||||||
const userResult = await client.query(
|
|
||||||
'SELECT id, username, email FROM users WHERE id = $1',
|
|
||||||
[1]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (userResult.rows.length === 0) {
|
|
||||||
return res.status(404).json({
|
|
||||||
error: 'Test user not found'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = userResult.rows[0];
|
|
||||||
|
|
||||||
// Check if user is already an admin
|
|
||||||
const adminCheckQuery = `
|
|
||||||
SELECT ur.user_id
|
|
||||||
FROM user_roles ur
|
|
||||||
JOIN roles r ON ur.role_id = r.id
|
|
||||||
WHERE ur.user_id = $1 AND r.name = 'admin'
|
|
||||||
`;
|
|
||||||
|
|
||||||
const adminCheck = await client.query(adminCheckQuery, [user.id]);
|
|
||||||
|
|
||||||
if (adminCheck.rows.length > 0) {
|
|
||||||
return res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'User is already an admin',
|
|
||||||
user: {
|
|
||||||
id: user.id,
|
|
||||||
username: user.username,
|
|
||||||
email: user.email
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get admin role ID
|
|
||||||
const roleResult = await client.query(
|
|
||||||
'SELECT id FROM roles WHERE name = $1',
|
|
||||||
['admin']
|
|
||||||
);
|
|
||||||
|
|
||||||
if (roleResult.rows.length === 0) {
|
|
||||||
return res.status(500).json({
|
|
||||||
error: 'Admin role not found in database'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const adminRoleId = roleResult.rows[0].id;
|
|
||||||
|
|
||||||
// Add user to admin role
|
|
||||||
await client.query(
|
|
||||||
'INSERT INTO user_roles (user_id, role_id) VALUES ($1, $2)',
|
|
||||||
[user.id, adminRoleId]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get updated user info with roles
|
|
||||||
const updatedUserQuery = `
|
|
||||||
SELECT
|
|
||||||
u.id, u.username, u.email, u.first_name, u.last_name,
|
|
||||||
ARRAY_AGG(DISTINCT r.name) as roles
|
|
||||||
FROM users u
|
|
||||||
LEFT JOIN user_roles ur ON u.id = ur.user_id
|
|
||||||
LEFT JOIN roles r ON ur.role_id = r.id
|
|
||||||
WHERE u.id = $1
|
|
||||||
GROUP BY u.id, u.username, u.email, u.first_name, u.last_name
|
|
||||||
`;
|
|
||||||
|
|
||||||
const updatedUser = await client.query(updatedUserQuery, [user.id]);
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Test user successfully promoted to admin',
|
|
||||||
user: {
|
|
||||||
id: updatedUser.rows[0].id,
|
|
||||||
username: updatedUser.rows[0].username,
|
|
||||||
email: updatedUser.rows[0].email,
|
|
||||||
firstName: updatedUser.rows[0].first_name,
|
|
||||||
lastName: updatedUser.rows[0].last_name,
|
|
||||||
roles: updatedUser.rows[0].roles || []
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Promote test user error:', error);
|
|
||||||
res.status(500).json({
|
|
||||||
error: 'Internal server error',
|
|
||||||
details: error.message
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
client.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
const { Pool } = require('pg');
|
|
||||||
|
|
||||||
export default async function handler(req, res) {
|
|
||||||
try {
|
|
||||||
const pool = new Pool({
|
|
||||||
connectionString: process.env.DATABASE_URL,
|
|
||||||
ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const client = await pool.connect();
|
|
||||||
|
|
||||||
// Test basic connection
|
|
||||||
const result = await client.query('SELECT NOW() as current_time');
|
|
||||||
|
|
||||||
// Test if users table exists
|
|
||||||
const tableCheck = await client.query(`
|
|
||||||
SELECT table_name
|
|
||||||
FROM information_schema.tables
|
|
||||||
WHERE table_schema = 'public'
|
|
||||||
AND table_name IN ('users', 'roles', 'user_roles')
|
|
||||||
`);
|
|
||||||
|
|
||||||
// If users table exists, check for test user
|
|
||||||
let userCheck = null;
|
|
||||||
if (tableCheck.rows.some(row => row.table_name === 'users')) {
|
|
||||||
try {
|
|
||||||
userCheck = await client.query(
|
|
||||||
'SELECT id, username, email FROM users WHERE username = $1',
|
|
||||||
['testuser']
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
userCheck = { error: err.message };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.release();
|
|
||||||
|
|
||||||
res.status(200).json({
|
|
||||||
success: true,
|
|
||||||
message: 'Database connection test',
|
|
||||||
timestamp: result.rows[0].current_time,
|
|
||||||
environment: {
|
|
||||||
NODE_ENV: process.env.NODE_ENV,
|
|
||||||
has_database_url: !!process.env.DATABASE_URL,
|
|
||||||
has_jwt_secret: !!process.env.JWT_SECRET
|
|
||||||
},
|
|
||||||
tables: tableCheck.rows.map(row => row.table_name),
|
|
||||||
testUser: userCheck ? {
|
|
||||||
exists: userCheck.rows ? userCheck.rows.length > 0 : false,
|
|
||||||
data: userCheck.rows ? userCheck.rows[0] : null,
|
|
||||||
error: userCheck.error || null
|
|
||||||
} : null
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Database test error:', error);
|
|
||||||
res.status(500).json({
|
|
||||||
success: false,
|
|
||||||
error: error.message,
|
|
||||||
stack: error.stack
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
package.json
14
package.json
|
|
@ -3,7 +3,7 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "18.x"
|
"node": "22.x"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@stackframe/stack": "^2.8.22",
|
"@stackframe/stack": "^2.8.22",
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
"@types/next": "^8.0.7",
|
"@types/next": "^8.0.7",
|
||||||
"@types/node": "^16.18.126",
|
"@types/node": "^16.18.126",
|
||||||
"@types/pg": "^8.15.4",
|
"@types/pg": "^8.15.4",
|
||||||
"@types/react": "^19.1.8",
|
"@types/react": "^18.3.17",
|
||||||
"@types/react-dom": "^19.1.6",
|
"@types/react-dom": "^18.3.5",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@vercel/analytics": "^1.5.0",
|
"@vercel/analytics": "^1.5.0",
|
||||||
"@vercel/blob": "^1.1.1",
|
"@vercel/blob": "^1.1.1",
|
||||||
|
|
@ -29,12 +29,12 @@
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"next": "^15.4.2",
|
"next": "^15.4.2",
|
||||||
"pg": "^8.16.3",
|
"pg": "^8.16.3",
|
||||||
"react": "^19.1.0",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^18.3.1",
|
||||||
"react-router-dom": "^7.7.0",
|
"react-router-dom": "^6.28.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"tesseract.js": "^6.0.1",
|
"tesseract.js": "^6.0.1",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^5.7.3",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue