Pure logic for database seeding.
A seed file is EDN, in either of two shapes.
A map of table -> rows, for the simple case:
{:tasks [{:title "Try the admin UI" :done false} {:title "Read AGENTS.md" :done true}]}
Or a vector of [table rows] pairs, which is ordered:
[[:users [{:email "admin@example.com"}]] [:tasks [{:title "Owned by that user" :user-id 1}]]]
Insert order matters as soon as one table references another, and EDN maps only preserve their written order up to 8 entries — a 9th turns the literal into a PersistentHashMap and the order becomes hash order. Rather than let a seed file quietly start inserting children before parents once it grows, a map larger than that is rejected with a pointer to the vector form.
Table and column names are written in kebab-case, like the rest of the codebase; the conversion to snake_case happens here, at the point where the data becomes a persistence concern.
Everything in this namespace is pure. Validation returns typed error values rather than throwing — the shell decides how to present them.
Pure logic for database seeding.
A seed file is EDN, in either of two shapes.
A map of table -> rows, for the simple case:
{:tasks [{:title "Try the admin UI" :done false}
{:title "Read AGENTS.md" :done true}]}
Or a vector of [table rows] pairs, which is ordered:
[[:users [{:email "admin@example.com"}]]
[:tasks [{:title "Owned by that user" :user-id 1}]]]
Insert order matters as soon as one table references another, and EDN maps
only preserve their written order up to 8 entries — a 9th turns the literal
into a PersistentHashMap and the order becomes hash order. Rather than let a
seed file quietly start inserting children before parents once it grows, a
map larger than that is rejected with a pointer to the vector form.
Table and column names are written in kebab-case, like the rest of the
codebase; the conversion to snake_case happens here, at the point where the
data becomes a persistence concern.
Everything in this namespace is pure. Validation returns typed error values
rather than throwing — the shell decides how to present them.(entries data)Normalises either accepted shape into a seq of [table rows] pairs.
Normalises either accepted shape into a seq of [table rows] pairs.
(row->columns row)Converts one kebab-case row map into its snake_case persistence form.
Converts one kebab-case row map into its snake_case persistence form.
(seed-plan data)Turns validated seed data into an ordered insert plan.
Returns a vector of {:table "tasks" :rows [{...}] :count n}, one entry per
table, in the order the file lists them, so a seed file can express
dependencies between tables by putting parents first.
That ordering is only trustworthy because validate-seed has already
rejected maps too large to preserve it — see max-ordered-map-entries.
Turns validated seed data into an ordered insert plan.
Returns a vector of `{:table "tasks" :rows [{...}] :count n}`, one entry per
table, in the order the file lists them, so a seed file can express
dependencies between tables by putting parents first.
That ordering is only trustworthy because `validate-seed` has already
rejected maps too large to preserve it — see `max-ordered-map-entries`.(table->name table)Persistence name for a seed table key: :audit-logs -> "audit_logs".
Persistence name for a seed table key: :audit-logs -> "audit_logs".
(validate-seed data)Checks the overall shape of parsed seed data.
Returns {:ok data} or {:error {:type :validation-error :message ...}}.
Rejects anything that would otherwise fail deep inside the insert loop with
a less obvious message — including a map too large to keep its order, which
would otherwise insert children before parents and fail on a foreign key.
Checks the overall shape of parsed seed data.
Returns `{:ok data}` or `{:error {:type :validation-error :message ...}}`.
Rejects anything that would otherwise fail deep inside the insert loop with
a less obvious message — including a map too large to keep its order, which
would otherwise insert children before parents and fail on a foreign key.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |