I wanted to provide a list of mime types supported in GraphQL, so I tried using the enum type. However, it doesn’t support strings with symbols such as the forward slash in mime type strings “image/png”. I looked into custom scalars, but it doesn’t have the same rich documentation as the enum field, so I wanted to extend the enum to support my use case. I then tried reading the library’s implementation of enum, but I’m still too new to Elixir to comprehend everything. Could anyone point me in the right direction please?
Hey @dagumak, unfortunately it won’t be possible to create a GraphQL Enum that looks literally like "image/png"
. Your options are to make it a simple string type with validations, an enum type like IMAGE_PNG
that you map to a proper string, or a custom scalar that accepts string inputs and validates that they are one of a set of allowed values.
4 Likes
Thank you for taking the time to reply! I ended up with this implementation for the time being.
scalar :mime_type, name: "MimeType" do
description("""
Currently support mimetypes:\n
"image/gif"\n
"image/png"\n
"image/jpeg"\n
""")
serialize(fn value -> value end)
parse(&allowed_mime_types/1)
end
defp allowed_mime_types(%Absinthe.Blueprint.Input.String{value: value}) do
result = value in ["image/gif", "image/png", "image/jpeg"]
case result do
true -> {:ok, value}
false -> :error
end
end
Maybe my library could help you : SimpleEnum - Use Enumerations in Elixir.
The equivalent of your current implementation would be :
# my_app/types.ex
defmodule MyApp.Types do
import SimpleEnum
defenum :mime_type_enum,
image_gif: "image/gif",
image_png: "image/png",
image_jpeg: "image/jpeg"
end
# my_app/schema.ex
import MyApp.Types
scalar :mime_type, name: "MimeType" do
description("""
Currently support mimetypes:\n
- #{mime_type_enum(:__values__) |> Enum.join("\n - ")}
""")
serialize(fn
value when value in mime_type_enum(:__values__) -> value
key when key in mime_type_enum(:__keys__) -> mime_type_enum(key, :value)
_ -> :error
end)
parse(fn
%Absinthe.Blueprint.Input.String{value: value} when value in mime_type_enum(:__values__) ->
{:ok, mime_type_enum(value, :key)}
_ ->
:error
end)
end
With this implementation :
- Adding an Enum is very simple, you just have to add the values in the
defenum/2
- It will automatically update
description
and theserialize/1
andparse/1
functions of your scalar - Once the scalar is parsed, you can use the
image_gif
,image_png
andimage_jpeg
atoms in Elixir for processing
2 Likes