# `Dala.Storage.Storage`
[🔗](https://github.com/manhvu/dala/blob/main/lib/dala/storage/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 dala.enable`)
  - `:cache`       — persists until OS needs space; not user-visible
  - `:app_support` — persists, hidden from user, backed up on iOS

## Platform-specific storage

See `Dala.Storage.Apple` and `Dala.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.

# `append`

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

Append `data` to the end of a file.

Creates the file if it doesn't exist.
Returns `{:ok, path}` on success.

    Dala.Storage.append("/tmp/log.txt", "New log entry\n")

# `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.

# `create`

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

Create a new empty file at `path`.

Creates parent directories if they don't exist.
Returns `{:ok, path}` on success.

    Dala.Storage.create("/tmp/new_file.txt")

# `create`

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

Create a new file at `path` with the given `content`.

Creates parent directories if they don't exist.
Returns `{:ok, path}` on success.

    Dala.Storage.create("/tmp/new_file.txt", "Hello, World!")

# `delete`

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

Delete a file or directory at `path`.

Use `force: true` to delete non-empty directories.
Returns `:ok` on success.

    Dala.Storage.delete("/tmp/old_file.txt")
    Dala.Storage.delete("/tmp/old_dir", force: true)

# `dir`

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

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

# `ensure_dir`

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

Ensure the parent directory for `path` exists, creating it if necessary.

Returns `:ok` on success.

    Dala.Storage.ensure_dir("/tmp/new_dir/file.txt")

# `exists?`

```elixir
@spec exists?(String.t()) :: boolean()
```

Check if a file or directory exists at `path`.

    Dala.Storage.exists?("/tmp/file.txt")  #=> true

# `export`

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

Export a file from a location to a destination path.

Creates parent directories of `dest` if needed.
Returns `{:ok, dest_path}` on success.

    Dala.Storage.export("/tmp/file.txt", "/tmp/backup/file.txt")

# `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.

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

# `info`

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

Return detailed file information.

Returns a map with `:name`, `:path`, `:size`, `:modified_at`, `:type`,
and `:extension`.

    Dala.Storage.info("/tmp/clip.mp4")
    #=> %{name: "clip.mp4", path: "/tmp/clip.mp4", size: 204800,
    #    modified_at: ~U[2026-04-24 10:00:00Z], type: :regular,
    #    extension: ".mp4"}

# `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 (file is placed there keeping its basename)
or a full absolute path. Creates parent directories of `dest` if needed.

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

    Dala.Storage.move("/tmp/old.txt", "/tmp/new.txt")
    Dala.Storage.move("/tmp/file.txt", :documents)

# `read`

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

Read a file's contents as a binary.

# `read_text`

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

Read a file and return its contents as a string.

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

    Dala.Storage.read_text("/tmp/file.txt")  #=> {:ok, "Hello"}

# `size`

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

Return the file size in bytes, or `{:error, reason}` if the file doesn't exist.

    Dala.Storage.size("/tmp/file.txt")  #=> {:ok, 1024}

# `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]}

# `update`

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

Update the contents of an existing file at `path`.

Returns `{:ok, path}` on success. Returns `{:error, :enoent}` if the file
doesn't exist.

    Dala.Storage.update("/tmp/existing_file.txt", "Updated content")

# `write`

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

Write `data` to `path`.

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

# `write_text`

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

Write `content` to a file as text.

Creates parent directories if they don't exist.
Returns `{:ok, path}` on success.

    Dala.Storage.write_text("/tmp/file.txt", "Hello, World!")

---

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