feat: make state-based attributes reactive

This commit is contained in:
2026-07-14 00:43:07 +05:30
parent 4ce087b238
commit 420706ca3b
61 changed files with 221 additions and 99 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/authz",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/authz — part of the WrNexus framework.",
"license": "MIT",
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/cli — part of the WrNexus framework.",
"license": "MIT",
@@ -28,16 +28,16 @@
"wrnexus": "./dist/index.js"
},
"dependencies": {
"@wrnexus/core": "^0.2.24",
"@wrnexus/router": "^0.2.24",
"@wrnexus/csr": "^0.2.24",
"@wrnexus/compiler": "^0.2.24",
"@wrnexus/styles": "^0.2.24",
"@wrnexus/dev-server": "^0.2.24",
"@wrnexus/ui": "^0.2.24",
"@wrnexus/validation": "^0.2.24",
"@wrnexus/i18n": "^0.2.24",
"@wrnexus/db": "^0.2.24"
"@wrnexus/core": "^0.2.25",
"@wrnexus/router": "^0.2.25",
"@wrnexus/csr": "^0.2.25",
"@wrnexus/compiler": "^0.2.25",
"@wrnexus/styles": "^0.2.25",
"@wrnexus/dev-server": "^0.2.25",
"@wrnexus/ui": "^0.2.25",
"@wrnexus/validation": "^0.2.25",
"@wrnexus/i18n": "^0.2.25",
"@wrnexus/db": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -149,7 +149,7 @@ A file opens with `page <Name>` or `component <Name>` followed by a `{ ... }` bo
- `layout = "<name>"` — selects `app/layouts/<name>.wrn` (pages only).
- `props { name = <default> ... }` — component props; each default's type drives coercion.
- `state <ident> = <expr>` — reactive state seeded from a raw JS expression.
- `view { <html> }` — plain HTML with `{expr}` interpolation, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`.
- `view { <html> }` — plain HTML with `{expr}` interpolation in text and attributes, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`. Attribute expressions that reference `state` keep an SSR value and update reactively in the browser.
- `seo { key = "value" ... }` — metadata merged into the generated `meta`.
- `style { <raw css> }` — inlined page/component stylesheet (repeatable).
- `functions { <raw js> }` — shared server-side helpers (repeatable).
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/compiler — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/core — part of the WrNexus framework.",
"license": "MIT",
+12 -1
View File
@@ -138,14 +138,25 @@ Bun.serve({
Browser side — server-rendered HTML that the reactive runtime hydrates:
```html
<div data-scope="count: 0">
<div data-scope="count: 0, showPassword: false">
<button data-on-click="count++">+1</button>
<span data-text="count"></span>
<p>Total: {{count}}</p>
<input type="{showPassword ? 'text' : 'password'}" />
<button
data-on-click="showPassword = !showPassword"
aria-label="{showPassword ? 'Hide password' : 'Show password'}"
>
Toggle password
</button>
</div>
<script src="/__wrnexus/reactive.js"></script>
```
State interpolation in ordinary attributes is reactive. The compiler keeps the
initial SSR value and emits an internal binding so attributes such as `type`,
`aria-label`, `aria-pressed`, `class`, and `href` update after state changes.
A realtime chat, fully declarative:
```html
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/csr — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.2.24"
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/db — part of the WrNexus framework.",
"license": "MIT",
+13 -13
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
"license": "MIT",
@@ -25,18 +25,18 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.2.24",
"@wrnexus/router": "^0.2.24",
"@wrnexus/ssr": "^0.2.24",
"@wrnexus/csr": "^0.2.24",
"@wrnexus/compiler": "^0.2.24",
"@wrnexus/styles": "^0.2.24",
"@wrnexus/ui": "^0.2.24",
"@wrnexus/validation": "^0.2.24",
"@wrnexus/i18n": "^0.2.24",
"@wrnexus/db": "^0.2.24",
"@wrnexus/pubsub": "^0.2.24",
"@wrnexus/uploader": "^0.2.24"
"@wrnexus/core": "^0.2.25",
"@wrnexus/router": "^0.2.25",
"@wrnexus/ssr": "^0.2.25",
"@wrnexus/csr": "^0.2.25",
"@wrnexus/compiler": "^0.2.25",
"@wrnexus/styles": "^0.2.25",
"@wrnexus/ui": "^0.2.25",
"@wrnexus/validation": "^0.2.25",
"@wrnexus/i18n": "^0.2.25",
"@wrnexus/db": "^0.2.25",
"@wrnexus/pubsub": "^0.2.25",
"@wrnexus/uploader": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/encryption — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.2.24"
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/i18n",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/i18n — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.2.24"
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/jwt — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/mobile — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/native": "^0.2.24"
"@wrnexus/native": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/native — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/oauth — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/queue — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/reactive — part of the WrNexus framework.",
"license": "MIT",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/router — part of the WrNexus framework.",
"license": "MIT",
@@ -21,8 +21,8 @@
}
},
"dependencies": {
"@wrnexus/compiler": "^0.2.24",
"@wrnexus/core": "^0.2.24"
"@wrnexus/compiler": "^0.2.25",
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/ssr — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.2.24"
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/styles — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/uploader": "^0.2.24"
"@wrnexus/uploader": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/test — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/tracking — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/ui — part of the WrNexus framework.",
"license": "MIT",
@@ -22,7 +22,7 @@
"./ui.css": "./ui.css"
},
"dependencies": {
"@wrnexus/core": "^0.2.24"
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/uploader — part of the WrNexus framework.",
"license": "MIT",
@@ -21,7 +21,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.2.24"
"@wrnexus/core": "^0.2.25"
},
"files": [
"dist"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"description": "@wrnexus/validation — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
"version": "0.2.24",
"version": "0.2.25",
"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.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+8
View File
@@ -296,6 +296,14 @@ const MIGRATIONS: Migration[] = [
// Explicit no-op: this release updates package and portal documentation only.
},
},
{
version: "0.2.25",
id: "reactive-state-attributes",
description: "No project-file changes; state expressions in attributes are reactive at runtime",
apply() {
// Explicit no-op: updating @wrnexus/compiler and @wrnexus/csr is sufficient.
},
},
];
/** Release tooling uses this to require an explicit migration entry per version. */
+1 -1
View File
@@ -149,7 +149,7 @@ A file opens with `page <Name>` or `component <Name>` followed by a `{ ... }` bo
- `layout = "<name>"` — selects `app/layouts/<name>.wrn` (pages only).
- `props { name = <default> ... }` — component props; each default's type drives coercion.
- `state <ident> = <expr>` — reactive state seeded from a raw JS expression.
- `view { <html> }` — plain HTML with `{expr}` interpolation, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`.
- `view { <html> }` — plain HTML with `{expr}` interpolation in text and attributes, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`. Attribute expressions that reference `state` keep an SSR value and update reactively in the browser.
- `seo { key = "value" ... }` — metadata merged into the generated `meta`.
- `style { <raw css> }` — inlined page/component stylesheet (repeatable).
- `functions { <raw js> }` — shared server-side helpers (repeatable).
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+40 -11
View File
@@ -79,8 +79,35 @@ function eventAttribute(name: string): string {
return `data-on-${name}`;
}
function renderAttrs(attrs: Attr[], csrId?: string): string {
const rendered = attrs.map(renderAttr).join("");
function reactiveAttrValue(raw: string, reactive: PageReactive): string | null {
let found = false;
const value = raw.replace(/\{([^{}]+)\}/g, (whole, inner: string) => {
const expr = inner.trim();
if (!exprRefsState(expr, reactive.stateNames)) return whole;
found = true;
try {
const result = new Function("with(this){return (" + expr + ");}").call(reactive.scope);
return result == null ? "" : String(result);
} catch {
return whole;
}
});
return found ? value : null;
}
function renderAttrs(attrs: Attr[], csrId?: string, reactive: PageReactive | null = null): string {
let bindIndex = 0;
const rendered = attrs
.map((attr) => {
const base = renderAttr(attr);
if (!reactive || attr.event || attr.boolean || !base || !attr.value.includes("{"))
return base;
const initial = reactiveAttrValue(attr.value, reactive);
if (initial === null) return base;
const marker = JSON.stringify([attr.name, attr.value]);
return ` ${attr.name}="${attrEscape(initial)}" data-wrn-bind-${bindIndex++}="${attrEscape(marker)}"`;
})
.join("");
return csrId ? `${rendered} data-wrnexus-csr="${attrEscape(csrId)}"` : rendered;
}
@@ -312,7 +339,7 @@ function renderNode(
// Void elements (<br>, <img>, …) have no closing tag and no children.
if (VOID_ELEMENTS.has(node.tag.toLowerCase())) {
return `<${node.tag}${renderAttrs(node.attrs, csrId)}>`;
return `<${node.tag}${renderAttrs(node.attrs, csrId, reactive)}>`;
}
const inner =
@@ -331,7 +358,7 @@ function renderNode(
)
.join("");
return `<${node.tag}${renderAttrs(node.attrs, csrId)}>${inner}</${node.tag}>`;
return `<${node.tag}${renderAttrs(node.attrs, csrId, reactive)}>${inner}</${node.tag}>`;
}
function ssrMarker(bindings: SsrBinding[], binding: RenderBinding): string {
@@ -745,14 +772,16 @@ function renderComponentNode(node: ViewNode, ctx: CompCtx): string {
);
}
let bindIndex = 0;
const attrs = node.attrs
.map((a) =>
a.event
? ` ${eventAttribute(a.name)}="${compileAttrValue(a.value, ctx)}"`
: a.boolean
? ` ${a.name}`
: ` ${a.name}="${compileAttrValue(a.value, ctx)}"`,
)
.map((a) => {
if (a.event) return ` ${eventAttribute(a.name)}="${compileAttrValue(a.value, ctx)}"`;
if (a.boolean) return ` ${a.name}`;
const rendered = ` ${a.name}="${compileAttrValue(a.value, ctx)}"`;
if (!a.value.includes("{") || !exprRefsState(a.value, ctx.stateNames)) return rendered;
const marker = attrEscape(JSON.stringify([a.name, a.value]));
return `${rendered} data-wrn-bind-${bindIndex++}="${escLit(marker)}"`;
})
.join("");
// A `data-for` element introduces loop variables for its subtree.
+14
View File
@@ -116,6 +116,20 @@ test("page state text bakes its initial value into a reactive data-text span", (
expect(page).toContain("data-scope"); // state still forces a reactive scope
});
test("page state attributes bake their initial value and retain a reactive binding", () => {
const page = compileWireFile(`page Password {
state show = false
view {
<input type="{show ? 'text' : 'password'}" aria-label="{show ? 'Hide' : 'Show'}">
<button @click="show = !show">Toggle</button>
}
}`);
expect(page).toContain('type="password"');
expect(page).toContain('aria-label="Show"');
expect(page.match(/data-wrn-bind-/g)).toHaveLength(2);
expect(page).toContain("show ? 'text' : 'password'");
});
test("data-for: loop-variable mustaches stay literal (not baked server-side)", () => {
const comp = compileWireFile(
`component TodoList {\n state todos = []\n view { <ul><li data-for="t in todos">{t.text}</li></ul> }\n}`,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+12 -1
View File
@@ -138,14 +138,25 @@ Bun.serve({
Browser side — server-rendered HTML that the reactive runtime hydrates:
```html
<div data-scope="count: 0">
<div data-scope="count: 0, showPassword: false">
<button data-on-click="count++">+1</button>
<span data-text="count"></span>
<p>Total: {{count}}</p>
<input type="{showPassword ? 'text' : 'password'}" />
<button
data-on-click="showPassword = !showPassword"
aria-label="{showPassword ? 'Hide password' : 'Show password'}"
>
Toggle password
</button>
</div>
<script src="/__wrnexus/reactive.js"></script>
```
State interpolation in ordinary attributes is reactive. The compiler keeps the
initial SSR value and emits an internal binding so attributes such as `type`,
`aria-label`, `aria-pressed`, `class`, and `href` update after state changes.
A realtime chat, fully declarative:
```html
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+32
View File
@@ -199,6 +199,38 @@ export const REACTIVE_RUNTIME = String.raw`
});
});
// Reactive ordinary attributes emitted by the compiler. Each marker stores
// [attributeName, originalTemplate], preserving an SSR value while allowing
// state changes to update type, aria-*, class, href, and other attributes.
var bindNodes = [el].concat(Array.prototype.slice.call(el.querySelectorAll("*")));
bindNodes.forEach(function (node) {
if (!owns(node)) return;
Array.prototype.slice.call(node.attributes).forEach(function (marker) {
if (marker.name.indexOf("data-wrn-bind-") !== 0) return;
var binding;
try { binding = JSON.parse(marker.value); } catch (e) { return; }
if (!binding || binding.length !== 2) return;
var name = binding[0];
var template = binding[1];
reactive(function () {
var exact = /^\{([^{}]+)\}$/.exec(template);
var raw;
if (exact) {
try { raw = evalExpr(exact[1].trim()); } catch (e) { return; }
} else {
raw = template.replace(/\{([^{}]+)\}/g, function (_, expr) {
try {
var value = evalExpr(expr.trim());
return value == null ? "" : String(value);
} catch (e) { return ""; }
});
}
if (raw === false || raw == null) node.removeAttribute(name);
else node.setAttribute(name, raw === true ? "" : String(raw));
});
});
});
// {{expr}} / {expr} interpolation in text nodes
var walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null);
var textNode;
+17
View File
@@ -128,6 +128,23 @@ test("data-show toggles visibility on a reactive expression (tabs pattern)", ()
expect(disp("b")).toBe("");
});
test("reactive attribute bindings update input and accessibility attributes", () => {
const win = mount(
`<div data-scope="show: false">
<input id="password" type="password" data-wrn-bind-0='["type","{show ? &#39;text&#39; : &#39;password&#39;}"]'>
<button data-on-click="show = !show" aria-label="Show password"
data-wrn-bind-0='["aria-label","{show ? &#39;Hide password&#39; : &#39;Show password&#39;}"]'>Toggle</button>
</div>`,
);
const input = win.document.getElementById("password") as unknown as HTMLInputElement;
const button = win.document.querySelector("button") as unknown as HTMLElement;
expect(input.type).toBe("password");
expect(button.getAttribute("aria-label")).toBe("Show password");
button.click();
expect(input.type).toBe("text");
expect(button.getAttribute("aria-label")).toBe("Hide password");
});
test("independent signals in one scope update correctly (dependency tracking)", () => {
const win = mount(
`<div data-scope="a: 0, b: 100">
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
"version": "0.2.24",
"version": "0.2.25",
"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.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
"version": "0.2.24",
"version": "0.2.25",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
"version": "0.2.24",
"version": "0.2.25",
"private": true,
"type": "module",
"main": "src/index.ts",