primate 0.1.4

A small DSL for cross-language constants. Write once, generate typed Rust, TypeScript, and Python.
Documentation
# Getting started

This page walks you from zero to a generated TypeScript module in about
five minutes. The same `.prim` source produces Rust and Python output too;
they're enabled the same way (just add another `[generators.*]` block).

## Install

primate isn't on crates.io yet — install from a checkout:

```bash
git clone https://github.com/valtyr/primate
cd primate
cargo install --path . --locked
```

That puts a release `primate` binary in `~/.cargo/bin`. Verify:

```bash
primate --version
```

## Project layout

primate expects a `primate.toml` at the project root that points at a
directory of `.prim` files and lists the targets to generate.

```text
my-app/
├── primate.toml
├── constants/
│   └── limits.prim
└── (generated output, paths defined in primate.toml)
```

## A minimal config

```toml
# primate.toml
input = "constants"

[[output]]
generator = "typescript"
path      = "web/src/generated/constants/"
```

Each `[[output]]` entry enables one target. The built-ins are `rust`,
`typescript`, and `python`. External plugins plug in here too — see
[Writing a generator](./plugins/writing-a-generator.md).

`path` is a directory for `typescript` and `python` (one file per
namespace); a single `.rs` file for `rust` (one `pub mod` per
namespace). See [`primate build`](./cli/build.md) for the rationale.

## A first `.prim` file

```primate
// constants/limits.prim

/// How long the app waits before giving up on a slow request.
duration TIMEOUT     = 30s
u32      MAX_RETRIES = 5
u64      MAX_UPLOAD  = 100MiB

enum LogLevel: u8 {
    Debug = 0,
    Info  = 1,
    Warn  = 2,
    Error = 3,
}
```

A few things to notice:

- **Type-first.** The type comes before the name — `duration TIMEOUT`,
  not `TIMEOUT: duration`. There's no inference; every constant is
  explicitly typed.
- **Suffixed literals.** `30s` is a duration, `100MiB` is a byte size.
  primate normalizes durations to nanoseconds and applies byte-size
  suffix multipliers at lex time, then bounds-checks the result against
  the declared type.
- **Doc comments.** `///` attaches to the next declaration and shows up
  in generated output where the target language supports docs.
- **One declaration per line.** Newlines terminate; no semicolons.
- **No `namespace` line.** The namespace defaults to the file's path
  relative to `input`. `constants/limits.prim` is in namespace
  `limits`. For nested folders, dirs become `::`-separated segments
  (e.g. `constants/net/limits.prim``net::limits`). You only need
  `namespace foo::bar` as an explicit override; see
  [Declarations]./language/declarations.md for when that's useful.

## Generate

```bash
primate build
```

primate reads `primate.toml`, parses every `.prim` file under `input`,
and writes the generated files. You'll see something like:

```text
Generated: web/src/generated/constants/limits.ts
Generated: web/src/generated/constants/index.ts
```

## What got generated

```typescript
// web/src/generated/constants/limits.ts
// Generated by primate. Do not edit.

/** Severity, integer-backed for fast filtering. */
export enum LogLevel {
  Debug = 0,
  Info = 1,
  Warn = 2,
  Error = 3,
}

/** How long the app waits before giving up on a slow request. */
export const timeout = 30_000 as const;            // milliseconds
export const maxRetries = 5 as const;
export const maxUpload = 104_857_600 as const;
```

…and an `index.ts` re-exporting each namespace, so consumers can write
`import { limits } from "./generated/constants"`.

You can also tune each generator through `primate.toml` — e.g.
`options.duration = "temporal"` on the TypeScript output emits
`Temporal.Duration` values instead of milliseconds. See
[`primate build`](./cli/build.md) for everything tunable.

## Editor setup

primate ships an LSP server (`primate lsp`). The dev experience is
significantly better with it on:

- Diagnostics live in your buffer (parse errors, unknown types,
  length-mismatch on fixed arrays, …).
- Hover docs on type names, including types in other namespaces.
- Go-to-definition for enums and aliases, including across files.
- Find references across the workspace, following `use` imports.
- Format on save.

Setup per editor:

- **[Zed]./editors/zed.md** — install the dev extension.
- **[VS Code]./editors/vscode.md** — install the extension.
- **[Vim]./editors/vim.md** — drop the syntax/ftdetect files in.

## Next steps

- [Language overview]./language/overview.md — the full set of
  declarations, types, and value literals.
- [Cookbook]./cookbook/enums.md — common shapes (matrices, lookup
  tables, platform-specific overrides).
- [Plugins]./plugins/writing-a-generator.md — write a generator for a
  language the built-ins don't cover.