Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support servant-pagination #45

Open
sir4ur0n opened this issue Jul 6, 2023 · 6 comments
Open

Support servant-pagination #45

sir4ur0n opened this issue Jul 6, 2023 · 6 comments

Comments

@sir4ur0n
Copy link

sir4ur0n commented Jul 6, 2023

Hello!

Have you considered supporting servant-pagination?

From the Servant pagination recipe, one needs to manually write these 3 instances:

instance ToParamSchema (Ranges '["name"] Color) where
  toParamSchema _ = -- ?

instance ToParamSchema (ContentRange '["name"] Color) where
  toParamSchema _ = -- ?

instance ToParamSchema (AcceptRanges '["name"]) where
  toParamSchema _ = -- ?

and I am thinking that this library (or maybe a new library servant-openapi-pagination?) could provide support (default Generic instances? Or just default instance for basic types like Int, Text, etc.? I haven't thought about that in detail).

@worm2fed
Copy link

worm2fed commented Jul 18, 2023

I have a same problem, working on it.
Actually you do not need Generic for defined types in this lib unless you want to derive openapi types. And seems like it will be quite hard to implement these Generics.

Actually, easier way is just to use mempty, but this is not very descriptive in spec and I didn't tested it yet. Trying to provide description for each header. Didn't have time to dive deeper.

P.S. I do no think that this is appropriate place to define instances for 3d-party lib, it should be defined in servant-pagination

@worm2fed
Copy link

So strange

instance ToParamSchema (Ranges fields resource) where
  toParamSchema :: Proxy (Ranges fields resource) -> Schema
  toParamSchema _ =
    mempty
      & ( O.description
            ?~ "Range: <field> [<value>][; offset <o>][; limit <l>][; order <asc|desc>]"
        )
      & (O.type_ ?~ O.OpenApiString)
      & ( O.example
            ?~ A.String "<field> [<value>][; offset <o>][; limit <l>][; order <asc|desc>]"
        )

As you can see, type_ and example is working, but not description

HI, @maksbotan! Hope you know what it can be :)

image

@worm2fed
Copy link

worm2fed commented Jul 19, 2023

Maybe, this is because in servant-openapi3 description is redefined, not sure

instance (KnownSymbol sym, ToParamSchema a, HasOpenApi sub, SBoolI (FoldRequired mods), KnownSymbol (FoldDescription mods)) => HasOpenApi (Header' mods sym a :> sub) where
toOpenApi _ = toOpenApi (Proxy :: Proxy sub)
& addParam param
& addDefaultResponse400 tname
where
tname = Text.pack (symbolVal (Proxy :: Proxy sym))
transDesc "" = Nothing
transDesc desc = Just (Text.pack desc)
param = mempty
& name .~ tname
& description .~ transDesc (reflectDescription (Proxy :: Proxy mods))
& required ?~ reflectBool (Proxy :: Proxy (FoldRequired mods))
& in_ .~ ParamHeader
& schema ?~ (Inline $ toParamSchema (Proxy :: Proxy a))

@worm2fed
Copy link

worm2fed commented Jul 19, 2023

UPD: in raw swagger.json description is defined
but this is Schema description, not Param

image

@worm2fed
Copy link

worm2fed commented Jul 19, 2023

I have a workaround, smth like this:

instance ToParamSchema (Ranges fields resource) where
  toParamSchema :: Proxy (Ranges fields resource) -> Schema
  toParamSchema _ =
    mempty
      & (O.type_ ?~ O. OpenApiString)
      & ( O.example
            ?~ A.String "<field> [<value>][; offset <o>][; limit <l>][; order <asc|desc>]"
        )

instance
  {-# OVERLAPS #-}
  (KnownSymbol sym, HasOpenApi sub)
  => HasOpenApi (Header' mods sym (Ranges fields resource) :> sub)
  where
  toOpenApi :: Proxy (Header' mods sym (Ranges fields resource) :> sub) -> OpenApi
  toOpenApi _ =
    toOpenApi (Proxy :: Proxy sub)
      & addParam param
      & addDefaultResponse400 name
    where
      name = toText (symbolVal (Proxy :: Proxy sym))
      param =
        mempty
          & (O.name .~ name)
          & ( O.description
                ?~ "Indicates to the server what parts of the collection is requested"
            )
          & (O.in_ .~ O.ParamHeader)
          & (O.required ?~ False)
          & (O.schema ?~ O.Inline (toParamSchema @(Ranges fields resource) Proxy))

but I'm wondering, how can I not define whole parameter by my own, but use default lib implementation and modify it

@worm2fed
Copy link

worm2fed commented Jul 19, 2023

here it is

-- | Request 'Header' for pagination.
type PaginationRequestHeader (fields :: [Symbol]) (resource :: Type) =
  Header'
    '[ Optional
     , Strict
     , Description "Indicates to the server what parts of the collection is requested"
     ]
    "Range"
    (Ranges fields resource)

instance ToParamSchema (Ranges fields resource) where
  toParamSchema :: Proxy (Ranges fields resource) -> Schema
  toParamSchema _ =
    mempty
      & (O.type_ ?~ O.OpenApiString)
      & ( O.example
            ?~ toJSON
              ("<field> [<value>][; offset <o>][; limit <l>][; order <asc|desc>]" :: Text)
        )

This way original version can get Header description (& description .~ transDesc (reflectDescription (Proxy :: Proxy mods))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants