# @wrnexus/compiler

> Compiler for the `.wrn` language — tokenizes, parses, and lowers `.wrn` page and component files to TypeScript.

Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.

## Overview

`@wrnexus/compiler` turns `.wrn` source into TypeScript that targets the framework's runtime primitives. A `.wrn` file declares either a `page` (a route) or a `component` (a reusable, prop-driven fragment) with blocks for `state`, `view` (plain HTML), `seo`, `style`, `functions`, `api`, `ssr`/`client` data bindings, and `realtime` websocket handlers. The pipeline is `source → Lexer → parse() → PageAst → generate() → TypeScript`. It is a build/server-side library — the WrNexus dev loader calls it to compile `.wrn` files on the fly, surfacing `ParseError` as a readable error page.

## Installation

```bash
bun add @wrnexus/compiler
```

> Private package — the machine must be authenticated to the `wrnexus` npm org
> (a read token in `~/.npmrc`). Requires **Bun** (Node is not supported).

## API

All exports come from the package root (`@wrnexus/compiler`).

### `compileWireFile(source: string): string`

Compile `.wrn` source to a TypeScript module string. Throws `ParseError` on invalid input. The output is prefixed with a `// compiled from .wrn` comment.

### `compile(source: string): CompileResult`

Richer entry point that returns the generated code, the AST, and any diagnostics.

```ts
interface CompileResult {
  code: string;
  ast: PageAst;
  diagnostics: string[];
}
```

On a `ParseError` it pushes the message into `diagnostics` and re-throws.

### `parse(source: string): PageAst`

Run the lexer + recursive-descent parser and return the AST. Throws `ParseError` (lexer `LexError`s are caught and rethrown as `ParseError`).

### `generate(ast: PageAst): string`

Lower a `PageAst` to TypeScript. `page` ASTs become a default-export page component (plus `meta`, optional `layout`, `__wrnexusApi`/method handlers, `websocket`, and SSR/CSR data bindings); `component` ASTs become a module exporting `render(props)` and `__wrnexusComponent`.

### `Lexer`

On-demand lexer for `.wrn`. Yields structural tokens and exposes raw-span readers for the parser.

```ts
class Lexer {
  pos: number;
  constructor(src: string);
  next(): Token; // consume next structural token
  peek(): Token; // look ahead without consuming
  readPath(): string; // route path, e.g. /users/[id]
  readToLineEnd(): string; // rest of line (state/prop initializers)
  readBalancedBraces(): string; // inner text of a { ... } block, string-aware
}
```

`Token` is `{ type: TokenType; value: string; pos: number }`, where `TokenType` is one of `ident`, `string`, `lbrace`, `rbrace`, `lparen`, `rparen`, `at`, `eq`, `comma`, `eof`.

### Errors

| Class        | Thrown by                                         | Meaning                                                         |
| ------------ | ------------------------------------------------- | --------------------------------------------------------------- |
| `ParseError` | `parse`, `compile`, `compileWireFile`, `generate` | Invalid `.wrn` grammar or (rewrapped) lex failure.              |
| `LexError`   | `Lexer`                                           | Unexpected character / unterminated string / unbalanced braces. |

### AST types

Exported type-only symbols describing the parsed tree:

| Type                 | Description                                                                                                                                                                        |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PageAst`            | Root node: `kind` (`"page" \| "component"`), `name`, optional `layout`, `props`, `states`, `seo`, `view`, `styles`, `functions`, `dataApis`, `modeFunctions`, `apis`, `realtimes`. |
| `ViewNode`           | `{ type: "text"; value }` or `{ type: "element"; tag; attrs; children }`.                                                                                                          |
| `Attr`               | `{ name; value; event; boolean? }` — `event` marks `@event` bindings.                                                                                                              |
| `StateDecl`          | `{ name; expr }` — a `state x = <expr>` declaration.                                                                                                                               |
| `SeoBlock`           | `Record<string, string>` from the `seo { ... }` block.                                                                                                                             |
| `ApiBlock`           | `{ method; path; body }` — a top-level `api METHOD /path { ... }`.                                                                                                                 |
| `DataApiBlock`       | `{ mode; name; method; path; body }` — an `api` inside an `ssr`/`client` block.                                                                                                    |
| `DataMode`           | `"ssr" \| "client"`.                                                                                                                                                               |
| `ModeFunctionsBlock` | `{ mode; body }` — a `functions { ... }` inside an `ssr`/`client` block.                                                                                                           |
| `RealtimeBlock`      | `{ name; handlers }` — a `realtime <name> { on evt(args) { ... } }` block.                                                                                                         |

## Usage

Compile a page:

```ts
import { compileWireFile } from "@wrnexus/compiler";

const ts = compileWireFile(`
page Home {
  state count = 0
  seo { title = "Home" description = "Welcome" }
  view {
    <button @click="count++">Clicked {count} times</button>
  }
}
`);
// ts is a TypeScript module: exports `meta`, and a default page component
// returning an HTML string, wrapped in a data-scope for the reactive runtime.
```

Inspect the AST and diagnostics:

```ts
import { compile, ParseError } from "@wrnexus/compiler";

try {
  const { code, ast, diagnostics } = compile(source);
  console.log(ast.kind, ast.name, ast.states.length);
} catch (err) {
  if (err instanceof ParseError) console.error(err.message);
}
```

Drive the parse/codegen stages directly:

```ts
import { parse, generate } from "@wrnexus/compiler";

const ast = parse(componentSource); // ast.kind === "component"
const module = generate(ast); // exports render(props) + __wrnexusComponent
```

Use the lexer standalone:

```ts
import { Lexer } from "@wrnexus/compiler";

const lx = new Lexer("page Home {");
lx.next(); // { type: "ident", value: "page", pos: 0 }
lx.next(); // { type: "ident", value: "Home", pos: 5 }
lx.next(); // { type: "lbrace", value: "{", pos: 10 }
```

## The `.wrn` language (as parsed)

A file opens with `page <Name>` or `component <Name>` followed by a `{ ... }` body containing zero or more members:

- `layout = "<name>"` — selects `app/layouts/<name>.wrn` (pages only).
- `props { name = <default> ... }` — component props; each default's type drives coercion.
- `state <ident> = <expr>` — reactive state seeded from a raw JS expression.
- `view { <html> }` — plain HTML with `{expr}` interpolation in text and attributes, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`. Attribute expressions that reference `state` keep an SSR value and update reactively in the browser.
- `seo { key = "value" ... }` — metadata merged into the generated `meta`.
- `style { <raw css> }` — inlined page/component stylesheet (repeatable).
- `functions { <raw js> }` — shared server-side helpers (repeatable).
- `api <METHOD> <path> { <raw js> }` — route handler, lowered to a `METHOD` export (repeatable).
- `ssr { ... }` / `client { ... }` — data blocks holding `api <name> <METHOD> <path> { ... }` bindings and their own `functions { ... }`.
- `realtime <name> { on <evt>(<args>) { <raw js> } ... }` — websocket handlers, lowered to a `websocket` export.

`view` markup is parsed by a lenient dedicated HTML parser (`parseHtmlView`); HTML void elements (`<br>`, `<img>`, …) take no closing tag. Line comments (`//`) are skipped by the lexer.

## Requirements / Notes

- Pure TypeScript with no runtime dependencies; runs under **Bun** as part of the WrNexus toolchain (Node is not supported).
- Generated modules target WrNexus runtime primitives (`data-scope`, `data-text`, `data-on-*`, `data-for`, `data-component`, `__wrnexus*`/`__wire*` helpers) — consume the output within a WrNexus app, e.g. via `@wrnexus/core`'s dev loader.
