release: WRNexusJS 0.2.31

This commit is contained in:
2026-07-14 21:58:19 +05:30
parent 3cfdc747fa
commit 8b4b7ca5ac
58 changed files with 1152 additions and 196 deletions
+73
View File
@@ -105,6 +105,19 @@ export interface ModeFunctionsBlock {
body: string;
}
export type LifecycleHookName = "mount" | "update" | "unmount";
export interface LifecycleBlock {
mount?: string;
update?: string;
unmount?: string;
}
export interface WatchBlock {
state: string;
body: string;
}
export interface RealtimeHandler {
event: string;
args: string[];
@@ -141,6 +154,8 @@ export interface PageAst {
functions: string[];
dataApis: DataApiBlock[];
modeFunctions: ModeFunctionsBlock[];
lifecycle: LifecycleBlock;
watches: WatchBlock[];
apis: ApiBlock[];
realtimes: RealtimeBlock[];
}
@@ -210,6 +225,8 @@ export function parse(source: string): PageAst {
const functions: string[] = [];
const dataApis: DataApiBlock[] = [];
const modeFunctions: ModeFunctionsBlock[] = [];
const lifecycle: LifecycleBlock = {};
const watches: WatchBlock[] = [];
const apis: ApiBlock[] = [];
const realtimes: RealtimeBlock[] = [];
@@ -339,6 +356,52 @@ export function parse(source: string): PageAst {
styles.push(lx.readBalancedBraces());
break;
}
case "lifecycle": {
lx.next();
expect("lbrace");
while (lx.peek().type !== "rbrace") {
const hook = lx.peek();
if (hook.type === "eof") {
throw new ParseError("Unexpected end of input inside lifecycle block");
}
if (hook.type !== "ident") {
throw new ParseError(`Expected a lifecycle hook at offset ${hook.pos}`);
}
if (hook.value !== "mount" && hook.value !== "update" && hook.value !== "unmount") {
throw new ParseError(`Unknown lifecycle hook '${hook.value}' at offset ${hook.pos}`);
}
const hookName = hook.value as LifecycleHookName;
lx.next();
if (lifecycle[hookName] !== undefined) {
throw new ParseError(`Duplicate lifecycle hook '${hookName}' at offset ${hook.pos}`);
}
lifecycle[hookName] = lx.readBalancedBraces();
}
expect("rbrace");
break;
}
case "watch": {
lx.next();
const stateName = expect("ident").value;
const body = lx.readBalancedBraces();
watches.push({
state: stateName,
body,
});
break;
}
case "functions": {
lx.next();
functions.push(lx.readBalancedBraces());
@@ -350,6 +413,14 @@ export function parse(source: string): PageAst {
}
expect("rbrace");
const declaredStates = new Set(states.map((state) => state.name));
for (const watcher of watches) {
if (!declaredStates.has(watcher.state)) {
throw new ParseError(`Cannot watch undeclared state '${watcher.state}'`);
}
}
return {
type: "page",
kind,
@@ -363,6 +434,8 @@ export function parse(source: string): PageAst {
functions,
dataApis,
modeFunctions,
lifecycle,
watches,
apis,
realtimes,
};