types.ex (1957B)
1 defmodule Absinthe.Plug.Types do 2 @moduledoc """ 3 This module provides GraphQL types that may be useful in Absinthe schema 4 and type modules. 5 6 ## `:upload` 7 8 Absinthe.Plug can be used to upload files via GraphQL. 9 10 For example, the following schema includes a mutation field that accepts 11 multiple uploaded files as arguments (`:users` and `:metadata`): 12 13 ```elixir 14 defmodule MyAppWeb.Schema do 15 use Absinthe.Schema 16 17 # Important: Needed to get the `:upload` type 18 import_types Absinthe.Plug.Types 19 20 mutation do 21 field :upload_file, :string do 22 arg :users, non_null(:upload) 23 arg :metadata, :upload 24 25 resolve fn args, _ -> 26 args.users # this is a `%Plug.Upload{}` struct. 27 28 {:ok, "success"} 29 end 30 end 31 end 32 end 33 ``` 34 35 To send a mutation that includes a file upload, you need to 36 use the `multipart/form-data` content type. For example, using `cURL`: 37 38 ```shell 39 $ curl -X POST \ 40 -F query='mutation { uploadFile(users: "users_csv", metadata: "metadata_json") }' \ 41 -F users_csv=@users.csv \ 42 -F metadata_json=@metadata.json \ 43 localhost:4000/graphql 44 ``` 45 46 Note how there is a correspondance between the value of the `:users` argument 47 and the `-F` option indicating the associated file. 48 49 By treating uploads as regular arguments we get all the usual GraphQL argument 50 benefits (such as validation and documentation), something we wouldn't get if 51 we were merely putting them in the context. 52 """ 53 54 use Absinthe.Schema.Notation 55 56 alias Absinthe.Blueprint 57 58 @desc """ 59 Represents an uploaded file. 60 """ 61 scalar :upload do 62 parse fn 63 %Blueprint.Input.String{value: value}, context -> 64 Map.fetch(context[:__absinthe_plug__][:uploads] || %{}, value) 65 66 %Blueprint.Input.Null{}, _ -> 67 {:ok, nil} 68 69 _, _ -> 70 :error 71 end 72 73 serialize fn _ -> 74 raise "The `:upload` scalar cannot be returned!" 75 end 76 end 77 end