- Bump every @wrnexus/* dependency to its latest release (ui 0.8.88, styles 0.8.26, cli 0.8.72, core 0.8.16, i18n 0.8.12, ...) and refresh bun.lock and package-lock.json. graphql/native 0.8.8 were republished, so their stale lockfile integrity entries were re-resolved. - wrnexus.config.ts: drop `functions` and `compatibility`, both removed from the framework. - Regenerate package, portal and discovery docs from the installed packages, including the new 0.8.72 release page. - Package pages now install each package's own released version (ui 0.8.88, core 0.8.16) instead of stamping the CLI version on all. - llms.txt / llms-full.txt: the generator kept every earlier run's CLI reference and appended another; it now replaces it, so the guide holds one current reference and no longer advertises the removed `wrnexus compatibility` command. - docs.test.ts: compileWireFile was renamed compileWrnFile; tests follow the per-package install versions and the removed command. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
539 lines
38 KiB
Plaintext
539 lines
38 KiB
Plaintext
page wrnexuscompiler {
|
|
seo {
|
|
title = "@wrnexus/compiler"
|
|
description = "Parser and code generators for the .wrn language."
|
|
}
|
|
|
|
view {
|
|
<div class="docs-shell">
|
|
<a href="#main" class="skip-link">Skip to content</a>
|
|
<header class="topbar">
|
|
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
|
|
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
|
|
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.8.72</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
|
|
</header>
|
|
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
|
|
<main id="main" class="portal-main docs-layout docs-layout--navigation"><aside class="docs-section-menu" aria-label="Documentation sections"><nav>
|
|
<section><strong>Get started</strong><a href="/getting-started">Quick start</a><a href="/tutorial">Tutorial</a><a href="/guides/full-stack-auth-demo">Auth dashboard demo</a><a href="/guides/configuration-and-profiles">Configuration</a></section>
|
|
<section><strong>Build</strong><a href="/guides/pages-and-components">Pages and components</a><a href="/guides/routing">Routing</a><a href="/guides/server-data">Server data</a><a href="/guides/forms-and-validation">Forms and validation</a><a href="/guides/database">Database</a></section>
|
|
<section><strong>Auth and security</strong><a href="/guides/authentication">Authentication</a><a href="/guides/authorization">Authorization</a><a href="/guides/security">Application security</a><a href="/security">Security policy</a></section>
|
|
<section><strong>Reference</strong><a href="/packages">Packages overview</a><a href="/packages/cli">CLI</a><a href="/language">.wrn language</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/examples">Examples</a></section>
|
|
<section class="package-menu"><strong>Packages</strong><a href="/packages/ai">@wrnexus/ai</a><a href="/packages/auth">@wrnexus/auth</a><a href="/packages/authz">@wrnexus/authz</a><a href="/packages/benchmark">@wrnexus/benchmark</a><a href="/packages/cache">@wrnexus/cache</a><a href="/packages/captcha">@wrnexus/captcha</a><a href="/packages/cli">@wrnexus/cli</a><a href="/packages/compiler">@wrnexus/compiler</a><a href="/packages/content">@wrnexus/content</a><a href="/packages/core">@wrnexus/core</a><a href="/packages/csr">@wrnexus/csr</a><a href="/packages/db">@wrnexus/db</a><a href="/packages/dev-server">@wrnexus/dev-server</a><a href="/packages/dev-toolbar">@wrnexus/dev-toolbar</a><a href="/packages/encryption">@wrnexus/encryption</a><a href="/packages/graphql">@wrnexus/graphql</a><a href="/packages/helpers">@wrnexus/helpers</a><a href="/packages/i18n">@wrnexus/i18n</a><a href="/packages/identity">@wrnexus/identity</a><a href="/packages/image">@wrnexus/image</a><a href="/packages/jwt">@wrnexus/jwt</a><a href="/packages/language-server">@wrnexus/language-server</a><a href="/packages/mcp">@wrnexus/mcp</a><a href="/packages/mobile">@wrnexus/mobile</a><a href="/packages/native">@wrnexus/native</a><a href="/packages/oauth">@wrnexus/oauth</a><a href="/packages/observability">@wrnexus/observability</a><a href="/packages/playground">@wrnexus/playground</a><a href="/packages/plugin">@wrnexus/plugin</a><a href="/packages/pubsub">@wrnexus/pubsub</a><a href="/packages/pwa">@wrnexus/pwa</a><a href="/packages/queue">@wrnexus/queue</a><a href="/packages/reactive">@wrnexus/reactive</a><a href="/packages/realtime">@wrnexus/realtime</a><a href="/packages/router">@wrnexus/router</a><a href="/packages/security">@wrnexus/security</a><a href="/packages/ssr">@wrnexus/ssr</a><a href="/packages/store">@wrnexus/store</a><a href="/packages/styles">@wrnexus/styles</a><a href="/packages/syntax">@wrnexus/syntax</a><a href="/packages/test">@wrnexus/test</a><a href="/packages/tracking">@wrnexus/tracking</a><a href="/packages/typecheck">@wrnexus/typecheck</a><a href="/packages/ui">@wrnexus/ui</a><a href="/packages/uploader">@wrnexus/uploader</a><a href="/packages/validation">@wrnexus/validation</a></section>
|
|
</nav></aside><div class="docs-reading-column">
|
|
<article class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/compiler</span></nav><section class="doc-intro"><span class="eyebrow">Core · Package reference</span><h1>@wrnexus/compiler</h1><p>Parser and code generators for the .wrn language.</p><div class="doc-meta"><span>v0.8.30</span><span>Private registry</span><span>Core</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the package:</p><pre><code>bun add @wrnexus/compiler@0.8.30</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><h3 id="partial-static-rendering">Partial-static rendering</h3>
|
|
<p>Pages can select <code>render = "partial-static"</code> and divide their view with <code><Static></code> and <code><Dynamic></code> boundaries. The compiler emits a build-only shell renderer that never evaluates dynamic-boundary children. <code>wrnexus build</code> expands static component mounts into <code>dist/partial-shells.json</code>, records byte/region evidence in <code>build-report.json</code>, 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.</p>
|
|
<blockquote>Compiler for the <code>.wrn</code> language — tokenizes, parses, and lowers <code>.wrn</code> page and component files to TypeScript.</blockquote>
|
|
<p>Part of the <strong>WRNexusJS</strong> framework — an SSR-first, Bun-native full-stack web framework.</p>
|
|
<p>Production adapters use <code>analyzeRuntimeImports</code> before bundling. Edge, worker, service-worker, and browser targets reject Node filesystem, TCP, and process modules with <code>WRN-RUNTIME-CAPABILITY</code>. Package manifests can declare supported <code>wrnexus.runtimes</code> and required <code>wrnexus.requires</code> capabilities; discovery fails when the selected deployment cannot satisfy them.</p>
|
|
<h3 id="server-actions">Server actions</h3>
|
|
<pre data-language="wrn"><code>action createUser using CreateUserSchema {
|
|
const user = await users.create(input)
|
|
invalidate("users")
|
|
return user
|
|
}
|
|
|
|
view {
|
|
<form @submit="createUser">...</form>
|
|
}</code></pre>
|
|
<p>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.</p>
|
|
<h3 id="overview">Overview</h3>
|
|
<p><code>@wrnexus/compiler</code> turns <code>.wrn</code> source into TypeScript that targets the framework's runtime primitives. A <code>.wrn</code> file declares either a <code>page</code> (a route) or a <code>component</code> (a reusable, prop-driven fragment) with blocks for <code>state</code>, <code>view</code> (plain HTML), <code>seo</code>, <code>style</code>, <code>functions</code>, <code>api</code>, <code>ssr</code>/<code>client</code> data bindings, and <code>realtime</code> websocket handlers. The pipeline is <code>source → Lexer → parse() → PageAst → generate() → TypeScript</code>. It is a build/server-side library — the WRNexusJS dev loader calls it to compile <code>.wrn</code> files on the fly, surfacing <code>ParseError</code> as a readable error page.</p>
|
|
<p>Static ES module imports may appear before the root declaration. Imported values are available to server-rendered expressions, including component props:</p>
|
|
<pre data-language="wrn"><code>import { appUrl } from "@wrnexus/helpers";
|
|
|
|
layout PublicLayout {
|
|
view {
|
|
<PublicHeader signInHref="{appUrl('sso', '/sign-in')}" />
|
|
}
|
|
}</code></pre>
|
|
<pre data-language="bash"><code>bun add @wrnexus/compiler</code></pre>
|
|
<blockquote>Private package — the machine must be authenticated to the <code>wrnexus</code> npm org</blockquote>
|
|
<blockquote>(a read token in <code>~/.npmrc</code>). Requires <strong>Bun</strong> (Node is not supported).</blockquote>
|
|
<h3 id="api">API</h3>
|
|
<p>All exports come from the package root (<code>@wrnexus/compiler</code>).</p>
|
|
<h4 id="compilewrnfile-source-string-string"><code>compileWrnFile(source: string): string</code></h4>
|
|
<p>Compile <code>.wrn</code> source to a TypeScript module string. Throws <code>ParseError</code> on invalid input. The output is prefixed with a <code>// compiled from .wrn</code> comment.</p>
|
|
<h4 id="compile-source-string-compileresult"><code>compile(source: string): CompileResult</code></h4>
|
|
<p>Richer entry point that returns the generated code, the AST, and any diagnostics.</p>
|
|
<pre data-language="ts"><code>interface CompileResult {
|
|
code: string;
|
|
ast: PageAst;
|
|
diagnostics: string[];
|
|
}</code></pre>
|
|
<p>On a <code>ParseError</code> it pushes the message into <code>diagnostics</code> and re-throws.</p>
|
|
<h4 id="parse-source-string-pageast"><code>parse(source: string): PageAst</code></h4>
|
|
<p>Run the lexer + recursive-descent parser and return the AST. Throws <code>ParseError</code> (lexer <code>LexError</code>s are caught and rethrown as <code>ParseError</code>).</p>
|
|
<h4 id="generate-ast-pageast-string"><code>generate(ast: PageAst): string</code></h4>
|
|
<p>Lower a <code>PageAst</code> to TypeScript. <code>page</code> ASTs become a default-export page component (plus <code>meta</code>, optional <code>layout</code>, <code>__wrnexusApi</code>/method handlers, <code>websocket</code>, and SSR/CSR data bindings); <code>component</code> ASTs become a module exporting <code>render(props)</code> and <code>__wrnexusComponent</code>.</p>
|
|
<h4 id="lexer"><code>Lexer</code></h4>
|
|
<p>On-demand lexer for <code>.wrn</code>. Yields structural tokens and exposes raw-span readers for the parser.</p>
|
|
<pre data-language="ts"><code>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
|
|
}</code></pre>
|
|
<p><code>Token</code> is <code>{ type: TokenType; value: string; pos: number }</code>, where <code>TokenType</code> is one of <code>ident</code>, <code>string</code>, <code>lbrace</code>, <code>rbrace</code>, <code>lparen</code>, <code>rparen</code>, <code>at</code>, <code>eq</code>, <code>comma</code>, <code>eof</code>.</p>
|
|
<h4 id="errors">Errors</h4>
|
|
<div class="table-wrap"><table>
|
|
<thead><tr><th>Class</th><th>Thrown by</th><th>Meaning</th></tr></thead>
|
|
<tbody><tr><td><code>ParseError</code></td><td><code>parse</code>, <code>compile</code>, <code>compileWrnFile</code>, <code>generate</code></td><td>Invalid <code>.wrn</code> grammar or (rewrapped) lex failure.</td></tr><tr><td><code>LexError</code></td><td><code>Lexer</code></td><td>Unexpected character / unterminated string / unbalanced braces.</td></tr></tbody></table></div>
|
|
<h4 id="ast-types">AST types</h4>
|
|
<p>Exported type-only symbols describing the parsed tree:</p>
|
|
<div class="table-wrap"><table>
|
|
<thead><tr><th>Type</th><th>Description</th></tr></thead>
|
|
<tbody><tr><td><code>PageAst</code></td><td>Root node including top-level <code>imports</code>, <code>kind</code>, <code>name</code>, <code>types</code>, typed <code>props</code>, typed <code>states</code>, <code>view</code>, styles, functions, data APIs, lifecycle, and routes.</td></tr><tr><td><code>ViewNode</code></td><td><code>{ type: "text"; value }</code> or <code>{ type: "element"; tag; attrs; children }</code>.</td></tr><tr><td><code>Attr</code></td><td><code>{ name; value; event; boolean? }</code> — <code>event</code> marks <code>@event</code> bindings.</td></tr><tr><td><code>StateDecl</code></td><td><code>{ name; valueType?; expr }</code> — a typed <code>state x: Type = <expr></code> declaration.</td></tr><tr><td><code>PropDecl</code></td><td><code>{ name; valueType?; required; default }</code> — a typed prop declaration.</td></tr><tr><td><code>SeoBlock</code></td><td><code>Record<string, string></code> from the <code>seo { ... }</code> block.</td></tr><tr><td><code>ApiBlock</code></td><td><code>{ method; path; body }</code> — a top-level <code>api METHOD /path { ... }</code>.</td></tr><tr><td><code>DataApiBlock</code></td><td><code>{ mode; name; method; path; body }</code> — an <code>api</code> inside an <code>ssr</code>/<code>client</code> block.</td></tr><tr><td><code>DataMode</code></td><td>`"ssr" \</td><td>"client"`.</td></tr><tr><td><code>ModeFunctionsBlock</code></td><td><code>{ mode; body }</code> — a <code>functions { ... }</code> inside an <code>ssr</code>/<code>client</code> block.</td></tr><tr><td><code>RealtimeBlock</code></td><td><code>{ name; handlers }</code> — a <code>realtime <name> { on evt(args) { ... } }</code> block.</td></tr></tbody></table></div>
|
|
<h3 id="usage">Usage</h3>
|
|
<p>Compile a page:</p>
|
|
<pre data-language="ts"><code>import { compileWrnFile } from "@wrnexus/compiler";
|
|
|
|
const ts = compileWrnFile(`
|
|
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.</code></pre>
|
|
<p>Inspect the AST and diagnostics:</p>
|
|
<pre data-language="ts"><code>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);
|
|
}</code></pre>
|
|
<p>Drive the parse/codegen stages directly:</p>
|
|
<pre data-language="ts"><code>import { parse, generate } from "@wrnexus/compiler";
|
|
|
|
const ast = parse(componentSource); // ast.kind === "component"
|
|
const module = generate(ast); // exports render(props) + __wrnexusComponent</code></pre>
|
|
<p>Use the lexer standalone:</p>
|
|
<pre data-language="ts"><code>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 }</code></pre>
|
|
<h3 id="the-wrn-language-as-parsed">The <code>.wrn</code> language (as parsed)</h3>
|
|
<p>A file opens with <code>page <Name></code> or <code>component <Name></code> followed by a <code>{ ... }</code> body containing zero or more members:</p>
|
|
<ul>
|
|
<li><code>layout = "<name>"</code> — selects <code>app/layouts/<name>.wrn</code> (pages only).</li>
|
|
<li><code>types { <TypeScript declarations> }</code> — reusable interfaces and aliases for the current file.</li>
|
|
<li><code>props { name: Type = <default> ... }</code> — typed component props. Omit <code>= <default></code> to make a prop required. Legacy inferred props remain supported.</li>
|
|
<li><code>@event name = function</code> inside <code>props</code> — declares a public component event. Emit it from component behavior with <code>name(detail)</code> or <code>$emit("name", detail)</code>, and consume it with <code><Component @name="handler(event)" /></code>.</li>
|
|
<li><code>state <ident>: Type = <expr></code> — typed reactive state seeded from a raw JS expression, including native array and object literals. The annotation is optional for backward compatibility.</li>
|
|
<li><code>view { <html> }</code> — plain HTML with <code>{expr}</code> interpolation in text and attributes, JSX-style component props such as <code>items={items}</code>, <code>items={[...]}</code>, and <code>options={{...}}</code>, hyphenated attributes, boolean attributes, <code>@event="..."</code> client bindings, and <code><!-- comments --></code>. Structured component props are serialized safely for SSR; expressions that reference <code>state</code> retain their initial value and update reactively in the browser.</li>
|
|
<li>Client functions automatically commit state changed by <code>setTimeout</code> callbacks. For other deferred callbacks (observers, third-party APIs, or detached promise callbacks), call the injected <code>commit()</code> function after changing local state; returning/awaiting a promise also commits through the normal function boundary.</li>
|
|
<li><code>seo { key = "value" ... }</code> — metadata merged into the generated <code>meta</code>.</li>
|
|
<li><code>style { <raw css> }</code> — inlined page/component stylesheet (repeatable).</li>
|
|
<li><code>functions { <TypeScript> }</code> — helpers with typed parameters and return values. Types remain in server output and are safely erased from browser behavior code.</li>
|
|
<li><code>api <METHOD> <path> { <raw js> }</code> — route handler, lowered to a <code>METHOD</code> export (repeatable).</li>
|
|
<li><code>ssr { ... }</code> / <code>client { ... }</code> — data blocks holding <code>api <name> <METHOD> <path> { ... }</code> bindings and their own <code>functions { ... }</code>.</li>
|
|
<li><code>realtime <name> { on <evt>(<args>) { <raw js> } ... }</code> — websocket handlers, lowered to a <code>websocket</code> export.</li>
|
|
</ul>
|
|
<p><code>view</code> markup is parsed by a lenient dedicated HTML parser (<code>parseHtmlView</code>); HTML void elements (<code><br></code>, <code><img></code>, …) take no closing tag. Line comments (<code>//</code>) are skipped by the lexer.</p>
|
|
<h3 id="requirements-notes">Requirements / Notes</h3>
|
|
<ul>
|
|
<li>Pure TypeScript with no runtime dependencies; runs under <strong>Bun</strong> as part of the WRNexusJS toolchain (Node is not supported).</li>
|
|
<li>Generated modules target WRNexusJS runtime primitives (<code>data-scope</code>, <code>data-text</code>, <code>data-on-*</code>, <code>data-for</code>, <code>data-component</code>, <code>__wrnexus*</code>/<code>__wrn*</code> helpers) — consume the output within a WRNexusJS app, e.g. via <code>@wrnexus/core</code>'s dev loader.</li>
|
|
</ul></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>import { PageAst, StructuredImportDecl, WrnDiagnostic } from '@wrnexus/syntax';
|
|
export { ActionBlock, ApiBlock, Attr, ComputedDecl, DataApiBlock, DataMode, EffectBlock, EventDecl, FormatWrnOptions, LexError, Lexer, LoadBlock, ModeFunctionsBlock, OutputDecl, PageAst, ParseError, PropDecl, RealtimeBlock, RuntimeFunctionDecl, SeoBlock, StateDecl, StateRuntime, StoreKind, StructuredImportDecl, ViewNode, WrnDiagnostic, assertValidAst, diagnose, diagnosticFromError, eraseFunctionTypes, formatDiagnostic, formatWrn, inferredRuntimeType, parse, runtimeTypeOf } from '@wrnexus/syntax';
|
|
|
|
/**
|
|
* Code generation: lower a `.wrn` AST to TypeScript that targets the framework's
|
|
* existing primitives.
|
|
*
|
|
* state -> a `data-scope` declaration consumed by the runtime
|
|
* view -> an HTML string returned by a page component
|
|
* @event="..." -> data-on-<event>="..."
|
|
* "...{expr}..." -> text kept verbatim ({expr} is mustache for runtime)
|
|
* api="<name>" -> SSR/client data binding declared in a mode block
|
|
* ssrGet/ssrText -> legacy server-side API fetch + render
|
|
* csrGet/csrText -> legacy browser-side API fetch + render
|
|
* style -> tagged local stylesheet metadata promoted by SSR
|
|
* functions -> server-only helpers for API/realtime code
|
|
* api M /p {b} -> export const M = async (ctx) => { b }
|
|
* realtime {..} -> export const websocket = { evt(ws, ...args) { b } }
|
|
*/
|
|
|
|
interface GenerateOptions {
|
|
/** Local names bound to .tsx island imports in this file. */
|
|
islands?: ReadonlySet<string>;
|
|
}
|
|
declare function generate(ast: PageAst, options?: GenerateOptions): string;
|
|
|
|
interface ComponentContractMetadata {
|
|
name: string;
|
|
kind: PageAst["kind"];
|
|
props: Array<{
|
|
name: string;
|
|
type: string;
|
|
required: boolean;
|
|
default?: string;
|
|
options?: string[];
|
|
}>;
|
|
outputs: Array<{
|
|
name: string;
|
|
payloadName?: string;
|
|
payloadType?: string;
|
|
}>;
|
|
functions: Array<{
|
|
name: string;
|
|
runtime: string;
|
|
async: boolean;
|
|
parameters: Array<{
|
|
name: string;
|
|
type: string;
|
|
optional: boolean;
|
|
}>;
|
|
returnType: string;
|
|
}>;
|
|
states: Array<{
|
|
name: string;
|
|
runtime: string;
|
|
type: string;
|
|
initializer: string;
|
|
}>;
|
|
computed: Array<{
|
|
name: string;
|
|
type: string;
|
|
expression: string;
|
|
}>;
|
|
imports: Array<{
|
|
source: string;
|
|
typeOnly: boolean;
|
|
defaultImport?: string;
|
|
namedImports: string[];
|
|
}>;
|
|
}
|
|
declare function createComponentContract(ast: PageAst): ComponentContractMetadata;
|
|
|
|
interface RpcManifestEntry {
|
|
id: string;
|
|
component: string;
|
|
function: string;
|
|
parameters: Array<{
|
|
name: string;
|
|
type: string;
|
|
optional: boolean;
|
|
}>;
|
|
returnType: string;
|
|
}
|
|
declare function rpcManifest(ast: PageAst): RpcManifestEntry[];
|
|
declare function generateServerFunctionsModule(ast: PageAst): string;
|
|
|
|
interface CompileTargets {
|
|
server: string;
|
|
browser: string;
|
|
declarations: string;
|
|
contract: ReturnType<typeof createComponentContract>;
|
|
rpc: ReturnType<typeof rpcManifest>;
|
|
}
|
|
declare function generateTargets(ast: PageAst): CompileTargets;
|
|
|
|
declare function generateBrowserModule(ast: PageAst): string;
|
|
|
|
/**
|
|
* Strip TypeScript from a generated browser module.
|
|
*
|
|
* A client function's body is emitted verbatim, so anything TypeScript-only
|
|
* inside one -- an annotated local, an `as` cast, a local interface -- reaches
|
|
* the browser module as TypeScript source. Codegen removes the types from the
|
|
* function's *signature*, which is what made this easy to miss: the emitted
|
|
* module looked transpiled, and only bodies carried types through.
|
|
*
|
|
* The artifact is written as `.mjs` and read back as plain JavaScript, so the
|
|
* failure surfaced as a syntax error pointing at generated code rather than at
|
|
* the `.wrn` line responsible.
|
|
*/
|
|
declare function stripBrowserTypes(code: string): string;
|
|
|
|
declare function generateDeclarations(ast: PageAst): string;
|
|
|
|
declare function generateStoreModule(ast: PageAst): string;
|
|
/** Standalone browser artifact for an imported `.wrn` store. */
|
|
declare function generateStoreBrowserModule(ast: PageAst): string;
|
|
|
|
type ImportMode = "legacy" | "compatible" | "explicit";
|
|
interface ImportResolverOptions {
|
|
appRoot: string;
|
|
mode?: ImportMode;
|
|
aliases?: Record<string, string>;
|
|
}
|
|
interface ResolvedImport {
|
|
declaration: StructuredImportDecl;
|
|
resolved?: string;
|
|
/** `.tsx` imports are React islands, not `.wrn` components. */
|
|
kind?: "island";
|
|
diagnostic?: {
|
|
code: string;
|
|
message: string;
|
|
severity: "error" | "warning";
|
|
};
|
|
}
|
|
declare function resolveWrnImport(declaration: StructuredImportDecl, importer: string, options: ImportResolverOptions): ResolvedImport;
|
|
declare function resolveWrnImports(declarations: StructuredImportDecl[], importer: string, options: ImportResolverOptions): ResolvedImport[];
|
|
|
|
interface WrnSourceMapEntry {
|
|
generatedLine: number;
|
|
sourceLine: number;
|
|
sourceColumn: number;
|
|
kind: string;
|
|
}
|
|
interface WrnSourceMap {
|
|
version: 1;
|
|
source: string;
|
|
generated: string;
|
|
mappings: WrnSourceMapEntry[];
|
|
}
|
|
declare function createWrnSourceMap(source: string, generated: string): WrnSourceMap;
|
|
|
|
type RouteExecutionKind = "static" | "static-interactive" | "request-ssr" | "authenticated-ssr" | "streaming-ssr" | "dynamic";
|
|
interface RuntimeRequirements {
|
|
kind: RouteExecutionKind;
|
|
canPrerender: boolean;
|
|
needsClientRuntime: boolean;
|
|
/** True when the route mounts a React island and must ship the island runtime. */
|
|
needsIslandRuntime: boolean;
|
|
needsServerRuntime: boolean;
|
|
hydrationStrategy: string | null;
|
|
reasons: string[];
|
|
optimization: OptimizationReport;
|
|
cachePolicy: Record<string, string>;
|
|
requiredPermission: string | null;
|
|
}
|
|
interface OptimizationReport {
|
|
staticNodes: number;
|
|
reactiveRegions: number;
|
|
eliminatedBranches: number;
|
|
unusedState: string[];
|
|
unusedHandlers: string[];
|
|
constantProps: string[];
|
|
unusedLocalCssClasses: string[];
|
|
batchableStateUpdates: number;
|
|
memoizableComponents: string[];
|
|
preloadDependencies: string[];
|
|
serverOnlyModules: string[];
|
|
}
|
|
/** Safe compile-time folding for literal conditional branches. */
|
|
declare function optimizeAst(ast: PageAst): {
|
|
ast: PageAst;
|
|
eliminatedBranches: number;
|
|
};
|
|
declare function analyzeOptimizations(ast: PageAst): OptimizationReport;
|
|
/**
|
|
* A route containing a React island ships JavaScript and can no longer be
|
|
* classified as zero-JS static, so island presence must reach the classifier.
|
|
*/
|
|
declare function routeNeedsIslands(imports: ResolvedImport[]): boolean;
|
|
declare function analyzeRuntimeRequirements(ast: PageAst, options?: {
|
|
hasIslands?: boolean;
|
|
}): RuntimeRequirements;
|
|
|
|
type DeploymentRuntime = "bun" | "node" | "edge" | "worker" | "service-worker" | "browser";
|
|
type RuntimeCapability = "filesystem" | "tcp" | "process" | "websocket" | "crypto" | "streams" | "background-tasks";
|
|
interface RuntimeCapabilityDiagnostic {
|
|
code: "WRN-RUNTIME-CAPABILITY";
|
|
runtime: DeploymentRuntime;
|
|
module: string;
|
|
capability: RuntimeCapability;
|
|
message: string;
|
|
}
|
|
declare function runtimeCapabilities(runtime: DeploymentRuntime): ReadonlySet<RuntimeCapability>;
|
|
declare function analyzeRuntimeImports(source: string, runtime: DeploymentRuntime): RuntimeCapabilityDiagnostic[];
|
|
|
|
declare class NativeCompileError extends Error {
|
|
constructor(message: string);
|
|
}
|
|
/** Compile a parsed `.wrn` page to an Expo Router React Native screen. */
|
|
declare function generateNative(ast: PageAst): string;
|
|
|
|
interface CompilationCacheEntry extends CompileResult {
|
|
key: string;
|
|
file: string;
|
|
sourceHash: string;
|
|
createdAt: number;
|
|
}
|
|
interface CompilationCacheOptions {
|
|
maxEntries?: number;
|
|
now?: () => number;
|
|
}
|
|
interface CompilationCache {
|
|
compile(source: string, file?: string, salt?: string): CompilationCacheEntry;
|
|
get(key: string): CompilationCacheEntry | undefined;
|
|
invalidate(file?: string): number;
|
|
clear(): void;
|
|
size(): number;
|
|
stats(): {
|
|
hits: number;
|
|
misses: number;
|
|
entries: number;
|
|
};
|
|
}
|
|
declare function compilationKey(source: string, file?: string, salt?: string): string;
|
|
declare function createCompilationCache(options?: CompilationCacheOptions): CompilationCache;
|
|
declare class DependencyGraph {
|
|
#private;
|
|
set(file: string, dependencies: Iterable<string>): void;
|
|
remove(file: string): void;
|
|
dependencies(file: string): string[];
|
|
dependents(file: string): string[];
|
|
affected(file: string): string[];
|
|
}
|
|
|
|
type IslandStrategy = "only" | "load" | "visible" | "idle";
|
|
interface IslandDiagnostic {
|
|
code: "WRN-ISLAND-PROPS";
|
|
message: string;
|
|
severity: "error";
|
|
}
|
|
declare function parseIslandStrategy(directives: string[]): IslandStrategy;
|
|
/**
|
|
* Interprets an island attribute value with JSX semantics.
|
|
*
|
|
* `title="Revenue"` is a string, `start={3}` is a number, `flag` alone is
|
|
* `true`. Without this every prop arrives as a string, so `start={3}` would be
|
|
* `"3"` and arithmetic in the island silently concatenates.
|
|
*
|
|
* Returns `dynamic` for a `{…}` value that is not JSON: such expressions are
|
|
* evaluated at runtime and cannot cross the serialization boundary.
|
|
*/
|
|
declare function islandPropValue(raw: string | undefined): {
|
|
value: unknown;
|
|
} | {
|
|
dynamic: string;
|
|
};
|
|
declare function serializeIslandProps(componentName: string, props: Record<string, unknown>): {
|
|
json: string;
|
|
} | {
|
|
diagnostic: IslandDiagnostic;
|
|
};
|
|
declare function renderIslandMarker(input: {
|
|
name: string;
|
|
strategy: IslandStrategy;
|
|
propsJson: string;
|
|
}): string;
|
|
/**
|
|
* Local binding names introduced by island imports.
|
|
*
|
|
* Codegen sees only component tag names, so it needs the set of names that came
|
|
* from `.tsx` imports to tell an island apart from a `.wrn` component.
|
|
*/
|
|
declare function islandNamesFrom(imports: Array<{
|
|
kind?: "island";
|
|
declaration: {
|
|
defaultImport?: string;
|
|
};
|
|
}>): Set<string>;
|
|
|
|
interface IslandInput {
|
|
name: string;
|
|
sourcePath: string;
|
|
}
|
|
interface IslandBuildResult {
|
|
assets: Array<{
|
|
name: string;
|
|
hash: string;
|
|
path: string;
|
|
}>;
|
|
sharedChunks: string[];
|
|
}
|
|
/**
|
|
* Generates the per-island browser entry.
|
|
*
|
|
* Never imports react-dom/server — islands are client-only.
|
|
*/
|
|
declare function generateIslandEntry(input: IslandInput): string;
|
|
declare function assertReactAvailable(appRoot: string): {
|
|
code: "WRN-ISLAND-REACT-MISSING";
|
|
message: string;
|
|
severity: "error";
|
|
} | null;
|
|
/**
|
|
* Bundles island entries. `splitting: true` is required so React is emitted
|
|
* once as a shared chunk rather than duplicated into every island.
|
|
*/
|
|
declare function buildIslands(input: {
|
|
islands: IslandInput[];
|
|
outDir: string;
|
|
/**
|
|
* App root used to resolve the island mount runtime. When given, the runtime
|
|
* is emitted as `runtime.js` in the SAME build as the islands.
|
|
*
|
|
* This is not a convenience: building the runtime separately gives it its own
|
|
* copy of React, and a component rendered by one copy while importing hooks
|
|
* from another fails with "Cannot read properties of null (reading
|
|
* 'useState')". One build with splitting keeps React in a single shared chunk.
|
|
*/
|
|
appRoot?: string;
|
|
}): Promise<IslandBuildResult>;
|
|
|
|
/**
|
|
* @wrnexus/compiler — the `.wrn` language compiler.
|
|
*
|
|
* Parsing and language diagnostics are provided by the canonical
|
|
* `@wrnexus/syntax` package. This package owns platform-specific codegen.
|
|
*/
|
|
|
|
interface CompileResult {
|
|
code: string;
|
|
ast: PageAst;
|
|
/** Backward-compatible plain diagnostic messages. */
|
|
diagnostics: string[];
|
|
/** Structured diagnostics for editors, CI, and the DevToolbar. */
|
|
richDiagnostics: WrnDiagnostic[];
|
|
}
|
|
/** Compile `.wrn` source into an Expo Router React Native screen. */
|
|
declare function compileNativeWrnFile(source: string): string;
|
|
/**
|
|
* Compile `.wrn` source into TypeScript source. Errors include a stable code,
|
|
* source location, code frame, and actionable hint whenever available.
|
|
*/
|
|
declare function compileWrnFile(source: string, filePath?: string): string;
|
|
/** Richer entry point returning the AST and structured diagnostics. */
|
|
declare function compile(source: string, filePath?: string): CompileResult;
|
|
|
|
export { type CompilationCache, type CompilationCacheEntry, type CompilationCacheOptions, type CompileResult, DependencyGraph, type DeploymentRuntime, type IslandBuildResult, type IslandDiagnostic, type IslandInput, type IslandStrategy, NativeCompileError, type OptimizationReport, type RouteExecutionKind, type RuntimeCapability, type RuntimeCapabilityDiagnostic, type RuntimeRequirements, analyzeOptimizations, analyzeRuntimeImports, analyzeRuntimeRequirements, assertReactAvailable, buildIslands, compilationKey, compile, compileNativeWrnFile, compileWrnFile, createCompilationCache, createComponentContract, createWrnSourceMap, generate, generateBrowserModule, generateDeclarations, generateIslandEntry, generateNative, generateServerFunctionsModule, generateStoreBrowserModule, generateStoreModule, generateTargets, islandNamesFrom, islandPropValue, optimizeAst, parseIslandStrategy, renderIslandMarker, resolveWrnImport, resolveWrnImports, routeNeedsIslands, rpcManifest, runtimeCapabilities, serializeIslandProps, stripBrowserTypes };
|
|
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>Compile a page</h3><pre data-language="ts"><code>import { compileWrnFile } from "@wrnexus/compiler";
|
|
|
|
const ts = compileWrnFile(`
|
|
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.</code></pre></article><article class="example-card"><h3>Inspect the AST and diagnostics</h3><pre data-language="ts"><code>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);
|
|
}</code></pre></article><article class="example-card"><h3>Drive the parse/codegen stages directly</h3><pre data-language="ts"><code>import { parse, generate } from "@wrnexus/compiler";
|
|
|
|
const ast = parse(componentSource); // ast.kind === "component"
|
|
const module = generate(ast); // exports render(props) + __wrnexusComponent</code></pre></article><article class="example-card"><h3>Use the lexer standalone</h3><pre data-language="ts"><code>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 }</code></pre></article></div></section></article></div>
|
|
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#partial-static-rendering">Partial-static rendering</a><a class="toc-level-3" href="#server-actions">Server actions</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-4" href="#compilewrnfile-source-string-string">compileWrnFile(source: string): string</a><a class="toc-level-4" href="#compile-source-string-compileresult">compile(source: string): CompileResult</a><a class="toc-level-4" href="#parse-source-string-pageast">parse(source: string): PageAst</a><a class="toc-level-4" href="#generate-ast-pageast-string">generate(ast: PageAst): string</a><a class="toc-level-4" href="#lexer">Lexer</a><a class="toc-level-4" href="#errors">Errors</a><a class="toc-level-4" href="#ast-types">AST types</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-3" href="#the-wrn-language-as-parsed">The .wrn language (as parsed)</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
|
|
</main>
|
|
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.8.72</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
|
|
</div>
|
|
}
|
|
}
|