# Meet Mimlet

**Test data, with character.** Build typed fixtures, keep scenarios connected, and
reproduce failures with explicit seeds and compatible replay records.

Mimlet's core has no runtime dependencies. Schema adapters, generation engines,
protocols, code generation and the local playground are independently installable
packages. [Choose an adapter](/mimlet/guide/adapters.md) for the capabilities you need.

## Install the alpha

The coordinated alpha is available on npm's `next` channel: `@mimlet/*` packages
at `0.1.0-alpha.2`, alongside `hey-api-builders@3.0.0-alpha.2`. Pin matching versions
when reproducing fixtures or generated clients. The existing Hey API `latest` tag
remains on v2.

For the TypeBox example below, use Node **22.18 or newer** and install:

```sh
npm install --save-dev @mimlet/core@0.1.0-alpha.2 @mimlet/typebox@0.1.0-alpha.2 typebox@1.3.34
```

For a plain factory, only `@mimlet/core` is needed. The `mimlet` executable comes
from `@mimlet/codegen`; the core package does not install a CLI. See
[compatibility](/mimlet/guide/compatibility.md) for tested runtime and schema-library versions.

## Your first fixture

This example uses modern `typebox@1.3.34` and `@mimlet/typebox`. It is the same
source compiled and executed by `pnpm test:examples` and shown on the home page.

```ts
import Type from 'typebox';
import { fluent } from '@mimlet/core';
import { fromTypeBox } from '@mimlet/typebox';

const User = Type.Object({
  id: Type.String({ default: 'user-1' }),
  role: Type.Union([
    Type.Literal('reader'),
    Type.Literal('admin'),
  ]),
});

const users = fluent(fromTypeBox(User), ['id', 'role']);
export const admin = users.withRole('admin').buildValidated();
```

The original builder remains unchanged when you call `.with()`. `.build()` creates
schema input; `.buildValidated()` validates that input and returns decoded output.
Those types can differ when your schema has a codec or transform. Use the async
methods when validation or the factory is asynchronous.

## Named fluent helpers

Use `fluent()` to add selected named setters directly to a schema builder. Declare
it once beside the test, then create the variations you need. No builder file or
code-generation step is required:

```sh
npm install --save-dev @mimlet/core@0.1.0-alpha.2 @mimlet/zod@0.1.0-alpha.2 zod@4.6.5
```

```ts
import { fluent } from '@mimlet/core';
import { fromZod } from '@mimlet/zod';
import { z } from 'zod';

const User = z.object({ name: z.string(), age: z.string().transform(Number) });
const users = fluent(fromZod(User), ['name', 'age']);

export const input = users.withName('Ada').withAge('42').build();
export const output = users.withName('Ada').withAge('42').buildValidated();
// input.age is a string; output.age is a number. No builder file is generated.
// Async transitions retain setters and remove synchronous build methods.
export const asynchronous = await users
  .transformAsync(async (value) => value)
  .withName('Grace')
  .withAge('24')
  .buildValidatedAsync();
```

The field tuple is checked against the schema's input. Generic `.with()` remains
available. For finite ordinary records, [named setters](/mimlet/guide/fluent-builders.md) retain
native validation, immutable branches and async capabilities. Existing generated
classes and the Hey API plugin remain optional alternatives.

## Build from source

Use the repository's pinned pnpm toolchain:

```sh
git clone https://github.com/JeffreyNijs/mimlet.git
cd mimlet
corepack pnpm install --frozen-lockfile
corepack pnpm build
corepack pnpm test:examples
corepack pnpm docs:dev
```

The example command installs toolkit tarballs in a temporary consumer, compiles
the recipes, and runs them. If Corepack is unavailable, use pnpm **10.34.5** directly.

## Try an isolated source consumer

From a clean, committed Mimlet checkout, `pnpm release:prepare` creates the verified
tarballs and their digest manifest in `release/`. The command requires a clean
tree and refuses to overwrite an existing release directory.

In a separate test project, install the core and TypeBox adapter tarballs together:

```sh
npm init -y
npm pkg set type=module
npm install /absolute/path/to/checkout/release/mimlet-core-0.1.0-alpha.2.tgz /absolute/path/to/checkout/release/mimlet-typebox-0.1.0-alpha.2.tgz typebox@1.3.34
```

Replace the absolute paths with the checkout you built. Add only the adapters you
need, using the matching release train. This local workflow lets you test source changes before publishing a new version.

## When generation needs your help

Automatic generation has a supported capability set. A native refinement, custom
format or callback may need an explicit factory:

```ts
import Type from 'typebox';
import { fromTypeBoxFactory } from '@mimlet/typebox';

const Code = Type.String({ pattern: '^APP-[0-9]+$' });
const codes = fromTypeBoxFactory(Code, (index: number) => `APP-${index}`);

export const code = codes.buildValidated(42); // 'APP-42'
```

Use a factory to express meaningful domain data while retaining native validation.
A generation failure does not prove that a schema has no valid values.

Continue with [scenarios](/mimlet/guide/correlated-scenarios.md), [replay](/mimlet/guide/sessions-and-replay.md),
or the [coding-agent recipes](/mimlet/guide/agents.md). Existing Hey API users should read the
[migration guide](/mimlet/guide/hey-api-migration.md).
