AshCsvInterchange
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 … endblock declaring one or more named CSV types viacsv_import :id do … endentities, dispatched to per-row Ash:createactions and re-run idempotently through Ash's upsert mechanism - a
csv_exports do … endblock declaringcsv_export :id do … endentities that stream a read action's records out to CSV
Installation
def deps do
[
{:ash_csv_interchange, "~> 0.1.0"}
]
end
Usage
Configure the app that owns your CSV resources and the domains to search:
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:
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:
# 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: a complete resource, from first dry run to first export
- Defining imports: headers, the upsert action, reshaping values, stamping imported records
- Running imports: reports, errors, large files, batching and authorisation
- Exports: columns, formatters, calculations, streaming and round trips
- DSL reference
The same guides are in the online documentation.
Development
Requires Elixir / OTP as pinned in .tool-versions.
mix deps.get
mix check # full local quality suite
mix test # just the tests
mix format # format all files
Or use the included devcontainer — opens with VS Code or any devcontainer-compatible editor and sets up Elixir + asdf automatically.
Releases
Releases are automated via git_ops and
conventional commits. To cut a release:
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.
This repository was generated from team-alembic/elixir_package_template.