Fil.Op (Fil v0.1.0)

Copy Markdown View Source

One call to a Fil function, as plugins see it.

Every operation builds a %Fil.Op{} and passes it through the disk's plugins to the adapter. See the Plugins guide for how to write a plugin.

  • :disk: the Fil.Disk the operation runs on
  • :name: the operation, :read, :write, :stat, :ls, :rm, :rm_rf, :cp, :rename, :url or :signed_url
  • :path: the normalized path, relative to the disk root
  • :dest: the destination path of a :cp or :rename on the same disk, nil otherwise
  • :content: the content of a :write, nil otherwise. Change it with update_content/2
  • :options: the validated options of the call
  • :result: nil on the way in, then {:ok, value} or {:error, exception} with the same value the Fil function returns. Change a read result with update_result/2
  • :private: a map for plugins to pass data along

Summary

Functions

Returns an option of the call.

Returns a private value.

Makes the content of a :write whole, for plugins that need all of it at once.

Sets an option unless the call already has it.

Sets an option before the adapter sees it.

Stores a private value, for a later plugin or for the way back.

Sets the result.

Transforms the content of a :write. Other operations are returned unchanged.

Transforms the content returned by a successful :read. Other operations and errors are returned unchanged.

Types

name()

@type name() ::
  :read
  | :write
  | :stat
  | :ls
  | :rm
  | :rm_rf
  | :cp
  | :rename
  | :url
  | :signed_url

t()

@type t() :: %Fil.Op{
  content: iodata() | nil,
  dest: Path.t() | nil,
  disk: Fil.Disk.t(),
  name: name(),
  options: keyword(),
  path: Path.t(),
  private: map(),
  result: {:ok, term()} | {:error, Exception.t()} | nil
}

transform()

@type transform() :: [binary: (binary() -> iodata()), chunk: (binary() -> iodata())]

Functions

get_option(op, key, default \\ nil)

@spec get_option(t(), atom(), term()) :: term()

Returns an option of the call.

iex> op = %Fil.Op{disk: nil, name: :write, path: "a.txt", options: [content_type: "text/plain"]}
iex> Fil.Op.get_option(op, :content_type)
"text/plain"
iex> Fil.Op.get_option(op, :missing, :default)
:default

get_private(op, key, default \\ nil)

@spec get_private(t(), term(), term()) :: term()

Returns a private value.

iex> op = %Fil.Op{disk: nil, name: :read, path: "a.txt"}
iex> Fil.Op.get_private(op, :seen, false)
false

materialize(op)

@spec materialize(t()) :: t()

Makes the content of a :write whole, for plugins that need all of it at once.

Content is always whole for now, so this only flattens iodata into a binary. Once streaming lands, it collects a stream into memory, so use it only when a plugin can't work chunk by chunk.

iex> op = %Fil.Op{disk: nil, name: :write, path: "a.txt", content: ["a", ["b"]]}
iex> Fil.Op.materialize(op).content
"ab"

put_new_option(op, key, value)

@spec put_new_option(t(), atom(), term()) :: t()

Sets an option unless the call already has it.

iex> op = %Fil.Op{disk: nil, name: :write, path: "a.txt", options: [content_type: "text/plain"]}
iex> op |> Fil.Op.put_new_option(:content_type, "text/csv") |> Fil.Op.get_option(:content_type)
"text/plain"

put_option(op, key, value)

@spec put_option(t(), atom(), term()) :: t()

Sets an option before the adapter sees it.

iex> op = %Fil.Op{disk: nil, name: :write, path: "a.txt", options: [content_type: "text/plain"]}
iex> op |> Fil.Op.put_option(:content_type, "text/csv") |> Fil.Op.get_option(:content_type)
"text/csv"

put_private(op, key, value)

@spec put_private(t(), term(), term()) :: t()

Stores a private value, for a later plugin or for the way back.

iex> op = %Fil.Op{disk: nil, name: :read, path: "a.txt"}
iex> op |> Fil.Op.put_private(:seen, true) |> Fil.Op.get_private(:seen)
true

put_result(op, result)

@spec put_result(t(), {:ok, term()} | {:error, Exception.t()}) :: t()

Sets the result.

A plugin that sets the result instead of calling next answers the call itself, and the adapter never runs. An error is an exception: one of Fil's (see Errors) or the plugin's own. Fil fills in the :op, :path and :disk of its own errors where the plugin left them nil.

update_content(op, funs)

@spec update_content(t(), transform()) :: t()

Transforms the content of a :write. Other operations are returned unchanged.

Pass binary: to transform the whole content at once and chunk: to transform it piece by piece:

Fil.Op.update_content(op, binary: &:zlib.gzip/1)

Content is always whole for now, so binary: runs and gets a binary (iodata is flattened first). Without binary:, the content is passed to chunk: as a single chunk. Once streaming lands, chunk: runs on each chunk of a stream, and a stream is collected first if there's only binary:.

update_result(op, funs)

@spec update_result(t(), transform()) :: t()

Transforms the content returned by a successful :read. Other operations and errors are returned unchanged.

Takes the same binary: and chunk: functions as update_content/2.