ad-on-is / adonis-autoswagger

Auto-Generate swagger docs for AdonisJS
MIT License
129 stars 41 forks source link

Question - Validators #105

Closed JulienGaladrim closed 4 months ago

JulienGaladrim commented 4 months ago

How can I use the validators parsing ?

In my project, I have some controllers and some vine schemas for the request body in my Validators folder.

I am trying to add these validators schemas to the swagger as request body with a @requestBody <testValidator> comment but it seems that the validator is not found. My request body stays empty.

I don't think the issue is my comment per say, I made some tests with interfaces and it works well.

ad-on-is commented 4 months ago

what version of adonisjs are you using? validators only work with v6.

Otherwise, could you post your validatior and comment, so I can have a look?

JulienGaladrim commented 4 months ago

Yes, sorry for not adding much details originally.

I am using Adonisjs v6, validators are setup with vine.

My controller is declared in a group_controller.ts file inside a app/controllers/Group folder :

  /**
   * @updateGroup
   * @requestBody <testValidator>
   */
  async updateGroup(ctx: HttpContext) {
    await updateGroup(ctx)
  }

I tried to create a custom validator to check, in a test.ts file inside the app/Validators folder :

import vine from '@vinejs/vine'

export const testValidator = vine.compile(
  vine.object({
    test: vine.string(),
  })
)

In this case I get an empty object as request body in the documentation image

Out of curiosity I tried using an interface instead, declared in a test.ts file in the app/Interfaces folder :

export interface TestInterface {
  test: string
}

And using this TestInterface in the controller's comment works well : image

ad-on-is commented 4 months ago

Oh.. I think I see your issue here.

You say, the file is in app/Validators ... but the structure in adonisjsv6 is lowerCase, so it should be app/validators This should also be reflected in the package.json like this:

"#validators/*": "./app/validators/*.js",

Ignoring the recursive call in your function, I highly doubt, that your validator would have even worked in adonisJS itself.

JulienGaladrim commented 4 months ago

Having my testValidator.ts in the app/validators folder doesn't fix the problem.

In fact all my validators are indeed in the app/validators folder and they work well with my controllers. I made this test validator in a Validators folder because it was written with a capital V in the readme and I wanted to rule out any case issue.

Also there is no recursive call in my controller, the function called comes from another file.

ad-on-is commented 4 months ago

Hmm... Are you on the latest version of AutoSwagger? I've just deployed a new version with more useful debug output... Could you install the new version, and set debug: true in the swagger-config?

JulienGaladrim commented 4 months ago

I was on the v3.52. I upgraded and enabled the logs, should I look for something specific ?

My test.ts file appears in the Found validator files array and my controller is annotated

✓ OK file app/controllers/Group/groups_controller.ts pattern /group/update action updateGroup

I was thinking of setting up a minimal project to check if the problem persists on my side, in this case I'd share it with you.

ad-on-is commented 4 months ago

can you post the whole debug? is the validator recognized in schemas?

GilTRipper commented 4 months ago

Have the same issue. Seems like it doesn't put validators in schema after AutoSwagger.default.docs(). but create after node ace docs:generate

muteusers commented 4 months ago

i have problem for adonis 6 i have controller user_controller and have function create

async create({response,request} : HttpContext){ const {firstName,lastName,email,password} = await request.validateUsing(createUserValidator) return response.json({ ok : true, result : { firstName, lastName, email, password } }) } and my createUserValidator is export const createUserValidator = vine.compile( vine.object({ firstName: vine.string(), lastName: vine.string(), email: vine.string().email().unique(async (_db, _value, _field) => { const user = await User.query() .where('email', _value) .first() return !user }), password: vine.string() }) )

but swagger request body is empety how to fix?

ad-on-is commented 4 months ago

Guys, without a debug output and without the full post of your comnent section of the controller, I cannot help you very much. Please provide (and code-format) more infos

GilTRipper commented 4 months ago
image

have this issue

example of controller


import PostService from '#services/post_service'
import { PostParams } from '#types/posts'
import { createPostValidator, createPostVoteValidator } from '#validators/post'
import { inject } from '@adonisjs/core'
import type { HttpContext } from '@adonisjs/core/http'
@inject()
export default class PostsController {
  constructor(protected postService: PostService) {}

  /*
   * @index
   * @responseBody 200 - <PostInterface[]>
   */
  async index({}: HttpContext) {
    const data = this.postService.getAll()

    return data
  }

  /*
   * @store
   * @requestBody - <createPostValidator>
   * @responseBody 200 - <PostInterface>
   */
  async store({ auth, request }: HttpContext) {
    const user = auth.getUserOrFail()
    const data = await request.validateUsing(createPostValidator)
    const post = await this.postService.create(data, user)

    return post
  }

  /*
   * @vote
   * @requestBody - <createPostVoteValidator>
   * @paramPath postId - Post to vote - @type(string) @required
   * @responseBody 200 - <PostInterface>
   */
  async vote({ auth, request, params }: HttpContext) {
    const { postId } = params as PostParams
    const { optionId } = await request.validateUsing(createPostVoteValidator)

    const user = auth.getUserOrFail()

    const post = await this.postService.vote(+postId, user, +optionId)

    return post
  }
}

Example of validators (storing at app/validators/*.js)

import vine from '@vinejs/vine'
import { ExtractSchemaType } from './types.js'

export const createPostValidator = vine.compile(
  vine.object({
    title: vine.string().minLength(1),
    description: vine.string(),
    options: vine.array(vine.string()),
    tagId: vine.number().optional(),
  })
)

export const createPostReactionValidator = vine.compile(
  vine.object({
    like: vine.boolean(),
  })
)

export const createPostVoteValidator = vine.compile(
  vine.object({
    optionId: vine.string(),
  })
)

export const createPostTagValidator = vine.compile(
  vine.object({
    tag: vine.string().minLength(2),
  })
)
ad-on-is commented 4 months ago

@GilTRipper could you please also provide the debug output of AutoSwagger?

GilTRipper commented 4 months ago

@ad-on-is seems like everything is fine rn. I think we can close the issue. Did you change smth?

ad-on-is commented 4 months ago

@GilTRipper I didn't change anything. But if it's working let's close this one, and feel free to reopen if it reoccurrs with more info.

eugenepro2 commented 2 months ago

same issue @ad-on-is

"adonis-autoswagger": "^3.63.0",

image

example of controller method

/**
   * @updateUser
   * @tag User
   * @responseBody 200 - <User>.only(id, email, hasOnboarded, firstName, lastName, profilePicture)
   * @requestBody - <updateUserValidator>
   */
  async updateUser({ auth, request, response }: HttpContext) {
    const { hasOnboarded, deviceId, firstName, lastName } =
      await request.validateUsing(updateUserValidator)

    const user = auth.getUserOrFail()
    try {
      await user.merge({ hasOnboarded, deviceId, firstName, lastName }).save()
      const loggedUser = await User.query()
        .where('id', user.id)
        .select(['id', 'email', 'hasOnboarded', 'firstName', 'lastName', 'profilePicture'])
        .firstOrFail()
      return response.status(200).json(loggedUser)
    } catch (error) {
      this.logger.error({ error, ip: request.ip(), user: user.id })
      return response.status(500).json(error)
    }
  }

Example of validators (storing at app/validators/*.ts)

import vine from '@vinejs/vine'

export const updateUserValidator = vine.compile(
  vine.object({
    hasOnboarded: vine.boolean().optional(),
    deviceId: vine.string().optional(),
    firstName: vine.string().optional(),
    lastName: vine.string().optional(),
  })
)
eugenepro2 commented 1 month ago

Just updated all dependencies to latest and that's works. Magic.