Spaces:
Runtime error
Runtime error
File size: 2,453 Bytes
24727a3 c3b49db 24727a3 05cee1f 24727a3 c3b49db 24727a3 05cee1f 24727a3 05cee1f 24727a3 05cee1f 24727a3 05cee1f 24727a3 c3b49db 05cee1f 47e2259 05cee1f c3b49db 47e2259 4a31b63 47e2259 05cee1f 4a31b63 47e2259 4a31b63 e8bface 24727a3 4b59f7c 24727a3 05cee1f 24727a3 05cee1f 24727a3 | 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 | import http from 'http'
import { Server } from 'socket.io'
import { execSync } from 'child_process'
import app from './app.js'
import { config } from './config/index.js'
import { prisma } from './config/database.js'
import { redis, safeRedis } from './config/redis.js'
import { setupChatSocket } from './modules/chat/chat.socket.js'
import { verifySocketToken } from './lib/jwt.js'
import { logger } from './lib/logger.js'
async function bootstrap() {
try { await redis.connect() } catch {}
try {
await redis.ping()
logger.info('Redis connected')
} catch {
logger.warn('Redis unavailable, running without cache')
}
try {
await prisma.$connect()
logger.info('Database connected')
} catch (err) {
logger.fatal(err, 'Database connection failed')
process.exit(1)
}
try {
logger.info('Running database migrations...')
execSync('npx --yes prisma migrate deploy', { stdio: 'inherit', cwd: process.cwd(), timeout: 30000 })
logger.info('Database schema synced')
} catch (err) {
logger.warn({ err: err.message }, 'Migrate deploy failed, trying db push...')
try {
execSync('npx --yes prisma db push --skip-generate', { stdio: 'inherit', cwd: process.cwd(), timeout: 30000 })
logger.info('Database schema synced via push')
} catch (err2) {
logger.warn('Db push also failed, server will start anyway — schema may be out of date')
}
}
const server = http.createServer(app)
const io = new Server(server, {
cors: {
origin: config.FRONTEND_URL,
credentials: true,
},
pingTimeout: 60000,
pingInterval: 25000,
transports: ['websocket', 'polling'],
})
io.use(async (socket, next) => {
const token = socket.handshake.auth.token
if (!token) return next(new Error('Authentication required'))
const decoded = await verifySocketToken(token)
if (!decoded) return next(new Error('Invalid token'))
socket.userId = decoded.sub
socket.userRole = decoded.role
next()
})
setupChatSocket(io)
app.set('io', io)
server.listen(config.PORT, () => {
logger.info({ port: config.PORT, env: config.NODE_ENV }, 'Server started')
})
const shutdown = async () => {
logger.info('Shutting down gracefully...')
io.close()
server.close()
await prisma.$disconnect()
await redis.quit()
process.exit(0)
}
process.on('SIGINT', shutdown)
process.on('SIGTERM', shutdown)
}
bootstrap()
|