# `MishkaCmsCore.Dev.Seeds`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/dev/seeds.ex#L5)

Dev and stress seeds for MishkaCmsCore resources.

Returns a map with foundation data so extension seeds can build on top:
  %{
    sites: [site, ...],
    users: %{master: [user, ...], tenant: %{site_id => [user, ...]}},
    permissions: [permission, ...]
  }

Seeds run from any caller (a `mix run` script or a LiveView). `Ash.Generator.sequence`
walks the process's `$ancestors` and calls `Process.info/2`, which raises on a
registered-NAME (atom) ancestor such as a LiveView's Socket; the ancestor chain is
pruned to pids before generating so the generators work from any caller.

Site-scoped JS hook names are slugified to lowercase-dashed; the JS compiler prepends
the site name in PascalCase at compile time, so `console-logger` on the `localhost`
site becomes the `LocalhostConsoleLogger` Phoenix LiveView hook identifier.

## What a seeded site is made of

`MishkaCmsCore.Install.StarterContent` first — the theme, the logo, the header, the footer, the
layout, the home page and the error page a stranger's first install gets, and the sign-in pages
every site gets, with the about, contact and privacy pages of `MishkaCmsCore.Dev.StarterPages`
beside the home — and then the pages that site exists to demonstrate, out of its own module:
`MishkaCmsCore.Dev.LocalhostPages`, `MishkaCmsCore.Dev.SiteAPages`,
`MishkaCmsCore.Dev.SiteBPages`. Running the production starter here is what keeps it exercised; a
path nobody opens is a path nobody has seen.

THE HOME IS PRODUCTION'S, NOT THE SITE'S OWN. `/` on every dev site is exactly the page a first
install writes, template and stamps, so dev and production draw the same one. What each site's
own home used to be is its showcase, at `/:lang/showcase`, linked from the header beside the
demos.

Every address written is in the `/:lang` path mode (`MishkaCmsCore.Runtime.Languages`) and none of
them is one this application's own router answers — `/blog` reaches the database, `/mish-blog` is
the hand-written page.

## A DEV SEED IS RUN AGAIN

Reseeding is how a developer picks up whatever the seeds have learned to write since — the media
set is the current example — without dropping the database they have been working in, and it is
the only way anyone exercises this file after changing it. `mix ecto.reset` is the alternative,
and it throws that developer's own work away and signs everyone out.

So every step here CREATES ONLY WHAT IS MISSING. It asks what the site already holds before it
writes, leaves a row it recognises exactly as it is — an admin may have edited it — and counts a
row they ARCHIVED as present as well, because archiving it is what they said about it. That is
`MishkaBlog.Provision`'s rule, and it is the one the whole file follows: nothing below updates.

# `announce`

Prints a seeding progress line, unless `config :mishka_cms_core, seed_announce: false`.

Public because every extension seeds through its own `Dev.Seeds` and they all need the same switch —
a suite that turned it off for the core seeder but still had extensions writing straight to stdout
would fill the test output with progress it cannot silence.

# `categories`

```elixir
@spec categories() :: [%{key: atom(), label: String.t(), module: module()}]
```

The optional extension seed categories the installer's dev step can layer on top of the core
foundation — only those whose seed module is actually loaded. The core data (sites, users,
permissions, components, …) is always seeded by `run/1`, so it is not listed here.

# `dev_seed`

Creates realistic dev seed data: 3 sites a browser on this machine can open, fixed users per site,
real Unix-style permissions, the production starter content, the dev showcase pages, media and JS
hooks.

# `run`

```elixir
@spec run([atom()], (term() -&gt; any())) :: map()
```

Runs the dev seed for local development: the core foundation, every UI-kit component and the
content (always), plus — when chosen — the extension seeds per site (mirrors
`priv/repo/dev_seeds.exs`). For DEV ONLY — never in production. `progress` is called with
`{phase, status, detail}` so the installer can show a live checklist. Returns the core foundation
map.

# `seed_role_accounts`

```elixir
@spec seed_role_accounts(String.t(), [{String.t(), [String.t()]}]) :: [
  MishkaCmsCore.Accounts.User.t()
]
```

One account per role on `site_id`, at `<role>@<site>.test`, holding the role's names — for an
extension's dev seed, after installing it has created its names. An account already there is
reused and granted what it is missing.

# `steps`

```elixir
@spec steps([atom()]) :: [{atom(), String.t()}]
```

The ordered seed phases for `selected`, as `{id, label}` — one progress row per phase (the installer
renders these as a live checklist). Always starts with `:core`, which installs every UI-kit
component too; the extension seeds are added when selected.

# `stress_seed`

Stress seed: creates `count` sites with proportional data per site.

---

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