turkerdev / fastify-type-provider-zod

MIT License
337 stars 21 forks source link

Error 'schema.safeParse is not a function' throws #37

Closed GangYang-ADL closed 1 year ago

GangYang-ADL commented 1 year ago

Hi there, I found a problem with the schema check:

Background:

app.get(
    '/xsolla/transactions',
    {
      schema: {
        response: {
          200: z.array(Transaction),
        },
      },
    },
    async ({ user }) => {
      const transactions = await app.transactionsCollection.find({ userId: user.id }).toArray()  
      return transactions
    }
  )

if the schema object only has the successful response type in it (no params, no querystring), the code will throw schema.safeParse is not a function.

because the value of schema in the serializerCompiler func is:

{
  schema: {
    type: 'object',
    properties: ZodArray {
      spa: [Function: bound safeParseAsync] AsyncFunction,
      superRefine: [Function: bound _refinement],
      _def: [Object],
      parse: [Function: bound parse],
      safeParse: [Function: bound safeParse],
      parseAsync: [Function: bound parseAsync] AsyncFunction,
      safeParseAsync: [Function: bound safeParseAsync] AsyncFunction,
      refine: [Function: bound refine],
      refinement: [Function: bound refinement],
      optional: [Function: bound optional],
      nullable: [Function: bound nullable],
      nullish: [Function: bound nullish],
      array: [Function: bound array],
      promise: [Function: bound promise],
      or: [Function: bound or],
      and: [Function: bound and],
      transform: [Function: bound transform],
      default: [Function: bound default],
      describe: [Function: bound describe],
      isNullable: [Function: bound isNullable],
      isOptional: [Function: bound isOptional]
    }
  },
  url: '/v1/iap/xsolla/transactions',
  method: 'GET',
  httpStatus: '200'
}

absolutely it will throw error schema.safeParse is not a function because it should be schema.properties.safeParse

BUT, the tricky thing is if I add params: z.any() into the schema before the response,

app.get(
    '/xsolla/transactions',
    {
      schema: {
        params: z.any(),
        response: {
          200: z.array(Transaction),
        },
      },
    },
    async ({ user }) => {
      const transactions = await app.transactionsCollection.find({ userId: user.id }).toArray()  
      return transactions
    }
  )

the schema turns to:

{
  schema: ZodArray {
    spa: [Function: bound safeParseAsync] AsyncFunction,
    superRefine: [Function: bound _refinement],
    _def: {
      type: [ZodObject],
      minLength: null,
      maxLength: null,
      typeName: 'ZodArray'
    },
    parse: [Function: bound parse],
    safeParse: [Function: bound safeParse],
    parseAsync: [Function: bound parseAsync] AsyncFunction,
    safeParseAsync: [Function: bound safeParseAsync] AsyncFunction,
    refine: [Function: bound refine],
    refinement: [Function: bound refinement],
    optional: [Function: bound optional],
    nullable: [Function: bound nullable],
    nullish: [Function: bound nullish],
    array: [Function: bound array],
    promise: [Function: bound promise],
    or: [Function: bound or],
    and: [Function: bound and],
    transform: [Function: bound transform],
    default: [Function: bound default],
    describe: [Function: bound describe],
    isNullable: [Function: bound isNullable],
    isOptional: [Function: bound isOptional]
  },
  url: '/v1/iap/xsolla/transactions',
  method: 'GET',
  httpStatus: '200'
}

which makes the schema.safeParse reachable.

GangYang-ADL commented 1 year ago

it seems like this error was fixed 5 months ago.