TheEdoRan / next-safe-action

Type safe and validated Server Actions in your Next.js project.
https://next-safe-action.dev
MIT License
2.29k stars 35 forks source link

[BUG] Valibot schema.safeParseAsync is not a function #242

Closed pedro757 closed 3 weeks ago

pedro757 commented 2 months ago

Are you using the latest version of this library?

Is there an existing issue for this?

Describe the bug

I get this validation error

schema.safeParseAsync is not a function

for this

action
  .schema(
    object({
      id: number(),
      status: enum_(StatusEnum),
    }),
  )
  .action(async function ({ parsedInput }) {
...

With this input

{
    "id": 4,
    "status": "Draft"
}

Reproduction steps

  1. use latest version of valibot@0.38.0
  2. use latest version of next-safe-action@7.7.1

Expected behavior

Not to error with latest valibot version

Minimal reproduction example

The code is in the description of the issue

Operating System

Linux

Library version

7.7.1

Next.js version

14.2.6

Additional context

No response

TheEdoRan commented 2 months ago

The code is in the description of the issue

Unfortunately this is not a link to a project with a minimal reproduction of the issue. In order to help you, I need to see the code where you create the safe action client, so I can understand what's really happening here, half of the action definition isn't enough to debug this problem. Please provide it as a comment, thanks!

TheEdoRan commented 2 months ago

A quick question: have you set up the safe action client with the correct validation adapter for Valibot as explained in this page of the website?

This might be the only issue.

Heitorh3 commented 1 month ago

I'm trying to implement safe-action but I'm getting the error below.

safe-action.ts ` 'use server'

import { env } from '@proflin/env' import { setupAnalytics } from '@proflin/events/server' import * as Sentry from '@sentry/nextjs' import { headers } from 'next/headers' import { createSafeActionClient, DEFAULT_SERVER_ERROR_MESSAGE, } from 'next-safe-action' import { z } from 'zod'

import { logger } from '@/lib/logger' import { rateLimit } from '@/lib/ratelimit'

import { getProfile } from './get-profile'

export const actionClient = createSafeActionClient({ handleServerError(e) { if (e instanceof Error) { return e.message }

return DEFAULT_SERVER_ERROR_MESSAGE

}, })

export const actionClientWithMeta = createSafeActionClient({ handleServerError(e) { if (e instanceof Error) { return e.message }

return DEFAULT_SERVER_ERROR_MESSAGE

}, defineMetadataSchema() { return z.object({ name: z.string(), track: z .object({ event: z.string(), channel: z.string(), }) .optional(), }) }, })

export const authActionClient = actionClientWithMeta .use(async ({ next, clientInput, metadata }) => { const result = await next({ ctx: undefined })

if (env.NODE_ENV === 'development') {
  logger('Input ->', clientInput)
  logger('Result ->', result.data)
  logger('Metadata ->', metadata)

  return result
}

return result

}) .use(async ({ next, metadata }) => { const ip = headers().get('x-forwarded-for')

const { success, remaining } = await rateLimit.paid.limit(
  `${ip}-${metadata.name}`,
)

if (!success) {
  throw new Error('Too many requests')
}

return next({
  ctx: {
    ratelimit: {
      remaining,
    },
  },
})

}) .use(async ({ next, metadata }) => { const { user } = await getProfile()

if (!user) {
  throw new Error('Unauthorized')
}

if (metadata) {
  const analytics = await setupAnalytics({
    userId: user.id,
    fullName: user.nome,
  })

  if (metadata.track) {
    analytics.track(metadata.track)
  }
}

return Sentry.withServerActionInstrumentation(metadata.name, async () => {
  return next({
    ctx: {
      user,
    },
  })
})

})

delete-user import { LogEvents } from '@proflin/events/events' import z from 'zod'

import { api } from './http-client' import { authActionClient } from './safe-action'

type deleteUsuarioResponse = void

const schemaValidation = z.object({ userId: z.string().min(1) })

export const deleteUsuarioAction = authActionClient .schema(schemaValidation) .metadata({ name: 'delete-usuario', track: { event: LogEvents.DeleteUser.name, channel: LogEvents.DeleteUser.channel, }, }) .action(async ({ parsedInput: { userId } }) => { await api.delete(user/${userId}/delete) }) ` image

TheEdoRan commented 1 month ago

@Heitorh3 That doesn't seem related to this issue, can you please open a new one with correct formatting so I can investigate it? Thanks!