1
1
import { randomUUID } from 'crypto' ;
2
- import { ErrorRequestHandler , json , Router } from 'express' ;
2
+ import {
3
+ ErrorRequestHandler ,
4
+ json ,
5
+ Router ,
6
+ type RequestHandler ,
7
+ } from 'express' ;
3
8
import { Task } from 'interface' ;
4
9
import pg from 'pg' ;
5
10
import { z } from 'zod' ;
@@ -46,6 +51,16 @@ const unknownErrorHandler: ErrorRequestHandler = (err, req, res, next) => {
46
51
console . error ( err ) ;
47
52
next ( ) ;
48
53
} ;
54
+
55
+ const validate =
56
+ < T extends z . ZodType < unknown > > (
57
+ schema : T ,
58
+ ) : RequestHandler < Record < string , string > , unknown , z . infer < T > > =>
59
+ async ( req , _ , next ) => {
60
+ const validated = await schema . parseAsync ( req . body ) ;
61
+ req . body = validated ;
62
+ return next ( ) ;
63
+ } ;
49
64
export function taskRouter ( client : pg . Pool , router = Router ( ) ) {
50
65
router . use ( json ( ) ) ;
51
66
@@ -85,8 +100,8 @@ export function taskRouter(client: pg.Pool, router = Router()) {
85
100
res . status ( 200 ) . json ( { rowsDeleted : response . rowCount } ) ;
86
101
} ) ;
87
102
88
- router . post ( '/:id' , async ( req , res ) => {
89
- const task = await Task . parseAsync ( req . body ) ;
103
+ router . post ( '/:id' , validate ( Task ) , async ( req , res ) => {
104
+ const task = req . body ;
90
105
const response = await client . query (
91
106
'UPDATE tasks SET name = $1::text, etag = etag + 1 WHERE id = $2::integer AND etag = $3::integer RETURNING etag' ,
92
107
[ task . name , req . params . id , task . etag ] ,
@@ -105,16 +120,20 @@ export function taskRouter(client: pg.Pool, router = Router()) {
105
120
res . status ( 200 ) . json ( returnedTask ) ;
106
121
} ) ;
107
122
108
- router . post ( '/' , async ( req , res ) => {
109
- const task = await Task . omit ( { etag : true , id : true } ) . parseAsync ( req . body ) ;
110
- const result = await client . query (
111
- 'INSERT INTO tasks (name) VALUES ($1::text) RETURNING *' ,
112
- [ task . name ] ,
113
- ) ;
114
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
115
- const response = { ...req . body , ...result . rows [ 0 ] } ;
116
- res . status ( 201 ) . send ( await Task . parseAsync ( response ) ) ;
117
- } ) ;
123
+ router . post (
124
+ '/' ,
125
+ validate ( Task . omit ( { etag : true , id : true } ) ) ,
126
+ async ( req , res ) => {
127
+ const task = req . body ;
128
+ const result = await client . query (
129
+ 'INSERT INTO tasks (name) VALUES ($1::text) RETURNING *' ,
130
+ [ task . name ] ,
131
+ ) ;
132
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
133
+ const response = { ...req . body , ...result . rows [ 0 ] } ;
134
+ res . status ( 201 ) . send ( await Task . parseAsync ( response ) ) ;
135
+ } ,
136
+ ) ;
118
137
119
138
router . get ( '/debug/populate' , async ( req , res ) => {
120
139
const n = req . query . n ;
0 commit comments