Kotoba.Storage behaviour (Kotoba v0.8.0)

Copy Markdown View Source

The store of attachments, kept with Storehouse.

Kotoba.Live.consume_uploads/4 and Kotoba.Attachments.store/2 check each file and store it with Storehouse.store/2, through the store of adapter/0, and put the URL that it gives in the attachment node. Name the store in Storehouse's config:

config :storehouse, adapter: Storehouse.S3

The default is Storehouse.Local, the local disk, served by Storehouse.Local.Plug. Storehouse's Stores guide has S3 (and R2, MinIO, LocalStack), and a store of your own.

Keys

A key is a relative path with segments of ASCII letters, digits, ., - and _, separated by /. Storehouse.key/2 makes a new key in the form yyyy/mm/<uuid>-<safe name><extension>; the extension comes from the checked content type, never from the client's file name, so a key never ends in .html or .svg.

The store of Kotoba 0.7 and before (deprecated)

A store of the app's written for Kotoba.Storage (put/3, url/1, delete/1) is a Storehouse.Adapter as it is: the callbacks are the same, so it changes only its @behaviour. Until Kotoba 1.0, config :kotoba, storage: MyApp.KotobaStorage still names it, and Kotoba.Storage.Local (config :kotoba, Kotoba.Storage.Local) still works, each with a deprecation warning: move to config :storehouse, adapter: and Storehouse.Local (see the CHANGELOG).

Storehouse is an optional dependency of Kotoba: an app with uploads has {:storehouse, "~> 0.2"} in its deps, and this module is there only with it.

Summary

Types

A storage key, for example "2026/09/0b6…-cat.png".

What Kotoba knows about the file: :name (the client's file name, for display only, with control and format characters removed), :content_type (checked on the server, see Kotoba.Attachments) and :bytes.

Callbacks

Deletes the file with key. A key with no file gives :ok.

Stores the file at path under key, and returns its URL.

Returns the URL of the file with key.

Functions

Returns the store of attachments: config :kotoba, storage: when the app names one (deprecated), Kotoba.Storage.Local when the app configures it (deprecated), else Storehouse's (Storehouse.adapter/0).

Types

key()

@type key() :: Storehouse.Adapter.key()

A storage key, for example "2026/09/0b6…-cat.png".

meta()

@type meta() :: %{
  optional(:name) => String.t(),
  optional(:content_type) => String.t(),
  optional(:bytes) => non_neg_integer()
}

What Kotoba knows about the file: :name (the client's file name, for display only, with control and format characters removed), :content_type (checked on the server, see Kotoba.Attachments) and :bytes.

Callbacks

delete(key)

@callback delete(key()) :: :ok | {:error, term()}

Deletes the file with key. A key with no file gives :ok.

put(key, path, meta)

@callback put(key(), path :: Path.t(), meta()) ::
  {:ok, url :: String.t()} | {:error, term()}

Stores the file at path under key, and returns its URL.

The file at path is a temporary file: the adapter copies it, and must not keep a reference to it.

url(key)

@callback url(key()) :: String.t()

Returns the URL of the file with key.

Functions

adapter()

@spec adapter() :: module()

Returns the store of attachments: config :kotoba, storage: when the app names one (deprecated), Kotoba.Storage.Local when the app configures it (deprecated), else Storehouse's (Storehouse.adapter/0).