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

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
@@ -0,0 +1,166 @@
import { afterEach, expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { buildRouter } from "@wrnexus/router";
import { v } from "@wrnexus/validation";
import { createHandlers, type RuntimeDeps } from "../src/runtime.ts";
const roots: string[] = [];
afterEach(() => roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })));
const server = { upgrade: () => false };
test("server actions validate, enforce CSRF, invalidate, and progressively enhance forms", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-action-runtime-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages", "users.ts"), "export default () => '';");
const router = buildRouter(app);
const schema = v.object({ name: v.string().min(2) });
const security: Record<string, string> = {};
let authenticated = false;
let granted = false;
const handlers = createHandlers({
mode: "production",
hmr: false,
router,
loadModule: async () => ({
default: () => `<form method="post" data-wrn-action="createUser"><input name="name"></form>`,
__wrnexusActions: {
createUser: {
schema,
run: (input: { name: string }, ctx: { locals: Record<string, unknown> }) => {
ctx.locals.__wrnexusInvalidatedTags = ["users", "users"];
return { id: `user-${input.name}` };
},
},
},
__wrnexusSecurity: security,
}),
getMiddleware: async () => [
(ctx, next) => {
if (authenticated) ctx.user = { id: "operator" };
ctx.locals.permissions = granted ? ["users.create"] : [];
return next();
},
],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const page = await handlers.fetch(new Request("https://example.test/users"), server);
const html = await page!.text();
expect(html).toContain('name="_csrf"');
expect(html).toContain("/__wrnexus/actions.js");
const cookie = page!.headers.get("set-cookie")!;
const token = /wire-csrf=([^;]+)/.exec(cookie)?.[1];
if (!token) throw new Error("expected CSRF cookie");
const invalid = await handlers.fetch(
new Request("https://example.test/users", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json",
cookie,
"x-wrnexus-action": "createUser",
"x-csrf-token": token,
},
body: JSON.stringify({ name: "x" }),
}),
server,
);
expect(invalid?.status).toBe(422);
expect(await invalid?.json()).toMatchObject({ errors: { name: expect.any(String) } });
const noCsrf = await handlers.fetch(
new Request("https://example.test/users", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json",
cookie,
"x-wrnexus-action": "createUser",
},
body: JSON.stringify({ name: "Ada" }),
}),
server,
);
expect(noCsrf?.status).toBe(403);
const success = await handlers.fetch(
new Request("https://example.test/users", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json",
cookie,
"x-wrnexus-action": "createUser",
"x-csrf-token": token,
},
body: JSON.stringify({ name: "Ada" }),
}),
server,
);
expect(await success?.json()).toEqual({
ok: true,
data: { id: "user-Ada" },
invalidated: ["users"],
});
security.auth = "required";
expect(
(
await handlers.fetch(
new Request("https://example.test/users", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json",
cookie,
"x-wrnexus-action": "createUser",
"x-csrf-token": token,
},
body: JSON.stringify({ name: "Ada" }),
}),
server,
)
)?.status,
).toBe(401);
authenticated = true;
security.permission = "users.create";
expect(
(
await handlers.fetch(
new Request("https://example.test/users", {
method: "POST",
headers: {
"content-type": "application/json",
accept: "application/json",
cookie,
"x-wrnexus-action": "createUser",
"x-csrf-token": token,
},
body: JSON.stringify({ name: "Ada" }),
}),
server,
)
)?.status,
).toBe(403);
granted = true;
const form = new FormData();
form.set("_wrnexus_action", "createUser");
form.set("_csrf", token);
form.set("name", "Grace");
const progressive = await handlers.fetch(
new Request("https://example.test/users", {
method: "POST",
headers: { cookie, origin: "https://example.test" },
body: form,
}),
server,
);
expect(progressive?.status).toBe(303);
expect(progressive?.headers.get("location")).toBe("/users");
});
@@ -0,0 +1,110 @@
import { afterEach, expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { CacheCoordinator } from "@wrnexus/cache";
import { buildRouter } from "@wrnexus/router";
import { createHandlers, type RuntimeDeps } from "../src/runtime.ts";
const roots: string[] = [];
afterEach(() => roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })));
test("declarative route policies cache loader data and expose inspection", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-cache-runtime-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages/dashboard.ts"), "export default () => '';\n");
let loads = 0;
const cache = new CacheCoordinator();
const handlers = createHandlers({
mode: "development",
hmr: false,
router: buildRouter(app),
cache,
loadModule: async () => ({
__wrnexusCache: {
strategy: "stale-while-revalidate",
ttl: "5m",
tags: '["dashboard"]',
vary: '["language"]',
},
__wrnexusLoad: async () => ({ count: ++loads }),
default: (ctx: { count: number }) => `<p>${ctx.count}</p>`,
}),
getMiddleware: async () => [],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const server = { upgrade: () => false };
const first = await handlers.fetch(new Request("https://example.test/dashboard"), server);
const second = await handlers.fetch(new Request("https://example.test/dashboard"), server);
expect(first?.headers.get("x-wrnexus-data-cache")).toBe("MISS");
expect(second?.headers.get("x-wrnexus-data-cache")).toBe("HIT");
expect(loads).toBe(1);
const inspection = await handlers.fetch(
new Request("https://example.test/__wrnexus/cache"),
server,
);
expect((await inspection?.json())?.layers.data).toHaveLength(1);
});
test("safe full-page policies reuse static documents", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-page-cache-runtime-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages/marketing.ts"), "export default () => '';\n");
let renders = 0;
const pageCache = new CacheCoordinator();
const handlers = createHandlers({
mode: "production",
hmr: false,
router: buildRouter(app),
cache: pageCache,
loadModule: async () => ({
__wrnexusCache: { scope: "page", strategy: "fresh", ttl: "5m", tags: '["marketing"]' },
default: () => `<h1>Render ${++renders}</h1>`,
}),
getMiddleware: async () => [],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const server = { upgrade: () => false };
const first = await handlers.fetch(new Request("https://example.test/marketing"), server);
const second = await handlers.fetch(new Request("https://example.test/marketing"), server);
expect(first?.headers.get("x-wrnexus-page-cache")).toBe("MISS");
expect(pageCache.inspect().layers.page).toHaveLength(1);
expect(second?.headers.get("x-wrnexus-page-cache")).toBe("HIT");
const firstHtml = await first!.text();
const secondHtml = await second!.text();
expect(secondHtml).toContain("Render 1");
expect(/nonce="([^"]+)"/.exec(firstHtml)?.[1]).not.toBe(/nonce="([^"]+)"/.exec(secondHtml)?.[1]);
expect(renders).toBe(1);
});
test("full-page cache refuses CSRF-bearing documents", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-page-cache-csrf-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages/account.ts"), "export default () => '';\n");
let renders = 0;
const cache = new CacheCoordinator();
const handlers = createHandlers({
mode: "production",
hmr: false,
router: buildRouter(app),
cache,
loadModule: async () => ({
__wrnexusCache: { scope: "page", strategy: "fresh", ttl: "5m" },
default: () =>
`<form method="post" data-wrn-action="save"><button>${++renders}</button></form>`,
}),
getMiddleware: async () => [],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const server = { upgrade: () => false };
await handlers.fetch(new Request("https://example.test/account"), server);
await handlers.fetch(new Request("https://example.test/account"), server);
expect(renders).toBe(2);
expect(cache.inspect().layers.page).toEqual([]);
});
@@ -53,3 +53,20 @@ test("legacy, compatible, and explicit import modes are enforced from app config
console.warn = originalWarn;
}
});
test("compiler-native reactive elements do not require application imports", () => {
const { root, page } = fixture();
writeFileSync(
page,
`page Home {
state active = "Admin"
view {
<Transition name="fade"><Component is={active}><div data-component-case="Admin">Admin</div></Component></Transition>
<Portal to="body"><p>Notice</p></Portal>
<Async source="profile"><Loading>Loading</Loading><Success data="profile">Ready</Success><Error error="error">Failed</Error></Async>
}
}`,
);
setCompileImportOptions(root, { mode: "explicit" });
expect(() => compileWireArtifacts(page, 5)).not.toThrow();
});
@@ -0,0 +1,72 @@
import { afterEach, expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { buildRouter } from "@wrnexus/router";
import { createHandlers, type RuntimeDeps } from "../src/runtime.ts";
const roots: string[] = [];
afterEach(() => roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })));
test("server loader data is available to page rendering", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-load-runtime-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages/users.ts"), "export default () => '';\n");
const handlers = createHandlers({
mode: "production",
hmr: false,
router: buildRouter(app),
loadModule: async () => ({
__wrnexusLoad: async () => ({ users: ["Ada", "Lin"] }),
default: (ctx: { users: string[]; data: { users: string[] } }) =>
`<p>${ctx.users.join(",")} / ${ctx.data.users.length}</p>`,
}),
getMiddleware: async () => [],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const response = await handlers.fetch(new Request("https://example.test/users"), {
upgrade: () => false,
});
expect(await response!.text()).toContain("Ada,Lin / 2");
});
test("HMR page synchronization initializes request-scoped loader caching", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-hmr-load-runtime-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages/async.ts"), "export default () => '';\n");
const handlers = createHandlers({
mode: "development",
hmr: true,
router: buildRouter(app),
loadModule: async () => ({
__wrnexusLoad: async () => ({ message: "Loaded through HMR" }),
default: (ctx: { message: string }) => `<p>${ctx.message}</p>`,
}),
getMiddleware: async () => [],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const html = await new Promise<string>((resolve, reject) => {
const timeout = setTimeout(() => reject(new Error("HMR response timed out")), 1_000);
handlers.websocket.message(
{
data: { kind: "hmr", baseUrl: "http://localhost", headers: [] },
send(value) {
clearTimeout(timeout);
resolve(String(value));
},
close() {},
},
JSON.stringify({ type: "sync", path: "/async" }),
);
});
const message = JSON.parse(html) as { type: string; html?: string; message?: string };
expect(message.type).toBe("html");
expect(message.message).toBeUndefined();
expect(message.html).toContain("Loaded through HMR");
});
@@ -0,0 +1,55 @@
import { expect, test } from "bun:test";
import { HealthRegistry } from "@wrnexus/core";
import type { Router } from "@wrnexus/router";
import { createHandlers, type RuntimeDeps } from "../src/runtime.ts";
function runtime(health: HealthRegistry) {
const router: Router = {
pages: [],
api: [],
realtime: [],
middlewareFiles: [],
components: [],
layouts: [],
stores: [],
schemas: [],
matchPage: () => null,
matchApi: () => null,
matchRealtime: () => null,
};
return createHandlers({
mode: "production",
hmr: false,
router,
loadModule: async () => ({}),
getMiddleware: async () => [],
assets: { serve: async () => null },
health,
observability: { enabled: true, sampleRate: 1, exporter: "none" },
} satisfies RuntimeDeps);
}
const server = { upgrade: () => false };
test("runtime exposes separate liveness and dependency readiness probes", async () => {
const health = new HealthRegistry();
health.register("database", () => ({ status: "down", message: "offline" }));
const handlers = runtime(health);
const live = await handlers.fetch(new Request("https://example.test/healthz"), server);
const ready = await handlers.fetch(new Request("https://example.test/readyz"), server);
expect(live?.status).toBe(200);
expect(await live?.json()).toEqual({ status: "up" });
expect(ready?.status).toBe(503);
expect(await ready?.json()).toEqual({ status: "down" });
});
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);
expect(response?.headers.get("strict-transport-security")).toContain("max-age=");
expect(response?.headers.get("content-security-policy")).toContain("default-src 'self'");
expect(response?.headers.get("x-content-type-options")).toBe("nosniff");
expect(response?.headers.get("referrer-policy")).toBeTruthy();
});
@@ -0,0 +1,21 @@
import { expect, test } from "bun:test";
import { precomputePartialStaticShell } from "../src/partial-build.ts";
test("precomputes nested page components while erasing dynamic region bodies", async () => {
const result = await precomputePartialStaticShell(
{
__wrnexusBuildStaticShell: () =>
'<div data-component="Card" title="Docs"></div><wrn-dynamic-region data-wrn-dynamic="true"></wrn-dynamic-region>',
},
[
{
name: "Card",
mod: { render: (props) => `<article>${props?.title}</article>` },
},
],
);
expect(result.regions).toBe(1);
expect(result.shell).toContain("<article>Docs</article>");
expect(result.shell).toContain('data-wrn-dynamic-placeholder="wrn-region-0"');
expect(result.shell).not.toContain("wrn-dynamic-region");
});
@@ -1,5 +1,5 @@
import { expect, test } from "bun:test";
import { PWA_CLIENT, usesMobileRuntime } from "../src/runtime.ts";
import { PWA_CLIENT, PWA_DEV_CLEANUP_CLIENT, usesMobileRuntime } from "../src/runtime.ts";
test("PWA registration is valid JavaScript and Trusted Types compatible", () => {
expect(() => new Bun.Transpiler({ loader: "js" }).transformSync(PWA_CLIENT)).not.toThrow();
@@ -7,6 +7,14 @@ test("PWA registration is valid JavaScript and Trusted Types compatible", () =>
expect(PWA_CLIENT).toContain("createScriptURL(swUrl)");
});
test("development PWA cleanup removes stale WRNexus service workers and caches", () => {
expect(() =>
new Bun.Transpiler({ loader: "js" }).transformSync(PWA_DEV_CLEANUP_CLIENT),
).not.toThrow();
expect(PWA_DEV_CLEANUP_CLIENT).toContain("registration.unregister()");
expect(PWA_DEV_CLEANUP_CLIENT).toContain("wrnexus-pwa-");
});
test("mobile runtime is shipped only for pages using mobile or native directives", () => {
expect(usesMobileRuntime('<main class="page">Docs</main>')).toBe(false);
expect(usesMobileRuntime('<button data-native-mobile="share">Share</button>')).toBe(true);
+61 -1
View File
@@ -2,7 +2,67 @@ import { expect, test } from "bun:test";
import { mkdtempSync, rmSync, utimesSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { invalidateModule, loadModule, setCompileCacheDir } from "../src/pipeline.ts";
import {
compileWireArtifacts,
compileWireArtifactsAsync,
getWrnCompileMetrics,
invalidateModule,
loadModule,
resetWrnCompileMetrics,
setCompileCacheDir,
setDevCompilerPipeline,
} from "../src/pipeline.ts";
test("development compilation awaits plugin AST and code transforms", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-plugin-pipeline-"));
const file = join(root, "page.wrn");
let astTransformed = false;
setCompileCacheDir(join(root, ".wrnexus"));
setDevCompilerPipeline({
async transformAst(ast) {
await Promise.resolve();
astTransformed = true;
return ast;
},
async transformCode(code) {
await Promise.resolve();
return `${code}\nexport const pluginTransformed = true;\n`;
},
virtualModules: new Map(),
});
try {
writeFileSync(file, "page Home { view { <h1>Plugin</h1> } }\n");
const artifact = await compileWireArtifactsAsync(file);
expect(astTransformed).toBeTrue();
expect((await import(artifact.main)).pluginTransformed).toBeTrue();
} finally {
setDevCompilerPipeline(null);
rmSync(root, { recursive: true, force: true });
}
});
test("WRN compilation exposes cache hit, miss, timing, and error metrics", () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-cache-metrics-"));
const file = join(root, "page.wrn");
setCompileCacheDir(join(root, ".wrnexus"));
resetWrnCompileMetrics();
try {
writeFileSync(file, "page Home { view { <h1>Metrics</h1> } }\n");
compileWireArtifacts(file);
compileWireArtifacts(file);
writeFileSync(file, "page Broken { view { <h1> } }\n");
expect(() => compileWireArtifacts(file)).toThrow();
expect(getWrnCompileMetrics()).toMatchObject({
hits: 1,
misses: 2,
compilations: 1,
errors: 1,
});
expect(getWrnCompileMetrics().totalDurationMs).toBeGreaterThanOrEqual(0);
} finally {
rmSync(root, { recursive: true, force: true });
}
});
test("invalidateModule loads changed server modules without restarting the process", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-hmr-"));
@@ -0,0 +1,30 @@
import { afterEach, expect, test } from "bun:test";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { buildRouter } from "@wrnexus/router";
import { createHandlers, type RuntimeDeps } from "../src/runtime.ts";
const roots: string[] = [];
afterEach(() => roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true })));
test("plugin render lifecycle transforms final documents", async () => {
const root = mkdtempSync(join(tmpdir(), "wrnexus-plugin-render-"));
roots.push(root);
const app = join(root, "app");
mkdirSync(join(app, "pages"), { recursive: true });
writeFileSync(join(app, "pages/index.ts"), "export default () => '';\n");
const handlers = createHandlers({
mode: "development",
hmr: false,
router: buildRouter(app),
loadModule: async () => ({ default: () => "<h1>Home</h1>" }),
renderHtml: (html) => html.replace("</body>", "<!-- plugin-render --></body>"),
getMiddleware: async () => [],
assets: { serve: async () => null },
} satisfies RuntimeDeps);
const response = await handlers.fetch(new Request("https://example.test/"), {
upgrade: () => false,
});
expect(await response?.text()).toContain("<!-- plugin-render -->");
});
@@ -0,0 +1,74 @@
import { expect, test } from "bun:test";
import { createProductionHandlers, type ProdManifest } from "../src/prod.ts";
const manifest: ProdManifest = {
pages: [
{
raw: "/",
mod: { default: () => "<main>Production artifact</main>", meta: { title: "Prod" } },
},
{
raw: "/partial",
staticShell:
'<main>Build shell<template data-wrn-dynamic-placeholder="wrn-region-0"></template></main>',
mod: {
default: () =>
'<main>Request shell<wrn-dynamic-region data-wrn-dynamic="true"><strong>User 42</strong></wrn-dynamic-region></main>',
meta: { title: "Partial" },
__wrnexusRender: "partial-static",
},
},
{
raw: "/async",
mod: {
default: () => "<main>Async page</main>",
meta: { title: "Async" },
__wrnexusClientLoad: async () => ({ users: [{ id: 1, name: "Ada" }] }),
},
},
],
api: [],
realtime: [],
middleware: [],
components: [],
layouts: [],
};
const server = { upgrade: () => false } as never;
test("supervised production runtime injects reconnecting DOM-morph support", async () => {
const handlers = createProductionHandlers(manifest, { developmentRuntime: true });
const response = await handlers.fetch(new Request("http://localhost/"), server);
expect(response).toBeInstanceOf(Response);
expect(await (response as Response).text()).toContain("/__wrnexus/hmr");
});
test("production streams request regions into the build-time static shell", async () => {
const handlers = createProductionHandlers(manifest, {});
const response = (await handlers.fetch(
new Request("http://localhost/partial"),
server,
)) as Response;
const html = await response.text();
expect(response.headers.get("x-wrnexus-static-shell")).toBe("build");
expect(html).toContain("Build shell");
expect(html).not.toContain("Request shell");
expect(html).toContain("User 42");
});
test("normal production output remains free of development HMR", async () => {
const handlers = createProductionHandlers(manifest, {});
const response = await handlers.fetch(new Request("http://localhost/"), server);
expect(await (response as Response).text()).not.toContain("/__wrnexus/hmr");
});
test("production client-load endpoint returns only the requested named result", async () => {
const handlers = createProductionHandlers(manifest, {});
const response = (await handlers.fetch(
new Request("http://localhost/__wrnexus/client-load?route=%2Fasync&name=users"),
server,
)) as Response;
expect(response.status).toBe(200);
expect(response.headers.get("cache-control")).toBe("private, no-store");
expect(await response.json()).toEqual({ data: [{ id: 1, name: "Ada" }] });
});