2026-08-18 16:21:22 +00:00
|
|
|
import 'localstorage-polyfill'
|
|
|
|
|
|
|
|
|
|
import { PORT } from './env.js'
|
|
|
|
|
import { server } from './server.js'
|
|
|
|
|
import { migrate, getActiveSubscriptions } from './database.js'
|
|
|
|
|
import { registerSubscription } from './worker/index.js'
|
|
|
|
|
|
|
|
|
|
process.on('unhandledRejection', (error: Error) => {
|
|
|
|
|
console.error('Unhandled rejection:', error.stack)
|
2026-09-18 14:39:04 +00:00
|
|
|
// Do not process.exit(1) — an async rejection from a library's internal
|
|
|
|
|
// timer (e.g. @welshman/net's batcher) would let an attacker crash the
|
|
|
|
|
// entire server with a single malformed request. Log and continue.
|
2026-08-18 16:21:22 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
process.on('uncaughtException', (error: Error) => {
|
|
|
|
|
console.error('Uncaught exception:', error.stack)
|
|
|
|
|
process.exit(1)
|
|
|
|
|
})
|
|
|
|
|
|
2026-09-18 14:39:04 +00:00
|
|
|
|
2026-08-18 16:21:22 +00:00
|
|
|
migrate().then(async () => {
|
|
|
|
|
server.listen(PORT, () => {
|
|
|
|
|
console.log('Running on port', PORT)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
for (const sub of await getActiveSubscriptions()) {
|
|
|
|
|
registerSubscription(sub)
|
|
|
|
|
}
|
|
|
|
|
})
|