diff --git a/CHANGELOG.md b/CHANGELOG.md index a9c9810..773dac5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Add support for [Perspectives](https://www.sanity.io/blog/introducing-perspectives-sanity-previews) (https://github.com/balexand/sanity/pull/83). +- Support for [Perspectives](https://www.sanity.io/blog/introducing-perspectives-sanity-previews) (https://github.com/balexand/sanity/pull/83). +- Support for streaming uploads via `Sanity.upload_asset/3`. This feature came for free with the switch to `Req`. ### Removed - (BREAKING) The `:drafts` option has been removed and passing it will result in an error. The `:perspective` option should be used instead. The default behavior is the same so you will only need to update your code if you are explicitly passing the `:drafts` option. diff --git a/lib/sanity.ex b/lib/sanity.ex index babd522..f14c625 100644 --- a/lib/sanity.ex +++ b/lib/sanity.ex @@ -378,7 +378,9 @@ defmodule Sanity do end @doc """ - Generates a request for the [asset endpoint](https://www.sanity.io/docs/http-api-assets). + Generates a request for the [asset endpoint](https://www.sanity.io/docs/http-api-assets). The + `body` argument can be a binary or iolist to upload content from memory. Or it can be an + `Enumerable`, such as a value returned by `File.stream!/2`, for streaming uploads. ## Options @@ -398,7 +400,8 @@ defmodule Sanity do * `creditLine` - The credit to person(s) and/or organization(s) required by the supplier of the image to be used when published """ - @spec upload_asset(iodata(), keyword() | map(), keyword() | map()) :: Request.t() + @spec upload_asset(iodata() | Enumerable.t(), keyword() | map(), keyword() | map()) :: + Request.t() def upload_asset(body, opts \\ [], query_params \\ []) do opts = NimbleOptions.validate!(opts, @asset_options_schema) diff --git a/test/fixtures/danielle-stein-10OL1q7oX6c-unsplash.jpg b/test/fixtures/danielle-stein-10OL1q7oX6c-unsplash.jpg new file mode 100644 index 0000000..abff451 Binary files /dev/null and b/test/fixtures/danielle-stein-10OL1q7oX6c-unsplash.jpg differ diff --git a/test/integration_test.exs b/test/integration_test.exs index 2e1406c..bce443e 100644 --- a/test/integration_test.exs +++ b/test/integration_test.exs @@ -192,6 +192,56 @@ defmodule Sanity.MutateIntegrationTest do end end + describe "upload_asset" do + test "binary jpg asset", %{config: config} do + binary = File.read!("test/fixtures/danielle-stein-10OL1q7oX6c-unsplash.jpg") + + assert %Sanity.Response{ + body: %{ + "document" => %{ + "_type" => "sanity.imageAsset", + "metadata" => %{ + "dimensions" => %{ + "_type" => "sanity.imageDimensions", + "height" => 960, + "width" => 640 + } + }, + "mimeType" => "image/jpeg", + "sha1hash" => "41de39c94c974305bdda7d901cfca3102a8e6e77", + "size" => 169_633 + } + } + } = + Sanity.upload_asset(binary) + |> Sanity.request!(config) + end + + test "stream jpg asset", %{config: config} do + path = "test/fixtures/danielle-stein-10OL1q7oX6c-unsplash.jpg" + + stream = + if System.version() |> String.split(".") |> Enum.map(&String.to_integer/1) >= [1, 16, 0] do + File.stream!(path, 2048) + else + File.stream!(path, [:raw, :read_ahead, :binary], 2048) + end + + assert %Sanity.Response{ + body: %{ + "document" => %{ + "_type" => "sanity.imageAsset", + "mimeType" => "image/jpeg", + "sha1hash" => "41de39c94c974305bdda7d901cfca3102a8e6e77", + "size" => 169_633 + } + } + } = + Sanity.upload_asset(stream) + |> Sanity.request!(config) + end + end + test "timeout error", %{config: config} do config = Keyword.put(config, :http_options, receive_timeout: 0, retry: false)