# `Mob.Storage`
[🔗](https://github.com/genericjam/mob/blob/main/lib/mob/storage.ex#L1)

App-local file storage.

Provides a thin Elixir wrapper over the device filesystem using named
locations instead of raw paths. Basic file operations (`list`, `stat`,
`delete`, `copy`, `move`, `read`, `write`) are pure `File.*` calls —
no NIF overhead except for the initial `dir/1` path resolution.

## Locations

  - `:temp`        — ephemeral; may be purged by the OS at any time
  - `:documents`   — persists across app sessions; user-visible on iOS
                     when `UIFileSharingEnabled` is set (see `mix mob.enable`)
  - `:cache`       — persists until OS needs space; not user-visible
  - `:app_support` — persists, hidden from user, backed up on iOS

## Platform-specific storage

See `Mob.Storage.Apple` and `Mob.Storage.Android` for saving to the native
photo/media library and accessing platform-specific directories.

## Results

Operations that can fail return `{:ok, value} | {:error, posix}`.
`dir/1` raises on an unknown location atom.

# `copy`

```elixir
@spec copy(String.t(), atom() | String.t()) :: {:ok, String.t()} | {:error, atom()}
```

Copy `src` to `dest`.

`dest` may be a location atom (file is placed there keeping its basename)
or a full absolute path.

Returns `{:ok, dest_path}` on success.

# `delete`

```elixir
@spec delete(String.t()) :: :ok | {:error, atom()}
```

Delete a file.

# `dir`

```elixir
@spec dir(atom()) :: String.t()
```

Resolve a location atom to its absolute path on the current device.

# `extension`

```elixir
@spec extension(String.t()) :: String.t()
```

Return the file extension including the leading dot, or `""` if none.

No I/O — derived from the filename only.

    Mob.Storage.extension("/tmp/clip.mp4")   #=> ".mp4"
    Mob.Storage.extension("/tmp/notes")      #=> ""

# `list`

```elixir
@spec list(atom() | String.t()) :: {:ok, [String.t()]} | {:error, atom()}
```

List all files in a location or an absolute path.

Returns full paths, not just names.

# `move`

```elixir
@spec move(String.t(), atom() | String.t()) :: {:ok, String.t()} | {:error, atom()}
```

Move `src` to `dest`.

`dest` may be a location atom or a full absolute path.

Returns `{:ok, dest_path}` on success.

# `read`

```elixir
@spec read(String.t()) :: {:ok, binary()} | {:error, atom()}
```

Read a file's contents as a binary.

# `stat`

```elixir
@spec stat(String.t()) :: {:ok, map()} | {:error, atom()}
```

Return metadata for a file.

    %{name: "clip.mp4", path: "/…/clip.mp4", size: 204_800,
      modified_at: ~U[2026-04-24 10:00:00Z]}

# `write`

```elixir
@spec write(String.t(), binary()) :: {:ok, String.t()} | {:error, atom()}
```

Write `data` to `path`.

Returns `{:ok, path}` on success.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
