Packages
An Ash extension for declaring CSV-importable and CSV-exportable resources via a Spark DSL.
Current section
Files
Jump to
Current section
Files
ash_csv_interchange
README.md
README.md
# AshCsvInterchange
[](https://github.com/team-alembic/ash_csv_interchange/actions/workflows/elixir.yml)
[](https://hex.pm/packages/ash_csv_interchange)
[](https://hexdocs.pm/ash_csv_interchange)
[](https://opensource.org/licenses/Apache-2.0)
An Ash extension for declaring CSV-importable and CSV-exportable resources via a Spark DSL.
Resources that use the extension expose:
- a `csv_imports do … end` block declaring one or more named CSV types via
`csv_import :id do … end` entities, dispatched to per-row Ash `:create`
actions and re-run idempotently through Ash's upsert mechanism
- a `csv_exports do … end` block declaring `csv_export :id do … end` entities
that stream a read action's records out to CSV
## Installation
```elixir
def deps do
[
{:ash_csv_interchange, "~> 0.1.0"}
]
end
```
## Usage
Configure the app that owns your CSV resources and the domains to search:
```elixir
config :ash_csv_interchange, otp_app: :my_app
config :my_app, AshCsvInterchange, domains: [MyApp.Crm]
```
Add the extension to a resource and declare its CSV types:
```elixir
defmodule MyApp.Crm.Contact do
use Ash.Resource,
domain: MyApp.Crm,
extensions: [AshCsvInterchange]
csv_imports do
csv_import :contacts do
label "Contacts"
headers required: ["external_id", "first_name"], optional: ["last_name"]
upsert_action :import_from_csv
end
end
csv_exports do
csv_export :contacts do
label "Contacts"
read_action :for_csv_export
columns [
{"external_id", :external_id},
{"first_name", :first_name},
{"last_name", :last_name}
]
end
end
# ... an upsert action, a keyset-paginated read action, attributes and
# an identity. See the getting started guide for the full resource.
end
```
Then import and export:
```elixir
# Check a file without writing anything, then commit it.
{:ok, report} = AshCsvInterchange.import_csv(:contacts, csv)
{:ok, report} = AshCsvInterchange.import_csv(:contacts, csv, mode: :commit)
# Stream a large file; rows are written as the stream is consumed.
{:ok, %{outcomes: outcomes}} =
AshCsvInterchange.stream_import(:contacts, {:path, "/tmp/contacts.csv"}, mode: :commit)
# Export as one binary, or as a stream of chunks.
{:ok, csv} = AshCsvInterchange.export_csv(:contacts)
{:ok, stream} = AshCsvInterchange.stream_export(:contacts, batch_size: 500)
```
## Guides
- [Getting started](guides/getting-started.md): a complete resource, from
first dry run to first export
- [Defining imports](guides/defining-imports.md): headers, the upsert
action, reshaping values, stamping imported records
- [Running imports](guides/running-imports.md): reports, errors, large
files, batching and authorisation
- [Exports](guides/exports.md): columns, formatters, calculations,
streaming and round trips
- [DSL reference](documentation/dsls/DSL-AshCsvInterchange.md)
The same guides are in the [online documentation](https://hexdocs.pm/ash_csv_interchange).
## Development
Requires Elixir / OTP as pinned in [`.tool-versions`](https://github.com/team-alembic/ash_csv_interchange/blob/main/.tool-versions).
```bash
mix deps.get
mix check # full local quality suite
mix test # just the tests
mix format # format all files
```
Or use the included [devcontainer](./.devcontainer/devcontainer.json) — opens
with VS Code or any devcontainer-compatible editor and sets up Elixir + asdf
automatically.
## Releases
Releases are automated via [`git_ops`](https://hex.pm/packages/git_ops) and
conventional commits. To cut a release:
```bash
mix git_ops.release
git push && git push --tags
```
Then create a GitHub Release from the tag — the `release.yml` workflow
publishes to Hex on your behalf.
## License
Apache 2.0. See [LICENSE](https://github.com/team-alembic/ash_csv_interchange/blob/main/LICENSE).
---
<sub>This repository was generated from [team-alembic/elixir_package_template](https://github.com/team-alembic/elixir_package_template).</sub>