# @rythazhur/mizan (TypeScript)

React client for the mizan framework. See the [monorepo root](../README.md) for full documentation.

## Install

```bash
npm install @rythazhur/mizan@git+https://git.impactsoundworks.com/isw/mizan.git#workspace=react
```

## Usage

You don't use this package directly. You use the **generated hooks**.

This is the pre-kernel React adapter: it ships its own `MizanProvider`
(`src/context.tsx`) that owns HTTP/WebSocket/CSRF/session/context state
directly, rather than subscribing to the `@mizan/base` kernel. It is still
the provider the Django + desktop example wires against. (`DjangoContext`,
`useDjango`, etc. are deprecated aliases for the `Mizan*` names.)

### 1. Configure

```toml
# mizan.toml
output = "src/api"
targets = ["react"]

[source.django]
manage_path = "../backend/manage.py"
command = ["uv", "run", "python"]
```

### 2. Generate

The codegen is the `mizan-generate` Rust binary (source at
`protocol/mizan-codegen/`; `protocol/mizan-generate/` is the npm launcher):

```bash
mizan-generate --config mizan.toml
```

### 3. Wrap your app

```tsx
import { MizanProvider } from '@rythazhur/mizan'

<MizanProvider>
    <App />
</MizanProvider>
```

`MizanProvider` is the only provider you need. It handles HTTP, WebSocket, CSRF, session init, context auto-fetching, and channel connections.

### 4. Use generated hooks

```tsx
import { useCurrentUser, useEcho, useContactForm, useChatChannel } from '@/api'

// Context (SSR-hydrated, auto-refreshed)
const user = useCurrentUser()

// Server function
const echo = useEcho()
const result = await echo({ text: 'hello' })

// Form (Zod + server validation)
const form = useContactForm()
form.set('email', 'test@example.com')
await form.submit()

// Channel (WebSocket)
const chat = useChatChannel({ room: 'general' })
chat.send({ text: 'hello' })
chat.messages  // typed, reactive
```

## Generated Files

The Rust codegen emits per-target files into the configured `output`
directory (Stage 1 is auto-included whenever `react` is a target):

| File | Contents |
|------|----------|
| `types.ts` | Pydantic types |
| `contexts/<name>.ts` | Per-context `fetchXxx` bundles |
| `react.tsx` | `<MizanContext>` provider + typed `use{Hook}()` hooks |
| `channels.ts` / `channels.hooks.tsx` | Channel types + hooks (when the schema carries channels) |
| `index.ts` | Stage 1 re-export root |

## Sub-exports

| Import | When to use |
|--------|------------|
| `@rythazhur/mizan` | Core: `MizanProvider`, hooks, forms, errors |
| `@rythazhur/mizan/channels` | WebSocket channels |
| `@rythazhur/mizan/jwt` | JWT token management |
| `@rythazhur/mizan/client` | HTTP clients (CSR/SSR) |

These are **library internals** used by the generated code. You should import from `@/api` (your generated index), not from the library directly.

## Running Tests

```bash
# Unit tests (Vitest, jsdom)
npm test

# E2E tests (Playwright, real browser)
# Requires Docker backend running
npx playwright test
```
