release: WRNexusJS 0.2.32

This commit is contained in:
2026-07-14 22:39:50 +05:30
parent 8b4b7ca5ac
commit 959ed24009
66 changed files with 3135 additions and 648 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/authz",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+9
View File
@@ -357,6 +357,15 @@ const MIGRATIONS: Migration[] = [
// No generated application files require automatic migration.
},
},
{
version: "0.2.32",
id: "fix-runtime-bug",
description:
"Fixes safe encoding and browser parsing of multiline component behavior metadata.",
apply() {
// No generated application files require automatic migration.
},
},
];
/** Release tooling uses this to require an explicit migration entry per version. */
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+3 -1
View File
@@ -925,7 +925,9 @@ function behaviorAttribute(behavior: ComponentBehavior | null): string {
return "";
}
return ` data-wrn-behavior="${attrEscape(JSON.stringify(behavior))}"`;
const encoded = encodeURIComponent(JSON.stringify(behavior));
return ` data-wrn-behavior="${encoded}"`;
}
const INTERP_RE = /\{([^{}]+)\}/g;
+122 -4
View File
@@ -382,11 +382,11 @@ component LifecycleTest {
`),
);
expect(output).toContain(""mount"");
expect(output).toContain("%22mount%22");
expect(output).toContain(""update"");
expect(output).toContain("%22update%22");
expect(output).toContain(""unmount"");
expect(output).toContain("%22unmount%22");
});
test("component watchers compile into behavior metadata", () => {
const output = generate(
@@ -405,7 +405,7 @@ component WatchTest {
`),
);
expect(output).toContain(""state":"visible"");
expect(output).toContain("%22state%22%3A%22visible%22");
expect(output).toContain("console.log");
});
@@ -436,3 +436,121 @@ component BehaviorOnly {
expect(output).toContain("data-wrn-behavior");
});
test("component behavior metadata safely encodes multiline code", () => {
const output = generate(
parse(`
component BackToTop {
state visible = false
functions {
function updateVisibility() {
visible = window.scrollY > 500
}
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: "smooth"
})
}
}
lifecycle {
mount {
updateVisibility()
}
}
watch visible {
console.log(
value,
previous
)
}
view {
<button @click="scrollToTop()">
Top
</button>
}
}
`),
);
expect(output).toContain("data-wrn-behavior=");
expect(output).toContain("%7B");
expect(output).toContain("%22functions%22");
expect(output).not.toContain('data-wrn-behavior="{');
});
test("component watchers compile into behavior metadata", () => {
const output = generate(
parse(`
component WatchTest {
state visible = false
watch visible {
console.log("changed", visible)
}
view {
<div>{visible}</div>
}
}
`),
);
const match = /data-wrn-behavior="([^"]+)"/.exec(output);
expect(match).not.toBeNull();
const behavior = JSON.parse(decodeURIComponent(match![1]));
expect(behavior.watches).toEqual([
{
state: "visible",
body: expect.stringContaining('console.log("changed", visible)'),
},
]);
});
test("component lifecycle hooks compile into behavior metadata", () => {
const output = generate(
parse(`
component LifecycleTest {
state ready = false
lifecycle {
mount {
ready = true
}
update {
console.log(ready)
}
unmount {
ready = false
}
}
view {
<div>{ready}</div>
}
}
`),
);
const match = /data-wrn-behavior="([^"]+)"/.exec(output);
expect(match).not.toBeNull();
const behavior = JSON.parse(decodeURIComponent(match![1]));
expect(behavior.lifecycle.mount).toContain("ready = true");
expect(behavior.lifecycle.update).toContain("console.log(ready)");
expect(behavior.lifecycle.unmount).toContain("ready = false");
});
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+24 -5
View File
@@ -44,13 +44,32 @@ export const REACTIVE_RUNTIME = String.raw`
}
function parseBehavior(element) {
var raw = element.getAttribute("data-wrn-behavior");
if (!raw) return null;
var raw = element.getAttribute(
"data-wrn-behavior",
);
if (!raw) {
return null;
}
try {
var parsed = JSON.parse(raw);
return parsed && typeof parsed === "object" ? parsed : null;
var decoded = decodeURIComponent(raw);
var parsed = JSON.parse(decoded);
if (
!parsed ||
typeof parsed !== "object"
) {
return null;
}
return parsed;
} catch (error) {
console.error("[wrnexus] failed to parse component behavior", error);
console.error(
"[wrnexus] failed to parse component behavior",
error,
);
return null;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/i18n",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
"version": "0.2.31",
"version": "0.2.32",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
"version": "0.2.31",
"version": "0.2.32",
"private": true,
"type": "module",
"main": "src/index.ts",