# `ActorSimulation.TemplateVersions`
[🔗](https://github.com/d-led/gen_server_virtual_time/blob/v1.1.1/packages/actor_simulation/lib/actor_simulation/template_versions.ex#L1)

The third-party versions that the code generators pin in the projects they
emit.

A generated project is a real project: it has a `conanfile.txt`, a `go.mod`, a
`Cargo.toml`, a `pom.xml` and a CI workflow of its own. Each of those pins
versions, and those pins drift. Keeping the literals scattered across six
generator modules made drift invisible; this module makes it a single table
that can be read, reviewed, and upgraded.

Generators read versions through `get/1`, for example:

    ActorSimulation.TemplateVersions.get(:caf)

## Checking for drift

    mix actor_simulation.upgrade --check

## Upgrading

    mix actor_simulation.upgrade

`sources/0` records where each version comes from, so `mix actor_simulation.upgrade`
can ask upstream for the latest release. Versions marked `:manual` have no
meaningful upstream (a language level, a minimum CMake, a floating release
channel) and are reported but never rewritten automatically.

## Generated projects

The generated project templates and the projects checked into `examples/` and
`generated/` come from the same generators, so after upgrading run
`mix actor_simulation.upgrade --examples` to regenerate the checked-in ones.

# `all`

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

Every pin in presentation order, as `{key, version}` pairs.

# `describe`

```elixir
@spec describe(term()) :: String.t()
```

A human-readable description of `source`, used as the trailing comment in the
rendered version table.

# `get`

```elixir
@spec get(atom()) :: String.t()
```

The version pinned under `key`.

Raises `KeyError` for a key that is not in the table.

## Examples

    iex> ActorSimulation.TemplateVersions.get(:checkout_action) |> String.starts_with?("v")
    true

# `major`

```elixir
@spec major(atom()) :: String.t() | nil
```

The major component of `key`'s version, or `nil` when the pin is not a version
at all (a release channel, or a Go pseudo-version).

Templates that must name a major (a CMake package major, a JS library major)
use this instead of repeating the digit, so the major cannot drift away from
the pinned version.

## Examples

    iex> ActorSimulation.TemplateVersions.major(:caf)
    "1"

    iex> ActorSimulation.TemplateVersions.major(:ponyc_channel)
    nil

# `sources`

```elixir
@spec sources() :: [{atom(), term()}]
```

Where each pin comes from, in the order the table should be presented.

A source is `{kind, target, transform}`:

  * `{:conan_center, package, transform}` — ConanCenter recipes
  * `{:crates_io, crate, transform}` — crates.io
  * `{:go_module, module, transform}` — the Go module proxy
  * `{:maven_central, "group:artifact", transform}` — Maven Central metadata
  * `{:github_release, "owner/repo", transform}` — the latest GitHub release
  * `{:github_tags, "owner/repo", transform}` — the highest semver tag, for
    repositories whose newest release is not the library we pin (Mermaid)
  * `{:manual, reason, :none}` — deliberately not tracked against an upstream

`transform` says how much of the upstream version we take:

  * `:version` — the whole version (`"6.2.0"`)
  * `:latest_within_major` — the newest release on the *current* major, so a
    script never pushes a generated project across a breaking major
  * `:major` — only the major (`"11"`), for pins that float within it
  * `:major_tag` — `"v7"`, how GitHub Actions are pinned
  * `:raw` — the upstream value untouched (`"v0.0.0-2022..."`)

# `versions`

```elixir
@spec versions() :: %{required(atom()) =&gt; String.t()}
```

Every pinned version as a map.

## Examples

    iex> ActorSimulation.TemplateVersions.get(:caf) |> is_binary()
    true

---

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