Skip to content

Commit

Permalink
try out a new route declaration syntax, aimed at compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
swain committed Oct 31, 2023
1 parent b5f7dc5 commit d3ce293
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
});
});
59 changes: 59 additions & 0 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,53 @@ export type NamedClientFor<Router> = Router extends OneSchemaRouter<
? NamedClient<Schema>
: never;

type MethodMap = {
get: 'GET';
post: 'POST';
put: 'PUT';
patch: 'PATCH';
delete: 'DELETE';
};

export type CompatRouter<Schema extends ZodSchema, R extends Router> = {
[Method in keyof MethodMap]: <
Path extends string,
Name extends string,
Endpoint extends RouterEndpointDefinition<Name>,
>(
path: Path,
meta: Endpoint,
...middlewares: [
...OneSchemaRouterMiddleware<
ContextOfEndpoint<
`${MethodMap[Method]} ${Path}`,
z.output<Endpoint['request']>,
R
>
>[],
EndpointImplementation<
`${MethodMap[Method]} ${Path}`,
z.output<Endpoint['request']>,
z.infer<Endpoint['response']>,
R
>,
]
) => OneSchemaRouter<
Schema & {
[Route in `${MethodMap[Method]} ${Path}`]: Endpoint;
},
R
>;
};

export class OneSchemaRouter<
Schema extends ZodSchema,
R extends Router<any, any>,
> {
private router: R;

public compat: CompatRouter<Schema, R>;

private constructor(
private schema: Schema,
private config: OneSchemaRouterConfig<R>,
Expand All @@ -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<R extends Router<any, any>>(
Expand Down

0 comments on commit d3ce293

Please sign in to comment.