release: WRNexusJS 0.8.2
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-03 02:14:54 +05:30
parent 3c6b659f36
commit 4550a11460
84 changed files with 214 additions and 150 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
"version": "0.8.1",
"version": "0.8.2",
"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.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/authz — part of the WrNexus framework.",
"license": "MIT",
+17 -17
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/cli — part of the WrNexus framework.",
"license": "MIT",
@@ -44,22 +44,22 @@
"wrnexus": "./dist/index.js"
},
"dependencies": {
"@wrnexus/core": "^0.8.1",
"@wrnexus/router": "^0.8.1",
"@wrnexus/csr": "^0.8.1",
"@wrnexus/compiler": "^0.8.1",
"@wrnexus/styles": "^0.8.1",
"@wrnexus/dev-server": "^0.8.1",
"@wrnexus/ui": "^0.8.1",
"@wrnexus/validation": "^0.8.1",
"@wrnexus/i18n": "^0.8.1",
"@wrnexus/mcp": "^0.8.1",
"@wrnexus/playground": "^0.8.1",
"@wrnexus/db": "^0.8.1",
"@wrnexus/plugin": "^0.8.1",
"@wrnexus/syntax": "^0.8.1",
"@wrnexus/typecheck": "^0.8.1",
"@wrnexus/security": "^0.8.1",
"@wrnexus/core": "^0.8.2",
"@wrnexus/router": "^0.8.2",
"@wrnexus/csr": "^0.8.2",
"@wrnexus/compiler": "^0.8.2",
"@wrnexus/styles": "^0.8.2",
"@wrnexus/dev-server": "^0.8.2",
"@wrnexus/ui": "^0.8.2",
"@wrnexus/validation": "^0.8.2",
"@wrnexus/i18n": "^0.8.2",
"@wrnexus/mcp": "^0.8.2",
"@wrnexus/playground": "^0.8.2",
"@wrnexus/db": "^0.8.2",
"@wrnexus/plugin": "^0.8.2",
"@wrnexus/syntax": "^0.8.2",
"@wrnexus/typecheck": "^0.8.2",
"@wrnexus/security": "^0.8.2",
"selfsigned": "^5.5.0"
},
"files": [
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/compiler — part of the WrNexus framework.",
"license": "MIT",
@@ -37,10 +37,10 @@
}
},
"dependencies": {
"@wrnexus/csr": "^0.8.1",
"@wrnexus/syntax": "^0.8.1",
"@wrnexus/store": "^0.8.1",
"@wrnexus/validation": "^0.8.1"
"@wrnexus/csr": "^0.8.2",
"@wrnexus/syntax": "^0.8.2",
"@wrnexus/store": "^0.8.2",
"@wrnexus/validation": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/core — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/csr — part of the WrNexus framework.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1"
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Typed database drivers, migrations, instrumentation, repositories, pagination, and transaction helpers.",
"license": "MIT",
+20 -20
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/dev-server — part of the WrNexus framework.",
"license": "MIT",
@@ -41,25 +41,25 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1",
"@wrnexus/dev-toolbar": "^0.8.1",
"@wrnexus/router": "^0.8.1",
"@wrnexus/ssr": "^0.8.1",
"@wrnexus/csr": "^0.8.1",
"@wrnexus/compiler": "^0.8.1",
"@wrnexus/styles": "^0.8.1",
"@wrnexus/ui": "^0.8.1",
"@wrnexus/validation": "^0.8.1",
"@wrnexus/i18n": "^0.8.1",
"@wrnexus/db": "^0.8.1",
"@wrnexus/pubsub": "^0.8.1",
"@wrnexus/uploader": "^0.8.1",
"@wrnexus/plugin": "^0.8.1",
"@wrnexus/store": "^0.8.1",
"@wrnexus/security": "^0.8.1",
"@wrnexus/observability": "^0.8.1",
"@wrnexus/cache": "^0.8.1",
"@wrnexus/pwa": "^0.8.1"
"@wrnexus/core": "^0.8.2",
"@wrnexus/dev-toolbar": "^0.8.2",
"@wrnexus/router": "^0.8.2",
"@wrnexus/ssr": "^0.8.2",
"@wrnexus/csr": "^0.8.2",
"@wrnexus/compiler": "^0.8.2",
"@wrnexus/styles": "^0.8.2",
"@wrnexus/ui": "^0.8.2",
"@wrnexus/validation": "^0.8.2",
"@wrnexus/i18n": "^0.8.2",
"@wrnexus/db": "^0.8.2",
"@wrnexus/pubsub": "^0.8.2",
"@wrnexus/uploader": "^0.8.2",
"@wrnexus/plugin": "^0.8.2",
"@wrnexus/store": "^0.8.2",
"@wrnexus/security": "^0.8.2",
"@wrnexus/observability": "^0.8.2",
"@wrnexus/cache": "^0.8.2",
"@wrnexus/pwa": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-toolbar",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/dev-toolbar — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Authenticated encryption, key rotation, hashing, and optional application-layer encrypted HTTP envelopes.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1"
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1"
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/i18n",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Locale loading, fallback resolution, SSR/browser translations, formatters, and WRNexusJS language components.",
"license": "MIT",
@@ -42,9 +42,9 @@
"./components/*": "./components/*"
},
"dependencies": {
"@wrnexus/core": "^0.8.1",
"@wrnexus/plugin": "^0.8.1",
"@wrnexus/ui": "^0.8.1"
"@wrnexus/core": "^0.8.2",
"@wrnexus/plugin": "^0.8.2",
"@wrnexus/ui": "^0.8.2"
},
"wrnexus": {
"plugin": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "HS256 JSON Web Tokens, key rotation, access/refresh helpers, scopes, cookies, and auth middleware.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1"
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/mobile — part of the WrNexus framework.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/native": "^0.8.1"
"@wrnexus/native": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/native — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/oauth — part of the WrNexus framework.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/jwt": "^0.8.1"
"@wrnexus/jwt": "^0.8.2"
},
"files": [
"dist",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/plugin",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/plugin — part of the WrNexus framework.",
"license": "MIT",
@@ -49,7 +49,7 @@
}
},
"dependencies": {
"@wrnexus/syntax": "^0.8.1"
"@wrnexus/syntax": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/pubsub — part of the WrNexus framework.",
"license": "MIT",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/queue — part of the WrNexus framework.",
"license": "MIT",
@@ -37,7 +37,7 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1"
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
"version": "0.8.1",
"version": "0.8.2",
"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.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/router — part of the WrNexus framework.",
"license": "MIT",
@@ -37,8 +37,8 @@
}
},
"dependencies": {
"@wrnexus/compiler": "^0.8.1",
"@wrnexus/core": "^0.8.1"
"@wrnexus/compiler": "^0.8.2",
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/ssr — part of the WrNexus framework.",
"license": "MIT",
@@ -45,9 +45,9 @@
}
},
"dependencies": {
"@wrnexus/core": "^0.8.1",
"@wrnexus/store": "^0.8.1",
"@wrnexus/security": "^0.8.1"
"@wrnexus/core": "^0.8.2",
"@wrnexus/store": "^0.8.2",
"@wrnexus/security": "^0.8.2"
},
"files": [
"dist",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/styles — part of the WrNexus framework.",
"license": "MIT",
@@ -37,9 +37,9 @@
}
},
"dependencies": {
"@wrnexus/uploader": "^0.8.1",
"@wrnexus/core": "^0.8.1",
"@wrnexus/plugin": "^0.8.1"
"@wrnexus/uploader": "^0.8.2",
"@wrnexus/core": "^0.8.2",
"@wrnexus/plugin": "^0.8.2"
},
"files": [
"dist",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/syntax",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/syntax — part of the WrNexus framework.",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
"version": "0.8.1",
"version": "0.8.2",
"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.8.1",
"version": "0.8.2",
"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.8.1",
"version": "0.8.2",
"type": "module",
"description": "@wrnexus/ui — part of the WrNexus framework.",
"license": "MIT",
@@ -42,7 +42,7 @@
"./ui.css": "./ui.css"
},
"dependencies": {
"@wrnexus/core": "^0.8.1"
"@wrnexus/core": "^0.8.2"
},
"files": [
"dist",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Secure upload drivers, policies, client runtime, helper functions, and reusable upload components.",
"license": "MIT",
@@ -42,9 +42,9 @@
"./components/*": "./components/*"
},
"dependencies": {
"@wrnexus/core": "^0.8.1",
"@wrnexus/plugin": "^0.8.1",
"@wrnexus/ui": "^0.8.1"
"@wrnexus/core": "^0.8.2",
"@wrnexus/plugin": "^0.8.2",
"@wrnexus/ui": "^0.8.2"
},
"wrnexus": {
"plugin": {
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Shared server/browser schemas, validation helpers, form runtime, and reusable error components.",
"license": "MIT",
@@ -42,9 +42,9 @@
"./components/*": "./components/*"
},
"dependencies": {
"@wrnexus/core": "^0.8.1",
"@wrnexus/plugin": "^0.8.1",
"@wrnexus/ui": "^0.8.1"
"@wrnexus/core": "^0.8.2",
"@wrnexus/plugin": "^0.8.2",
"@wrnexus/ui": "^0.8.2"
},
"wrnexus": {
"plugin": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wrnexus",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"description": "An SSR-first full-stack web framework with server-rendered reactive components. Bun-first, Node-friendly.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ai",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/auth",
"version": "0.8.1",
"version": "0.8.2",
"description": "Complete authentication, account security, MFA, passkeys, recovery, devices, risk, and audit system for WRNexusJS.",
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/authz",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/benchmark",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Deterministic benchmark runner and performance regression budgets for WRNexusJS.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cache",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Tag-aware memory and response caching with stale-while-revalidate for WRNexusJS.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/captcha",
"version": "0.8.1",
"version": "0.8.2",
"description": "First-class CAPTCHA challenges, providers, verification guards, page gates, and WRNexusJS UI.",
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+9
View File
@@ -1980,6 +1980,15 @@ const MIGRATIONS: Migration[] = [
// Package-managed production optimizations require no application source rewrite.
},
},
{
version: "0.8.2",
id: "0.8.2-navigation-and-vitals-stability",
description:
"Stops scroll-driven route prefetch storms, batches browser vitals, and supports telemetry behind trusted reverse proxies.",
apply() {
// Runtime stability fixes require no application source rewrite.
},
},
];
/** 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.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/content",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Typed Markdown content collections, loaders, indexes, feeds, and preview workflows for WRNexusJS.",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/core",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/csr",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+4 -1
View File
@@ -638,7 +638,10 @@ export const NAV_RUNTIME = String.raw`
while (prefetched.size > 20) prefetched.delete(prefetched.keys().next().value);
}
document.addEventListener("pointerover", function (event) {
// Prefetch only on explicit pointer intent. Delegated pointerover fires when
// scrolling moves links underneath a stationary pointer, which can otherwise
// download every link on a long index page.
document.addEventListener("pointerdown", function (event) {
var anchor = event.target && event.target.closest ? event.target.closest("a") : null;
prefetch(anchor);
}, { passive: true });
+12
View File
@@ -82,6 +82,18 @@ test("prefetches focused routes once and reuses the document during navigation",
expect(win.document.querySelector("h1")?.textContent).toBe("Prefetched");
});
test("does not prefetch links merely passing under the pointer while scrolling", async () => {
install(`<div id="app"><a href="/about" id="prefetch">About</a></div>`);
const link = win.document.getElementById("prefetch");
link.dispatchEvent(new win.PointerEvent("pointerover", { bubbles: true }));
await flush();
expect(fetchCalls).toHaveLength(0);
link.dispatchEvent(new win.PointerEvent("pointerdown", { bubbles: true }));
await flush();
expect(fetchCalls).toHaveLength(1);
expect(fetchCalls[0]?.opts.headers["x-wrnexus-prefetch"]).toBe("1");
});
test("ignores cross-origin links (full navigation)", async () => {
install(`<div id="app"><a href="https://other.test/x" id="lnk">x</a></div>`);
win.document.getElementById("lnk").click();
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/db",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-server",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+3 -1
View File
@@ -959,7 +959,9 @@ export function createHandlers(deps: RuntimeDeps): Handlers {
return secure(await readinessHandler(req));
}
if (webVitalsEnabled && url.pathname === webVitalsEndpoint) {
return secure(await webVitalsHandler(req));
// Validate same-origin telemetry against the proxy-resolved public URL,
// rather than the internal listener URL used by the hosting platform.
return secure(await webVitalsHandler(new Request(url, req)));
}
if (webVitalsEnabled && url.pathname === "/__wrnexus/vitals.js") {
return secure(
@@ -3,7 +3,7 @@ import { HealthRegistry } from "@wrnexus/core";
import type { Router } from "@wrnexus/router";
import { createHandlers, type RuntimeDeps } from "../src/runtime.ts";
function runtime(health: HealthRegistry) {
function runtime(health: HealthRegistry, trustProxy = false) {
const router: Router = {
pages: [],
api: [],
@@ -25,7 +25,8 @@ function runtime(health: HealthRegistry) {
getMiddleware: async () => [],
assets: { serve: async () => null },
health,
observability: { enabled: true, sampleRate: 1, exporter: "none" },
security: { trustProxy },
observability: { enabled: true, webVitals: true, sampleRate: 1, exporter: "none" },
} satisfies RuntimeDeps);
}
@@ -45,6 +46,24 @@ test("runtime exposes separate liveness and dependency readiness probes", async
expect(await ready?.json()).toEqual({ status: "down" });
});
test("accepts same-origin vitals behind a trusted HTTPS proxy", async () => {
const handlers = runtime(new HealthRegistry(), true);
const response = await handlers.fetch(
new Request("http://internal:3000/__wrnexus/metrics/vitals", {
method: "POST",
headers: {
origin: "https://wrnexusjs.dev",
"x-forwarded-host": "wrnexusjs.dev",
"x-forwarded-proto": "https",
"content-type": "application/json",
},
body: JSON.stringify({ name: "LCP", value: 1200, route: "/packages" }),
}),
server,
);
expect(response?.status).toBe(204);
});
test("built production responses carry the framework security-header baseline", async () => {
const handlers = runtime(new HealthRegistry());
const response = await handlers.fetch(new Request("https://example.test/healthz"), server);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/dev-toolbar",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/encryption",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/graphql",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "./src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/helpers",
"version": "0.8.1",
"version": "0.8.2",
"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.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/identity",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Enterprise federation, provisioning, machine identity, and privacy governance for WRNexusJS.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/image",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Responsive image planning, secure remote image policies, and performance auditing for WRNexusJS.",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/jwt",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/language-server",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Editor-neutral Language Server Protocol implementation for WRNexus .wrn files.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mcp",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Model Context Protocol server exposing WRNexus application and framework context.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/mobile",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/native",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/oauth",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/observability",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Metrics, Web Vitals collection, request instrumentation, and exporter adapters for WRNexusJS.",
"main": "src/index.ts",
+14 -3
View File
@@ -10,6 +10,9 @@ export function webVitalsClient(options: WebVitalsClientOptions = {}): string {
if (!window.PerformanceObserver || Math.random() > ${sampleRate}) return;
var endpoint = ${endpoint};
var cls = 0;
var lcp = 0;
var inp = 0;
var flushed = false;
function rating(name, value) {
if (name === "LCP") return value <= 2500 ? "good" : value <= 4000 ? "needs-improvement" : "poor";
if (name === "INP") return value <= 200 ? "good" : value <= 500 ? "needs-improvement" : "poor";
@@ -21,9 +24,17 @@ export function webVitalsClient(options: WebVitalsClientOptions = {}): string {
if (navigator.sendBeacon) navigator.sendBeacon(endpoint, new Blob([body], { type: "application/json" }));
else fetch(endpoint, { method: "POST", headers: { "content-type": "application/json" }, body: body, keepalive: true }).catch(function(){});
}
try { new PerformanceObserver(function(list){ var entries=list.getEntries(); var last=entries[entries.length-1]; if(last) send("LCP", last.startTime); }).observe({type:"largest-contentful-paint",buffered:true}); } catch(_) {}
function flush() {
if (flushed) return;
flushed = true;
if (lcp) send("LCP", lcp);
if (inp) send("INP", inp);
if (cls) send("CLS", cls);
}
try { new PerformanceObserver(function(list){ var entries=list.getEntries(); var last=entries[entries.length-1]; if(last) lcp = Math.max(lcp, last.startTime); }).observe({type:"largest-contentful-paint",buffered:true}); } catch(_) {}
try { new PerformanceObserver(function(list){ list.getEntries().forEach(function(e){ if(!e.hadRecentInput) cls += e.value; }); }).observe({type:"layout-shift",buffered:true}); } catch(_) {}
try { new PerformanceObserver(function(list){ var max=0; list.getEntries().forEach(function(e){ max=Math.max(max,e.duration||0); }); if(max) send("INP",max); }).observe({type:"event",durationThreshold:40,buffered:true}); } catch(_) {}
addEventListener("visibilitychange", function(){ if(document.visibilityState === "hidden" && cls) send("CLS", cls); }, { once: true });
try { new PerformanceObserver(function(list){ list.getEntries().forEach(function(e){ inp=Math.max(inp,e.duration||0); }); }).observe({type:"event",durationThreshold:40,buffered:true}); } catch(_) {}
addEventListener("visibilitychange", function(){ if(document.visibilityState === "hidden") flush(); });
addEventListener("pagehide", flush, { once: true });
})();`;
}
@@ -1,7 +1,15 @@
import { describe, expect, test } from "bun:test";
import { createWebVitalsHandler, MetricsRegistry } from "../src/index.ts";
import { createWebVitalsHandler, MetricsRegistry, webVitalsClient } from "../src/index.ts";
describe("@wrnexus/observability", () => {
test("aggregates browser vitals and flushes them once at page exit", () => {
const client = webVitalsClient({ sampleRate: 1 });
expect(client).toContain("var flushed = false");
expect(client).toContain('addEventListener("pagehide", flush');
expect(client).not.toContain('send("INP",max)');
expect(client).not.toContain('send("LCP", last.startTime)');
});
test("records deterministic counters and histograms", () => {
const registry = new MetricsRegistry(() => 123);
registry.increment("requests", 1, { route: "/" });
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/playground",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Secure, shareable WRNexus compiler and UI playground.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/plugin",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pubsub",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/pwa",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Service workers, manifests, offline queues, background sync, push, and conflict resolution for WRNexusJS.",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/queue",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/reactive",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/realtime",
"version": "0.8.1",
"version": "0.8.2",
"description": "Typed realtime rooms, message helpers, presence utilities, package UI blocks, and WRNexusJS integration.",
"type": "module",
"sideEffects": false,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/router",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/security",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"description": "Security policies, safe serialization, SSRF protection, request limits, and secure cookie helpers for WRNexusJS.",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ssr",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/store",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/styles",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/syntax",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/test",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/tracking",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/typecheck",
"version": "0.8.1",
"version": "0.8.2",
"type": "module",
"main": "src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/ui",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/uploader",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/validation",
"version": "0.8.1",
"version": "0.8.2",
"private": true,
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,7 +1,7 @@
import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
const version = "0.8.1";
const version = "0.8.2";
const dependencyGroups = [
"dependencies",