primate 0.1.0

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

A small DSL for cross-language constants. Write your shared values once,
generate typed Rust, TypeScript, and Python — with documentation, enums,
type aliases, and bounds-checked numeric literals carried through to each
target.

```text
constants/                      ┌────────────────────────────┐
└── limits.prim    ─────────►   │  primate build             │
                                └────────────────────────────┘
                ┌─────────────────────────┼─────────────────────────┐
                ▼                         ▼                         ▼
   src/generated/constants.rs    web/src/generated/limits.ts   scripts/generated/limits.py
```

## Why

If you ship a backend, a web client, and a script, you've already written
`MAX_UPLOAD_SIZE = 100 * 1024 * 1024` three times — and at least one of
them is wrong. primate makes that one declaration produce one number per
target, in the form each language wants:

```primate
// constants/limits.prim
//! Application-wide limits.

/// Maximum upload size for a single request.
u64 MAX_UPLOAD_SIZE = 100MiB

/// Time after which an idle session is considered offline.
duration OFFLINE_THRESHOLD = 20min

/// Severity level. Integer-backed for fast filtering.
enum LogLevel: u8 {
    Debug = 0,
    Info  = 1,
    Warn  = 2,
    Error = 3,
}

LogLevel DEFAULT_LEVEL = Info
```

Generated **Rust** (`pub mod` per namespace, `std::time::Duration`,
`#[repr(u8)]` enums):

```rust
pub mod limits {
    pub const MAX_UPLOAD_SIZE: u64 = 104857600;
    pub const OFFLINE_THRESHOLD: std::time::Duration = std::time::Duration::from_nanos(1200000000000);
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    #[repr(i32)]
    pub enum LogLevel {
        Debug = 0,
        Info = 1,
        Warn = 2,
        Error = 3,
    }
    pub const DEFAULT_LEVEL: LogLevel = LogLevel::Info;
}
```

Generated **TypeScript** (one `.ts` per namespace + `index.ts`,
`Temporal.Duration` available, real ES enums):

```typescript
// generated/constants/limits.ts
export enum LogLevel {
  Debug = 0,
  Info = 1,
  Warn = 2,
  Error = 3,
}
export const maxUploadSize = 104857600 as const;
export const offlineThreshold = 1200000 as const;  // milliseconds
export const defaultLevel = LogLevel.Info as const;
```

Generated **Python** (package directory, `IntEnum`, `timedelta`):

```python
# generated/constants/limits.py
from enum import IntEnum
from datetime import timedelta

class LogLevel(IntEnum):
    DEBUG = 0
    INFO = 1
    WARN = 2
    ERROR = 3

MAX_UPLOAD_SIZE: int = 104857600
OFFLINE_THRESHOLD: timedelta = timedelta(seconds=1200)
DEFAULT_LEVEL: LogLevel = LogLevel.INFO
```

## Highlights

- **Unit-suffixed literals.** `30s`, `100MiB`, `5%`, `1w` — readable in
  source, normalized in generated code.
- **Bounds-checked.** `u32 X = 5GiB` is a compile-time error.
- **Cross-namespace `use`.** Files in `constants/auth/*.prim` can
  `use logging::LogLevel`; the right import is emitted in each target.
- **One canonical formatter.** `primate fmt` — no flags.
- **Editor support.** A real LSP server (`primate lsp`) ships with the
  binary: diagnostics, hover, go-to-definition, find-references, format
  on save, and contextual completion (enum variants, unit suffixes).
  Editor integrations for Zed and VS Code are in [`editors/`]./editors.
- **Plugin protocol.** Add a target language by writing any executable
  that reads JSON on stdin and writes JSON on stdout — see
  [docs/plugins]./docs/src/plugins/protocol.md.

## Install

```bash
cargo install primate --locked
```

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

```bash
primate --version
```

## Quick start

```bash
mkdir my-app && cd my-app

cat > primate.toml <<'EOF'
input = "constants"

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

[[output]]
generator = "rust"
path      = "src/generated/constants.rs"
EOF

mkdir constants
cat > constants/limits.prim <<'EOF'
duration TIMEOUT     = 30s
u32      MAX_RETRIES = 5
u64      MAX_UPLOAD  = 100MiB
EOF

primate build
```

You'll see one file per target appear under the configured paths.

## Project status

**v0.1** — usable, but evolving. The language is stable enough to depend
on, generators produce idiomatic output for the three built-ins, and the
LSP works in real editors. Things still on the roadmap: `@deprecated`
attributes, configurable formatter rules, plugin distribution. See
[`docs/src/roadmap.md`](./docs/src/roadmap.md).

## Documentation

The full book is at [`docs/`](./docs/), browsable via mdBook:

```bash
cd docs && mdbook serve --open
```

Top-level pages:

- [Getting started]./docs/src/getting-started.md
- [Language overview]./docs/src/language/overview.md
- [`primate build`]./docs/src/cli/build.md
- [Cookbook]./docs/src/cookbook/enums.md
- [Plugin protocol]./docs/src/plugins/protocol.md

## License

MIT — see [LICENSE](./LICENSE).