IdoPesok / zsa

https://zsa.vercel.app
MIT License
436 stars 13 forks source link

Schema Functions #120

Closed IdoPesok closed 2 weeks ago

IdoPesok commented 3 weeks ago

Requested by @andresgutgon in #107

Added ability to pass functions that return the input schema

export const inputFunctionAction = ownsPostAction
  .input(async ({ ctx }) => {
    return z.object({
      matchingPostId: z.string().refine((s) => s === ctx.post.id),
    })
  })
  .handler(async ({ input }) => {
    return input.matchingPostId
  })

Also for outputs

export const outputFunctionAction = ownsPostAction
  .output(async ({ ctx }) => {
    return z.object({
      matchingPostId: z
        .string()
        .refine((s) => s === ctx.post.id, "not the same"),
    })
  })
  .handler(async ({ input }) => {
    return {
      matchingPostId: "testUserAuthor",
    }
  })
vercel[bot] commented 3 weeks ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
zsa ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 21, 2024 1:01am
changeset-bot[bot] commented 3 weeks ago

🦋 Changeset detected

Latest commit: 09c5ada8d8f3c1f9b592cae8be087e1ba7ca6f8a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages | Name | Type | | ----------- | ----- | | zsa-openapi | Minor | | zsa | Minor |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

IdoPesok commented 3 weeks ago

Added ability to dynamically generate the input/output schemas from the openapi metadata. @blechatellier I think you may find this interesting. Prob not the safest idea to change validation based on just headers, but maybe a use case can be to parse an API key in the input function then have different schemas for different roles.

export const dynamicSchemasAction = publicAction
  .input(({ request }) =>
    z.object({
      min: z
        .number()
        .min(parseInt(request?.headers.get("x-min-number") || "0")),
      max: z
        .number()
        .max(parseInt(request?.headers.get("x-max-number") || "100")),
    })
  )
  .output(({ request, responseMeta }) =>
    z.object({
      randomNumber: z.number().transform((n) => {
        const min = parseInt(request?.headers.get("x-min-number") || "0")
        const max = parseInt(request?.headers.get("x-max-number") || "100")
        const mid = (min + max) / 2

        if (n > mid) {
          responseMeta?.headers.set("x-test", ">")
        } else {
          responseMeta?.headers.set("x-test", "<")
        }

        return n
      }),
    })
  )
  .handler(({ input }) => {
    const { min, max } = input
    return {
      randomNumber: Math.random() * (max - min) + min,
    }
  })
IdoPesok commented 2 weeks ago

Changed input chains from zod intersections to zod merges