sendMessage.ts31 lines · main
| 1 | import { brivenError, mutation, type Ctx } from '@briven/cli/server'; |
| 2 | import { ulid } from '@briven/shared'; |
| 3 | |
| 4 | interface Args { |
| 5 | roomId: string; |
| 6 | authorName: string; |
| 7 | body: string; |
| 8 | } |
| 9 | |
| 10 | export default mutation(async (ctx: Ctx, args: Args) => { |
| 11 | if (!args.roomId) |
| 12 | throw new brivenError('validation_failed', 'roomId is required', { status: 400 }); |
| 13 | const author = args.authorName?.trim(); |
| 14 | const body = args.body?.trim(); |
| 15 | if (!author) |
| 16 | throw new brivenError('validation_failed', 'authorName is required', { status: 400 }); |
| 17 | if (!body) throw new brivenError('validation_failed', 'body is required', { status: 400 }); |
| 18 | if (body.length > 2000) |
| 19 | throw new brivenError('validation_failed', 'body too long (max 2000 chars)', { status: 400 }); |
| 20 | |
| 21 | const [room] = await ctx.db('rooms').select(['id']).where({ id: args.roomId }).limit(1); |
| 22 | if (!room) |
| 23 | throw new brivenError('not_found', `no room ${args.roomId}`, { status: 404 }); |
| 24 | |
| 25 | const id = ulid('msg'); |
| 26 | const [row] = await ctx |
| 27 | .db('messages') |
| 28 | .insert({ id, roomId: args.roomId, authorName: author, body }) |
| 29 | .returning(); |
| 30 | return row; |
| 31 | }); |