Packaging
- Drop stale `main: dist/index.js` from package.json (no build workflow)
- Move `prisma` to dependencies and add `postinstall: prisma generate`
so a fresh `npm ci` on the server produces a runnable client
- Add `prisma:deploy` script for `prisma migrate deploy`
- Rename src/services/Twilioservice.ts -> TwilioService.ts (case fix;
invisible on macOS APFS, would crash on Linux)
Node version guards
- .nvmrc (22.23.1) so `nvm use` picks the right runtime
- .npmrc `engine-strict=true` so npm respects `engines` on install
- Runtime guard in scripts/navigator-patch.cjs that fails fast with an
actionable message on Node < 22.18 (native .ts stripping requirement)
Twilio error taxonomy (src/lib/twilioErrors.ts)
- `classifyTwilioError(err)` for send-time exceptions, mapping known
Twilio REST codes (20003/20429/20500/21211..21614) plus HTTP-status
and Node errno fallback to `{ kind: retryable|terminal, category }`
- `classifyDeliveryFailure(code)` for the 30xxx delivery-status family
- `sendViaTwilio` persists a `send_error[_retryable]` Message row on
failure and surfaces the classified message to the user
- `/callback` extracts ErrorCode and passes classified failure info to
`deliveryStatusCard`, which renders the code + retry-hint inline
Persistent PendingMessageStore
- New PrismaPendingMessageStore (upsert-based) becomes the default
singleton; InMemoryPendingMessageStore retained for tests
- `startPendingMessageSweeper()` runs hourly, drops entries >24h old,
unref()s its timer, and is disabled under NODE_ENV=test
- Wired into the shutdown handler in src/index.ts
Tests (39 total, up from 13)
- Integration: tests/integration/twilioRoutes.test.ts hits /sms and
/callback through the real createApp() with a stub bot, real Twilio
signatures, plus /healthz
- Unit: twilioErrors.test.ts (14), pendingMessageStore.test.ts (5)
- typecheck clean
Co-authored-by: Cursor <cursoragent@cursor.com>
45 lines
1.3 KiB
JSON
45 lines
1.3 KiB
JSON
{
|
|
"name": "sendi",
|
|
"version": "2.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "node --watch --require ./scripts/navigator-patch.cjs src/index.ts",
|
|
"start": "node --require ./scripts/navigator-patch.cjs src/index.ts",
|
|
"build": "tsc",
|
|
"start:built": "node --require ./scripts/navigator-patch.cjs dist/index.js",
|
|
"typecheck": "tsc --noEmit",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"postinstall": "prisma generate",
|
|
"prisma:generate": "prisma generate",
|
|
"prisma:migrate": "prisma migrate dev",
|
|
"prisma:deploy": "prisma migrate deploy",
|
|
"migrate-old": "node legacy/migrate-old-data.ts"
|
|
},
|
|
"engines": {
|
|
"node": ">=22.18.0"
|
|
},
|
|
"dependencies": {
|
|
"@prisma/adapter-better-sqlite3": "^6.19.3",
|
|
"@prisma/client": "^6.19.3",
|
|
"better-sqlite3": "^12.8.0",
|
|
"dotenv": "^16.4.7",
|
|
"express": "^5.2.1",
|
|
"pino": "^9.6.0",
|
|
"pino-pretty": "^13.1.3",
|
|
"prisma": "^6.19.3",
|
|
"twilio": "^5.13.1",
|
|
"webex-node-bot-framework": "^2.5.1",
|
|
"zod": "^3.24.2"
|
|
},
|
|
"devDependencies": {
|
|
"@types/better-sqlite3": "^7.6.13",
|
|
"@types/express": "^5.0.6",
|
|
"@types/node": "^22.13.10",
|
|
"@types/supertest": "^6.0.2",
|
|
"supertest": "^7.0.0",
|
|
"typescript": "^5.8.2",
|
|
"vitest": "^3.2.6"
|
|
}
|
|
}
|