# @wrnexus/compiler

## Partial-static rendering

Pages can select `render = "partial-static"` and divide their view with `<Static>` and
`<Dynamic>` boundaries. The compiler emits a build-only shell renderer that never evaluates
dynamic-boundary children. `wrnexus build` expands static component mounts into
`dist/partial-shells.json`, records byte/region evidence in `build-report.json`, and embeds
the shell in the production route manifest. At request time the production runtime retains
request-aware layouts, locale/theme metadata and security nonces while streaming dynamic
regions into stable placeholders.

> 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.

Production adapters use `analyzeRuntimeImports` before bundling. Edge, worker,
service-worker, and browser targets reject Node filesystem, TCP, and process
modules with `WRN-RUNTIME-CAPABILITY`. Package manifests can declare supported
`wrnexus.runtimes` and required `wrnexus.requires` capabilities; discovery fails
when the selected deployment cannot satisfy them.

## Server actions

```wrn
action createUser using CreateUserSchema {
  const user = await users.create(input)
  invalidate("users")
  return user
}

view {
  <form @submit="createUser">...</form>
}
```

The compiler produces a schema-aware server registry, a fully inferred action
client, and progressively enhanced form metadata. The shared runtime performs
validation, authentication/permission checks, CSRF verification, serialization,
invalidation reporting, and browser lifecycle events.

## 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.

Static ES module imports may appear before the root declaration. Imported values are
available to server-rendered expressions, including component props:

```wrn
import { appUrl } from "@wrnexus/helpers";

layout PublicLayout {
  view {
    <PublicHeader signInHref="{appUrl('sso', '/sign-in')}" />
  }
}
```

## 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 including top-level `imports`, `kind`, `name`, `types`, typed `props`, typed `states`, `view`, styles, functions, data APIs, lifecycle, and routes. |
| `ViewNode`           | `{ type: "text"; value }` or `{ type: "element"; tag; attrs; children }`.                                                                                     |
| `Attr`               | `{ name; value; event; boolean? }` — `event` marks `@event` bindings.                                                                                         |
| `StateDecl`          | `{ name; valueType?; expr }` — a typed `state x: Type = <expr>` declaration.                                                                                  |
| `PropDecl`           | `{ name; valueType?; required; default }` — a typed prop 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).
- `types { <TypeScript declarations> }` — reusable interfaces and aliases for the current file.
- `props { name: Type = <default> ... }` — typed component props. Omit `= <default>` to make a prop required. Legacy inferred props remain supported.
- `@event name = function` inside `props` — declares a public component event. Emit it from component behavior with `name(detail)` or `$emit("name", detail)`, and consume it with `<Component @name="handler(event)" />`.
- `state <ident>: Type = <expr>` — typed reactive state seeded from a raw JS expression, including native array and object literals. The annotation is optional for backward compatibility.
- `view { <html> }` — plain HTML with `{expr}` interpolation in text and attributes, JSX-style component props such as `items={items}`, `items={[...]}`, and `options={{...}}`, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`. Structured component props are serialized safely for SSR; expressions that reference `state` retain their initial value and update reactively in the browser.
- Client functions automatically commit state changed by `setTimeout` callbacks. For other deferred callbacks (observers, third-party APIs, or detached promise callbacks), call the injected `commit()` function after changing local state; returning/awaiting a promise also commits through the normal function boundary.
- `seo { key = "value" ... }` — metadata merged into the generated `meta`.
- `style { <raw css> }` — inlined page/component stylesheet (repeatable).
- `functions { <TypeScript> }` — helpers with typed parameters and return values. Types remain in server output and are safely erased from browser behavior code.
- `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.
