# `DocShell.Artifact.Transaction`
[🔗](https://github.com/futhr/doc_shell/blob/v2.0.0/lib/doc_shell/artifact/transaction.ex#L1)

Stages a batch of JSON files before replacing any published artifact.

Each output is encoded beside its destination and each existing destination
is backed up before publication starts. Returned publication failures restore
already replaced files in reverse order. If restoration itself fails, backup
paths are retained and returned for recovery instead of deleting the last copy.

Directory locks serialize cooperating builds across BEAM instances. A crashed
writer can leave a `.doc-shell-build.lock` directory and hidden stage/backup
files; recover those before removing the lock and rebuilding. This is not a
filesystem transaction across power loss. Cache readers continue to validate
generation IDs, since individual renames cannot publish multiple files at once.
Use dedicated output directories without external writers or symlink aliases.

# `write`

```elixir
@spec write([{Path.t(), term()}], keyword()) :: :ok | {:error, term()}
```

Writes JSON payloads in order, restoring earlier files on publication failure.

A payload is either a JSON term, staged as canonical JSON, or a
`DocShell.Artifact.Encoded` value, staged verbatim. Builds pass encoded bytes
so an artifact is encoded once even when its digest is also needed.

The optional `:delete` list removes stale files in the same transaction.
Deletions publish before writes, after every original has been backed up.
Missing deletion targets are harmless. Targets must be distinct regular files
or absent paths; directories and symlinks are rejected before publication.

---

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