ecyrbe / zodios

typescript http client and server with zod validation
https://www.zodios.org/
MIT License
1.71k stars 46 forks source link

Spread ZodObject to parameters #339

Closed matannahmani closed 1 year ago

matannahmani commented 1 year ago

Hey, I love the package and I've been trying to make a util function to spread a ZodObject into parameters instead of having to manually write the fields. I was wondering if there is any built-in function for this or if would you mind adding support for it. I tried making my own function but the types aren't being drilled properly, client get's a type error and no Intellisense

Here is my run so far: Here we define the params generator

type paramsType = Parameters<typeof makeParameters>[number][number]['type'];
function genParamsFromZ<O extends z.ZodRawShape, K extends z.UnknownKeysParam>(
  schema: z.ZodObject<O, K>,
  type: paramsType
) {
  const object = schema.shape;
  return Object.keys(object).map(
    (key) =>
      ({
        type,
        name: key,
        schema: object[key],
      } as const)
  );
}

and then on the client:

apiBuilder({
  method: 'get',
  path: path('aptinfo'),
  parameters: genParamsFromZ(getApartmentInfoInputZod, 'Query'),
  errors,
  response: responseZ(getApartmentInfoOutputZod),
  alias: 'group.apt.info',
  description: 'Get Apartment Info',
})
  // .addEndPoint({...})
  .build();
matannahmani commented 1 year ago

After more playing around i managed to almost get it, but the client still doesn't recognize the parameters client: image api builder:

function genParamsFromZ<R extends z.ZodRawShape>(
  schema: z.ZodObject<R, 'strip'>,
  type: 'Query' | 'Body' | 'Header'
) {
  const object = schema.shape;
  const params = Object.keys(object).map((key) => {
    const keyTyped = key as keyof R;
    return {
      type,
      name: keyTyped,
      schema: object[keyTyped],
    };
  });
  return params;
}

export const sesGroupZodiosRouter = apiBuilder({
  method: 'get',
  path: path('aptinfo'),
  parameters: [...genParamsFromZ(getApartmentInfoInputZod, 'Query')],
  errors,
  response: responseZ(getApartmentInfoOutputZod),
  alias: 'group.apt.info',
  description: 'Get Apartment Info',
})
  // .addEndPoint({...})
  .build();

typescript definition on hover: image

ecyrbe commented 1 year ago

sorry i can't provide help to do this. if you need inspiration go check : https://github.com/thelinuxlich/zodios-api-shorthand