ecyrbe / zodios

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

Is it possible to allow pass object schema to `ParametersBuilder#addQueries, #addPaths, #addHeaders`? #413

Closed michael-land closed 1 year ago

michael-land commented 1 year ago

I also want to expose schema and type for parameters, it would be nice we pass pass a object schema to the builder.

for example

export type MyApiHeaderSchema = z.TypeOf<typeof MyApiHeaderSchema>
export const MyApiHeaderSchema = z.object({
  a: z.number().positive(),
});
export type MyApiSearchSchema = z.TypeOf<typeof MyApiSearchSchema>
export const MyApiSearchSchema = z.object({
  b: z.number().positive(),
});
export type MyApiPathSchema = z.TypeOf<typeof MyApiPathSchema>
export const MyApiPathSchema = z.object({
  c: z.number().positive(),
});
export type MyApiBodySchema = z.TypeOf<typeof MyApiBodySchema>
export const MyApiBodySchema = z.object({
  d: z.number().positive(),
});

const params = parametersBuilder()
  .addParameters("Headers", MyApiHeaderSchema)
  .addParameters("Paths", MyApiPathSchema)
  .addParameters("Queries", MyApiSearchSchema)
  .addParameters("Body", MyApiBodySchema)
  .build();
ecyrbe commented 1 year ago

It could but i decided not. Let me explain why.
Each parameter is validated independently, so when using a zod object we actually need to extract the sub schemas for each property. This means knowing that the schema is written with zod. But in upcoming zodios v11, schema will be independant of zod (you'll be able to use io-ts, typescript types, yup, arktype, whatever you want), with no way to extract sub schemas without zodios having a dependancy on every schema library out there (aka not possible) here is an exemple of what will be possible with zodios v11 :

// io-ts validation
const jsonplaceholderApi = makeApi([
  {
    method: "get",
    path: "/users",
    alias: "getUsers",
    description: "Get all users",
    parameters: [
      {
        name: "q",
        description: "full text search",
        type: "Query",
        schema: t.string,
      },
      {
        name: "page",
        description: "page number",
        type: "Query",
        schema: t.union([t.number, t.undefined]),
      },
    ],
    response: usersSchema,
  },
  {
    method: "get",
    path: "/users/:id",
    description: "Get a user",
    response: userSchema,
  },
]);

or with typescript schemas :

// no runtime validation, on ts compile time definition
const jsonplaceholderApi = makeApi([
  {
    method: "get",
    path: "/users",
    description: "Get all users",
    parameters: [
      {
        name: "q",
        description: "full text search",
        type: "Query",
        schema: tsSchema<string>(),
      },
      {
        name: "page",
        description: "page number",
        type: "Query",
        schema: tsSchema<number | undefined>(),
      },
    ],
    response: usersSchema,
  },
  {
    method: "get",
    path: "/users/:id",
    description: "Get a user",
    response: userSchema,
  },
]);

So while it's technically possible to do that for zod only, since zodios v11 will be agnostic to validation library, i decided to not add this feature to parameterBuilder.

However, you can still have an implementation at user level code, see here an exemple on how to do that : https://twitter.com/ecyrbedev/status/1642511317943631875