4.6 KiB
WRN Language Specification 1.0
This document is the canonical public contract for .wrn files in WRNexusJS 0.3.x.
The executable source of truth is @wrnexus/syntax; the compiler re-exports its
parser and AST for compatibility.
Compatibility promise
WRNexusJS 0.3 keeps all previously supported declarations, including:
page,component, andlayoutrootslayout = "...",types,props,state,view,seo, andstylefunctions,lifecycle, andwatchapi,ssr,client, andrealtimedata-for,{#each}, conditions, interpolations, events, andclass:*
New syntax is additive. Existing projects do not need to adopt it immediately. Dynamic attribute expressions should be single-quoted so braces remain unambiguous:
<FeatureList items='{items}' primaryAction='{{ label: "Open" }}' />
The 0.3 updater only rewrites simple, unambiguous prop={expression} values. Nested
brace expressions are left unchanged and reported for manual review.
File structure
A file may begin with TypeScript imports and must contain one root declaration:
import { appUrl } from "@wrnexus/helpers";
page Home {
view {
<main>Home</main>
}
}
Root names are JavaScript identifiers. The valid root kinds are page, component,
and layout.
Execution declarations
runtime = "universal"
hydrate = "visible"
Runtime targets:
server: never emits an interactive browser scopeclient: intended for browser executionuniversal: server-rendered and optionally hydrated
Hydration strategies:
loadidlevisibleinteractionnonemedia:<media-query>
client = "..." remains an alias for a hydration declaration. The existing
client { ... } mode block remains valid.
Props and state
props {
title: string
count: number = 0
enabled: boolean = false
}
state open: boolean = false
A prop without an initializer is required. State always requires an initializer. Typed initializers are validated when their literal type can be determined.
Computed values and effects
computed {
total = price * quantity
label = `${quantity} items`
}
effect {
document.title = label
}
Computed values are dependency-tracked and cached. Effects rerun after a batched reactive update when a referenced state or computed value changes.
Data loading and actions
load server {
return await repository.list(ctx.tenant?.id)
}
load client {
return await fetch("/api/live").then((response) => response.json())
}
action save(input) {
return await repository.save(input)
}
Server and client loaders are exported separately by the compiler. Named actions
are exported individually and through __wrnexusActions for framework adapters.
Security metadata
security {
auth = "required"
csrf = "true"
roles = "admin,editor"
rateLimit = "strict"
}
The compiler exports this metadata as __wrnexusSecurity. Runtime middleware or
plugins can enforce organization-specific policy. Metadata does not replace global
security headers or API validation.
View syntax
view {
<button
type="button"
class:opacity-50='loading'
@click='save()'
>
{loading ? "Saving..." : title}
</button>
}
Supported view features include:
- HTML and component tags
- escaped
{expression}interpolation - event attributes such as
@click,@window:scroll, and@document:click - conditional
class:*attributes data-showdata-for="item, index in items", optionally keyed withkey item.idordata-key="item.id"{#if},{:else if},{:else}, and{/if}{#each items as item, index key item.id}, optional keys, and optional{:empty}branches- comments and scoped styles
Output is escaped by default. Explicit raw HTML APIs must be treated as security boundaries.
Stable diagnostics
Canonical diagnostics use stable identifiers such as:
WRN-PARSE-001WRN-PARSE-MEMBERWRN-PROP-INITIALIZERWRN-SYMBOL-DUPLICATEWRN-HYDRATE-STRATEGYWRN-RUNTIME-TARGETWRN-RUNTIME-SERVER-INTERACTIVEWRN-A11Y-001
Compiler, doctor, build, and future language-server integrations should consume
@wrnexus/syntax diagnostics rather than implementing independent parsers.
AST ownership
The canonical packages are:
@wrnexus/syntax lexer, parser, AST, specification, diagnostics
@wrnexus/compiler code generation and compatibility re-exports
Direct imports from compiler internals are deprecated. Public imports from
@wrnexus/compiler continue to work in 0.3.x.