diff --git a/src/router.test.ts b/src/router.test.ts index 5261bf5..5c45186 100644 --- a/src/router.test.ts +++ b/src/router.test.ts @@ -942,3 +942,44 @@ test('the client(...) helper', async () => { expect(postResponse.status).toStrictEqual(200); expect(postResponse.data).toStrictEqual({ id: 'some-id' }); }); + +describe('compat router', () => { + test('get + post', async () => { + const { typed: client } = setup((router) => + router.compat + .post( + '/items', + { + name: 'createItem', + request: z.object({ id: z.string() }), + response: z.object({ id: z.string() }), + }, + (ctx) => ({ id: ctx.request.body.id }), + ) + .compat.get( + '/items/:id', + { + name: 'getItemById', + request: z.object({ + filter: z.string(), + }), + response: z.object({ id: z.string() }), + }, + (ctx) => ({ + id: ctx.params.id + ':' + ctx.request.query.filter, + }), + ), + ); + + const res1 = await client.createItem({ id: 'test-id' }); + expect(res1.status).toStrictEqual(200); + expect(res1.data).toStrictEqual({ id: 'test-id' }); + + const res2 = await client.getItemById({ + id: 'test-id', + filter: 'test-filter', + }); + expect(res2.status).toStrictEqual(200); + expect(res2.data).toStrictEqual({ id: 'test-id:test-filter' }); + }); +}); diff --git a/src/router.ts b/src/router.ts index a06af6f..175d111 100644 --- a/src/router.ts +++ b/src/router.ts @@ -47,12 +47,53 @@ export type NamedClientFor = Router extends OneSchemaRouter< ? NamedClient : never; +type MethodMap = { + get: 'GET'; + post: 'POST'; + put: 'PUT'; + patch: 'PATCH'; + delete: 'DELETE'; +}; + +export type CompatRouter = { + [Method in keyof MethodMap]: < + Path extends string, + Name extends string, + Endpoint extends RouterEndpointDefinition, + >( + path: Path, + meta: Endpoint, + ...middlewares: [ + ...OneSchemaRouterMiddleware< + ContextOfEndpoint< + `${MethodMap[Method]} ${Path}`, + z.output, + R + > + >[], + EndpointImplementation< + `${MethodMap[Method]} ${Path}`, + z.output, + z.infer, + R + >, + ] + ) => OneSchemaRouter< + Schema & { + [Route in `${MethodMap[Method]} ${Path}`]: Endpoint; + }, + R + >; +}; + export class OneSchemaRouter< Schema extends ZodSchema, R extends Router, > { private router: R; + public compat: CompatRouter; + private constructor( private schema: Schema, private config: OneSchemaRouterConfig, @@ -66,6 +107,24 @@ export class OneSchemaRouter< router, ); } + + const routerCompat: any = {}; + for (const method of ['get', 'post', 'put', 'patch', 'delete'] as const) { + routerCompat[method] = ( + path: string, + endpoint: any, + ...middlewares: any[] + ) => { + const route = `${method.toUpperCase()} ${path}`; + return this.declare({ ...endpoint, route }).implement( + route, + // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + ...middlewares, + ); + }; + } + this.compat = routerCompat; } static create>(