From 8d5d4b8f129579644ef425f439153ecd15d65df5 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Sun, 2 Aug 2026 23:57:41 +0530 Subject: [PATCH] docs: update portal for WRNexusJS 0.8.0 --- app/docs.test.ts | 25 +- app/pages/404.wrn | 4 +- app/pages/access.wrn | 6 +- app/pages/architecture.wrn | 6 +- app/pages/benchmarks.wrn | 4 +- app/pages/changelog.wrn | 6 +- app/pages/examples.wrn | 6 +- app/pages/getting-started.wrn | 6 +- app/pages/guides/api-routes.wrn | 6 +- app/pages/guides/authentication.wrn | 6 +- app/pages/guides/authorization.wrn | 6 +- .../guides/configuration-and-profiles.wrn | 6 +- app/pages/guides/database.wrn | 6 +- app/pages/guides/deployment.wrn | 6 +- app/pages/guides/forms-and-validation.wrn | 6 +- app/pages/guides/i18n-and-themes.wrn | 6 +- app/pages/guides/middleware.wrn | 6 +- app/pages/guides/mobile.wrn | 6 +- app/pages/guides/observability.wrn | 6 +- app/pages/guides/pages-and-components.wrn | 6 +- app/pages/guides/project-structure.wrn | 6 +- app/pages/guides/pubsub.wrn | 6 +- app/pages/guides/queues.wrn | 6 +- app/pages/guides/realtime.wrn | 6 +- app/pages/guides/routing.wrn | 6 +- app/pages/guides/security.wrn | 6 +- app/pages/guides/server-data.wrn | 6 +- app/pages/guides/testing.wrn | 6 +- app/pages/guides/troubleshooting.wrn | 6 +- app/pages/guides/upgrading.wrn | 6 +- app/pages/guides/uploads.wrn | 6 +- app/pages/guides/workspaces-and-gateway.wrn | 8 +- app/pages/index.wrn | 12 +- app/pages/language.wrn | 6 +- app/pages/license.wrn | 4 +- app/pages/packages.wrn | 51 +- app/pages/packages/ai.wrn | 131 +- app/pages/packages/auth.wrn | 46 +- app/pages/packages/authz.wrn | 6 +- app/pages/packages/benchmark.wrn | 68 + app/pages/packages/cache.wrn | 242 + app/pages/packages/captcha.wrn | 31 +- app/pages/packages/cli.wrn | 28 +- app/pages/packages/compiler.wrn | 60 +- app/pages/packages/content.wrn | 177 + app/pages/packages/core.wrn | 237 +- app/pages/packages/csr.wrn | 45 +- app/pages/packages/db.wrn | 151 +- app/pages/packages/dev-server.wrn | 73 +- app/pages/packages/dev-toolbar.wrn | 14 +- app/pages/packages/encryption.wrn | 196 +- app/pages/packages/graphql.wrn | 26 + app/pages/packages/helpers.wrn | 6 +- app/pages/packages/i18n.wrn | 312 +- app/pages/packages/identity.wrn | 240 + app/pages/packages/image.wrn | 226 + app/pages/packages/jwt.wrn | 136 +- app/pages/packages/language-server.wrn | 164 + app/pages/packages/mcp.wrn | 50 + app/pages/packages/mobile.wrn | 52 +- app/pages/packages/native.wrn | 20 +- app/pages/packages/oauth.wrn | 49 +- app/pages/packages/observability.wrn | 133 + app/pages/packages/playground.wrn | 66 + app/pages/packages/plugin.wrn | 72 +- app/pages/packages/pubsub.wrn | 41 +- app/pages/packages/pwa.wrn | 183 + app/pages/packages/queue.wrn | 193 +- app/pages/packages/reactive.wrn | 58 +- app/pages/packages/realtime.wrn | 274 ++ app/pages/packages/router.wrn | 6 +- app/pages/packages/security.wrn | 66 + app/pages/packages/ssr.wrn | 19 +- app/pages/packages/store.wrn | 69 + app/pages/packages/styles.wrn | 80 +- app/pages/packages/syntax.wrn | 9 +- app/pages/packages/test.wrn | 57 +- app/pages/packages/tracking.wrn | 6 +- app/pages/packages/typecheck.wrn | 72 + app/pages/packages/ui.wrn | 6 +- app/pages/packages/uploader.wrn | 191 +- app/pages/packages/validation.wrn | 211 +- app/pages/releases/0.2.15.wrn | 69 +- app/pages/releases/0.2.17.wrn | 69 +- app/pages/releases/0.2.18.wrn | 69 +- app/pages/releases/0.2.19.wrn | 69 +- app/pages/releases/0.2.20.wrn | 69 +- app/pages/releases/0.2.21.wrn | 69 +- app/pages/releases/0.2.22.wrn | 69 +- app/pages/releases/0.2.23.wrn | 69 +- app/pages/releases/0.2.24.wrn | 69 +- app/pages/releases/0.2.25.wrn | 69 +- app/pages/releases/0.2.26.wrn | 69 +- app/pages/releases/0.2.27.wrn | 69 +- app/pages/releases/0.2.28.wrn | 69 +- app/pages/releases/0.2.29.wrn | 69 +- app/pages/releases/0.2.30.wrn | 69 +- app/pages/releases/0.2.31.wrn | 69 +- app/pages/releases/0.2.32.wrn | 69 +- app/pages/releases/0.2.33.wrn | 69 +- app/pages/releases/0.2.34.wrn | 69 +- app/pages/releases/0.2.35.wrn | 69 +- app/pages/releases/0.2.36.wrn | 69 +- app/pages/releases/0.2.37.wrn | 69 +- app/pages/releases/0.2.38.wrn | 69 +- app/pages/releases/0.2.39.wrn | 69 +- app/pages/releases/0.2.40.wrn | 69 +- app/pages/releases/0.2.41.wrn | 69 +- app/pages/releases/0.2.42.wrn | 69 +- app/pages/releases/0.2.43.wrn | 69 +- app/pages/releases/0.2.44.wrn | 69 +- app/pages/releases/0.2.45.wrn | 69 +- app/pages/releases/0.2.46.wrn | 69 +- app/pages/releases/0.2.47.wrn | 69 +- app/pages/releases/0.2.48.wrn | 69 +- app/pages/releases/0.2.49.wrn | 69 +- app/pages/releases/0.2.50.wrn | 69 +- app/pages/releases/0.2.51.wrn | 69 +- app/pages/releases/0.2.52.wrn | 69 +- app/pages/releases/0.2.53.wrn | 69 +- app/pages/releases/0.2.54.wrn | 69 +- app/pages/releases/0.2.55.wrn | 69 +- app/pages/releases/0.2.56.wrn | 69 +- app/pages/releases/0.2.57.wrn | 69 +- app/pages/releases/0.2.58.wrn | 69 +- app/pages/releases/0.2.59.wrn | 69 +- app/pages/releases/0.2.60.wrn | 69 +- app/pages/releases/0.2.61.wrn | 69 +- app/pages/releases/0.2.62.wrn | 69 +- app/pages/releases/0.2.63.wrn | 69 +- app/pages/releases/0.2.64.wrn | 71 +- app/pages/releases/0.2.65.wrn | 71 +- app/pages/releases/0.2.66.wrn | 71 +- app/pages/releases/0.2.67.wrn | 71 +- app/pages/releases/0.2.68.wrn | 71 +- app/pages/releases/0.2.69.wrn | 71 +- app/pages/releases/0.2.70.wrn | 71 +- app/pages/releases/0.2.71.wrn | 71 +- app/pages/releases/0.2.72.wrn | 71 +- app/pages/releases/0.2.73.wrn | 71 +- app/pages/releases/0.2.74.wrn | 71 +- app/pages/releases/0.2.75.wrn | 71 +- app/pages/releases/0.2.76.wrn | 71 +- app/pages/releases/0.2.77.wrn | 71 +- app/pages/releases/0.2.78.wrn | 71 +- app/pages/releases/0.2.79.wrn | 71 +- app/pages/releases/0.3.0.wrn | 71 +- app/pages/releases/0.3.1.wrn | 71 +- app/pages/releases/0.3.2.wrn | 71 +- app/pages/releases/0.3.3.wrn | 71 +- app/pages/releases/0.3.4.wrn | 71 +- app/pages/releases/0.3.5.wrn | 71 +- app/pages/releases/0.3.6.wrn | 71 +- app/pages/releases/0.4.0.wrn | 71 +- app/pages/releases/0.5.0.wrn | 71 +- app/pages/releases/0.5.1.wrn | 71 +- app/pages/releases/0.5.10.wrn | 71 +- app/pages/releases/0.5.11.wrn | 71 +- app/pages/releases/0.5.12.wrn | 71 +- app/pages/releases/0.5.13.wrn | 71 +- app/pages/releases/0.6.0.wrn | 71 +- app/pages/releases/0.7.0.wrn | 71 +- app/pages/releases/0.8.0.wrn | 17 + app/pages/roadmap.wrn | 4 +- app/pages/search.wrn | 6 +- app/pages/security.wrn | 6 +- app/pages/showcase.wrn | 6 +- app/pages/support.wrn | 4 +- app/pages/tutorial.wrn | 6 +- app/routes.gen.ts | 566 ++- app/types/wrnexus.generated.d.ts | 42 + app/types/wrnexus.plugins.generated.d.ts | 2 + bun.lock | 222 +- docs/documentation-coverage-matrix.md | 88 +- docs/release-access-status.md | 4 +- docs/site-audit.md | 6 +- package-lock.json | 869 +++- package.json | 86 +- public/docs-index.json | 222 +- public/llms-full.txt | 4140 +++++++++++++++-- public/llms.txt | 130 +- public/sitemap.xml | 2 +- scripts/generate-docs.ts | 33 + 183 files changed, 14433 insertions(+), 2492 deletions(-) create mode 100644 app/pages/packages/benchmark.wrn create mode 100644 app/pages/packages/cache.wrn create mode 100644 app/pages/packages/content.wrn create mode 100644 app/pages/packages/graphql.wrn create mode 100644 app/pages/packages/identity.wrn create mode 100644 app/pages/packages/image.wrn create mode 100644 app/pages/packages/language-server.wrn create mode 100644 app/pages/packages/mcp.wrn create mode 100644 app/pages/packages/observability.wrn create mode 100644 app/pages/packages/playground.wrn create mode 100644 app/pages/packages/pwa.wrn create mode 100644 app/pages/packages/realtime.wrn create mode 100644 app/pages/packages/security.wrn create mode 100644 app/pages/packages/store.wrn create mode 100644 app/pages/packages/typecheck.wrn create mode 100644 app/pages/releases/0.8.0.wrn create mode 100644 app/types/wrnexus.generated.d.ts create mode 100644 app/types/wrnexus.plugins.generated.d.ts diff --git a/app/docs.test.ts b/app/docs.test.ts index 0f2ab796..df1ccf11 100644 --- a/app/docs.test.ts +++ b/app/docs.test.ts @@ -14,31 +14,46 @@ const expected = [ "ai", "auth", "authz", + "benchmark", + "cache", "captcha", "cli", "compiler", + "content", "core", "csr", "db", "dev-server", "dev-toolbar", "encryption", + "graphql", "helpers", "i18n", + "identity", + "image", "jwt", + "language-server", + "mcp", "mobile", "native", "oauth", + "observability", + "playground", "plugin", "pubsub", + "pwa", "queue", "reactive", + "realtime", "router", + "security", "ssr", + "store", "styles", "syntax", "test", "tracking", + "typecheck", "ui", "uploader", "validation", @@ -201,5 +216,13 @@ test("clicking a category hides packages from other categories", async () => { .querySelectorAll(".package-card") .filter((card) => (card as HTMLElement).style.display !== "none") .map((card) => card.getAttribute("href")); - expect(visible).toEqual(["/packages/db", "/packages/queue", "/packages/uploader"]); + expect(visible).toEqual([ + "/packages/cache", + "/packages/content", + "/packages/db", + "/packages/graphql", + "/packages/queue", + "/packages/store", + "/packages/uploader", + ]); }); diff --git a/app/pages/404.wrn b/app/pages/404.wrn index 3be2cad2..11e7fbd3 100644 --- a/app/pages/404.wrn +++ b/app/pages/404.wrn @@ -7,10 +7,10 @@ page Pagenotfound { view {
-
W WRNexusJS
+
W WRNexusJS
- +
} diff --git a/app/pages/access.wrn b/app/pages/access.wrn index 7c4e9a51..2bd44190 100644 --- a/app/pages/access.wrn +++ b/app/pages/access.wrn @@ -7,10 +7,10 @@ page Access { view {
-
W WRNexusJS
+
W WRNexusJS
-

Request preview access

WRNexusJS 0.7.0 packages are not available from the public npm registry. Installation requires approval and private registry credentials supplied by WorkRoot. Never paste registry tokens into source control, issue reports, or support messages.

Request process

  1. Contact WorkRoot through the public contact path at workroot.in.
  2. Describe the application, team, expected deployment, and Bun environment.
  3. After approval, follow the registry instructions supplied privately.
  4. Use the canonical scaffold command below only after authentication.
bunx @wrnexus/cli@0.7.0 create my-app

Access approval, response time, licensing terms, and support level remain owner-controlled. This site does not collect access requests directly.

- +

Request preview access

WRNexusJS 0.8.0 packages are not available from the public npm registry. Installation requires approval and private registry credentials supplied by WorkRoot. Never paste registry tokens into source control, issue reports, or support messages.

Request process

  1. Contact WorkRoot through the public contact path at workroot.in.
  2. Describe the application, team, expected deployment, and Bun environment.
  3. After approval, follow the registry instructions supplied privately.
  4. Use the canonical scaffold command below only after authentication.
bunx @wrnexus/cli@0.8.0 create my-app

Access approval, response time, licensing terms, and support level remain owner-controlled. This site does not collect access requests directly.

+
} diff --git a/app/pages/architecture.wrn b/app/pages/architecture.wrn index aef5595a..676fc930 100644 --- a/app/pages/architecture.wrn +++ b/app/pages/architecture.wrn @@ -7,10 +7,10 @@ page Architecture { view {
-
W WRNexusJS
+
W WRNexusJS
-
Framework architecture · 0.7.0

Architecture

WRNexusJS is Bun-native and SSR-first. File discovery maps pages and API handlers; middleware enriches or short-circuits a request; the compiler turns .wrn declarations into server render functions and small feature runtimes.

Request and build lifecycle

  1. DiscoverPages, APIs, middleware, components, layouts, schemas, rooms
  2. CompileParse .wrn, validate grammar, generate server code
  3. RequestLimits, security, locale, session, middleware
  4. MatchStatic and dynamic file route
  5. RenderSSR data, escaped interpolation, components, metadata
  6. EnhanceOnly required reactive/directive runtimes

Package boundaries

core owns contexts, middleware, sessions and rooms; router discovers routes; compiler parses .wrn; ssr renders documents; csr supplies browser runtimes; dev-server and cli orchestrate development and builds.

Security and data flow

Validation happens at trust boundaries. Session authentication establishes identity; authorization makes resource decisions. CSP, Trusted Types, CSRF, upload checks, WebSocket origins, request limits, and output escaping are layered controls—not substitutes for application policy.

Realtime and scale

Rooms are process-local unless connected through pub/sub. Redis-backed pub/sub distributes events. Queue durability depends on the selected driver and must be evaluated explicitly.

Workspaces and gateways

The gateway can dispatch multiple applications while preserving route, component, asset, config, and session boundaries. Validate host routing and isolation before production.

Build and deployment

wrnexus build . produces dist/server.js and hashed/static assets. Run the server with Bun, apply migrations before traffic, terminate TLS at a trusted edge, and forward only expected proxy headers.

Mobile

Mobile compatibility bridges SSR-safe Capacitor capabilities; native route generation is experimental and is not general web portability. Test each target platform.

Generated files and limits

app/routes.gen.ts, .wrnexus/, and dist/ are generated. The runtime is Bun-only. Preview packages are private. Historical compatibility and long-term support policy are not yet published.

- +
Framework architecture · 0.8.0

Architecture

WRNexusJS is Bun-native and SSR-first. File discovery maps pages and API handlers; middleware enriches or short-circuits a request; the compiler turns .wrn declarations into server render functions and small feature runtimes.

Request and build lifecycle

  1. DiscoverPages, APIs, middleware, components, layouts, schemas, rooms
  2. CompileParse .wrn, validate grammar, generate server code
  3. RequestLimits, security, locale, session, middleware
  4. MatchStatic and dynamic file route
  5. RenderSSR data, escaped interpolation, components, metadata
  6. EnhanceOnly required reactive/directive runtimes

Package boundaries

core owns contexts, middleware, sessions and rooms; router discovers routes; compiler parses .wrn; ssr renders documents; csr supplies browser runtimes; dev-server and cli orchestrate development and builds.

Security and data flow

Validation happens at trust boundaries. Session authentication establishes identity; authorization makes resource decisions. CSP, Trusted Types, CSRF, upload checks, WebSocket origins, request limits, and output escaping are layered controls—not substitutes for application policy.

Realtime and scale

Rooms are process-local unless connected through pub/sub. Redis-backed pub/sub distributes events. Queue durability depends on the selected driver and must be evaluated explicitly.

Workspaces and gateways

The gateway can dispatch multiple applications while preserving route, component, asset, config, and session boundaries. Validate host routing and isolation before production.

Build and deployment

wrnexus build . produces dist/server.js and hashed/static assets. Run the server with Bun, apply migrations before traffic, terminate TLS at a trusted edge, and forward only expected proxy headers.

Mobile

Mobile compatibility bridges SSR-safe Capacitor capabilities; native route generation is experimental and is not general web portability. Test each target platform.

Generated files and limits

app/routes.gen.ts, .wrnexus/, and dist/ are generated. The runtime is Bun-only. Preview packages are private. Historical compatibility and long-term support policy are not yet published.

+
} diff --git a/app/pages/benchmarks.wrn b/app/pages/benchmarks.wrn index 6707922b..41298469 100644 --- a/app/pages/benchmarks.wrn +++ b/app/pages/benchmarks.wrn @@ -7,10 +7,10 @@ page Benchmarks { view {
-
W WRNexusJS
+
W WRNexusJS

Benchmarks

No publishable benchmark dataset yet

No comparative speed claims are published. A valid baseline must record scripts, commit, Bun/framework versions, hardware, OS, warmup, samples, workload, raw results, median, percentiles, memory, HTML size, browser JavaScript size, and run date.

The roadmap starts with WRNexusJS-only measurements before any maintained equivalent-workload comparison.

- +
} diff --git a/app/pages/changelog.wrn b/app/pages/changelog.wrn index fc8ee6a0..ace5827d 100644 --- a/app/pages/changelog.wrn +++ b/app/pages/changelog.wrn @@ -7,10 +7,10 @@ page Changelog { view {
-
W WRNexusJS
+
W WRNexusJS
-

Changelog

0.7.0 2026-07-13

Documentation is aligned to all 38 installed packages. This release adds @wrnexus/helpers, original-request URL helpers, safe login redirects, working wrnexus workspace add, and forward-auth redirect propagation.

Migration notes

Run wrnexus update --latest and keep every @wrnexus/* package on 0.7.0. Existing applications must explicitly add @wrnexus/helpers before importing it; newly scaffolded applications include it automatically.

Versioning and support

The packages use semantic-looking versions, but a formal compatibility and old-release support policy has not been approved. Preview consumers should treat minor releases as potentially requiring migration review.

- +

Changelog

0.8.0 2026-07-13

Documentation is aligned to all 46 installed packages. This release adds @wrnexus/helpers, original-request URL helpers, safe login redirects, working wrnexus workspace add, and forward-auth redirect propagation.

Migration notes

Run wrnexus update --latest and keep every @wrnexus/* package on 0.8.0. Existing applications must explicitly add @wrnexus/helpers before importing it; newly scaffolded applications include it automatically.

Versioning and support

The packages use semantic-looking versions, but a formal compatibility and old-release support policy has not been approved. Preview consumers should treat minor releases as potentially requiring migration review.

+
} diff --git a/app/pages/examples.wrn b/app/pages/examples.wrn index 232da8cb..2af1af67 100644 --- a/app/pages/examples.wrn +++ b/app/pages/examples.wrn @@ -7,10 +7,10 @@ page Examples { view {
-
W WRNexusJS
+
W WRNexusJS
-

Examples

Examples are tied to installed 0.7.0 package documentation. The focused snippets in guides are source-verified; standalone runnable projects and CI compilation are tracked as remaining work.

Minimal .wrn page

Documented

Database CRUD

Planned fixture

Authentication and protected route

Planned fixture

Permissions

Planned fixture

Forms and validation

Documented

Realtime dashboard

Planned fixture

File upload

Planned fixture

Background queue

Planned fixture

Redis pub/sub

Planned fixture

Workspace gateway

Planned fixture

Deployment

Planned fixture

Experimental mobile mode

Planned fixture
- +

Examples

Examples are tied to installed 0.8.0 package documentation. The focused snippets in guides are source-verified; standalone runnable projects and CI compilation are tracked as remaining work.

Minimal .wrn page

Documented

Database CRUD

Planned fixture

Authentication and protected route

Planned fixture

Permissions

Planned fixture

Forms and validation

Documented

Realtime dashboard

Planned fixture

File upload

Planned fixture

Background queue

Planned fixture

Redis pub/sub

Planned fixture

Workspace gateway

Planned fixture

Deployment

Planned fixture

Experimental mobile mode

Planned fixture
+
} diff --git a/app/pages/getting-started.wrn b/app/pages/getting-started.wrn index a9328c96..adabfe2f 100644 --- a/app/pages/getting-started.wrn +++ b/app/pages/getting-started.wrn @@ -7,9 +7,9 @@ page Gettingstarted { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · v0.7.0

Build a contact inbox

This path creates a server-rendered page, validated API route, middleware, and realtime next step. It requires approved registry access and Bun 1.3.x; this site was verified with Bun 1.3.14.

1. Create the project

bunx @wrnexus/cli@0.7.0 create my-app
+      
Preview guide · v0.8.0

Build a contact inbox

This path creates a server-rendered page, validated API route, middleware, and realtime next step. It requires approved registry access and Bun 1.3.x; this site was verified with Bun 1.3.14.

1. Create the project

bunx @wrnexus/cli@0.8.0 create my-app
 cd my-app
 bun install
 bun run dev

2. Know the structure

app/pages/       # file-based .wrn routes
@@ -39,7 +39,7 @@ export const POST = async (ctx) => {
 }

7. Test and ship

bun run test
 bun run build
 bun dist/server.js

Next: deployment, database, authentication, and workspaces.

- +
} diff --git a/app/pages/guides/api-routes.wrn b/app/pages/guides/api-routes.wrn index c5adc9b8..3e81137a 100644 --- a/app/pages/guides/api-routes.wrn +++ b/app/pages/guides/api-routes.wrn @@ -7,10 +7,10 @@ page APIroutes { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

API routes

Export GET, POST, PUT, PATCH, or DELETE from app/api files. Validate request bodies, enforce authentication and authorization, cap request sizes, and return Web Responses.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

API routes

Export GET, POST, PUT, PATCH, or DELETE from app/api files. Validate request bodies, enforce authentication and authorization, cap request sizes, and return Web Responses.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/authentication.wrn b/app/pages/guides/authentication.wrn index 5a3130e4..fe1f9ad5 100644 --- a/app/pages/guides/authentication.wrn +++ b/app/pages/guides/authentication.wrn @@ -7,10 +7,10 @@ page Authentication { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Authentication

Configure session authentication, log users in through supported auth helpers, and read identity from context. Cookie flags, rotation, expiry, and secret storage remain deployment responsibilities.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Authentication

Configure session authentication, log users in through supported auth helpers, and read identity from context. Cookie flags, rotation, expiry, and secret storage remain deployment responsibilities.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/authorization.wrn b/app/pages/guides/authorization.wrn index 42d8112d..f7671ffd 100644 --- a/app/pages/guides/authorization.wrn +++ b/app/pages/guides/authorization.wrn @@ -7,10 +7,10 @@ page Authorization { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Authorization

Authentication identifies; authorization decides. Enforce permissions in server routes and policies, including object ownership. UI hiding is never an authorization boundary.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Authorization

Authentication identifies; authorization decides. Enforce permissions in server routes and policies, including object ownership. UI hiding is never an authorization boundary.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/configuration-and-profiles.wrn b/app/pages/guides/configuration-and-profiles.wrn index 44c7d3cd..42b2214c 100644 --- a/app/pages/guides/configuration-and-profiles.wrn +++ b/app/pages/guides/configuration-and-profiles.wrn @@ -7,10 +7,10 @@ page Configurationandprofiles { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Configuration and profiles

wrnexus.config.ts owns styles, SEO, security, data, mobile, fonts, and profiles. Keep secrets in validated environment variables and review merged production configuration.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Configuration and profiles

wrnexus.config.ts owns styles, SEO, security, data, mobile, fonts, and profiles. Keep secrets in validated environment variables and review merged production configuration.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/database.wrn b/app/pages/guides/database.wrn index 6990eb4c..12be4fbe 100644 --- a/app/pages/guides/database.wrn +++ b/app/pages/guides/database.wrn @@ -7,10 +7,10 @@ page Database { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Database

Configure SQLite or the installed supported driver, keep queries in named SQL blocks, generate typed functions, and apply migrations before traffic. Back up data and test rollback independently.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Database

Configure SQLite or the installed supported driver, keep queries in named SQL blocks, generate typed functions, and apply migrations before traffic. Back up data and test rollback independently.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/deployment.wrn b/app/pages/guides/deployment.wrn index 8389fcc2..3b989581 100644 --- a/app/pages/guides/deployment.wrn +++ b/app/pages/guides/deployment.wrn @@ -7,10 +7,10 @@ page Deployment { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Deployment

Run bun run build, apply migrations, and start dist/server.js with Bun. Configure TLS, proxy trust, environment validation, health checks, graceful restarts, logs, backups, and restrictive security headers.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Deployment

Run bun run build, apply migrations, and start dist/server.js with Bun. Configure TLS, proxy trust, environment validation, health checks, graceful restarts, logs, backups, and restrictive security headers.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/forms-and-validation.wrn b/app/pages/guides/forms-and-validation.wrn index 82688bb1..e85a548a 100644 --- a/app/pages/guides/forms-and-validation.wrn +++ b/app/pages/guides/forms-and-validation.wrn @@ -7,10 +7,10 @@ page Formsandvalidation { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Forms and validation

Define a v.object schema, use data-schema on the form, show field errors with data-error, and always call parseBody on the server. refine is server-only.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Forms and validation

Define a v.object schema, use data-schema on the form, show field errors with data-error, and always call parseBody on the server. refine is server-only.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/i18n-and-themes.wrn b/app/pages/guides/i18n-and-themes.wrn index 5e1b145e..cdad720b 100644 --- a/app/pages/guides/i18n-and-themes.wrn +++ b/app/pages/guides/i18n-and-themes.wrn @@ -7,10 +7,10 @@ page Internationalizationandthemes { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Internationalization and themes

Store locale JSON under app/locales and use translation directives. Themes resolve CSS tokens; ensure contrast, system preference behavior, persistence, and non-color cues.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Internationalization and themes

Store locale JSON under app/locales and use translation directives. Themes resolve CSS tokens; ensure contrast, system preference behavior, persistence, and non-color cues.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/middleware.wrn b/app/pages/guides/middleware.wrn index 02dab39d..0c732a3d 100644 --- a/app/pages/guides/middleware.wrn +++ b/app/pages/guides/middleware.wrn @@ -7,10 +7,10 @@ page Middleware { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Middleware

Middleware receives context and next. Return next() to continue or return a Response to stop. Put request limits and trust-boundary controls before business logic.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Middleware

Middleware receives context and next. Return next() to continue or return a Response to stop. Put request limits and trust-boundary controls before business logic.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/mobile.wrn b/app/pages/guides/mobile.wrn index d041c4d8..ef492d0c 100644 --- a/app/pages/guides/mobile.wrn +++ b/app/pages/guides/mobile.wrn @@ -7,10 +7,10 @@ page Mobile { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Mobile

Mobile capabilities are experimental in this preview. Test Capacitor permissions and lifecycle on each platform; do not assume every .wrn or browser API converts to native.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Mobile

Mobile capabilities are experimental in this preview. Test Capacitor permissions and lifecycle on each platform; do not assume every .wrn or browser API converts to native.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/observability.wrn b/app/pages/guides/observability.wrn index 92231d40..2f542592 100644 --- a/app/pages/guides/observability.wrn +++ b/app/pages/guides/observability.wrn @@ -7,10 +7,10 @@ page Observability { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Observability

Use tracking middleware and sinks with redaction, sampling, stable request identifiers, alert ownership, and retention limits. Never capture registry tokens or session secrets.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Observability

Use tracking middleware and sinks with redaction, sampling, stable request identifiers, alert ownership, and retention limits. Never capture registry tokens or session secrets.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/pages-and-components.wrn b/app/pages/guides/pages-and-components.wrn index 9f455493..8fb24725 100644 --- a/app/pages/guides/pages-and-components.wrn +++ b/app/pages/guides/pages-and-components.wrn @@ -7,10 +7,10 @@ page Pagesandcomponents { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Pages and components

Pages are routable, components are reusable, and layouts provide shared slots. Mount a component with data-component and keep browser state scoped and minimal.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Pages and components

Pages are routable, components are reusable, and layouts provide shared slots. Mount a component with data-component and keep browser state scoped and minimal.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/project-structure.wrn b/app/pages/guides/project-structure.wrn index e6c463e0..6c71777a 100644 --- a/app/pages/guides/project-structure.wrn +++ b/app/pages/guides/project-structure.wrn @@ -7,10 +7,10 @@ page Projectstructure { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Project structure

Pages, components, layouts, APIs, middleware, schemas, database files, locales, realtime rooms, and styles live under app. Never edit app/routes.gen.ts, .wrnexus, or dist by hand.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Project structure

Pages, components, layouts, APIs, middleware, schemas, database files, locales, realtime rooms, and styles live under app. Never edit app/routes.gen.ts, .wrnexus, or dist by hand.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/pubsub.wrn b/app/pages/guides/pubsub.wrn index feb4328b..9bdffebb 100644 --- a/app/pages/guides/pubsub.wrn +++ b/app/pages/guides/pubsub.wrn @@ -7,10 +7,10 @@ page Pubsub { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Pub/sub

The in-process driver cannot cross processes. Use Redis where instances must share events, define channel ownership, and design for reconnects and duplicate delivery.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Pub/sub

The in-process driver cannot cross processes. Use Redis where instances must share events, define channel ownership, and design for reconnects and duplicate delivery.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/queues.wrn b/app/pages/guides/queues.wrn index 173c486d..973832f5 100644 --- a/app/pages/guides/queues.wrn +++ b/app/pages/guides/queues.wrn @@ -7,10 +7,10 @@ page Queues { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Queues

Queue behavior is preview-level. Treat in-process work as non-durable, make handlers idempotent, cap retries, record failures, and choose a production persistence strategy.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Queues

Queue behavior is preview-level. Treat in-process work as non-durable, make handlers idempotent, cap retries, record failures, and choose a production persistence strategy.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/realtime.wrn b/app/pages/guides/realtime.wrn index 38eb24b9..206b0125 100644 --- a/app/pages/guides/realtime.wrn +++ b/app/pages/guides/realtime.wrn @@ -7,10 +7,10 @@ page Realtime { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Realtime

defineRoom handles connection and messages. Validate message shapes, authorize subscriptions, restrict origins, bound payloads, and use pub/sub to scale across processes.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Realtime

defineRoom handles connection and messages. Validate message shapes, authorize subscriptions, restrict origins, bound payloads, and use pub/sub to scale across processes.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/routing.wrn b/app/pages/guides/routing.wrn index c7d9ee93..2ac9bb75 100644 --- a/app/pages/guides/routing.wrn +++ b/app/pages/guides/routing.wrn @@ -7,10 +7,10 @@ page Routing { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Routing

A page filename defines its URL; index maps to the directory root and bracket segments are dynamic parameters. API files under app/api expose HTTP method functions and receive a Context.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Routing

A page filename defines its URL; index maps to the directory root and bracket segments are dynamic parameters. API files under app/api expose HTTP method functions and receive a Context.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/security.wrn b/app/pages/guides/security.wrn index bf56888f..142df2a7 100644 --- a/app/pages/guides/security.wrn +++ b/app/pages/guides/security.wrn @@ -7,10 +7,10 @@ page Applicationsecurity { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Application security

Use CSP, CSRF, Trusted Types, session hardening, validation, origin checks, upload restrictions, encryption, request limits, and explicit CORS. See the security policy for reporting.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Application security

Use CSP, CSRF, Trusted Types, session hardening, validation, origin checks, upload restrictions, encryption, request limits, and explicit CORS. See the security policy for reporting.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/server-data.wrn b/app/pages/guides/server-data.wrn index cc0df5c7..a30f523f 100644 --- a/app/pages/guides/server-data.wrn +++ b/app/pages/guides/server-data.wrn @@ -7,10 +7,10 @@ page Serverdata { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Server data

Use an ssr API binding, return the desired response field, and render it with a server #each block. Values are escaped. Avoid fetching private data through a route that lacks authorization.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Server data

Use an ssr API binding, return the desired response field, and render it with a server #each block. Values are escaped. Avoid fetching private data through a route that lacks authorization.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/testing.wrn b/app/pages/guides/testing.wrn index 41a4765b..92aab9fb 100644 --- a/app/pages/guides/testing.wrn +++ b/app/pages/guides/testing.wrn @@ -7,10 +7,10 @@ page Testing { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Testing

Use Bun tests and @wrnexus/test helpers. Cover server HTML, API status and validation, authorization failures, reactive behavior, and a production startup smoke test.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Testing

Use Bun tests and @wrnexus/test helpers. Cover server HTML, API status and validation, authorization failures, reactive behavior, and a production startup smoke test.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/troubleshooting.wrn b/app/pages/guides/troubleshooting.wrn index 36487714..e795f27a 100644 --- a/app/pages/guides/troubleshooting.wrn +++ b/app/pages/guides/troubleshooting.wrn @@ -7,10 +7,10 @@ page Troubleshooting { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Troubleshooting

Confirm Bun and package versions, regenerate docs/routes through supported commands, read the first compiler diagnostic, check file naming, validate config, and reproduce under a production build.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Troubleshooting

Confirm Bun and package versions, regenerate docs/routes through supported commands, read the first compiler diagnostic, check file naming, validate config, and reproduce under a production build.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/upgrading.wrn b/app/pages/guides/upgrading.wrn index aaad06c9..26c434ad 100644 --- a/app/pages/guides/upgrading.wrn +++ b/app/pages/guides/upgrading.wrn @@ -7,10 +7,10 @@ page Upgrading { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Upgrading

Back up and commit first, then use wrnexus update --latest as documented by the installed CLI. Review migrations and keep every @wrnexus package aligned. Current release: 0.7.0.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Upgrading

Back up and commit first, then use wrnexus update --latest as documented by the installed CLI. Review migrations and keep every @wrnexus package aligned. Current release: 0.8.0.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/uploads.wrn b/app/pages/guides/uploads.wrn index a1ae5ab1..9ebb8941 100644 --- a/app/pages/guides/uploads.wrn +++ b/app/pages/guides/uploads.wrn @@ -7,10 +7,10 @@ page Uploads { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Uploads

Configure named stores, accepted MIME/extensions, and maxBytes. Random keys avoid path traversal. Private files require an authenticated serving route; v1 buffers each file in memory.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +
Preview guide · 0.8.0

Uploads

Configure named stores, accepted MIME/extensions, and maxBytes. Random keys avoid path traversal. Private files require an authenticated serving route; v1 buffers each file in memory.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/guides/workspaces-and-gateway.wrn b/app/pages/guides/workspaces-and-gateway.wrn index fbc6a96f..f1fa491d 100644 --- a/app/pages/guides/workspaces-and-gateway.wrn +++ b/app/pages/guides/workspaces-and-gateway.wrn @@ -7,9 +7,9 @@ page Workspacesandgateway { view {
-
W WRNexusJS
+
W WRNexusJS
-
Preview guide · 0.7.0

Workspaces and gateway

A workspace runs isolated applications behind one domain-routing gateway. Add an application from the workspace root; the CLI scaffolds apps/reports and registers it in wrnexus.workspace.ts:

wrnexus workspace add reports --domain=reports.localhost
+      
Preview guide · 0.8.0

Workspaces and gateway

A workspace runs isolated applications behind one domain-routing gateway. Add an application from the workspace root; the CLI scaffolds apps/reports and registers it in wrnexus.workspace.ts:

wrnexus workspace add reports --domain=reports.localhost
 bun install
 bun run dev

Forward authentication

Point protected applications at a dedicated verifier endpoint. The verifier must return 2xx for an authenticated session, 401/403 to deny access, or an HTTP redirect to begin browser login.

// wrnexus.workspace.ts
 {
@@ -28,8 +28,8 @@ export const GET = async (ctx: Context) => {
   return redirectToLogin(ctx, "/login", {
     allowedHosts: ["admin.localhost:3000", "reports.localhost:3000"],
   });
-};

Always allowlist redirect hosts. After login, validate or sign the returnTo value before redirecting. Keep internal app ports private and open applications through the gateway port.

Release scope

This guide describes installed 0.7.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

- +};

Always allowlist redirect hosts. After login, validate or sign the returnTo value before redirecting. Keep internal app ports private and open applications through the gateway port.

Release scope

This guide describes installed 0.8.0 capabilities. Follow linked package declarations for exact signatures; undocumented behavior is not guaranteed.

Browse package APIs · Troubleshooting · Support

+
} diff --git a/app/pages/index.wrn b/app/pages/index.wrn index d67fa2f0..cb866a70 100644 --- a/app/pages/index.wrn +++ b/app/pages/index.wrn @@ -7,9 +7,9 @@ page Home { view {
-
W WRNexusJS
+
W WRNexusJS
-

WRNexusJS v0.7.0

Build from the server.
Ship only what matters.

WRNexusJS is an SSR-first, Bun-native full-stack framework. Build typed pages, APIs, validated forms, realtime rooms, secure sessions, workspaces, and optional mobile experiences with the .wrn component language.

Private developer preview. Request access to the package registry.

app/pages/dashboard.wrn
page Dashboard {
+      

WRNexusJS v0.8.0

Build from the server.
Ship only what matters.

WRNexusJS is an SSR-first, Bun-native full-stack framework. Build typed pages, APIs, validated forms, realtime rooms, secure sessions, workspaces, and optional mobile experiences with the .wrn component language.

Private developer preview. Request access to the package registry.

app/pages/dashboard.wrn
page Dashboard {
   ssr { api tasks GET /api/tasks { return tasks } }
   view {
     <main>
@@ -35,10 +35,10 @@ export const POST = async (ctx) => {
   return result.ok ? Response.json({ ok: true }, { status: 201 }) : result.response;
 };

Request lifecycle

  1. RequestSecurity headers and request limits
  2. MiddlewareAuthentication, policy, and context
  3. File routePage or API handler
  4. Compiler + SSRSafe HTML and scoped runtime
  5. ResponseHTML, JSON, stream, or realtime upgrade
-

Production proof

WorkRoot

Public creator/company site and approved WRNexusJS production showcase.

wrnexusjs.dev

This documentation application runs WRNexusJS 0.7.0.

View deployment notes and showcase status →

-

Capability status

CapabilityStatusDetails
SSR, routing, compiler, APIsPreviewInstalled in 0.7.0; public support policy pending.
Mobile/nativeExperimentalCapacitor compatibility and native generation have platform limitations.
Durable queuesExperimentalProduction durability requires an appropriate driver strategy.
-

Continue exploring

- +

Production proof

WorkRoot

Public creator/company site and approved WRNexusJS production showcase.

wrnexusjs.dev

This documentation application runs WRNexusJS 0.8.0.

View deployment notes and showcase status →

+

Capability status

CapabilityStatusDetails
SSR, routing, compiler, APIsPreviewInstalled in 0.8.0; public support policy pending.
Mobile/nativeExperimentalCapacitor compatibility and native generation have platform limitations.
Durable queuesExperimentalProduction durability requires an appropriate driver strategy.
+

Continue exploring

+
} diff --git a/app/pages/language.wrn b/app/pages/language.wrn index de8eb1ed..de95d38b 100644 --- a/app/pages/language.wrn +++ b/app/pages/language.wrn @@ -7,15 +7,15 @@ page Thewrnlanguage { view {
-
W WRNexusJS
+
W WRNexusJS
-
Language reference · 0.7.0

The .wrn language

File anatomy

page Account {
+      
Language reference · 0.8.0

The .wrn language

File anatomy

page Account {
   layout = "public"
   seo { title = "Account" description = "Manage your account." }
   state count = 0
   view { <button @click="count++">Count {count}</button> }
 }

Pages, components, layouts, props, and state

Pages are routes. Components declare default-valued props and may hold state. Layouts provide shared slots. Mount components with data-component; fill default or named slots with data-slot.

Interpolation, conditionals, and loops

Interpolation is HTML-escaped. Use server {#if} and {#each} for SSR data. Use data-show for reactive client visibility.

Events and directives

@click and other events execute in the reactive scope. Data attributes opt into forms, i18n, themes, realtime, uploader, browser, and mobile behavior. Consult the exact package page because availability varies.

Forms, i18n, themes, and realtime

form[data-schema] connects descriptors to client and server validation. Translation keys use {t:key}. Theme toggles use data-wire-theme-toggle. Realtime pages opt into a named room.

Escaping and security

Text interpolation is escaped by default. Do not construct trusted HTML from user input. Server-only refinements must be repeated at the authoritative mutation boundary.

Common compiler errors

  • Use balanced braces; a literal brace must be escaped.
  • Declare UI in view, not JSX or hooks.
  • Use a valid page, component, or layout declaration matching the file role.
  • Keep server loops tied to available SSR bindings.
  • Check troubleshooting and compiler API for this release.
- +
} diff --git a/app/pages/license.wrn b/app/pages/license.wrn index 934bcaed..c10e8eb6 100644 --- a/app/pages/license.wrn +++ b/app/pages/license.wrn @@ -7,10 +7,10 @@ page License { view {
-
W WRNexusJS
+
W WRNexusJS

License

Owner decision required

This documentation repository contains no public license file, and the packages are unavailable from the public npm registry. No open-source license or redistribution right should be inferred.

Approved preview users must follow the private/commercial terms supplied by WorkRoot. Contact WorkRoot before copying, redistributing, or using WRNexusJS in production.

- +
} diff --git a/app/pages/packages.wrn b/app/pages/packages.wrn index 13be1e1f..2b2a874b 100644 --- a/app/pages/packages.wrn +++ b/app/pages/packages.wrn @@ -12,10 +12,10 @@ page Packages {
W WRNexusJS - +
-
31 focused packages

Package reference

Everything in the framework, organized by responsibility and documented from the published 0.7.0 APIs.

Showing {category} packages

+
46 focused packages

Package reference

Everything in the framework, organized by responsibility and documented from the published 0.8.0 APIs.

Showing {category} packages

AI

@wrnexus/ai

Server-side Anthropic client with generation and streaming.

Open documentation →
@@ -24,6 +24,12 @@ page Packages { Security

@wrnexus/authz

Role, permission, policy, and authorization guards.

Open documentation →
+ + Tooling

@wrnexus/benchmark

Framework benchmark scenarios and repeatable performance measurements.

Open documentation → +
+ + Data

@wrnexus/cache

Memory and distributed caching with coordination and invalidation.

Open documentation → +
Security

@wrnexus/captcha

Managed CAPTCHA verification, middleware, and UI integration.

Open documentation →
@@ -33,6 +39,9 @@ page Packages { Core

@wrnexus/compiler

Parser and code generators for the .wrn language.

Open documentation →
+ + Data

@wrnexus/content

Content collections, validation, querying, and publishing workflows.

Open documentation → +
Core

@wrnexus/core

Contexts, middleware, security, sessions, caching, JSX, and realtime.

Open documentation →
@@ -51,15 +60,30 @@ page Packages { Security

@wrnexus/encryption

Hashing, HMAC, authenticated encryption, and key derivation.

Open documentation →
+ + Data

@wrnexus/graphql

GraphQL schemas, routes, and framework plugin integration.

Open documentation → +
Tooling

@wrnexus/helpers

Safe Context URL helpers and forward-auth login redirects.

Open documentation →
Frontend

@wrnexus/i18n

Translation loading, locale resolution, and Intl formatting.

Open documentation →
+ + Security

@wrnexus/identity

Portable identity records, claims, and account linking.

Open documentation → +
+ + Frontend

@wrnexus/image

Responsive image optimization, loaders, placeholders, and components.

Open documentation → +
Security

@wrnexus/jwt

HS256 JWT signing, verification, and bearer authentication.

Open documentation →
+ + Tooling

@wrnexus/language-server

Editor-neutral language intelligence for WRN files.

Open documentation → +
+ + Tooling

@wrnexus/mcp

Model Context Protocol tools for WRNexus projects.

Open documentation → +
Native

@wrnexus/mobile

SSR-safe compatibility access to Capacitor plugins.

Open documentation →
@@ -69,24 +93,42 @@ page Packages { Security

@wrnexus/oauth

OAuth 2.0, PKCE, provider presets, and profile mapping.

Open documentation →
+ + Runtime

@wrnexus/observability

Structured logging, tracing, health, and integration adapters.

Open documentation → +
+ + Tooling

@wrnexus/playground

Interactive framework examples and executable playground utilities.

Open documentation → +
Core

@wrnexus/plugin

Plugin contracts, lifecycle hooks, composition, and framework integration.

Open documentation →
Realtime

@wrnexus/pubsub

In-process and Redis-backed publish/subscribe.

Open documentation →
+ + Frontend

@wrnexus/pwa

Progressive Web App manifests, service workers, and offline strategies.

Open documentation → +
Data

@wrnexus/queue

Background jobs with delay, concurrency, retry, and repetition.

Open documentation →
Frontend

@wrnexus/reactive

Small type-safe reactive signal primitives.

Open documentation →
+ + Realtime

@wrnexus/realtime

Rooms, presence, messaging, history, streams, and UI components.

Open documentation → +
Core

@wrnexus/router

Filesystem discovery, route matching, and typed route generation.

Open documentation →
+ + Security

@wrnexus/security

Security headers, CSRF protection, rate limits, and safe rendering.

Open documentation → +
Runtime

@wrnexus/ssr

Secure HTML document rendering and SEO metadata.

Open documentation →
+ + Data

@wrnexus/store

Application state stores shared across server and browser runtimes.

Open documentation → +
Frontend

@wrnexus/styles

CSS pipeline, themes, fonts, profiles, and application config.

Open documentation →
@@ -99,6 +141,9 @@ page Packages { Runtime

@wrnexus/tracking

Error/event capture, middleware, filtering, and sinks.

Open documentation →
+ + Tooling

@wrnexus/typecheck

WRN-aware TypeScript diagnostics and virtual documents.

Open documentation → +
Frontend

@wrnexus/ui

Themeable server-rendered UI components and CSS.

Open documentation →
@@ -108,7 +153,7 @@ page Packages { Security

@wrnexus/validation

Typed schemas, coercion, validation, and browser descriptors.

Open documentation →
- + } diff --git a/app/pages/packages/ai.wrn b/app/pages/packages/ai.wrn index 6b344a29..4d9dcefa 100644 --- a/app/pages/packages/ai.wrn +++ b/app/pages/packages/ai.wrn @@ -10,11 +10,12 @@ page wrnexusai {
W WRNexusJS - +
-
AI · Package reference

@wrnexus/ai

Server-side Anthropic client with generation and streaming.

v0.7.0Private registryAI

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/ai@0.7.0

Request preview access. Never put registry tokens in source control.

A tiny, zero-dependency Claude (Anthropic) client for WRNexusJS apps — generate and stream text with Claude from any server-side code.
+
AI · Package reference

@wrnexus/ai

Server-side Anthropic client with generation and streaming.

v0.8.0Private registryAI

Install the package

After WorkRoot approves private registry access, install the release-aligned package:

bun add @wrnexus/ai@0.8.0

Request preview access. Never put registry tokens in source control.

Provider-neutral AI orchestration for OpenAI, Anthropic, Google and local OpenAI-compatible models, with streaming, structured output, tools, embeddings, vector search/RAG, conversation persistence, templates, guardrails, usage events, fallback, rate limits and evaluation reports.

+
A tiny, zero-dependency Claude (Anthropic) client for WRNexusJS apps — generate and stream text with Claude from any server-side code.

Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

Overview

@wrnexus/ai is a thin, dependency-free wrapper over the Anthropic Messages API, built on fetch (Bun-native, no SDK). Use it in API routes, jobs, or middleware to call Claude. It defaults to the most capable model, claude-opus-4-8, reads your key from ANTHROPIC_API_KEY, and supports both one-shot generation and streaming.

@@ -75,6 +76,21 @@ try { /* back off */ } }
+

Multi-provider client

+

createAIClient adds named-provider selection and fallback, capability discovery, validated JSON output, validated tool execution, abort-aware exponential retries, and per-provider circuit breakers. Attempt events intentionally contain metadata only: prompts, credentials, and raw model responses are never passed to telemetry.

+
import { anthropicProvider, createAIClient } from "@wrnexus/ai";
+
+const ai = createAIClient({
+  providers: [anthropicProvider()],
+  retry: { attempts: 3, baseDelayMs: 100, maxDelayMs: 2_000 },
+  circuitBreaker: { failureThreshold: 5, resetAfterMs: 30_000 },
+});
+
+const result = await ai.generateObject<{ title: string }>("Return a JSON title", {
+  validate: (value): value is { title: string } =>
+    typeof value === "object" && value !== null && "title" in value,
+});
+

Providers can return normalized usage (inputTokens, outputTokens, totalTokens, and costUsd) and toolCalls. Use executeTools with a named, validated tool registry; unknown tools and invalid arguments are rejected before application code runs. deterministicAIProvider supplies ordered or computed offline responses for tests and examples without API keys or network calls.

Usage

Return generated JSON from an API route

// app/api/summarize.ts — summarize posted text
@@ -109,112 +125,7 @@ export const POST = async (ctx) => {
 
  • Zero dependencies — no @anthropic-ai/sdk; talks to the Messages API directly.
  • Defaults to claude-opus-4-8. Pass { model } for a different model (e.g.
  • "claude-sonnet-5" for speed/cost, "claude-haiku-4-5" for the fastest).

    -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface AIUsage {
    -    inputTokens?: number;
    -    outputTokens?: number;
    -    totalTokens?: number;
    -}
    -interface AIResult<T = string> {
    -    value: T;
    -    provider: string;
    -    model?: string;
    -    usage?: AIUsage;
    -    finishReason?: string;
    -    raw?: unknown;
    -}
    -interface AIProvider {
    -    name: string;
    -    generate(prompt: string | Message[], options?: GenerateOptions): Promise<AIResult<string>>;
    -    stream?(prompt: string | Message[], options?: GenerateOptions): AsyncGenerator<string, void, unknown>;
    -}
    -interface AIClientOptions {
    -    providers: AIProvider[];
    -    fallback?: boolean;
    -    onAttempt?: (provider: string, error?: unknown) => void | Promise<void>;
    -}
    -interface AIClient {
    -    generate(prompt: string | Message[], options?: GenerateOptions & {
    -        provider?: string;
    -    }): Promise<AIResult<string>>;
    -    generateObject<T>(prompt: string | Message[], options?: GenerateOptions & {
    -        provider?: string;
    -        validate?: (value: unknown) => value is T;
    -    }): Promise<AIResult<T>>;
    -    stream(prompt: string | Message[], options?: GenerateOptions & {
    -        provider?: string;
    -    }): AsyncGenerator<string, void, unknown>;
    -}
    -declare function anthropicProvider(config?: AIConfig): AIProvider;
    -declare function aiProvider(name: string, client: AI): AIProvider;
    -declare function createAIClient(options: AIClientOptions): AIClient;
    -
    -/**
    - * @wrnexus/ai — a tiny, zero-dependency Claude (Anthropic) client for WRNexusJS apps.
    - *
    - * Use it in API routes, jobs, or anywhere server-side to generate text with Claude.
    - * It talks to the Anthropic Messages API over `fetch` (no SDK dependency, Bun-native),
    - * and defaults to the most capable model, `claude-opus-4-8`.
    - *
    - *   import { createAI } from "@wrnexus/ai";
    - *   const ai = createAI();                       // reads ANTHROPIC_API_KEY
    - *   const text = await ai.generate("Write a haiku about Bun.");
    - *
    - * Streaming (great for API routes):
    - *   export const POST = async (ctx) => ai.streamResponse(await ctx.req.text());
    - */
    -type Role = "user" | "assistant";
    -interface Message {
    -    role: Role;
    -    content: string;
    -}
    -/** Reasoning effort — higher means deeper thinking + more tokens. */
    -type Effort = "low" | "medium" | "high" | "xhigh" | "max";
    -interface AIConfig {
    -    /** Anthropic API key. Default: `ANTHROPIC_API_KEY` from the environment. */
    -    apiKey?: string;
    -    /** Model id. Default: `claude-opus-4-8` (the most capable Claude model). */
    -    model?: string;
    -    /** Default max output tokens. Default: 4096. */
    -    maxTokens?: number;
    -    /** API base URL. Default: `https://api.anthropic.com`. */
    -    baseURL?: string;
    -    /** `anthropic-version` header. Default: `2023-06-01`. */
    -    version?: string;
    -}
    -interface GenerateOptions {
    -    /** System prompt — sets the assistant's role/behavior. */
    -    system?: string;
    -    /** Override the model for this call. */
    -    model?: string;
    -    /** Override max output tokens for this call. */
    -    maxTokens?: number;
    -    /** Enable adaptive extended thinking (slower, deeper reasoning). */
    -    thinking?: boolean;
    -    /** Reasoning effort / token spend (`output_config.effort`). */
    -    effort?: Effort;
    -    /** Full message history — supersedes the `prompt` argument when provided. */
    -    messages?: Message[];
    -    /** Abort the request. */
    -    signal?: AbortSignal;
    -}
    -/** Thrown when the API returns a non-2xx response or refuses the request. */
    -declare class AIError extends Error {
    -    readonly status: number;
    -    readonly type: string;
    -    constructor(message: string, status?: number, type?: string);
    -}
    -interface AI {
    -    /** Generate a full text response (non-streaming). */
    -    generate(prompt: string | Message[], opts?: GenerateOptions): Promise<string>;
    -    /** Stream the response as text deltas, as they arrive. */
    -    stream(prompt: string | Message[], opts?: GenerateOptions): AsyncGenerator<string, void, unknown>;
    -    /** Stream straight to a `Response` (text/plain) — drop-in for an API route return. */
    -    streamResponse(prompt: string | Message[], opts?: GenerateOptions): Response;
    -}
    -/** Create a Claude client. Reads `ANTHROPIC_API_KEY` from the environment by default. */
    -declare function createAI(config?: AIConfig): AI;
    -
    -export { type AI, type AIClient, type AIClientOptions, type AIConfig, AIError, type AIProvider, type AIResult, type AIUsage, type Effort, type GenerateOptions, type Message, type Role, aiProvider, anthropicProvider, createAI, createAIClient };
    +

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { A as AI, a as AIAttemptEvent, b as AICircuitBreakerOptions, c as AIClient, d as AIClientOptions, e as AIConfig, f as AIError, AIGuardrail, g as AIProvider, h as AIProviderCapabilities, i as AIResult, j as AIRetryOptions, k as AITool, l as AIToolCall, m as AIUsage, ConversationStore, D as DeterministicAIProviderOptions, E as Effort, EmbeddingProvider, G as GenerateOptions, HttpAIProviderOptions, M as Message, R as Role, VectorMatch, VectorRecord, VectorStore, n as aiProvider, aiRateLimiter, o as anthropicProvider, p as createAI, q as createAIClient, createRagPipeline, r as deterministicAIProvider, evaluateAI, googleAIProvider, guardedProvider, localAIProvider, maxPromptLength, memoryConversationStore, memoryVectorStore, openAIEmbeddings, openAIProvider, promptTemplate } from './platform.js';
     

    Examples

    Copy-ready examples from the installed package documentation.

    Return generated JSON from an API route

    // app/api/summarize.ts — summarize posted text
     import { createAI } from "@wrnexus/ai";
     const ai = createAI();
    @@ -238,9 +149,9 @@ export const POST = async (ctx) => {
         maxTokens: 1_500,
       });
     };
    - +
    - + } diff --git a/app/pages/packages/auth.wrn b/app/pages/packages/auth.wrn index 874c08bd..49db5dc8 100644 --- a/app/pages/packages/auth.wrn +++ b/app/pages/packages/auth.wrn @@ -10,11 +10,11 @@ page wrnexusauth {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/auth

    Authentication routes, sessions, forms, guards, and account flows.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/auth@0.7.0

    Request preview access. Never put registry tokens in source control.

    Framework-native authentication, identity, account-security, and session management for WRNexusJS.

    +
    Security · Package reference

    @wrnexus/auth

    Authentication routes, sessions, forms, guards, and account flows.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/auth@0.8.0

    Request preview access. Never put registry tokens in source control.

    Framework-native authentication, identity, account-security, and session management for WRNexusJS.

    Capabilities

    • Password registration, login, recovery, reset, and authenticated password changes
    • @@ -271,19 +271,29 @@ const auth = createAuthEngine({

      Development

      bun run auth:dev
       bun run validate:auth
      -

      Read [SECURITY.md](./SECURITY.md) before production deployment.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { A as AuthEngine, c as createAuthEngine, i as inferIdentityType, n as normalizeEmail, a as normalizeIdentity, b as normalizePhone, d as normalizeUsername, p as publicUser, s as safeAuthReturnTo } from './engine-ZXtjHSyW.js';
    -import { n as AuthRiskSignals, l as AuthRiskDecision } from './types-CbJKeaWh.js';
    -export { A as AuthAccountStatus, a as AuthClock, b as AuthDeliveryMessage, c as AuthDeliveryProvider, d as AuthEngineOptions, e as AuthIdentity, f as AuthIdentityType, g as AuthImpersonationDecision, h as AuthMfaMethod, i as AuthPublicUser, j as AuthRandom, k as AuthResult, m as AuthRiskLevel, o as AuthSecretProtector, p as AuthSecurityEvent, q as AuthSession, r as AuthSessionVerificationHandler, s as AuthSignedInHandler, t as AuthSignedOutHandler, N as AuthStore, u as AuthSuccessfulSignUpAction, v as AuthSuccessfulSignUpHandler, w as AuthTokenPurpose, x as AuthTokenUrlInput, y as AuthUser, z as AuthenticatedContext, L as LoginAttempt, B as LoginInput, Q as MemoryPasskeyChallengeStore, O as OAuthAccount, C as OneTimeToken, D as OtpChallenge, P as PasskeyAuthenticationOptions, S as PasskeyChallengeKind, U as PasskeyChallengeRecord, V as PasskeyChallengeStore, E as PasskeyCredential, F as PasskeyProvider, G as PasskeyRegistrationOptions, H as PasskeyVerificationResult, I as PasswordBreachProvider, J as PasswordCredential, R as RecoveryCodeRecord, K as RegisterInput, T as TotpCredential, M as TrustedDevice, W as assertPasskeyProvider } from './types-CbJKeaWh.js';
    +

    Read [SECURITY.md](./SECURITY.md) before production deployment.

    +

    Package-owned UI blocks and route helpers

    +

    Authentication forms continue to compose @wrnexus/ui inputs, buttons, cards, alerts, badges, avatars, and PIN controls. The package also provides:

    +
      +
    • <AuthShell />
    • +
    • <AuthProviderButtons />
    • +
    • <AuthSecurityNotice />
    • +
    • complete sign-in, sign-up, MFA, passkey, recovery, account-status, session, and impersonation blocks
    • +
    +

    Server helpers include authRoute, authSuccess, authFailure, requireAuthUser, optionalAuthUser, currentAuthSession, and authComponentProps.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { A as AuthEngine } from './engine-BDu0-aZp.js';
    +export { c as createAuthEngine, i as inferIdentityType, n as normalizeEmail, a as normalizeIdentity, b as normalizePhone, d as normalizeUsername, p as publicUser, s as safeAuthReturnTo } from './engine-BDu0-aZp.js';
    +import { o as AuthRiskSignals, m as AuthRiskDecision, s as AuthSession, B as AuthUser } from './types-BhwPi3qr.js';
    +export { A as AUTH_SECURITY_EVENT_TYPES, a as AuthAccountStatus, b as AuthClock, c as AuthDeliveryMessage, d as AuthDeliveryProvider, e as AuthEngineOptions, f as AuthIdentity, g as AuthIdentityType, h as AuthImpersonationDecision, i as AuthMfaMethod, j as AuthPublicUser, k as AuthRandom, l as AuthResult, n as AuthRiskLevel, p as AuthSecretProtector, q as AuthSecurityEvent, r as AuthSecurityEventType, t as AuthSessionVerificationHandler, u as AuthSignedInHandler, v as AuthSignedOutHandler, U as AuthStore, w as AuthSuccessfulSignUpAction, x as AuthSuccessfulSignUpHandler, y as AuthTokenPurpose, z as AuthTokenUrlInput, C as AuthenticatedContext, K as KnownAuthSecurityEventType, L as LoginAttempt, D as LoginInput, V as MemoryPasskeyChallengeStore, O as OAuthAccount, E as OneTimeToken, F as OtpChallenge, P as PasskeyAuthenticationOptions, W as PasskeyChallengeKind, X as PasskeyChallengeRecord, Y as PasskeyChallengeStore, G as PasskeyCredential, H as PasskeyProvider, I as PasskeyRegistrationOptions, J as PasskeyVerificationResult, M as PasswordBreachProvider, N as PasswordCredential, R as RecoveryCodeRecord, Q as RegisterInput, T as TotpCredential, S as TrustedDevice, Z as assertPasskeyProvider } from './types-BhwPi3qr.js';
     export { MemoryAuthStore } from './stores/memory.js';
     export { SqlAuthStore } from './stores/sql.js';
     export { AUTH_SESSION_KEY, authSession, clearAuthSession, establishAuthSession, getAuthSession, getAuthUser, isAuthenticatedContext, requireAuth } from './middleware.js';
    -export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-DS1geh2P.js';
    +export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-B4uaD0Z3.js';
     export { AuthAuditIssue, AuthConfig, AuthPluginOptions, AuthRoutesConfig, authComponentsDir, authPlugin } from './plugin.js';
     export { DefaultAuthRouteOptions, clearDefaultAuthEngine, getDefaultAuthEngine, getDefaultAuthRouteOptions, getDefaultAuthSchemas, hasDefaultAuthEngine, setDefaultAuthEngine, setDefaultAuthRouteOptions, setDefaultAuthSchemas, tryGetDefaultAuthEngine } from './runtime.js';
     export { createAuthSecretProtector } from './protector.js';
     export { decodeBase32, encodeBase32, generateTotp, generateTotpSecret, totpUri, verifyTotp } from './totp/index.js';
    +import { Context } from '@wrnexus/core';
     import '@wrnexus/oauth';
    -import '@wrnexus/core';
     import '@wrnexus/db';
     import '@wrnexus/validation';
     import '@wrnexus/plugin';
    @@ -296,7 +306,23 @@ interface RiskPolicy {
     }
     declare function evaluateAuthRisk(signals?: AuthRiskSignals, policy?: RiskPolicy): AuthRiskDecision;
     
    -export { AuthRiskDecision, AuthRiskSignals, type RiskPolicy, evaluateAuthRisk };
    +type AuthRouteName = "signIn" | "signUp" | "signOut" | "forgotPassword" | "resetPassword" | "verifyEmail" | "verifyPhone" | "twoFactor" | "sessions" | "passkeys";
    +declare function authRoute(name: AuthRouteName, options?: {
    +    basePath?: string;
    +    overrides?: Partial<Record<AuthRouteName, string>>;
    +}): string;
    +declare function authSuccess<T extends Record<string, unknown>>(data: T, init?: ResponseInit): Response;
    +declare function authFailure(code: string, message: string, status?: number, details?: Record<string, unknown>): Response;
    +declare function requireAuthUser(ctx: Context): AuthUser;
    +declare function optionalAuthUser(ctx: Context): AuthUser | null;
    +declare function currentAuthSession(engine: AuthEngine, sessionId: string | undefined): Promise<AuthSession | null>;
    +declare function authComponentProps(input: Record<string, unknown>, defaults?: {
    +    color?: string;
    +    size?: string;
    +    class?: string;
    +}): Record<string, unknown>;
    +
    +export { AuthEngine, AuthRiskDecision, AuthRiskSignals, type AuthRouteName, AuthSession, AuthUser, type RiskPolicy, authComponentProps, authFailure, authRoute, authSuccess, currentAuthSession, evaluateAuthRisk, optionalAuthUser, requireAuthUser };
     

    Examples

    Copy-ready examples from the installed package documentation.

    ## Install

    bun add @wrnexus/auth

    Create the engine

    // app/lib/auth.ts
     import { createAuthEngine, MemoryAuthStore } from "@wrnexus/auth";
     
    @@ -358,9 +384,9 @@ export const auth = createAuthEngine({
         migrations: true,
       },
     };
    - +
    - + } diff --git a/app/pages/packages/authz.wrn b/app/pages/packages/authz.wrn index 39c786b0..754aafab 100644 --- a/app/pages/packages/authz.wrn +++ b/app/pages/packages/authz.wrn @@ -10,11 +10,11 @@ page wrnexusauthz {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/authz

    Role, permission, policy, and authorization guards.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/authz@0.7.0

    Request preview access. Never put registry tokens in source control.

    Composable authorization for WRNexusJS — role-based (RBAC), policy-based (PBAC), and attribute-based (ABAC) access control that reduces to a boolean check plus an authorize() guard.
    +
    Security · Package reference

    @wrnexus/authz

    Role, permission, policy, and authorization guards.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/authz@0.8.0

    Request preview access. Never put registry tokens in source control.

    Composable authorization for WRNexusJS — role-based (RBAC), policy-based (PBAC), and attribute-based (ABAC) access control that reduces to a boolean check plus an authorize() guard.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/authz is a small, server-side authorization toolkit. It gives you three interchangeable models — RBAC (roles → permissions), PBAC (policy predicates), and ABAC (attribute matchers) — that all collapse to a boolean | Promise<boolean> decision. Wrap any decision in a Middleware guard (authorize, requireRole, requirePermission) to protect WRNexusJS routes. Reach for it whenever a route or action needs to be gated on who the user is, what roles they hold, or attributes of the user and the resource. It plugs into @wrnexus/core by reading ctx.user as the authorization subject.

    @@ -242,7 +242,7 @@ app.put( );
    - + } diff --git a/app/pages/packages/benchmark.wrn b/app/pages/packages/benchmark.wrn new file mode 100644 index 00000000..e08371f5 --- /dev/null +++ b/app/pages/packages/benchmark.wrn @@ -0,0 +1,68 @@ +page wrnexusbenchmark { + seo { + title = "@wrnexus/benchmark" + description = "Framework benchmark scenarios and repeatable performance measurements." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Tooling · Package reference

    @wrnexus/benchmark

    Framework benchmark scenarios and repeatable performance measurements.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/benchmark@0.8.0

    Request preview access. Never put registry tokens in source control.

    Deterministic benchmark execution, percentiles, baseline comparisons, and regression budgets for builds, SSR, hydration, stores, and application hot paths.

    +
    import { runBenchmark, assertBenchmarkBudget } from "@wrnexus/benchmark";
    +const result = await runBenchmark("render", render, { iterations: 100 });
    +assertBenchmarkBudget(result, baseline, { p95Percent: 5 });

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface BenchmarkOptions {
    +    iterations?: number;
    +    warmup?: number;
    +    clock?: () => number;
    +    setup?: () => void | Promise<void>;
    +    teardown?: () => void | Promise<void>;
    +}
    +interface BenchmarkResult {
    +    name: string;
    +    iterations: number;
    +    totalMs: number;
    +    meanMs: number;
    +    minMs: number;
    +    maxMs: number;
    +    p50Ms: number;
    +    p95Ms: number;
    +    p99Ms: number;
    +    operationsPerSecond: number;
    +    samples: number[];
    +}
    +interface RegressionBudget {
    +    meanPercent?: number;
    +    p95Percent?: number;
    +    maxAbsoluteMs?: number;
    +    minOperationsPerSecond?: number;
    +}
    +interface RegressionViolation {
    +    metric: "meanMs" | "p95Ms" | "maxMs" | "operationsPerSecond";
    +    baseline?: number;
    +    current: number;
    +    limit: number;
    +    message: string;
    +}
    +declare function percentile(values: readonly number[], quantile: number): number;
    +declare function runBenchmark(name: string, operation: () => void | Promise<void>, options?: BenchmarkOptions): Promise<BenchmarkResult>;
    +declare function compareBenchmark(current: BenchmarkResult, baseline: BenchmarkResult | undefined, budget?: RegressionBudget): RegressionViolation[];
    +declare function assertBenchmarkBudget(current: BenchmarkResult, baseline: BenchmarkResult | undefined, budget: RegressionBudget): void;
    +
    +export { type BenchmarkOptions, type BenchmarkResult, type RegressionBudget, type RegressionViolation, assertBenchmarkBudget, compareBenchmark, percentile, runBenchmark };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Deterministic benchmark execution, percentiles, baseline comparisons, and regression budgets for builds, SSR, hydration, stores, and application hot paths.

    import { runBenchmark, assertBenchmarkBudget } from "@wrnexus/benchmark";
    +const result = await runBenchmark("render", render, { iterations: 100 });
    +assertBenchmarkBudget(result, baseline, { p95Percent: 5 });

    Install @wrnexus/benchmark

    bun add @wrnexus/benchmark
    + +
    + + +
    + } +} diff --git a/app/pages/packages/cache.wrn b/app/pages/packages/cache.wrn new file mode 100644 index 00000000..9c2ab0b9 --- /dev/null +++ b/app/pages/packages/cache.wrn @@ -0,0 +1,242 @@ +page wrnexuscache { + seo { + title = "@wrnexus/cache" + description = "Memory and distributed caching with coordination and invalidation." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Data · Package reference

    @wrnexus/cache

    Memory and distributed caching with coordination and invalidation.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cache@0.8.0

    Request preview access. Never put registry tokens in source control.

    Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation.

    +
    import { connectCacheInvalidation, TagCache, responseCache } from "@wrnexus/cache";
    +const cache = new TagCache({ ttlMs: 60_000, staleWhileRevalidateMs: 300_000 });
    +export default responseCache({ cache, tags: ["products"] });
    +

    TagCache bounds entries with LRU-style eviction, deduplicates concurrent loaders, and prevents an invalidated in-flight loader from repopulating stale data. Use lookup() when fresh/stale state matters, or getOrLoad() for stampede-safe loading.

    +

    For multi-instance applications, connect the cache to any compatible pub/sub bus (including @wrnexus/pubsub). Namespaces isolate applications sharing the same broker. Local invalidation happens first and the returned promise confirms cross-instance publication; failures remain visible to the caller.

    +
    import { connectCacheInvalidation, TagCache } from "@wrnexus/cache";
    +import { createPubSub } from "@wrnexus/pubsub";
    +import { redisDriver } from "@wrnexus/pubsub/redis";
    +
    +const cache = new TagCache({ maxEntries: 10_000 });
    +const bus = createPubSub(redisDriver(process.env.REDIS_URL));
    +const invalidation = connectCacheInvalidation(cache, bus, {
    +  namespace: "storefront-production",
    +  onError: (error) => logger.error("cache invalidation failed", { error }),
    +});
    +
    +await invalidation.invalidateTag("products");
    +await invalidation.delete("product:42");
    +
    +// Unsubscribes this cache only; the shared bus remains owned by the app.
    +invalidation.close();
    +await bus.close();
    +

    Framework cache layers

    +

    CacheCoordinator keeps the four cache lifetimes explicit:

    +
      +
    • coordinator.request() creates request-only deduplication.
    • +
    • coordinator.data caches loader/query results.
    • +
    • coordinator.component caches reusable rendered fragments.
    • +
    • coordinator.page caches complete safe documents.
    • +
    +

    All cross-request layers are bounded, tag-aware, stale-while-revalidate capable, stampede-safe, and expose withLock() for exclusive per-key work. inspect() returns metadata without cached values. Development applications expose that inspection through the Cache panel and GET /__wrnexus/cache.

    +

    Pages and components can opt in declaratively:

    +
    cache {
    +  scope = "page"
    +  strategy = "stale-while-revalidate"
    +  ttl = "5m"
    +  stale = "10m"
    +  tags = ["catalog", "marketing"]
    +  vary = ["tenant", "language"]
    +}
    +

    Omit scope to cache named loader data. Use scope = "page" for full-page caching. Component policies cache their rendered fragment. Authenticated user and tenant identities are always included automatically; page caches also vary by language, theme, and accent. Add header names or cookie:name entries for other application-specific variation. Pages containing CSRF forms are never stored in the full-page cache.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context, Middleware } from '@wrnexus/core';
    +
    +interface CacheEntry<V> {
    +    value: V;
    +    createdAt: number;
    +    expiresAt: number;
    +    staleUntil: number;
    +    tags: string[];
    +}
    +type CacheLookup<V> = {
    +    state: "miss";
    +} | {
    +    state: "fresh" | "stale";
    +    entry: CacheEntry<V>;
    +};
    +interface CacheSetOptions {
    +    ttlMs?: number;
    +    staleWhileRevalidateMs?: number;
    +    tags?: string[];
    +}
    +interface TagCacheOptions {
    +    ttlMs?: number;
    +    staleWhileRevalidateMs?: number;
    +    maxEntries?: number;
    +    clock?: () => number;
    +    onEvent?: (event: CacheEvent) => void;
    +}
    +interface CacheEvent {
    +    operation: "hit" | "stale" | "miss" | "set" | "delete" | "invalidate" | "clear" | "load";
    +    key?: string;
    +    tags?: string[];
    +    at: number;
    +}
    +interface CacheSnapshotEntry {
    +    key: string;
    +    state: "fresh" | "stale";
    +    createdAt: number;
    +    expiresAt: number;
    +    staleUntil: number;
    +    tags: string[];
    +}
    +declare class TagCache<V = unknown> {
    +    private entries;
    +    private tagIndex;
    +    private pending;
    +    private locks;
    +    private revisions;
    +    private readonly ttlMs;
    +    private readonly staleMs;
    +    private readonly maxEntries;
    +    private readonly clock;
    +    private readonly onEvent?;
    +    constructor(options?: TagCacheOptions);
    +    private emit;
    +    lookup(key: string): CacheLookup<V>;
    +    get(key: string): V | undefined;
    +    set(key: string, value: V, options?: CacheSetOptions): void;
    +    private store;
    +    getOrLoad(key: string, loader: () => V | Promise<V>, options?: CacheSetOptions): Promise<V>;
    +    /** Serialize arbitrary cache-adjacent work for a key without storing its result. */
    +    withLock<T>(key: string, task: () => T | Promise<T>): Promise<T>;
    +    delete(key: string): boolean;
    +    private removeEntry;
    +    invalidateTag(tag: string): number;
    +    invalidateTags(tags: Iterable<string>): number;
    +    clear(): void;
    +    get size(): number;
    +    snapshot(): CacheSnapshotEntry[];
    +    private revision;
    +    private bump;
    +}
    +
    +type CacheLayerName = "data" | "component" | "page";
    +interface CacheInspection {
    +    layers: Record<CacheLayerName, ReturnType<TagCache<unknown>["snapshot"]>>;
    +    recentEvents: Array<CacheEvent & {
    +        layer: CacheLayerName;
    +    }>;
    +}
    +interface CacheCoordinatorOptions extends Omit<TagCacheOptions, "onEvent"> {
    +    eventLimit?: number;
    +    onEvent?: (event: CacheEvent & {
    +        layer: CacheLayerName;
    +    }) => void;
    +}
    +/** A request-lifetime cache: deduplicates work without leaking values between requests. */
    +declare class RequestCache {
    +    private pending;
    +    getOrLoad<V>(key: string, loader: () => V | Promise<V>): Promise<V>;
    +    clear(): void;
    +}
    +/** Owns the three cross-request cache layers and creates isolated request caches. */
    +declare class CacheCoordinator {
    +    readonly data: TagCache<unknown>;
    +    readonly component: TagCache<unknown>;
    +    readonly page: TagCache<unknown>;
    +    private readonly events;
    +    private readonly eventLimit;
    +    constructor(options?: CacheCoordinatorOptions);
    +    request(): RequestCache;
    +    layer(name: CacheLayerName): TagCache<unknown>;
    +    getOrLoad<V>(layer: CacheLayerName, key: string, loader: () => V | Promise<V>, options?: CacheSetOptions): Promise<V>;
    +    invalidateTags(tags: Iterable<string>): number;
    +    inspect(): CacheInspection;
    +    clear(): void;
    +}
    +
    +interface CachedResponse {
    +    status: number;
    +    statusText: string;
    +    headers: [string, string][];
    +    body: Uint8Array;
    +    etag: string;
    +}
    +interface ResponseCacheOptions extends CacheSetOptions {
    +    cache?: TagCache<CachedResponse>;
    +    key?: (ctx: Context) => string;
    +    vary?: string[];
    +    shouldCache?: (ctx: Context, response: Response) => boolean;
    +    /**
    +     * Optional detached revalidator used for stale-while-revalidate. Middleware
    +     * `next()` is deliberately never called after a response has been returned,
    +     * because many middleware pipelines are single-use.
    +     */
    +    revalidate?: (ctx: Context) => Promise<Response>;
    +    onRevalidateError?: (error: unknown, ctx: Context) => void;
    +}
    +declare function responseCache(options?: ResponseCacheOptions): Middleware;
    +
    +interface CacheInvalidationBus {
    +    publish(topic: string, message: unknown): void | Promise<void>;
    +    subscribe(pattern: string, handler: (message: unknown) => void | Promise<void>): () => void;
    +}
    +interface DistributedInvalidationOptions {
    +    namespace?: string;
    +    instanceId?: string;
    +    onError?: (error: unknown) => void;
    +}
    +interface DistributedInvalidation {
    +    invalidateTag(tag: string): Promise<number>;
    +    invalidateTags(tags: Iterable<string>): Promise<number>;
    +    delete(key: string): Promise<boolean>;
    +    clear(): Promise<void>;
    +    close(): void;
    +}
    +/**
    + * Propagate cache invalidations over any structurally compatible pub/sub bus.
    + * The bus is intentionally not closed because applications commonly share it.
    + */
    +declare function connectCacheInvalidation<V>(cache: TagCache<V>, bus: CacheInvalidationBus, options?: DistributedInvalidationOptions): DistributedInvalidation;
    +
    +export { CacheCoordinator, type CacheCoordinatorOptions, type CacheEntry, type CacheEvent, type CacheInspection, type CacheInvalidationBus, type CacheLayerName, type CacheLookup, type CacheSetOptions, type CacheSnapshotEntry, type CachedResponse, type DistributedInvalidation, type DistributedInvalidationOptions, RequestCache, type ResponseCacheOptions, TagCache, type TagCacheOptions, connectCacheInvalidation, responseCache };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation.

    import { connectCacheInvalidation, TagCache, responseCache } from "@wrnexus/cache";
    +const cache = new TagCache({ ttlMs: 60_000, staleWhileRevalidateMs: 300_000 });
    +export default responseCache({ cache, tags: ["products"] });

    cross-instance publication; failures remain visible to the caller.

    import { connectCacheInvalidation, TagCache } from "@wrnexus/cache";
    +import { createPubSub } from "@wrnexus/pubsub";
    +import { redisDriver } from "@wrnexus/pubsub/redis";
    +
    +const cache = new TagCache({ maxEntries: 10_000 });
    +const bus = createPubSub(redisDriver(process.env.REDIS_URL));
    +const invalidation = connectCacheInvalidation(cache, bus, {
    +  namespace: "storefront-production",
    +  onError: (error) => logger.error("cache invalidation failed", { error }),
    +});
    +
    +await invalidation.invalidateTag("products");
    +await invalidation.delete("product:42");
    +
    +// Unsubscribes this cache only; the shared bus remains owned by the app.
    +invalidation.close();
    +await bus.close();

    Pages and components can opt in declaratively

    cache {
    +  scope = "page"
    +  strategy = "stale-while-revalidate"
    +  ttl = "5m"
    +  stale = "10m"
    +  tags = ["catalog", "marketing"]
    +  vary = ["tenant", "language"]
    +}
    + +
    + + +
    + } +} diff --git a/app/pages/packages/captcha.wrn b/app/pages/packages/captcha.wrn index beabdd88..02893fd0 100644 --- a/app/pages/packages/captcha.wrn +++ b/app/pages/packages/captcha.wrn @@ -10,11 +10,11 @@ page wrnexuscaptcha {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/captcha

    Managed CAPTCHA verification, middleware, and UI integration.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/captcha@0.7.0

    Request preview access. Never put registry tokens in source control.

    A first-class CAPTCHA and anti-automation package for WRNexusJS. It supports self-hosted challenges, a managed WRNexus service, external providers, form submission guards, page gates, accessible audio, adaptive risk checks, and a Tailwind-only .wrn component.

    +
    Security · Package reference

    @wrnexus/captcha

    Managed CAPTCHA verification, middleware, and UI integration.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/captcha@0.8.0

    Request preview access. Never put registry tokens in source control.

    A first-class CAPTCHA and anti-automation package for WRNexusJS. It supports self-hosted challenges, a managed WRNexus service, external providers, form submission guards, page gates, accessible audio, adaptive risk checks, and a Tailwind-only .wrn component.

    Install

    bun add @wrnexus/captcha

    WRNexusJS automatically discovers the package plugin, component, client runtime, styles, and DevToolbar audit. Use <Captcha /> directly after installation. The browser runtime is injected once only on responses that render a CAPTCHA; no script tag, public-file copy, or manual plugin registration is required. Call captchaPlugin(options) explicitly only when an application needs to override the discovered package configuration.

    @@ -253,7 +253,16 @@ const wordChallenge = defineCaptchaGenerator({ }); const engine = createCaptchaEngine({ secret, generators: [wordChallenge] });
    -

    Applications may also implement CaptchaStore, CaptchaAudioRenderer, or use defineCaptchaProvider() for a completely custom service.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { CaptchaAudioRenderer, CaptchaBinding, CaptchaChallenge, CaptchaChallengeGenerator, CaptchaChallengeRecord, CaptchaChallengeType, CaptchaConcreteImageStyle, CaptchaDifficulty, CaptchaEngine, CaptchaEngineOptions, CaptchaFailureCode, CaptchaGeneratorContext, CaptchaGuardOptions, CaptchaHttpHandlers, CaptchaImageItem, CaptchaImageStyle, CaptchaMiddleware, CaptchaPageGateOptions, CaptchaPolicyMode, CaptchaPolicyOptions, CaptchaPresentation, CaptchaProvider, CaptchaProviderClientConfig, CaptchaProviderName, CaptchaResponseTokenRecord, CaptchaRiskResult, CaptchaRiskSignals, CaptchaStore, CaptchaVerificationResult, CreateCaptchaOptions, GeneratedCaptchaChallenge, VerifyCaptchaInput } from './types.js';
    +

    Applications may also implement CaptchaStore, CaptchaAudioRenderer, or use defineCaptchaProvider() for a completely custom service.

    +

    Helper and block kit

    +

    The package exports captchaTokenFrom, captchaHeaders, captchaFields, verifyCaptcha, verifyCaptchaOrThrow, captchaResultResponse, and captchaContext for consistent server and client integration.

    +

    Enable the CAPTCHA plugin to use the low-level <Captcha /> challenge plus complete UI-composed blocks:

    +
      +
    • <CaptchaField />
    • +
    • <CaptchaStatus />
    • +
    +

    CaptchaField composes Card from @wrnexus/ui and keeps the CAPTCHA-specific size separate from the surrounding UI size.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { CaptchaVerificationResult, CaptchaProvider, CaptchaEngine, VerifyCaptchaInput } from './types.js';
    +export { CaptchaAudioRenderer, CaptchaBinding, CaptchaChallenge, CaptchaChallengeGenerator, CaptchaChallengeRecord, CaptchaChallengeType, CaptchaConcreteImageStyle, CaptchaDifficulty, CaptchaEngineOptions, CaptchaFailureCode, CaptchaGeneratorContext, CaptchaGuardOptions, CaptchaHttpHandlers, CaptchaImageItem, CaptchaImageStyle, CaptchaMiddleware, CaptchaPageGateOptions, CaptchaPolicyMode, CaptchaPolicyOptions, CaptchaPresentation, CaptchaProviderClientConfig, CaptchaProviderName, CaptchaResponseTokenRecord, CaptchaRiskResult, CaptchaRiskSignals, CaptchaStore, CreateCaptchaOptions, GeneratedCaptchaChallenge } from './types.js';
     export { CaptchaHttpOptions, CaptchaParseResult, CaptchaSessionGrant, DefaultCaptchaEngine, ParseWithCaptchaOptions, bindingHash, bytesToBase64Url, captchaGuard, captchaPageGate, clearCaptchaGrants, constantTimeEqual, createCaptchaEngine, createCaptchaHttpHandlers, defaultRandomBytes, evaluateCaptchaRisk, hmacSha256, parseWithCaptcha, randomId, sha256, shouldRequireCaptcha, validCaptchaGrant } from './server/index.js';
     export { CaptchaAuditIssue, CaptchaPluginOptions, captchaComponentsDir, captchaPlugin } from './plugin.js';
     export { MemoryCaptchaStore, MemoryCaptchaStoreOptions, createMemoryCaptchaStore } from './stores/memory.js';
    @@ -268,9 +277,19 @@ export { ManagedCaptchaProvider, ManagedCaptchaProviderOptions, managedCapt
     export { defineCaptchaProvider } from './providers/custom.js';
     export { CAPTCHA_CONCRETE_IMAGE_STYLES, CAPTCHA_IMAGE_STYLES, CalculationCaptchaGenerator, ImageCaptchaGenerator, InvisibleCaptchaGenerator, ResolveCaptchaImageStyleOptions, ResolvedCaptchaImageStyle, Rgba, RgbaImage, TextCaptchaGenerator, alphaCaptchaGenerator, alphanumericCaptchaGenerator, bytesToBase64, calculationCaptchaGenerator, createImage, defaultCaptchaGenerators, defineCaptchaGenerator, drawGlyph, drawLine, drawText, encodePng, fillCircle, fillPolygon, fillRect, honeypotCaptchaGenerator, imageCaptchaGenerator, isCaptchaImageStyle, normalizeCaptchaImageStyle, normalizeCaptchaImageStyleList, notRobotCaptchaGenerator, numberCaptchaGenerator, pngDataUri, resolveCaptchaImageStyle, setPixel, timingCaptchaGenerator } from './challenges/index.js';
     export { AssetAudioRenderer, AssetAudioRendererOptions, createAssetAudioRenderer, resolveCaptchaAudioAssetsDir } from './audio/index.js';
    -import '@wrnexus/core';
    +import { Context } from '@wrnexus/core';
     import '@wrnexus/validation';
     import '@wrnexus/plugin';
    +
    +declare function captchaTokenFrom(value: Request | Headers | FormData | URLSearchParams | Record<string, unknown>, field?: string): Promise<string | undefined> | string | undefined;
    +declare function captchaHeaders(token: string): HeadersInit;
    +declare function captchaFields(token: string, field?: string): Record<string, string>;
    +declare function verifyCaptcha(providerOrEngine: CaptchaProvider | CaptchaEngine, input: VerifyCaptchaInput): Promise<CaptchaVerificationResult>;
    +declare function verifyCaptchaOrThrow(providerOrEngine: CaptchaProvider | CaptchaEngine, input: VerifyCaptchaInput): Promise<CaptchaVerificationResult>;
    +declare function captchaResultResponse(result: CaptchaVerificationResult): Response;
    +declare function captchaContext(ctx: Context): CaptchaVerificationResult | null;
    +
    +export { CaptchaEngine, CaptchaProvider, CaptchaVerificationResult, VerifyCaptchaInput, captchaContext, captchaFields, captchaHeaders, captchaResultResponse, captchaTokenFrom, verifyCaptcha, verifyCaptchaOrThrow };
     

    Examples

    Copy-ready examples from the installed package documentation.

    ## Install

    bun add @wrnexus/captcha

    ## Create the self-hosted engine

    import {
       createCaptchaEngine,
       createCaptchaHttpHandlers,
    @@ -312,9 +331,9 @@ export const HEAD = POST;

    Listen button visibility

    <Captcha showListen="false" action="without-listen-button" />
     <Captcha showAudio="false" action="without-audio-alternative" />
    - +
    - + } diff --git a/app/pages/packages/cli.wrn b/app/pages/packages/cli.wrn index 2aa77955..95432fde 100644 --- a/app/pages/packages/cli.wrn +++ b/app/pages/packages/cli.wrn @@ -10,11 +10,16 @@ page wrnexuscli {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/cli

    Create, develop, build, generate, test, and maintain WRNexusJS apps.

    v0.7.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cli@0.7.0

    Request preview access. Never put registry tokens in source control.

    The wrnexus command-line tool that scaffolds, runs, builds, tests, and manages WRNexusJS apps.
    +
    Tooling · Package reference

    @wrnexus/cli

    Create, develop, build, generate, test, and maintain WRNexusJS apps.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/cli@0.8.0

    Request preview access. Never put registry tokens in source control.

    Production parity commands:

    +
    wrnexus build .
    +wrnexus preview . --port=3000
    +wrnexus dev . --production-runtime
    +

    preview refuses to start without dist/server.js and executes that exact artifact with the production profile. Production-runtime development rebuilds the same minified artifact after app, public, or configuration changes and keeps the last good server running when a rebuild fails.

    +
    The wrnexus command-line tool that scaffolds, runs, builds, tests, and manages WRNexusJS apps.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/cli provides the wrnexus executable — the single entry point for developing a WRNexusJS app. It runs the HMR dev server, produces a self-contained production build, scaffolds apps/pages/components, drives database migrations, regenerates typed routes and queries, runs tests, and manages configuration profiles. It also scaffolds multi-app monorepos and serves them behind a domain-routing gateway. This is a CLI/build-time package (it shells out to the Bun binary for the dev child and tests) and it also exports the workspace config types via a subpath.

    @@ -25,11 +30,18 @@ page wrnexuscli {
    bunx wrnexus dev
     # or add scripts: "dev": "wrnexus dev .", "build": "wrnexus build ."

    Commands

    +

    Local production services

    +

    wrnexus dev . --services starts the application and the bounded local database, cache, mail, SMS, webhook, storage, queue, cron, authentication and metrics simulator. It generates a localhost/*.localhost development certificate under .wrnexus/certificates/ and serves both the application and service console over HTTPS. Trust that certificate locally to remove the browser warning. Use --services-http only when an external development proxy already terminates TLS.

    +

    Exact production runtime with live updates

    +

    wrnexus dev . --production-runtime rebuilds and executes dist/server.js with production resolution, serialization, caching, headers and assets. The supervisor keeps the last good process when a build fails. On a successful rebuild the opt-in production HMR socket reconnects, requests the new document and morphs it into the browser; ordinary wrnexus preview and deployed production servers never include that client.

    +

    API platform

    +

    wrnexus api generate [app-dir] (or api docs) derives operations from file routes and emits generated/api/openapi.json, safe static documentation, Postman collection, curl examples, and TypeScript, JavaScript, Java, Go and Python SDKs. Generate one client with wrnexus sdk generate <language> [app-dir].

    Every command accepts an optional [app-dir] (defaults to .). Commands that read config or .env also accept --profile=<name> (see [Profiles](#profiles)).

    -
    CommandPurpose
    wrnexus dev [app-dir] [--port=3000]Start the development server with live reload / HMR.
    wrnexus build [app-dir]Build a self-contained production server bundle + assets into dist/.
    wrnexus create <app-name>Scaffold a new single app from an inline template.
    wrnexus workspace <name>Scaffold a monorepo (apps/* + shared packages/*).
    wrnexus workspace add <name>Add and register an app in the current workspace.
    wrnexus gateway [--port=3000]Serve every workspace app behind one port, routed by domain.
    wrnexus production [workspace-dir]Build, migrate, and serve every workspace app in production.
    wrnexus generate <type> <name>Scaffold a page \component \api \schema.
    wrnexus generate routesRegenerate the typed routes file (app/routes.gen.ts).
    wrnexus generate dockerScaffold Dockerfile, .dockerignore, and docker-compose.yml.
    wrnexus generate mobileScaffold a Capacitor shell for iOS and Android.
    wrnexus mobile add <package...>Install Capacitor plugins and sync native projects.
    wrnexus eject <name...>Copy Wire UI component .wrn sources into app/components/.
    wrnexus db <cmd>Database migrations and tooling (see [db](#wrnexus-db)).
    wrnexus test [app-dir] [--watch]Run the app's tests via bun test (defaults to the test profile).
    wrnexus profiles [app-dir]List config profiles and their .env files, marking the active one.
    wrnexus helpPrint usage.
    +wrnexus dev [app-dir] [--port=3000]Start the development server with live reload / HMR.wrnexus build [app-dir]Build a self-contained production server bundle + assets into dist/.wrnexus create <app-name>Scaffold a new single app from an inline template.wrnexus workspace <name>Scaffold a monorepo (apps/* + shared packages/*).wrnexus workspace add <name>Add and register an app in the current workspace.wrnexus gateway [--port=3000]Serve every workspace app behind one port, routed by domain.wrnexus production [workspace-dir]Build, migrate, and serve every workspace app in production.wrnexus generate <type> <name>Scaffold a page \component \api \schema.wrnexus generate routesRegenerate the typed routes file (app/routes.gen.ts).wrnexus generate dockerScaffold Dockerfile, .dockerignore, and docker-compose.yml.wrnexus generate mobileScaffold a Capacitor shell for iOS and Android.wrnexus mobile add <package...>Install Capacitor plugins and sync native projects.wrnexus eject <name...>Copy Wire UI component .wrn sources into app/components/.wrnexus db <cmd>Database migrations and tooling (see [db](#wrnexus-db)).wrnexus test [app-dir] [--watch]Run the app's tests via bun test (defaults to the test profile).wrnexus profiles [app-dir]List config profiles and their .env files, marking the active one.wrnexus compatibility checkCheck whether behavior defaults are explicitly pinned and current.wrnexus compatibility explainExplain configured, effective, and current compatibility behavior.wrnexus compatibility upgradeBack up config and explicitly opt into reviewed current behavior.wrnexus helpPrint usage.

    wrnexus g is an alias for wrnexus generate.

    +

    Compatibility upgrades never happen implicitly. New applications pin compatibilityDate and frameworkBehaviour; existing applications use wrnexus compatibility explain before the backed-up, idempotent upgrade command.

    wrnexus dev

    Supervises a child dev-server process (from @wrnexus/dev-server). The child owns file watching and HMR: CSS and client-island edits update the live page over a WebSocket with no restart; when a server module changes, the child exits with a restart code and the supervisor respawns it (the browser reconnects and morphs in the new HTML). On startup it regenerates typed DB queries and typed routes (best effort). Use --port= to change the port (default 3000).

    wrnexus dev . --port=8080
    @@ -45,7 +57,8 @@ page wrnexuscli { # Generated apps also provide: npm start # Build and start together: npm run production

    wrnexus create

    -

    Scaffolds a new app from an inline (dependency-free) template — package.json, .gitignore, config, and starter app/ files. Use npm run dev during development, npm run build && npm start for production, or npm run production to build and start in one command. The generated production server currently requires Bun even when npm is used to manage packages and scripts.

    +

    Scaffolds a complete v0.8 app from an inline template. The generated project includes strict TypeScript, ESLint and Prettier, editor recommendations, environment templates, database migrations, locales, schemas, tests, API/middleware/realtime examples, Tailwind and Iconify, PWA/mobile defaults, and the framework package kits. Its wrnexus.config.ts documents the current imports, types, stores, performance, observability, tenancy, build, navigation, theme, i18n, database, storage, realtime, security, and profile configuration.

    +

    Use bun run dev during development, bun run check for the complete typecheck/lint/test/format gate, bun run build && bun run start for production, or bun run production to build and start in one command.

    wrnexus update

    wrnexus update --latest performs a complete project upgrade. It hands control to the exact target CLI, backs up important project files under .wrnexus/update-backups/, updates every @wrnexus/* dependency, refreshes framework-owned references, and applies every versioned syntax/config/file migration between the project version and target version. After installation it runs the project's check and build scripts; the new version is recorded only after verification succeeds.

    Use --dry-run to preview an upgrade or --no-verify when verification is intentionally handled elsewhere. Migrations never overwrite user-owned configuration wholesale: each release must provide a focused, idempotent transformation for any changed syntax or config contract.

    @@ -81,7 +94,7 @@ wrnexus db migrate wrnexus db studio users wrnexus db status --db=analytics

    wrnexus workspace and wrnexus gateway

    -

    workspace <name> scaffolds a monorepo: several WRNexusJS apps under apps/* and shared libraries under packages/*, plus a wrnexus.workspace.ts that maps each app to the domains it serves. gateway runs every app behind one port and routes by Host header, with optional per-app auth and gateway-wide security (trusted hosts, rate limit, security headers, access log).

    +

    workspace <name> scaffolds a monorepo: complete v0.8 apps under apps/*, shared libraries under packages/*, root TypeScript/lint/format/editor/environment tooling, and a wrnexus.workspace.ts that maps each app to the domains it serves. gateway runs every app behind one port and routes by Host header, with optional per-app auth and gateway-wide security (trusted hosts, rate limit, security headers, access log). Newly added workspace apps use the same current scaffold.

    wrnexus workspace acme
     wrnexus gateway --port=3000

    For a complete production start, use the first-class workspace orchestrator:

    @@ -116,6 +129,7 @@ wrnexus gateway --port=3000
    wrnexus update --latest --dry-run
     wrnexus update --latest
     wrnexus doctor
    +

    Use wrnexus doctor --fix [app-dir] to apply conservative repairs before the health check: create missing app/pages and a default config, align skewed @wrnexus/* dependency ranges, record the current migration marker, and format only syntax-valid .wrn files. Invalid JSON or WRN sources are reported/skipped instead of overwritten; repeat runs are idempotent.

    Profiles

    Pass --profile=<name> to dev, build, db (or set WRNEXUS_PROFILE) to select a config profile. The CLI publishes WRNEXUS_PROFILE so config loaders and the dev child pick it up, and loads that profile's .env cascade (.env, .env.local, .env.<profile>, .env.<profile>.local) into process.env.

    wrnexus dev --profile=uat
    @@ -151,9 +165,9 @@ bun install
     wrnexus gateway --port=3000

    Upgrade with migrations and verification

    wrnexus update --latest --dry-run
     wrnexus update --latest
     wrnexus doctor
    - +
    - + } diff --git a/app/pages/packages/compiler.wrn b/app/pages/packages/compiler.wrn index 8a675d02..91d58783 100644 --- a/app/pages/packages/compiler.wrn +++ b/app/pages/packages/compiler.wrn @@ -10,12 +10,26 @@ page wrnexuscompiler {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/compiler

    Parser and code generators for the .wrn language.

    v0.7.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/compiler@0.7.0

    Request preview access. Never put registry tokens in source control.

    Compiler for the .wrn language — tokenizes, parses, and lowers .wrn page and component files to TypeScript.
    +
    Core · Package reference

    @wrnexus/compiler

    Parser and code generators for the .wrn language.

    v0.8.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/compiler@0.8.0

    Request preview access. Never put registry tokens in source control.

    Partial-static rendering

    +

    Pages can select render = "partial-static" and divide their view with <Static> and <Dynamic> boundaries. The compiler emits a build-only shell renderer that never evaluates dynamic-boundary children. wrnexus build expands static component mounts into dist/partial-shells.json, records byte/region evidence in build-report.json, and embeds the shell in the production route manifest. At request time the production runtime retains request-aware layouts, locale/theme metadata and security nonces while streaming dynamic regions into stable placeholders.

    +
    Compiler for the .wrn language — tokenizes, parses, and lowers .wrn page and component files to TypeScript.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    +

    Production adapters use analyzeRuntimeImports before bundling. Edge, worker, service-worker, and browser targets reject Node filesystem, TCP, and process modules with WRN-RUNTIME-CAPABILITY. Package manifests can declare supported wrnexus.runtimes and required wrnexus.requires capabilities; discovery fails when the selected deployment cannot satisfy them.

    +

    Server actions

    +
    action createUser using CreateUserSchema {
    +  const user = await users.create(input)
    +  invalidate("users")
    +  return user
    +}
    +
    +view {
    +  <form @submit="createUser">...</form>
    +}
    +

    The compiler produces a schema-aware server registry, a fully inferred action client, and progressively enhanced form metadata. The shared runtime performs validation, authentication/permission checks, CSRF verification, serialization, invalidation reporting, and browser lifecycle events.

    Overview

    @wrnexus/compiler turns .wrn source into TypeScript that targets the framework's runtime primitives. A .wrn file declares either a page (a route) or a component (a reusable, prop-driven fragment) with blocks for state, view (plain HTML), seo, style, functions, api, ssr/client data bindings, and realtime websocket handlers. The pipeline is source → Lexer → parse() → PageAst → generate() → TypeScript. It is a build/server-side library — the WRNexusJS dev loader calls it to compile .wrn files on the fly, surfacing ParseError as a readable error page.

    Static ES module imports may appear before the root declaration. Imported values are available to server-rendered expressions, including component props:

    @@ -124,7 +138,7 @@ lx.next(); // { type: "lbrace", value: "{", pos: 1
  • Pure TypeScript with no runtime dependencies; runs under Bun as part of the WRNexusJS toolchain (Node is not supported).
  • Generated modules target WRNexusJS runtime primitives (data-scope, data-text, data-on-*, data-for, data-component, __wrnexus*/__wire* helpers) — consume the output within a WRNexusJS app, e.g. via @wrnexus/core's dev loader.
  • Complete TypeScript API

    Generated from the exact installed package declarations.

    import { PageAst as PageAst$1, StructuredImportDecl, WrnDiagnostic } from '@wrnexus/syntax';
    -export { ActionBlock, ApiBlock, Attr, ComputedDecl, DataApiBlock, DataMode, EffectBlock, EventDecl, LexError, Lexer, LoadBlock, ModeFunctionsBlock, OutputDecl, PageAst, ParseError, PropDecl, RealtimeBlock, RuntimeFunctionDecl, SeoBlock, StateDecl, StateRuntime, StoreKind, StructuredImportDecl, ViewNode, WrnDiagnostic, assertValidAst, diagnose, diagnosticFromError, eraseFunctionTypes, formatDiagnostic, inferredRuntimeType, parse, runtimeTypeOf } from '@wrnexus/syntax';
    +export { ActionBlock, ApiBlock, Attr, ComputedDecl, DataApiBlock, DataMode, EffectBlock, EventDecl, FormatWrnOptions, LexError, Lexer, LoadBlock, ModeFunctionsBlock, OutputDecl, PageAst, ParseError, PropDecl, RealtimeBlock, RuntimeFunctionDecl, SeoBlock, StateDecl, StateRuntime, StoreKind, StructuredImportDecl, ViewNode, WrnDiagnostic, assertValidAst, diagnose, diagnosticFromError, eraseFunctionTypes, formatDiagnostic, formatWrn, inferredRuntimeType, parse, runtimeTypeOf } from '@wrnexus/syntax';
     import { PageAst } from '@wrnexus/syntax/parser';
     
     /**
    @@ -263,9 +277,43 @@ interface RuntimeRequirements {
         needsServerRuntime: boolean;
         hydrationStrategy: string | null;
         reasons: string[];
    +    optimization: OptimizationReport;
    +    cachePolicy: Record<string, string>;
    +    requiredPermission: string | null;
     }
    +interface OptimizationReport {
    +    staticNodes: number;
    +    reactiveRegions: number;
    +    eliminatedBranches: number;
    +    unusedState: string[];
    +    unusedHandlers: string[];
    +    constantProps: string[];
    +    unusedLocalCssClasses: string[];
    +    batchableStateUpdates: number;
    +    memoizableComponents: string[];
    +    preloadDependencies: string[];
    +    serverOnlyModules: string[];
    +}
    +/** Safe compile-time folding for literal conditional branches. */
    +declare function optimizeAst(ast: PageAst$1): {
    +    ast: PageAst$1;
    +    eliminatedBranches: number;
    +};
    +declare function analyzeOptimizations(ast: PageAst$1): OptimizationReport;
     declare function analyzeRuntimeRequirements(ast: PageAst$1): RuntimeRequirements;
     
    +type DeploymentRuntime = "bun" | "node" | "edge" | "worker" | "service-worker" | "browser";
    +type RuntimeCapability = "filesystem" | "tcp" | "process" | "websocket" | "crypto" | "streams" | "background-tasks";
    +interface RuntimeCapabilityDiagnostic {
    +    code: "WRN-RUNTIME-CAPABILITY";
    +    runtime: DeploymentRuntime;
    +    module: string;
    +    capability: RuntimeCapability;
    +    message: string;
    +}
    +declare function runtimeCapabilities(runtime: DeploymentRuntime): ReadonlySet<RuntimeCapability>;
    +declare function analyzeRuntimeImports(source: string, runtime: DeploymentRuntime): RuntimeCapabilityDiagnostic[];
    +
     declare class NativeCompileError extends Error {
         constructor(message: string);
     }
    @@ -330,7 +378,7 @@ declare function compileWireFile(source: string, filePath?: string): string;
     /** Richer entry point returning the AST and structured diagnostics. */
     declare function compile(source: string, filePath?: string): CompileResult;
     
    -export { type CompilationCache, type CompilationCacheEntry, type CompilationCacheOptions, type CompileResult, DependencyGraph, NativeCompileError, type RouteExecutionKind, type RuntimeRequirements, analyzeRuntimeRequirements, compilationKey, compile, compileNativeWireFile, compileWireFile, createCompilationCache, createComponentContract, createWrnSourceMap, generate, generateBrowserModule, generateDeclarations, generateNative, generateServerFunctionsModule, generateStoreBrowserModule, generateStoreModule, generateTargets, resolveWrnImport, resolveWrnImports, rpcManifest };
    +export { type CompilationCache, type CompilationCacheEntry, type CompilationCacheOptions, type CompileResult, DependencyGraph, type DeploymentRuntime, NativeCompileError, type OptimizationReport, type RouteExecutionKind, type RuntimeCapability, type RuntimeCapabilityDiagnostic, type RuntimeRequirements, analyzeOptimizations, analyzeRuntimeImports, analyzeRuntimeRequirements, compilationKey, compile, compileNativeWireFile, compileWireFile, createCompilationCache, createComponentContract, createWrnSourceMap, generate, generateBrowserModule, generateDeclarations, generateNative, generateServerFunctionsModule, generateStoreBrowserModule, generateStoreModule, generateTargets, optimizeAst, resolveWrnImport, resolveWrnImports, rpcManifest, runtimeCapabilities };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Compile a page

    import { compileWireFile } from "@wrnexus/compiler";
     
     const ts = compileWireFile(`
    @@ -359,9 +407,9 @@ const lx = new Lexer("page Home {");
     lx.next(); // { type: "ident", value: "page", pos: 0 }
     lx.next(); // { type: "ident", value: "Home", pos: 5 }
     lx.next(); // { type: "lbrace", value: "{", pos: 10 }
    - +
    - + } diff --git a/app/pages/packages/content.wrn b/app/pages/packages/content.wrn new file mode 100644 index 00000000..7fc48d8f --- /dev/null +++ b/app/pages/packages/content.wrn @@ -0,0 +1,177 @@ +page wrnexuscontent { + seo { + title = "@wrnexus/content" + description = "Content collections, validation, querying, and publishing workflows." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Data · Package reference

    @wrnexus/content

    Content collections, validation, querying, and publishing workflows.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/content@0.8.0

    Request preview access. Never put registry tokens in source control.

    Typed content collections for Markdown/MDX-like documents and remote CMS records. Collections validate frontmatter through any { parse(input) } schema, render escaped HTML, and expose draft preview, versions, references, headings, search indexes, pagination, RSS and sitemaps.

    +
    const posts = defineCollection({
    +  name: "posts",
    +  schema: PostSchema,
    +  loader: localContentLoader("content/posts"),
    +  previewToken: process.env.CONTENT_PREVIEW_TOKEN,
    +});
    +
    +const published = await posts.load();
    +const preview = await posts.load({ previewToken: request.headers.get("x-preview-token") ?? "" });
    +

    Remote systems implement CmsAdapter, use cmsContentLoader, or return JSON records through remoteContentLoader. Markdown HTML is escaped by default; raw executable HTML is never trusted.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    type MdxComponent = (props: Record<string, string>, children: string) => string;
    +/** Execute explicitly registered MDX components without evaluating arbitrary JavaScript. */
    +declare function renderMdxComponents(source: string, components: Record<string, MdxComponent>): string;
    +interface SyntaxLanguageBundle {
    +    highlight(source: string): string;
    +}
    +declare function createIncrementalHighlighter(loaders: Record<string, () => SyntaxLanguageBundle | Promise<SyntaxLanguageBundle>>): {
    +    languages: () => string[];
    +    highlight(language: string, source: string): Promise<string>;
    +    render(html: string): Promise<string>;
    +};
    +interface VendorAdapterOptions {
    +    fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
    +    token?: string;
    +    map?: (entry: any) => {
    +        id: string;
    +        content: string;
    +        source?: string;
    +    };
    +}
    +declare function contentfulAdapter(space: string, environment?: string, options?: VendorAdapterOptions): {
    +    list(collection: string): Promise<any>;
    +};
    +declare function sanityAdapter(project: string, dataset: string, options?: VendorAdapterOptions & {
    +    apiVersion?: string;
    +}): {
    +    list(collection: string): Promise<any>;
    +};
    +declare function strapiAdapter(baseUrl: string, options?: VendorAdapterOptions): {
    +    list(collection: string): Promise<any>;
    +};
    +
    +interface ContentSchema<T> {
    +    parse(input: unknown): T;
    +}
    +interface ContentEntry<T = Record<string, unknown>> {
    +    id: string;
    +    slug: string;
    +    collection: string;
    +    data: T;
    +    body: string;
    +    html: string;
    +    excerpt: string;
    +    headings: ContentHeading[];
    +    draft: boolean;
    +    version?: string;
    +    source: string;
    +}
    +interface ContentHeading {
    +    depth: number;
    +    text: string;
    +    slug: string;
    +}
    +interface ContentLoaderResult {
    +    id: string;
    +    source: string;
    +    content: string;
    +}
    +interface ContentLoader {
    +    load(): ContentLoaderResult[] | Promise<ContentLoaderResult[]>;
    +}
    +interface ContentCollectionOptions<T> {
    +    name: string;
    +    schema: ContentSchema<T>;
    +    loader: ContentLoader;
    +    includeDrafts?: boolean;
    +    previewToken?: string;
    +    references?: Record<string, ContentCollection<unknown>>;
    +}
    +interface ContentCollection<T> {
    +    name: string;
    +    load(options?: {
    +        drafts?: boolean;
    +        previewToken?: string;
    +        version?: string;
    +    }): Promise<ContentEntry<T>[]>;
    +    get(id: string, options?: {
    +        drafts?: boolean;
    +        previewToken?: string;
    +        version?: string;
    +    }): Promise<ContentEntry<T> | null>;
    +}
    +declare function parseFrontmatter(source: string): {
    +    data: Record<string, unknown>;
    +    body: string;
    +};
    +declare function renderMarkdown(source: string): {
    +    html: string;
    +    headings: ContentHeading[];
    +    excerpt: string;
    +};
    +declare function localContentLoader(directory: string): ContentLoader;
    +declare function remoteContentLoader(url: string, options?: {
    +    fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
    +    headers?: HeadersInit;
    +}): ContentLoader;
    +declare function defineCollection<T>(options: ContentCollectionOptions<T>): ContentCollection<T>;
    +declare function resolveContentReference(collections: Record<string, ContentCollection<unknown>>, reference: string): Promise<ContentEntry<unknown> | null>;
    +declare function paginateContent<T>(entries: T[], page?: number, pageSize?: number): {
    +    items: T[];
    +    page: number;
    +    pageSize: number;
    +    total: number;
    +    totalPages: number;
    +    hasNext: boolean;
    +    hasPrevious: boolean;
    +};
    +declare function createSearchIndex(entries: ContentEntry[]): {
    +    id: string;
    +    slug: string;
    +    title: string;
    +    text: string;
    +}[];
    +declare function searchContent(index: ReturnType<typeof createSearchIndex>, query: string): {
    +    id: string;
    +    slug: string;
    +    title: string;
    +    text: string;
    +}[];
    +declare function contentSitemap(entries: ContentEntry[], baseUrl: string): string;
    +declare function contentRss(entries: ContentEntry[], options: {
    +    title: string;
    +    baseUrl: string;
    +    description?: string;
    +}): string;
    +interface CmsAdapter {
    +    list(collection: string): Promise<Array<{
    +        id: string;
    +        content: string;
    +        source?: string;
    +    }>>;
    +}
    +declare function cmsContentLoader(adapter: CmsAdapter, collection: string): ContentLoader;
    +
    +export { type CmsAdapter, type ContentCollection, type ContentCollectionOptions, type ContentEntry, type ContentHeading, type ContentLoader, type ContentLoaderResult, type ContentSchema, type MdxComponent, type SyntaxLanguageBundle, type VendorAdapterOptions, cmsContentLoader, contentRss, contentSitemap, contentfulAdapter, createIncrementalHighlighter, createSearchIndex, defineCollection, localContentLoader, paginateContent, parseFrontmatter, remoteContentLoader, renderMarkdown, renderMdxComponents, resolveContentReference, sanityAdapter, searchContent, strapiAdapter };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    preview, versions, references, headings, search indexes, pagination, RSS and sitemaps.

    const posts = defineCollection({
    +  name: "posts",
    +  schema: PostSchema,
    +  loader: localContentLoader("content/posts"),
    +  previewToken: process.env.CONTENT_PREVIEW_TOKEN,
    +});
    +
    +const published = await posts.load();
    +const preview = await posts.load({ previewToken: request.headers.get("x-preview-token") ?? "" });

    Install @wrnexus/content

    bun add @wrnexus/content
    + +
    + + +
    + } +} diff --git a/app/pages/packages/core.wrn b/app/pages/packages/core.wrn index 9cdc01dd..8a8500fe 100644 --- a/app/pages/packages/core.wrn +++ b/app/pages/packages/core.wrn @@ -10,11 +10,11 @@ page wrnexuscore {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/core

    Contexts, middleware, security, sessions, caching, JSX, and realtime.

    v0.7.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/core@0.7.0

    Request preview access. Never put registry tokens in source control.

    The framework core: the request Context, middleware contract, and the security, session, caching, streaming, realtime, and JSX primitives every other WRNexusJS package builds on.
    +
    Core · Package reference

    @wrnexus/core

    Contexts, middleware, security, sessions, caching, JSX, and realtime.

    v0.8.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/core@0.8.0

    Request preview access. Never put registry tokens in source control.

    The framework core: the request Context, middleware contract, and the security, session, caching, streaming, realtime, and JSX primitives every other WRNexusJS package builds on.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/core is the shared foundation of WRNexusJS. It defines the Context object that flows through every middleware, page, and API route, plus the Middleware/Next contract they implement. On top of that it ships the building blocks a real app needs: cookie-backed sessions, password auth, CSRF protection, rate limiting, request logging, HTTP + in-memory caching, file uploads, streaming/SSE responses, WebSocket "rooms", security headers/CORS, and a server-side JSX runtime that renders to HTML strings. Everything here is server-side and Bun-native (it uses Bun.password, Bun.write, the web-standard Request/Response, and crypto). You depend on it directly and transitively through the rest of the framework.

    @@ -57,6 +57,23 @@ page wrnexuscore { ExportSignatureNotes requestLogger(options?)(RequestLoggerOptions?) => MiddlewareOne record per request with a request id (stored on ctx.locals[requestIdKey]).

    RequestLoggerOptions: format ("pretty" default \| "json"), sink(line, record) (default console.log), requestIdKey (default "requestId"), now. RequestRecord = { time, id, method, path, status, durationMs }.

    +

    Resilience — @wrnexus/core

    +

    resilientCall standardizes cancellation-aware timeouts, controlled retries, fixed or exponential backoff, fallback responses, circuit breaking, and bounded concurrency. Reuse a declarative circuit/bulkhead options object, or an explicit CircuitBreaker/Bulkhead instance, wherever calls must share health and capacity state.

    +
    import { resilientCall } from "@wrnexus/core";
    +
    +const paymentCircuit = { failures: 5, resetAfter: "30s" } as const;
    +
    +const status = await resilientCall({
    +  timeout: "5s",
    +  retries: 3,
    +  retryDelay: "100ms",
    +  backoff: "exponential",
    +  circuitBreaker: paymentCircuit,
    +  bulkhead: { concurrency: 20, queue: 100 },
    +  run: (signal) => paymentProvider.checkStatus({ signal }),
    +  fallback: () => ({ state: "unavailable" }),
    +});
    +

    CircuitBreaker.snapshot() reports closed, open, or half-open, failure and success counts, and the remaining retry delay for health endpoints and development tooling. Fail-fast conditions use stable WRN-RESILIENCE-* codes. Core's existing HealthRegistry, withIdempotency, and pluggable stores/locks cover health reporting, idempotent requests, and distributed coordination.

    Caching — @wrnexus/core

    @@ -217,6 +234,36 @@ interface Tenant { name?: string; metadata?: Record<string, unknown>; } +interface TenantResource { + tenantId: string; +} +interface TenantMembership { + tenantId: string; + userId: string; + roles?: string[]; + workspaceIds?: string[]; +} +interface TenantAuditEvent { + tenantId: string; + action: string; + actorId?: string; + resource?: string; + metadata?: Record<string, unknown>; + createdAt: number; +} +interface TenantQuota { + tenantId: string; + resource: string; + limit: number; + usage: number; +} +interface TenantDirectoryStore { + putMembership(value: TenantMembership): Promise<void>; + getMembership(tenantId: string, userId: string): Promise<TenantMembership | null>; + listMemberships(tenantId: string): Promise<TenantMembership[]>; + putQuota(value: TenantQuota): Promise<void>; + getQuota(tenantId: string, resource: string): Promise<TenantQuota | null>; +} type TenantResolver = (ctx: Context) => Tenant | null | Promise<Tenant | null>; interface TenantMiddlewareOptions { required?: boolean; @@ -224,11 +271,68 @@ interface TenantMiddlewareOptions { } declare function tenantMiddleware(resolveTenant: TenantResolver, options?: TenantMiddlewareOptions): Middleware; declare function tenantFromSubdomain(lookup: (slug: string, ctx: Context) => Tenant | null | Promise<Tenant | null>, rootDomains?: string[]): TenantResolver; +declare function tenantFromDomain(lookup: (domain: string, ctx: Context) => Tenant | null | Promise<Tenant | null>): TenantResolver; +declare function tenantFromPath(lookup: (slug: string, ctx: Context) => Tenant | null | Promise<Tenant | null>, prefix?: string): TenantResolver; +/** Header resolution is intentionally opt-in and must only be used behind a trusted proxy. */ +declare function tenantFromHeader(lookup: (id: string, ctx: Context) => Tenant | null | Promise<Tenant | null>, header?: string): TenantResolver; +declare function tenantFromSession(resolveId: (ctx: Context) => string | null | Promise<string | null>, lookup: (id: string, ctx: Context) => Tenant | null | Promise<Tenant | null>): TenantResolver; +declare function composeTenantResolvers(...resolvers: TenantResolver[]): TenantResolver; declare function requireTenant(ctx: Context): Tenant; /** Wrap a repository so every operation receives the current tenant id. */ declare function tenantScope<T extends object>(tenant: Tenant, repository: T): T & { tenantId: string; }; +declare function assertTenantAccess(tenant: Tenant, resource: TenantResource): void; +declare function tenantKey(tenant: Tenant | string, ...parts: Array<string | number>): string; +declare function createTenantDirectory(options?: { + audit?: (event: TenantAuditEvent) => void | Promise<void>; + now?: () => number; +}): { + addMembership(membership: TenantMembership, actorId?: string): Promise<void>; + membership(tenantId: string, userId: string): TenantMembership | null; + switchWorkspace(tenantId: string, userId: string, workspaceId: string): Promise<{ + tenantId: string; + workspaceId: string; + }>; + setQuota(tenantId: string, resource: string, limit: number): void; + enforceQuota(tenantId: string, resource: string, usage: number, requested?: number): { + usage: number; + requested: number; + limit: number | undefined; + }; +}; +declare function memoryTenantDirectoryStore(): TenantDirectoryStore; +declare function createPersistentTenantDirectory(store: TenantDirectoryStore, options?: { + audit?: (event: TenantAuditEvent) => void | Promise<void>; + now?: () => number; +}): { + addMembership(membership: TenantMembership, actorId?: string): Promise<void>; + membership: (tenantId: string, userId: string) => Promise<TenantMembership | null>; + memberships: (tenantId: string) => Promise<TenantMembership[]>; + switchWorkspace(tenantId: string, userId: string, workspaceId: string): Promise<{ + tenantId: string; + workspaceId: string; + }>; + setQuota(tenantId: string, resource: string, limit: number, usage?: number): Promise<void>; + consumeQuota(tenantId: string, resource: string, requested: number): Promise<TenantQuota | null>; +}; +interface TenantSqlClient { + query<T = Record<string, unknown>>(sql: string, parameters?: unknown[]): Promise<{ + rows: T[]; + }>; +} +declare function postgresTenantDirectoryStore(db: TenantSqlClient): TenantDirectoryStore; +declare const POSTGRES_TENANT_DIRECTORY_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_tenant_memberships (tenant_id text NOT NULL,user_id text NOT NULL,roles jsonb NOT NULL DEFAULT '[]',workspace_ids jsonb NOT NULL DEFAULT '[]',PRIMARY KEY (tenant_id,user_id)); CREATE TABLE IF NOT EXISTS wrnexus_tenant_quotas (tenant_id text NOT NULL,resource text NOT NULL,quota_limit bigint NOT NULL,usage bigint NOT NULL DEFAULT 0,PRIMARY KEY (tenant_id,resource));"; +declare function migrateTenants<T extends Tenant>(tenants: T[], migrate: (tenant: T) => void | Promise<void>, options?: { + concurrency?: number; + continueOnError?: boolean; +}): Promise<{ + migrated: string[]; + failed: { + tenantId: string; + error: string; + }[]; +}>; interface SpanRecord { name: string; @@ -432,6 +536,47 @@ declare function createContext(req: Request, url: URL): Context; /** Apply headers accumulated on the context, such as Set-Cookie. */ declare function withContextHeaders(ctx: Context, res: Response): Response; +type ExecutionKind = "http" | "api" | "action" | "loader" | "middleware" | "realtime" | "queue" | "cron" | "webhook"; +interface ResponseContext { + status: number; + headers: Headers; + setStatus(status: number): void; +} +interface ExecutionContext { + kind: ExecutionKind; + id: string; + request: Request; + response: ResponseContext; + user: unknown | null; + session: unknown | null; + tenant: Tenant | null; + locale: string; + timezone: string; + db?: unknown; + cache?: unknown; + logger?: unknown; + trace?: Tracer; + signal: AbortSignal; + deadline: Date | null; + metadata: Record<string, unknown>; + authorize(permission: string): void | Promise<void>; +} +interface ExecutionContextInput extends Partial<Omit<ExecutionContext, "kind" | "id" | "request" | "response" | "signal" | "deadline" | "metadata" | "authorize">> { + kind: ExecutionKind; + id?: string; + request?: Request; + response?: Partial<Pick<ResponseContext, "status">> & { + headers?: HeadersInit; + }; + signal?: AbortSignal; + deadline?: Date | number | null; + timeoutMs?: number; + metadata?: Record<string, unknown>; + authorize?: (permission: string) => void | Promise<void>; +} +declare function createExecutionContext(input: ExecutionContextInput): ExecutionContext; +declare function executionContextFromHttp(context: Context, kind?: Extract<ExecutionKind, "http" | "api" | "action" | "loader" | "middleware" | "webhook">, input?: Omit<ExecutionContextInput, "kind" | "request" | "user" | "tenant" | "locale" | "trace">): ExecutionContext; + /** * Small, dependency-free security helpers shared across packages. */ @@ -861,7 +1006,7 @@ interface RealtimeSecurityOptions { /** Called when a connection is rejected or closed for a policy violation. */ onViolation?(reason: string, client?: RoomClient): void; } -interface RoomHandlers<TData = Record<string, unknown>> { +interface RoomHandlers<TData = Record<string, unknown>, TMessage = any> { /** Per-room abuse and payload controls. */ security?: RealtimeSecurityOptions; /** @@ -872,16 +1017,16 @@ interface RoomHandlers<TData = Record<string, unknown>> { /** A client connected (a new tab joined the room). */ onConnect?(client: RoomClient<TData>): void | Promise<void>; /** A message arrived (JSON is parsed; non-JSON arrives as a string). */ - onMessage?(client: RoomClient<TData>, message: any): void | Promise<void>; + onMessage?(client: RoomClient<TData>, message: TMessage): void | Promise<void>; /** A client disconnected. */ onLeave?(client: RoomClient<TData>): void | Promise<void>; } -interface RoomDefinition<TData = Record<string, unknown>> { +interface RoomDefinition<TData = Record<string, unknown>, TMessage = any> { readonly __wrnexusRoom: true; - readonly handlers: RoomHandlers<TData>; + readonly handlers: RoomHandlers<TData, TMessage>; } /** Define a realtime room. Export the result as the `default` of a realtime file. */ -declare function defineRoom<TData = Record<string, unknown>>(handlers: RoomHandlers<TData>): RoomDefinition<TData>; +declare function defineRoom<TData = Record<string, unknown>, TMessage = any>(handlers: RoomHandlers<TData, TMessage>): RoomDefinition<TData, TMessage>; declare function isRoomDefinition(value: unknown): value is RoomDefinition; interface RealtimeConnectMeta { room: string; @@ -1085,6 +1230,11 @@ declare function withSecurityHeaders(req: Request, res: Response, mode: Mode, se interface SchemaLike<T> { parse(input: unknown): T; } +interface OutputSchemaLike<T> { + readonly __output: T; + parse(input: unknown): unknown; +} +type InferEndpointSchema<TSchema> = TSchema extends OutputSchemaLike<infer TValue> ? TValue : never; interface EndpointErrorBody { code: string; message: string; @@ -1097,8 +1247,8 @@ declare class EndpointError extends Error { constructor(status: number, code: string, message: string, details?: unknown | undefined); } interface EndpointDefinition<I, O> { - input?: SchemaLike<I>; - output?: SchemaLike<O>; + input?: SchemaLike<I> | OutputSchemaLike<I>; + output?: SchemaLike<O> | OutputSchemaLike<O>; auth?: "optional" | "required"; description?: string; tags?: string[]; @@ -1109,6 +1259,10 @@ interface DefinedEndpoint<I, O> { (ctx: Context, input?: unknown): Promise<Response>; } /** Define a validated, typed endpoint that can also drive SDK/OpenAPI generation. */ +declare function defineEndpoint<InputSchema extends OutputSchemaLike<unknown>, OutputSchema extends OutputSchemaLike<unknown>>(definition: Omit<EndpointDefinition<InferEndpointSchema<InputSchema>, InferEndpointSchema<OutputSchema>>, "input" | "output"> & { + input: InputSchema; + output: OutputSchema; +}): DefinedEndpoint<InferEndpointSchema<InputSchema>, InferEndpointSchema<OutputSchema>>; declare function defineEndpoint<I = unknown, O = unknown>(definition: EndpointDefinition<I, O>): DefinedEndpoint<I, O>; interface RpcClientOptions { baseUrl?: string; @@ -1199,6 +1353,65 @@ interface BudgetViolation { declare const recommendedWebBudgets: Readonly<PerformanceBudgets>; declare function checkPerformanceBudgets(budgets: PerformanceBudgets, measurement: PerformanceMeasurement): BudgetViolation[]; +type Duration = number | `${number}${"ms" | "s" | "m" | "h"}`; +type BackoffStrategy = "fixed" | "exponential" | ((attempt: number) => Duration); +interface CircuitBreakerOptions { + failures: number; + resetAfter: Duration; + successesToClose?: number; +} +interface CircuitBreakerSnapshot { + state: "closed" | "open" | "half-open"; + failures: number; + successes: number; + retryAfterMs: number; +} +declare class ResilienceError extends Error { + readonly code: "WRN-RESILIENCE-TIMEOUT" | "WRN-RESILIENCE-ABORTED" | "WRN-RESILIENCE-CIRCUIT-OPEN" | "WRN-RESILIENCE-BULKHEAD-FULL"; + constructor(code: "WRN-RESILIENCE-TIMEOUT" | "WRN-RESILIENCE-ABORTED" | "WRN-RESILIENCE-CIRCUIT-OPEN" | "WRN-RESILIENCE-BULKHEAD-FULL", message: string, options?: ErrorOptions); +} +declare function durationMs(value: Duration): number; +declare class CircuitBreaker { + private readonly options; + private failures; + private successes; + private openedAt; + private probing; + constructor(options: CircuitBreakerOptions); + snapshot(now?: number): CircuitBreakerSnapshot; + execute<T>(operation: () => Promise<T>): Promise<T>; +} +interface BulkheadOptions { + concurrency: number; + queue?: number; +} +declare class Bulkhead { + private readonly options; + private active; + private readonly waiting; + constructor(options: BulkheadOptions); + get snapshot(): Readonly<{ + active: number; + queued: number; + capacity: number; + }>; + execute<T>(operation: () => Promise<T>): Promise<T>; +} +interface ResilientCallOptions<T> { + run: (signal: AbortSignal, attempt: number) => Promise<T>; + timeout?: Duration; + retries?: number; + retryDelay?: Duration; + backoff?: BackoffStrategy; + circuitBreaker?: CircuitBreaker | CircuitBreakerOptions; + bulkhead?: Bulkhead | BulkheadOptions; + signal?: AbortSignal; + retryWhen?: (error: unknown, attempt: number) => boolean | Promise<boolean>; + fallback?: (error: unknown, signal: AbortSignal) => T | Promise<T>; + onRetry?: (error: unknown, attempt: number, delayMs: number) => void; +} +declare function resilientCall<T>(options: ResilientCallOptions<T>): Promise<T>; + interface ProblemDetails { type: string; title: string; @@ -1273,7 +1486,7 @@ declare function withIdempotency<T>(store: IdempotencyStore<T>, key: replayed: boolean; }>; -export { type ActionDefinition, ApplicationLifecycle, type AsyncSessionBackend, type Bucket, type BudgetViolation, CSRF_COOKIE, CSRF_HEADER, type CacheControlOptions, type CachePolicy, type ContentSecurityPolicyConfig, type Context, type CookieOptions, type CookieStore, type CorsConfig, type CorsOrigin, type CspDirectiveValue, type CsrfProtectionOptions, type DefinedAction, type DefinedEndpoint, type DefinedLoader, type EndpointDefinition, EndpointError, type EndpointErrorBody, type FeatureFlags, type FeatureRule, type FeatureValue, type HealthCheck, type HealthCheckResult, HealthRegistry, type HstsConfig, type IdempotencyRecord, type IdempotencyStore, type LifecycleHandler, type LifecyclePhase, type LoaderDefinition, type LocalStorageSnapshot, type Middleware, type Mode, type Next, type PageComponent, type PageMeta, type PerformanceBudgets, type PerformanceMeasurement, type PermissionsPolicyConfig, type ProblemDetails, type ProblemDetailsInput, type RateLimitOptions, type RateLimitStore, type RawSocket, type RealtimeBridge, type RealtimeBus, type RealtimeConnectMeta, type RealtimeEnvelope, type RealtimeHandler, type RealtimeRegistry, type RealtimeRegistryOptions, type RealtimeSecurityOptions, type RealtimeSocket, type RequestLimitsConfig, type RequestLoggerOptions, type RequestRecord, type RequireAuthOptions, type Room, type RoomAuthInfo, type RoomClient, type RoomDefinition, type RoomHandlers, type RpcClientOptions, SESSION_USER_KEY, type SaveUploadOptions, type SavedUpload, type SchemaLike, type SecureUploadOptions, type SecurityConfig, type SeoConfig, type ServerSentEvent, ServiceContainer, type ServiceToken, type SessionBackend, type SessionEntry, type SessionPolicy, type SessionStore, type Span, type SpanRecord, type StreamResponseInit, type TFunction, TTLCache, type Target, type Tenant, type TenantMiddlewareOptions, type TenantResolver, type Tracer, type TrustedTypesConfig, UploadError, type UploadInspectionResult, type UploadInspector, type UploadScanner, bridgeRealtime, cacheControl, checkPerformanceBudgets, collectUploads, createContext, createCorsPreflightResponse, createRealtimeRegistry, createRpcClient, createTracer, csrfProtection, csrfToken, dedupe, defaultKey, defineAction, defineEndpoint, defineFeatureFlags, defineLoader, defineRoom, escapeHtml, etag, getUser, hashPassword, isRoomDefinition, isSafeIslandName, isSafeRequestPath, isWebSocketOriginAllowed, loadSession, logIn, logOut, memoryIdempotencyStore, notModified, peerKey, problem, proxyKey, randomUploadFilename, rateLimit, recommendedWebBudgets, renderDevError, renderError, renderNotFound, renderProdError, renderStatusPage, requestId, requestLogger, requireAuth, requireTenant, resolveRequestUrl, sanitizeFilename, saveUpload, saveUploadSecure, secureDownloadHeaders, serviceToken, sessionAuth, setSessionBackend, setSessionPolicy, sse, streamResponse, tenantFromSubdomain, tenantMiddleware, tenantScope, tracingMiddleware, verifyCsrf, verifyPassword, withCacheControl, withContextHeaders, withIdempotency, withSecurityHeaders, withSpan }; +export { type ActionDefinition, ApplicationLifecycle, type AsyncSessionBackend, type BackoffStrategy, type Bucket, type BudgetViolation, Bulkhead, type BulkheadOptions, CSRF_COOKIE, CSRF_HEADER, type CacheControlOptions, type CachePolicy, CircuitBreaker, type CircuitBreakerOptions, type CircuitBreakerSnapshot, type ContentSecurityPolicyConfig, type Context, type CookieOptions, type CookieStore, type CorsConfig, type CorsOrigin, type CspDirectiveValue, type CsrfProtectionOptions, type DefinedAction, type DefinedEndpoint, type DefinedLoader, type Duration, type EndpointDefinition, EndpointError, type EndpointErrorBody, type ExecutionContext, type ExecutionContextInput, type ExecutionKind, type FeatureFlags, type FeatureRule, type FeatureValue, type HealthCheck, type HealthCheckResult, HealthRegistry, type HstsConfig, type IdempotencyRecord, type IdempotencyStore, type InferEndpointSchema, type LifecycleHandler, type LifecyclePhase, type LoaderDefinition, type LocalStorageSnapshot, type Middleware, type Mode, type Next, type OutputSchemaLike, POSTGRES_TENANT_DIRECTORY_SCHEMA, type PageComponent, type PageMeta, type PerformanceBudgets, type PerformanceMeasurement, type PermissionsPolicyConfig, type ProblemDetails, type ProblemDetailsInput, type RateLimitOptions, type RateLimitStore, type RawSocket, type RealtimeBridge, type RealtimeBus, type RealtimeConnectMeta, type RealtimeEnvelope, type RealtimeHandler, type RealtimeRegistry, type RealtimeRegistryOptions, type RealtimeSecurityOptions, type RealtimeSocket, type RequestLimitsConfig, type RequestLoggerOptions, type RequestRecord, type RequireAuthOptions, ResilienceError, type ResilientCallOptions, type ResponseContext, type Room, type RoomAuthInfo, type RoomClient, type RoomDefinition, type RoomHandlers, type RpcClientOptions, SESSION_USER_KEY, type SaveUploadOptions, type SavedUpload, type SchemaLike, type SecureUploadOptions, type SecurityConfig, type SeoConfig, type ServerSentEvent, ServiceContainer, type ServiceToken, type SessionBackend, type SessionEntry, type SessionPolicy, type SessionStore, type Span, type SpanRecord, type StreamResponseInit, type TFunction, TTLCache, type Target, type Tenant, type TenantAuditEvent, type TenantDirectoryStore, type TenantMembership, type TenantMiddlewareOptions, type TenantQuota, type TenantResolver, type TenantResource, type TenantSqlClient, type Tracer, type TrustedTypesConfig, UploadError, type UploadInspectionResult, type UploadInspector, type UploadScanner, assertTenantAccess, bridgeRealtime, cacheControl, checkPerformanceBudgets, collectUploads, composeTenantResolvers, createContext, createCorsPreflightResponse, createExecutionContext, createPersistentTenantDirectory, createRealtimeRegistry, createRpcClient, createTenantDirectory, createTracer, csrfProtection, csrfToken, dedupe, defaultKey, defineAction, defineEndpoint, defineFeatureFlags, defineLoader, defineRoom, durationMs, escapeHtml, etag, executionContextFromHttp, getUser, hashPassword, isRoomDefinition, isSafeIslandName, isSafeRequestPath, isWebSocketOriginAllowed, loadSession, logIn, logOut, memoryIdempotencyStore, memoryTenantDirectoryStore, migrateTenants, notModified, peerKey, postgresTenantDirectoryStore, problem, proxyKey, randomUploadFilename, rateLimit, recommendedWebBudgets, renderDevError, renderError, renderNotFound, renderProdError, renderStatusPage, requestId, requestLogger, requireAuth, requireTenant, resilientCall, resolveRequestUrl, sanitizeFilename, saveUpload, saveUploadSecure, secureDownloadHeaders, serviceToken, sessionAuth, setSessionBackend, setSessionPolicy, sse, streamResponse, tenantFromDomain, tenantFromHeader, tenantFromPath, tenantFromSession, tenantFromSubdomain, tenantKey, tenantMiddleware, tenantScope, tracingMiddleware, verifyCsrf, verifyPassword, withCacheControl, withContextHeaders, withIdempotency, withSecurityHeaders, withSpan };

    Examples

    Copy-ready examples from the installed package documentation.

    A minimal middleware chain

    import {
       createContext,
       withContextHeaders,
    @@ -1335,9 +1548,9 @@ import { redisDriver } from "@wrnexus/pubsub/redis";
     
     const registry = createRealtimeRegistry();
     bridgeRealtime(registry, createPubSub(redisDriver(process.env.REDIS_URL)));
    - + - + } diff --git a/app/pages/packages/csr.wrn b/app/pages/packages/csr.wrn index 5ebda1d1..3c65effc 100644 --- a/app/pages/packages/csr.wrn +++ b/app/pages/packages/csr.wrn @@ -10,11 +10,21 @@ page wrnexuscsr {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/csr

    Reactive, navigation, and realtime browser runtimes.

    v0.7.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/csr@0.7.0

    Request preview access. Never put registry tokens in source control.

    The browser-side client runtime for WRNexusJS — generic, self-contained JS that hydrates server-rendered pages with reactivity, client-side navigation, and realtime rooms.
    +
    Frontend · Package reference

    @wrnexus/csr

    Reactive, navigation, and realtime browser runtimes.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/csr@0.8.0

    Request preview access. Never put registry tokens in source control.

    +

    Pages can opt into restoration across client navigation:

    +
    page Users {
    +  navigation {
    +    preserve = ["filters", "pagination", "scroll", "tabs", "expanded"]
    +  }
    +}
    +

    Form-like categories restore named inputs, selects, and textareas. Password, file, hidden, CSRF/token/secret/credential fields, and elements marked data-no-preserve are never saved. For tab, expanded, or component UI state, mark stable elements with data-wrn-preserve="key"; their value and ARIA selected/expanded state are restored. State is scoped to pathname plus query.

    +

    Typed server actions

    +

    createActionClient<Input, Output>(route, name) supports programmatic calls. Schema-backed WRN actions also export __wrnexusActionClients, whose input and output are inferred automatically. Enhanced forms expose data-wrn-action-state="pending|success|error" and dispatch bubbling wrnexus:action:optimistic, :pending, :success, and :error events. Success details contain returned data and invalidated cache tags; error details contain field errors. Without JavaScript, the same form posts to its page and receives a 303 redirect or accessible validation response.

    +
    The browser-side client runtime for WRNexusJS — generic, self-contained JS that hydrates server-rendered pages with reactivity, client-side navigation, and realtime rooms.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/csr holds the three client runtimes that WRNexusJS serves to the browser. Components are authored as .wrn files and rendered on the server; this package provides the single, generic runtime that hydrates that HTML in the browser — there are no per-component browser bundles. Each runtime is exported as a plain-JS string (no build step, no imports) intended to be served verbatim from a well-known URL:

    @@ -42,7 +52,10 @@ getRealtimeRuntime(): string // → REALTIME_RUNTIME

    Applied to any subtree containing data-scope. Expressions are parsed by a tiny eval-free evaluator, so a strict CSP with no unsafe-eval works.

    ExportKindNotes
    -
    DirectivePurpose
    data-scope="count: 0, name: 'x'"Declare reactive state on a subtree
    data-on-<event>="count++"Run a statement in scope on a DOM event
    data-text="expr"Bind an element's textContent to an expression
    data-show="expr"Toggle visibility (display) on truthiness
    data-for="item in list" (opt. index and key item.id)Per-item rendering; stable keys preserve DOM identity during reorder
    data-key="item.id"Alternative key declaration for data-for templates
    {{expr}} or {expr}Interpolation inside text nodes and attribute values
    data-wrnexus-csr="id"Target for a generated CSR fetch binding (fetches /__wrnexus/csr?...)
    +data-scope="count: 0, name: 'x'"Declare reactive state on a subtreedata-on-<event>="count++"Run a statement in scope on a DOM eventdata-text="expr"Bind an element's textContent to an expressiondata-show="expr"Toggle visibility while preserving interactive state +

    Compiled conditional rendering and dynamic component cases omit inactive elements from the live DOM. data-show is a visibility directive for stateful controls and keeps its element mounted. Neither mechanism is authorization: never place secrets in client-rendered branches. Authorize on the server and return only data the current request may access.

    +
    +
    data-for="item in list" (opt. index and key item.id)Per-item rendering; stable keys preserve DOM identity during reorder
    data-key="item.id"Alternative key declaration for data-for templates
    {{expr}} or {expr}Interpolation inside text nodes and attribute values
    data-wrnexus-csr="id"Target for a generated CSR fetch binding (fetches /__wrnexus/csr?...)

    Supported expression features: literals, identifiers, member access (a.b, a[b]), function/method calls, arrays, objects, arithmetic, comparison, equality, logical (&& ||), unary (! - +), and ternary. Statements support ++/--, assignment operators (= += -= *= /= %=), and bare expression/method calls. Rendering is dependency-tracked: a signal change only re-runs the renderers that actually read it.

    Browser globals installed: window.__wrnexusHydrateScopes(root) and window.__wrnexusHydrateCsrFetches(root) — both idempotent, so re-running after a DOM swap or HMR morph is safe. Both run automatically on DOMContentLoaded.

    Browser: navigation

    @@ -189,6 +202,8 @@ declare const NAV_RUNTIME: string; */ declare const REALTIME_RUNTIME: string; +declare const ACTION_RUNTIME: string; + type OutputHandler<T = unknown> = (payload: T) => void | Promise<void>; interface OutputHost extends HTMLElement { __wrnexusOutputHandlers?: Map<string, Set<OutputHandler>>; @@ -223,6 +238,23 @@ interface ClientModuleScope { declare function loadClientFunctions(url: string, scope: ClientModuleScope): Promise<Record<string, (...args: unknown[]) => unknown>>; declare function invalidateClientModule(url: string): void; +interface ActionClientOptions<I> { + signal?: AbortSignal; + csrfToken?: string; + headers?: HeadersInit; + serialize?: (input: I) => BodyInit; +} +interface ActionResult<O> { + data: O; + invalidated: string[]; +} +declare class ActionClientError extends Error { + readonly status: number; + readonly errors?: Record<string, string> | undefined; + constructor(status: number, errors?: Record<string, string> | undefined); +} +declare function createActionClient<I, O>(route: string, name: string): (input: I, options?: ActionClientOptions<I>) => Promise<ActionResult<O>>; + interface HydrationScopeApi { get(name: string): unknown; set(name: string, value: unknown): void; @@ -250,8 +282,9 @@ declare function getReactiveRuntime(): string; declare function getNavRuntime(): string; /** The realtime client runtime served at `/__wrnexus/realtime.js`. */ declare function getRealtimeRuntime(): string; +declare function getActionRuntime(): string; -export { type ClientModuleScope, type HydrationScopeApi, NAV_RUNTIME, type OutputHandler, type OutputHost, REACTIVE_RUNTIME, REALTIME_RUNTIME, type ServerCallOptions, WrnServerCallError, type WrnexusBrowserGlobals, callServerFunction, collectRefs, createOutputProxy, createServerProxy, getNavRuntime, getReactiveRuntime, getRealtimeRuntime, invalidateClientModule, invokeOutput, loadClientFunctions, registerOutputHandler }; +export { ACTION_RUNTIME, ActionClientError, type ActionClientOptions, type ActionResult, type ClientModuleScope, type HydrationScopeApi, NAV_RUNTIME, type OutputHandler, type OutputHost, REACTIVE_RUNTIME, REALTIME_RUNTIME, type ServerCallOptions, WrnServerCallError, type WrnexusBrowserGlobals, callServerFunction, collectRefs, createActionClient, createOutputProxy, createServerProxy, getActionRuntime, getNavRuntime, getReactiveRuntime, getRealtimeRuntime, invalidateClientModule, invokeOutput, loadClientFunctions, registerOutputHandler };

    Examples

    Copy-ready examples from the installed package documentation.

    Server side — serve the runtime strings from your router (example with Bun.serve)

    import { getReactiveRuntime, getNavRuntime, getRealtimeRuntime } from "@wrnexus/csr";
     
     const routes: Record<string, string> = {
    @@ -295,9 +328,9 @@ Bun.serve({
     <script src="/__wrnexus/realtime.js"></script>

    Or drive a room from code

    const room = wire.room("lobby");
     room.on("chat", (msg) => console.log(msg.user, msg.text));
     room.send({ type: "chat", user: "ada", text: "hi" });
    - +
    - + } diff --git a/app/pages/packages/db.wrn b/app/pages/packages/db.wrn index 2a3034d3..aee068ee 100644 --- a/app/pages/packages/db.wrn +++ b/app/pages/packages/db.wrn @@ -10,11 +10,13 @@ page wrnexusdb {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/db

    Database adapters, typed queries, models, migrations, and sessions.

    v0.7.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/db@0.7.0

    Request preview access. Never put registry tokens in source control.

    The database layer for WRNexusJS: TS models as the single source of truth for DDL, validation, and result typing, plus a driver-based Db client, migrations, and a sqlc-style query generator.
    +
    Data · Package reference

    @wrnexus/db

    Database adapters, typed queries, models, migrations, and sessions.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/db@0.8.0

    Request preview access. Never put registry tokens in source control.

    Rollout-safe migrations

    +

    Run wrnexus db check in CI before deployment. The analyzer reports stable diagnostics for drops, renames, type changes, new/enforced required columns, and potentially blocking index creation, with an expand/backfill/switch/contract recommendation. wrnexus db migrate blocks critical issues in pending migrations. --allow-breaking is an explicit operator override; already-applied migrations do not block later releases.

    +
    The database layer for WRNexusJS: TS models as the single source of truth for DDL, validation, and result typing, plus a driver-based Db client, migrations, and a sqlc-style query generator.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/db is the server-side data layer. You describe tables as TypeScript models (the v column builder + table()); those models drive migrations, coerce raw DB rows into typed objects, and feed the query generator. A thin Driver interface is implemented by adapters for SQLite (bun:sqlite), Postgres/MySQL (Bun.SQL), and MongoDB. The Db client adds ergonomics — model-mapped all/one, transactions, createTable, pagination, and batched relation loading. A process-wide registry (getDb/setDb) exposes configured connections to pages and API routes. Reach for it whenever a WRNexusJS app needs persistence.

    @@ -50,7 +52,8 @@ const users = table("users", {
  • exec(sql, params?)Promise<ExecResult> ({ changes, lastInsertId? }).
  • tx(fn) — run fn(db) in a transaction; rolls back on throw. Nested tx reuses the current transaction.
  • createTable(model) — runs the model's CREATE TABLE IF NOT EXISTS DDL.
  • -
  • close().
  • +
  • close() — idempotently rejects new top-level work, drains active queries and
  • +

    transactions, then closes the underlying pool.

    Every query is parameterized (positional params). createTableSql(model, dialect, ifNotExists?) renders CREATE TABLE directly; Dialect is "sqlite" | "postgres" | "mysql".

    Client registry — getDb / setDb

    @@ -59,7 +62,8 @@ const users = table("users", {
  • setDb(db) / setDb(name, db) — set the default or a named connection.
  • registerDb(name, db) — alias of setDb(name, db).
  • getDb(name = "default") — the default or a named Db (throws if unconfigured).
  • -
  • hasDb(name?), databaseNames(), closeDatabases().
  • +
  • hasDb(name?), databaseNames(), closeDatabases(). Registry shutdown clears
  • +

    registrations first, attempts every open database, and reports close failures together with AggregateError instead of leaking later pools.

    const users = await getDb().all("SELECT * FROM users");
     const events = await getDb("analytics").all("SELECT * FROM hits");
    @@ -76,8 +80,8 @@ const events = await getDb("analytics").all("SELECT * FROM hits&q
  • parseMigration(name, content)Migration ({ name, up, down }).
  • loadMigrations(dir) — parse all .sql files, sorted by filename.
  • appliedMigrations(db) — applied names, oldest first.
  • -
  • migrate(db, dir) — apply all pending (each in a transaction); returns applied names.
  • -
  • rollback(db, dir) — roll back the most recent; returns its name or null.
  • +
  • migrate(db, dir, options?) — apply all pending (each in a transaction); returns applied names.
  • +
  • rollback(db, dir, options?) — roll back the most recent; returns its name or null.
  • status(db, dir){ name, applied }[] for every migration file.
  • scaffoldMigration(dir, name, dialect, models?) — write a new numbered migration; with models it generates CREATE/DROP for every table (referenced tables first via topological sort). Returns the file path.
  • @@ -132,6 +136,12 @@ const pageTwo = await paginate( { sql: "SELECT * FROM users ORDER BY id", model: users }, { page: 2 }, ); +

    For deployments, { dryRun: true } reports pending names without applying their SQL, signal cancels safely between migrations, and the default database-backed lock prevents concurrent deploy runners. A live lock produces WRN-DB-MIGRATION-LOCKED; crash-stale locks expire after lockTimeoutMs (five minutes by default). Disable it with lock: false only when an external deploy coordinator already guarantees exclusivity.

    +
    const pending = await migrate(db, "app/db/migrations", { dryRun: true });
    +await migrate(db, "app/db/migrations", {
    +  signal: shutdownController.signal,
    +  lockTimeoutMs: 10 * 60_000,
    +});

    MongoDB (document API):

    import { mongo } from "@wrnexus/db/mongo";
     
    @@ -149,10 +159,39 @@ const active = await repo.find({ active: true });

    SessionBackend; getDb/setDb are wired by the WRNexusJS runtime from wrnexus.config.ts.

  • The mongodb npm package is an optional, lazily-imported peer — install it
  • only if you use @wrnexus/db/mongo. The core package stays dependency-free.

    -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { M as Model } from './schema-tVurYsbL.js';
    +
    +

    Repository and transaction helpers

    +

    Repositories accept an immutable equality scope, normally { column: "tenant_id", value: ctx.tenant.id }. The scope is injected into every read, count, update and delete, while create overwrites any caller-supplied tenant value. This makes accidental cross-tenant CRUD through the repository API fail closed.

    +
    import { createRepository, retryTransaction, databaseHealth, batch } from "@wrnexus/db";
    +
    +const users = createRepository<User>(db, {
    +  table: "users",
    +  allowedColumns: ["email", "name", "active"],
    +});
    +
    +const user = await users.require(42);
    +await users.update(42, { active: true });
    +

    Repository identifiers are validated, writes may be restricted to an allowlist, and values always use query parameters. Infrastructure packages remain helper-only and do not add UI dependencies to server code.

    +

    0.8 repository and transaction helpers

    +
    import { createRepository, databaseHealth, firstOrThrow, retryTransaction } from "@wrnexus/db";
    +
    +const usersRepo = createRepository<User>(db, {
    +  table: "users",
    +  allowedColumns: ["email", "name", "active"],
    +  maxListLimit: 250,
    +});
    +
    +const users = await usersRepo.all({
    +  orderBy: "name",
    +  direction: "asc",
    +  limit: 50,
    +  offset: 0,
    +});
    +

    Repository SQL identifiers are validated and values remain parameterized. Placeholder generation is dialect-aware: PostgreSQL uses $1, $2, and SQLite/MySQL use ?. List limits are bounded.

    +

    retryTransaction() retries recognized serialization, deadlock, and database-lock errors by default. Supply shouldRetry for application-specific retryable errors; ordinary validation or business errors are not retried automatically.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { M as Model } from './schema-tVurYsbL.js';
     export { B as BaseType, C as Column, a as ColumnDef, b as Columns, t as table, v } from './schema-tVurYsbL.js';
    -import { a as Db, b as Dialect, R as Row } from './driver-DA53QHkO.js';
    -export { D as Driver, E as ExecResult, T as TxHandle, c as createDb, d as createTableSql } from './driver-DA53QHkO.js';
    +import { a as Db, b as Dialect, R as Row, E as ExecResult } from './driver-DA53QHkO.js';
    +export { D as Driver, T as TxHandle, c as createDb, d as createTableSql } from './driver-DA53QHkO.js';
     
     /**
      * A process-wide database registry. The framework configures it at server
    @@ -200,6 +239,16 @@ interface Migration {
         up: string;
         down: string;
     }
    +interface MigrationRunOptions {
    +    /** Return pending migration names without executing their SQL. */
    +    dryRun?: boolean;
    +    /** Stop safely between migrations. Active database statements cannot be interrupted portably. */
    +    signal?: AbortSignal;
    +    /** Coordinate migration runners through the database. Default true. */
    +    lock?: boolean;
    +    /** Allow recovery of a lock left by a crashed process. Default 5 minutes. */
    +    lockTimeoutMs?: number;
    +}
     /** Split a migration file into its `up` and `down` SQL sections. */
     declare function parseMigration(name: string, content: string): Migration;
     /** Load and parse all migration files in a directory, sorted by filename. */
    @@ -207,11 +256,13 @@ declare function loadMigrations(dir: string): Migration[];
     /** Names of already-applied migrations, oldest first. */
     declare function appliedMigrations(db: Db): Promise<string[]>;
     /** Apply an ordered migration list (each in a transaction). Returns applied names. */
    -declare function applyMigrations(db: Db, migrations: readonly Migration[]): Promise<string[]>;
    +declare function applyMigrations(db: Db, migrations: readonly Migration[], options?: MigrationRunOptions): Promise<string[]>;
     /** Apply all pending migrations from a directory. */
    -declare function migrate(db: Db, dir: string): Promise<string[]>;
    +declare function migrate(db: Db, dir: string, options?: MigrationRunOptions): Promise<string[]>;
     /** Roll back the most recently applied migration. Returns its name, or null. */
    -declare function rollback(db: Db, dir: string): Promise<string | null>;
    +declare function rollback(db: Db, dir: string, options?: Omit<MigrationRunOptions, "dryRun"> & {
    +    dryRun?: boolean;
    +}): Promise<string | null>;
     /** Full status: every migration file with whether it has been applied. */
     declare function status(db: Db, dir: string): Promise<{
         name: string;
    @@ -224,6 +275,16 @@ declare function status(db: Db, dir: string): Promise<{
      */
     declare function scaffoldMigration(dir: string, name: string, dialect: Dialect, models?: Model[]): string;
     
    +interface MigrationSafetyIssue {
    +    code: "WRN-DB-DROP-TABLE" | "WRN-DB-DROP-COLUMN" | "WRN-DB-RENAME" | "WRN-DB-TYPE-CHANGE" | "WRN-DB-SET-NOT-NULL" | "WRN-DB-ADD-REQUIRED" | "WRN-DB-BLOCKING-INDEX";
    +    severity: "error" | "warning";
    +    migration: string;
    +    statement: string;
    +    recommendation: string;
    +}
    +declare function analyzeMigrationSafety(migration: Migration): MigrationSafetyIssue[];
    +declare function analyzeMigrations(migrations: readonly Migration[]): MigrationSafetyIssue[];
    +
     /**
      * sqlc-style query generator. Annotated SQL in `app/db/queries/*.sql` becomes
      * typed TS functions whose params + results are inferred from the TS models and
    @@ -366,10 +427,64 @@ interface QueryPolicy {
         onQuery?: (record: QueryRecord) => void | Promise<void>;
         onIssue?: (issue: QueryIssue) => void | Promise<void>;
     }
    +declare function getDbPerformanceSnapshot(): {
    +    queries: QueryRecord[];
    +    issues: QueryIssue[];
    +};
    +declare function resetDbPerformanceSnapshot(): void;
     declare function instrumentDb(db: Db, policy?: QueryPolicy): Db;
     declare function queryOperation(sql: string): string;
     
    -export { type CursorPage, type CursorPageOptions, Db, Dialect, type Migration, Model, type ModelRef, type PageOptions, type Paginated, type QueryDef, type QueryIssue, type QueryKind, type QueryPolicy, type QueryRecord, type RelationOptions, Row, appliedMigrations, applyMigrations, closeDatabases, cursorPaginate, databaseNames, generateQueriesFile, getDb, hasDb, instrumentDb, loadMigrations, loadRelated, migrate, optimisticUpdate, paginate, parseMigration, parseQueries, queryOperation, registerDb, registerLazyDb, rollback, scaffoldMigration, setDb, softDeleteClause, status, tenantScope };
    +declare class RecordNotFoundError extends Error {
    +    constructor(message?: string);
    +}
    +declare function firstOrThrow<T>(db: Db, sql: string, params?: unknown[], model?: Model<T>, message?: string): Promise<T>;
    +declare function exists(db: Db, sql: string, params?: unknown[]): Promise<boolean>;
    +declare function countRows(db: Db, table: string, where?: string, params?: unknown[]): Promise<number>;
    +declare function withTransaction<T>(db: Db, callback: (tx: Db) => Promise<T>): Promise<T>;
    +declare function retryTransaction<T>(db: Db, callback: (tx: Db, attempt: number) => Promise<T>, options?: {
    +    attempts?: number;
    +    baseDelayMs?: number;
    +    maxDelayMs?: number;
    +    jitter?: boolean;
    +    shouldRetry?: (error: unknown) => boolean;
    +}): Promise<T>;
    +declare function batch<T>(values: readonly T[], size?: number): T[][];
    +declare function databaseHealth(db: Db): Promise<{
    +    ok: boolean;
    +    latencyMs: number;
    +    error?: string;
    +}>;
    +interface RepositoryListOptions<T extends Row> {
    +    limit?: number;
    +    offset?: number;
    +    orderBy?: keyof T & string;
    +    direction?: "asc" | "desc";
    +}
    +interface Repository<T extends Row> {
    +    all(options?: RepositoryListOptions<T>): Promise<T[]>;
    +    find(id: string | number): Promise<T | null>;
    +    require(id: string | number): Promise<T>;
    +    create(values: Partial<T>): Promise<ExecResult>;
    +    update(id: string | number, values: Partial<T>): Promise<ExecResult>;
    +    remove(id: string | number): Promise<ExecResult>;
    +    exists(id: string | number): Promise<boolean>;
    +    count(): Promise<number>;
    +}
    +declare function createRepository<T extends Row>(db: Db, input: {
    +    table: string;
    +    idColumn?: string;
    +    model?: Model<T>;
    +    allowedColumns?: readonly (keyof T & string)[];
    +    maxListLimit?: number;
    +    /** Immutable equality scope (normally tenant_id) applied to every operation. */
    +    scope?: {
    +        column: keyof T & string;
    +        value: unknown;
    +    };
    +}): Repository<T>;
    +
    +export { type CursorPage, type CursorPageOptions, Db, Dialect, ExecResult, type Migration, type MigrationRunOptions, type MigrationSafetyIssue, Model, type ModelRef, type PageOptions, type Paginated, type QueryDef, type QueryIssue, type QueryKind, type QueryPolicy, type QueryRecord, RecordNotFoundError, type RelationOptions, type Repository, Row, analyzeMigrationSafety, analyzeMigrations, appliedMigrations, applyMigrations, batch, closeDatabases, countRows, createRepository, cursorPaginate, databaseHealth, databaseNames, exists, firstOrThrow, generateQueriesFile, getDb, getDbPerformanceSnapshot, hasDb, instrumentDb, loadMigrations, loadRelated, migrate, optimisticUpdate, paginate, parseMigration, parseQueries, queryOperation, registerDb, registerLazyDb, resetDbPerformanceSnapshot, retryTransaction, rollback, scaffoldMigration, setDb, softDeleteClause, status, tenantScope, withTransaction };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Define models, connect, create tables, and query with typed results

    import { v, table, createDb } from "@wrnexus/db";
     import { sqlite } from "@wrnexus/db/sqlite";
     
    @@ -400,15 +515,19 @@ const pageTwo = await paginate(
       db,
       { sql: "SELECT * FROM users ORDER BY id", model: users },
       { page: 2 },
    -);

    MongoDB (document API)

    import { mongo } from "@wrnexus/db/mongo";
    +);

    coordinator already guarantees exclusivity.

    const pending = await migrate(db, "app/db/migrations", { dryRun: true });
    +await migrate(db, "app/db/migrations", {
    +  signal: shutdownController.signal,
    +  lockTimeoutMs: 10 * 60_000,
    +});

    MongoDB (document API)

    import { mongo } from "@wrnexus/db/mongo";
     
     const mdb = await mongo(process.env.MONGO_URL!, "app");
     const repo = mdb.collection(users);
     await repo.insert({ email: "a@b.com" });
     const active = await repo.find({ active: true });
    - +
    - + } diff --git a/app/pages/packages/dev-server.wrn b/app/pages/packages/dev-server.wrn index 99433345..aea75605 100644 --- a/app/pages/packages/dev-server.wrn +++ b/app/pages/packages/dev-server.wrn @@ -10,11 +10,11 @@ page wrnexusdevserver {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/dev-server

    Development and production servers, HMR, assets, and gateways.

    v0.7.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-server@0.7.0

    Request preview access. Never put registry tokens in source control.

    The WRNexusJS HTTP + WebSocket server runtime — request dispatch, SSR document assembly, live-reload (HMR), and the portable production handler.
    +
    Runtime · Package reference

    @wrnexus/dev-server

    Development and production servers, HMR, assets, and gateways.

    v0.8.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-server@0.8.0

    Request preview access. Never put registry tokens in source control.

    The WRNexusJS HTTP + WebSocket server runtime — request dispatch, SSR document assembly, live-reload (HMR), and the portable production handler.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    This package is the server runtime that powers a WRNexusJS app in both development and production. A single request runtime (createHandlers) owns HTTP/WebSocket dispatch and SSR document assembly; it knows nothing about _how_ modules and assets are produced, so the dev and prod entry points wire in different backends: dev uses dynamic module loading plus on-the-fly bundling and injects a live-reload client; prod uses a static, pre-built manifest with cache-immutable assets. The package also ships a multi-app gateway (route several apps by Host header behind one port) and a portable node:http adapter for WinterCG hosts. It is entirely server-side and Bun-native (Bun.serve, Bun.file, Bun.gzipSync).

    @@ -54,6 +54,7 @@ interface RunningServer { stop(): void; }

    In development, startServer also connects app/db/migrations (and app/db/<name>/migrations) and auto-applies migrations, then starts an in-process file watcher. CSS edits hot-swap live. Page, component, layout, API, middleware, realtime, schema, locale, and public-asset edits invalidate only their cached modules, rescan routes where necessary, and morph fresh HTML through the existing HMR WebSocket. The server process and active gateway stay running.

    +

    getWrnCompileMetrics() exposes cumulative content-addressed compiler cache hits, misses, successful compilations, errors, totalDurationMs, and lastDurationMs for the DevToolbar or custom diagnostics. Tests and embedded servers can call resetWrnCompileMetrics() to establish a fresh measurement window.

    createHandlers(deps)

    The core runtime shared by dev and prod. It handles CORS preflight, /healthz and /__wrnexus/health, request-body size limits (413), HMR socket upgrades (/__wrnexus/hmr), realtime WebSocket upgrades (defineRoom default export or a raw websocket export), the middleware pipeline, API routes (/api/*), framework assets (/__wrnexus/*), public assets, and full SSR page rendering (component mounts, layouts, slots, i18n markers, per-page script selection, ETag/304, gzip).

    interface RuntimeDeps {
    @@ -222,23 +223,63 @@ await startGateway({
     
    • Bun-only. Uses Bun.serve (HTTP + WebSocket), Bun.file, and Bun.gzipSync. The full app also relies on bun:sqlite / Bun.SQL via @wrnexus/db.
    • Orchestrates the whole framework: @wrnexus/core (context, security, realtime registry), @wrnexus/router, @wrnexus/ssr (renderDocument), @wrnexus/csr (client runtimes), @wrnexus/compiler (.wrn → TS), @wrnexus/styles, @wrnexus/ui, @wrnexus/validation, @wrnexus/i18n, @wrnexus/db, and @wrnexus/pubsub (Redis-backed cross-process realtime).
    • -
    • .wrn files are compiled to TypeScript into a hidden sibling .wrnexus/ cache dir and dynamically imported; the module cache means each edited server module needs a fresh process (dev) — hence the restart-on-change model.
    • +
    • .wrn files compile into a content-addressed hidden .wrnexus/ cache. Targeted
    • +

      invalidation gives changed modules a fresh import identity without restarting the development server.

    • Responses are gzipped when the client accepts it and the body is a buffered, compressible payload ≥ 1 KB; streaming/SSE responses opt out via Cache-Control: no-transform.
    • </content>

    -

    </invoke>

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Mode, Middleware, SeoConfig, SecurityConfig, RealtimeBus, RealtimeConnectMeta } from '@wrnexus/core';
    +

    </invoke>

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Mode, Middleware, SeoConfig, SecurityConfig, HealthRegistry, RealtimeBus, RealtimeConnectMeta } from '@wrnexus/core';
     import { Router } from '@wrnexus/router';
     import { ResolvedTheme, MobileConfig, PwaConfig, ObservabilityConfig, TenancyConfig, NavigationConfig, StylesConfig, ThemeConfig } from '@wrnexus/styles';
     import { ResolvedI18n, I18nConfig } from '@wrnexus/i18n';
     import { StorageConfig } from '@wrnexus/uploader';
     import { DevToolbarConfig, DevToolbarPlatformSnapshot, DevToolbarPanel } from '@wrnexus/dev-toolbar/types';
     import { ClientRuntimeDefinition, PluginInput } from '@wrnexus/plugin';
    +import { CacheCoordinator } from '@wrnexus/cache';
     import { DevToolbarCollector } from '@wrnexus/dev-toolbar/server';
     import { IncomingMessage, ServerResponse, Server } from 'node:http';
     
     /** Exit code a dev-server child uses to request a clean supervisor restart. */
     declare const RESTART_EXIT_CODE = 97;
     
    +interface PartialBuildModule {
    +    default?: unknown;
    +    render?: (props?: Record<string, unknown>) => string | Promise<string>;
    +    layout?: string | {
    +        name?: string;
    +        render?: (props?: Record<string, unknown>) => string;
    +    };
    +    __wrnexusBuildStaticShell?: (ctx?: Record<string, unknown>) => string | Promise<string>;
    +}
    +interface PartialBuildEntry {
    +    name: string;
    +    mod: PartialBuildModule;
    +}
    +/** Expand compiler component mounts at build time using only their pure render exports. */
    +declare function expandStaticComponents(html: string, components: readonly PartialBuildEntry[], depth?: number): Promise<string>;
    +/** Produce the body shell stored in dist; dynamic region bodies are never evaluated here. */
    +declare function precomputePartialStaticShell(page: PartialBuildModule, components: readonly PartialBuildEntry[]): Promise<{
    +    shell: string;
    +    regions: number;
    +}>;
    +
    +/**
    + * Request pipeline helpers: middleware execution and safe module loading.
    + * These are deliberately runtime-agnostic (no Bun APIs) so they could run on
    + * Node too.
    + */
    +
    +interface WrnCompileMetrics {
    +    hits: number;
    +    misses: number;
    +    compilations: number;
    +    errors: number;
    +    totalDurationMs: number;
    +    lastDurationMs: number;
    +}
    +declare function getWrnCompileMetrics(): Readonly<WrnCompileMetrics>;
    +declare function resetWrnCompileMetrics(): void;
    +
     /**
      * HMR hub — tracks connected browser HMR sockets and broadcasts update events.
      *
    @@ -349,6 +390,8 @@ interface RuntimeDeps {
         security?: SecurityConfig;
         /** Built-in request tracing and Server-Timing policy. */
         observability?: ObservabilityConfig;
    +    /** Dependency health checks used by `/readyz` and `/__wrnexus/ready`. */
    +    health?: HealthRegistry;
         /** Built-in tenant identity resolution. */
         tenancy?: TenancyConfig;
         /** Max request body size in bytes (413 above this). Default 10 MB. */
    @@ -361,12 +404,16 @@ interface RuntimeDeps {
          * bus (use the Redis pub/sub driver). Enables realtime across multiple apps.
          */
         realtimeBus?: RealtimeBus;
    +    /** Shared first-class data/component/page caches. */
    +    cache?: CacheCoordinator;
    +    /** Final document transform supplied by the plugin render lifecycle. */
    +    renderHtml?: (html: string) => string | Promise<string>;
         devToolbar?: {
             config: DevToolbarConfig;
             collector: DevToolbarCollector;
             root: string;
             platform?: DevToolbarPlatformSnapshot;
    -        panels?: DevToolbarPanel[];
    +        panels?: DevToolbarPanel[] | (() => DevToolbarPanel[] | Promise<DevToolbarPanel[]>);
         };
     }
     interface UpgradeServer {
    @@ -500,7 +547,8 @@ declare function startGateway(opts: GatewayOptions): Promise<RunningGateway&g
      * `wrnexus build` generates an entry that statically imports every route and
      * component module and hands them here as a manifest. We rebuild the (cheap)
      * route-matching tables from the raw patterns and run the exact same request
    - * runtime as dev — just with production error pages and no live-reload client.
    + * runtime as dev. Normal preview/deploy output has no live-reload client; the
    + * supervised `dev --production-runtime` mode can explicitly enable it.
      */
     
     type RouteModule = Record<string, unknown>;
    @@ -509,6 +557,8 @@ interface ManifestRoute {
         raw: string;
         /** The statically-imported route module. */
         mod: RouteModule;
    +    /** Body shell precomputed by `wrnexus build` for a partial-static page. */
    +    staticShell?: string;
     }
     interface ProdManifest {
         pages: ManifestRoute[];
    @@ -609,6 +659,8 @@ interface ProdOptions {
         port?: number;
         hostname?: string;
         maxBodyBytes?: number;
    +    /** Enable only for the CLI's supervised exact-production development mode. */
    +    developmentRuntime?: boolean;
     }
     /**
      * Build the portable request handler from a precompiled manifest — a
    @@ -663,6 +715,11 @@ interface ServeOptions {
         appDir: string;
         port?: number;
         hostname?: string;
    +    /** Development TLS material. Production TLS is normally terminated by the deployment proxy. */
    +    tls?: {
    +        cert: string;
    +        key: string;
    +    };
         mode?: Mode;
         /** Inject the live-reload client (defaults to true in development). */
         hmr?: boolean;
    @@ -715,7 +772,7 @@ interface RunningServer {
     }
     declare function startServer(opts: ServeOptions): Promise<RunningServer>;
     
    -export { type AssetServer, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WsData, createHandlers, createProductionHandlers, createProductionServer, nodeListener, serveNode, startGateway, startServer, toRequest, writeResponse };
    +export { type AssetServer, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WrnCompileMetrics, type WsData, createHandlers, createProductionHandlers, createProductionServer, expandStaticComponents, getWrnCompileMetrics, nodeListener, precomputePartialStaticShell, resetWrnCompileMetrics, serveNode, startGateway, startServer, toRequest, writeResponse };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Programmatic dev server

    import { startServer } from "@wrnexus/dev-server";
     
     const server = await startServer({
    @@ -756,7 +813,7 @@ await startGateway({
     });
    - + } diff --git a/app/pages/packages/dev-toolbar.wrn b/app/pages/packages/dev-toolbar.wrn index a166b212..3782cc18 100644 --- a/app/pages/packages/dev-toolbar.wrn +++ b/app/pages/packages/dev-toolbar.wrn @@ -10,16 +10,19 @@ page wrnexusdevtoolbar {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/dev-toolbar

    Development toolbar diagnostics, inspection, and runtime status.

    v0.7.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-toolbar@0.7.0

    Request preview access. Never put registry tokens in source control.

    Development-only page quality toolbar for WRNexusJS.

    +
    Tooling · Package reference

    @wrnexus/dev-toolbar

    Development toolbar diagnostics, inspection, and runtime status.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/dev-toolbar@0.8.0

    Request preview access. Never put registry tokens in source control.

    Development-only page quality toolbar for WRNexusJS.

    Features

    • Runtime, resource and unhandled promise error capture
    • Accessibility, SEO, image, media, color, HTML, form, link, responsive and security checks
    • Performance and network observations
    • +
    • First-class application tabs for runtime, stores, cache, accessibility, SEO, performance,
    • +

      security, images, links, and JavaScript

      +
    • Plugin-contributed applications with badges, descriptions, issue feeds, and structured data
    • Element highlighting and issue filtering
    • Server-side issue collector
    • Development-only asset strings for direct serving by @wrnexus/dev-server
    • @@ -28,16 +31,17 @@ page wrnexusdevtoolbar {

      Dev-server integration

      Serve DEV_TOOLBAR_RUNTIME at /__wrnexus/dev-toolbar.js and DEV_TOOLBAR_CSS at /__wrnexus/dev-toolbar.css, then inject this before </body> in development:

      <script type="module" src="/__wrnexus/dev-toolbar.js" data-wrnexus-dev-toolbar></script>
      -

      The browser runtime exposes window.__wrnexusDevToolbar.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { DevToolbarCategory, DevToolbarClientApi, DevToolbarConfig, DevToolbarElementTarget, DevToolbarFix, DevToolbarIssue, DevToolbarMetrics, DevToolbarPageReport, DevToolbarPanel, DevToolbarPlatformSnapshot, DevToolbarServerMessage, DevToolbarSeverity, DevToolbarSourceLocation } from './types.js';
    +

    The browser runtime exposes window.__wrnexusDevToolbar.

    +

    Plugin panels returned through devToolbarPanels() are automatically added to the application strip. Their issue category is filterable, and structured data is rendered as escaped diagnostic content so a plugin never needs to inject toolbar HTML.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { DevToolbarCategory, DevToolbarClientApi, DevToolbarConfig, DevToolbarElementTarget, DevToolbarFix, DevToolbarIssue, DevToolbarMetrics, DevToolbarPageReport, DevToolbarPanel, DevToolbarPlatformSnapshot, DevToolbarServerMessage, DevToolbarSeverity, DevToolbarSourceLocation } from './types.js';
     export { DEV_TOOLBAR_RULES, DevToolbarRule, DevToolbarRuleContext, accessibilityRules, accessibleName, colorRules, contrastRatio, createFingerprint, createIssue, effectiveBackground, formRules, getStableSelector, htmlRules, imageRules, isVisible, linkRules, luminance, mediaRules, parseRgb, parseSource, performanceRules, responsiveRules, runDevToolbarRules, securityRules, seoRules } from './rules/index.js';
    -export { DevToolbarApp, DevToolbarCollector, DevToolbarIssueListener, DevToolbarRegistry, DevToolbarRouteOptions, OpenEditorOptions, OpenEditorRequest, buildEditorCommand, createDevToolbarCollector, createDevToolbarRegistry, createServerIssue, handleDevToolbarRoute, issueFromError, openInEditor, resolveEditorFile, serializeDevToolbarJson } from './server/index.js';
    +export { BuiltinPanelOptions, DevToolbarApp, DevToolbarCollector, DevToolbarIssueListener, DevToolbarRegistry, DevToolbarRouteOptions, OpenEditorOptions, OpenEditorRequest, buildEditorCommand, builtinDevToolbarPanels, createDevToolbarCollector, createDevToolbarRegistry, createServerIssue, handleDevToolbarRoute, issueFromError, openInEditor, resolveEditorFile, serializeDevToolbarJson } from './server/index.js';
     export { DEV_TOOLBAR_CSS, DEV_TOOLBAR_RUNTIME } from './client/index.js';
     

    Examples

    Copy-ready examples from the installed package documentation.

    Serve DEVTOOLBARRUNTIME at /wrnexus/dev-toolbar.js and DEVTOOLBARCSS at /wrnexus/dev-toolbar.css, then inject this before </body> in development

    <script type="module" src="/__wrnexus/dev-toolbar.js" data-wrnexus-dev-toolbar></script>

    Run development-toolbar rules

    import { runDevToolbarRules } from "@wrnexus/dev-toolbar";
     
     const issues = runDevToolbarRules(context);
    - + } diff --git a/app/pages/packages/encryption.wrn b/app/pages/packages/encryption.wrn index 0a6d327b..8742d2b6 100644 --- a/app/pages/packages/encryption.wrn +++ b/app/pages/packages/encryption.wrn @@ -10,57 +10,68 @@ page wrnexusencryption {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/encryption

    Hashing, HMAC, authenticated encryption, and key derivation.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/encryption@0.7.0

    Request preview access. Never put registry tokens in source control.

    Dependency-free crypto helpers for WRNexusJS: authenticated symmetric encryption (AES-256-GCM), hashing, and HMAC signing.
    -

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    -

    Overview

    -

    This package provides small, focused cryptographic primitives for server-side use: encrypting secrets/tokens/database fields at rest with AES-256-GCM, deriving keys from passwords via PBKDF2, computing SHA-256 digests, and signing/verifying payloads with HMAC-SHA256. It is built entirely on the standard Web Crypto API (crypto.subtle) plus btoa/atob and TextEncoder/TextDecoder — no third-party dependencies. Reach for it whenever you need to protect sensitive values or verify webhook signatures. All functions are async (Web Crypto is promise-based).

    -
    bun add @wrnexus/encryption
    -
    Private package — the machine must be authenticated to the wrnexus npm org
    -
    (a read token in ~/.npmrc). Requires Bun (Node is not supported).
    -

    API

    -

    All keys are exchanged as base64 strings and all digests/signatures as hex strings.

    -
    - -
    ExportSignatureDescription
    generateKey() => Promise<string>Generate a random 256-bit AES key, base64-encoded. Store it as a secret.
    deriveKey(password: string, salt: string) => Promise<string>Derive a base64 AES-256 key from a password + salt using PBKDF2 (100,000 iterations, SHA-256).
    encrypt(plaintext: string, key: string) => Promise<string>AES-256-GCM encrypt a string. Returns base64 of iv(12 bytes) ‖ ciphertext+tag. A fresh random IV is used each call.
    decrypt(payload: string, key: string) => Promise<string>Decrypt a value produced by encrypt. Throws if the key is wrong or the data was tampered with.
    sha256(data: string) => Promise<string>SHA-256 hex digest of a string (e.g. content hashing, dedup keys).
    hmacSign(data: string, secret: string) => Promise<string>HMAC-SHA256 hex signature of data with secret (e.g. signing webhooks).
    hmacVerify(data: string, secret: string, signature: string) => Promise<boolean>Constant-time verify of an HMAC-SHA256 hex signature.
    -

    Notes:

    +
    Security · Package reference

    @wrnexus/encryption

    Hashing, HMAC, authenticated encryption, and key derivation.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/encryption@0.8.0

    Request preview access. Never put registry tokens in source control.

    Authenticated encryption, hashing, HMAC, key rotation, and optional encrypted HTTP exchanges for WRNexusJS.

    +

    Core helpers

      -
    • generateKey produces a 32-byte (256-bit) key via crypto.getRandomValues.
    • -
    • encrypt/decrypt require a base64-encoded 256-bit key; anything else throws "Encryption key must be a base64 256-bit key".
    • -
    • decrypt throws "Invalid ciphertext" if the payload is shorter than the 12-byte IV, and the underlying Web Crypto call throws on any authentication (tag) mismatch.
    • -
    • hmacVerify compares in constant time (length check plus XOR accumulation) to avoid timing leaks.
    • +
    • generateKey() — random 256-bit AES key encoded as base64.
    • +
    • deriveKey(password, salt) — PBKDF2-derived AES key.
    • +
    • encrypt(plaintext, key) / decrypt(payload, key) — AES-256-GCM.
    • +
    • sha256(data) — SHA-256 digest.
    • +
    • hmacSign(data, secret) / hmacVerify(...) — HMAC-SHA256.
    • +
    • createKeyring(keys) — active/previous key management.
    • +
    • seal() / open() — versioned ciphertext with key ID.
    -

    Usage

    -

    Symmetric encryption of a secret at rest:

    -
    import { generateKey, encrypt, decrypt } from "@wrnexus/encryption";
    +

    Encrypted HTTP envelope

    +
    import {
    +  createEncryptedRequest,
    +  createKeyring,
    +  createMemoryReplayStore,
    +  decryptEncryptedResponse,
    +  encryptedExchange,
    +} from "@wrnexus/encryption";
     
    -const key = await generateKey(); // store this safely (env/secret manager)
    +const keyring = createKeyring([{ id: "2026-08", secret: process.env.API_BODY_KEY!, active: true }]);
     
    -const box = await encrypt("card #1234", key); // opaque base64 string, safe to persist
    -const plain = await decrypt(box, key); // "card #1234"
    -

    Deriving a key from a user password instead of a random key:

    -
    import { deriveKey, encrypt } from "@wrnexus/encryption";
    +const replayStore = createMemoryReplayStore();
     
    -const key = await deriveKey("correct horse battery staple", "per-user-salt");
    -const box = await encrypt("secret note", key);
    -

    Hashing and webhook signature verification:

    -
    import { sha256, hmacSign, hmacVerify } from "@wrnexus/encryption";
    +// Server middleware.
    +app.use(
    +  encryptedExchange({
    +    keyring,
    +    replayStore,
    +    maxAgeMs: 60_000,
    +    maxBodyBytes: 1_048_576,
    +  }),
    +);
     
    -const digest = await sha256("some content"); // 64-char hex string
    -
    -const signature = await hmacSign(rawBody, webhookSecret);
    -const ok = await hmacVerify(rawBody, webhookSecret, incomingSignatureHeader);
    -if (!ok) throw new Error("Invalid webhook signature");
    -

    Requirements / Notes

    +// Controlled service/native client. +const request = await createEncryptedRequest( + "https://api.example.com/private/report", + { reportId: "report-1" }, + { method: "POST", keyring }, +); +const response = await fetch(request); +const result = await decryptEncryptedResponse(response, request, { keyring });
    +

    The envelope binds authenticated ciphertext to:

      -
    • Bun-only. Relies on the Web Crypto API (crypto.subtle, crypto.getRandomValues) and the global btoa/atob, TextEncoder/TextDecoder — all available in Bun's runtime.
    • -
    • No dependencies. The package has an empty dependency set; nothing is bundled beyond standard runtime APIs.
    • -
    • Algorithms: AES-256-GCM (encryption), PBKDF2 with 100k SHA-256 iterations (key derivation), SHA-256 (digest), HMAC-SHA256 (signing).
    • -
    • Keep generated/derived keys and HMAC secrets out of source control; treat them as first-class secrets.
    • -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface EncryptionKey {
    +
  • HTTP method
  • +
  • URL path and query
  • +
  • request ID
  • +
  • timestamp and expiry window
  • +
  • encryption key ID
  • +
  • optional replay-store consumption
  • + +

    encryptedBody() decrypts request bodies only. encryptedExchange() also encrypts successful downstream responses while allowing application exceptions to propagate normally. encryptedFetch() provides a convenient controlled-client call.

    +

    Security boundary

    +

    Encrypted HTTP bodies do not replace TLS/HTTPS. Always use HTTPS.

    +

    This layer is appropriate for service-to-service traffic, native/mobile applications, controlled agents, and selected fields protected with server-managed keys. It cannot conceal data from an end user when browser JavaScript receives the decryption key. Never ship a long-lived server encryption key to a browser.

    +

    Use a shared replay store such as Redis in multi-instance deployments. The memory replay store is process-local.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Middleware } from '@wrnexus/core';
    +
    +interface EncryptionKey {
         id: string;
         secret: string;
         active?: boolean;
    @@ -80,6 +91,66 @@ declare function open(sealed: string, keyring: EncryptionKeyring): Promise<st
     declare function sealedKeyId(sealed: string): string | null;
     declare function needsRotation(sealed: string, keyring: EncryptionKeyring): boolean;
     
    +declare const ENCRYPTED_HTTP_CONTENT_TYPE = "application/wrn+json";
    +declare const ENCRYPTED_HTTP_VERSION = "wrn-http-1";
    +interface EncryptedHttpEnvelope {
    +    version: typeof ENCRYPTED_HTTP_VERSION;
    +    keyId: string;
    +    requestId: string;
    +    timestamp: number;
    +    ciphertext: string;
    +}
    +interface ReplayStore {
    +    consume(id: string, expiresAt: number): boolean | Promise<boolean>;
    +}
    +interface EncryptedHttpOptions {
    +    keyring: EncryptionKeyring;
    +    maxAgeMs?: number;
    +    maxBodyBytes?: number;
    +    replayStore?: ReplayStore;
    +    now?: () => number;
    +    /** Require the clear request-id header used to bind encrypted responses. Default true. */
    +    requireRequestIdHeader?: boolean;
    +}
    +interface DecryptedHttpBody<T> {
    +    body: T;
    +    requestId: string;
    +    timestamp: number;
    +    keyId: string;
    +}
    +declare function createMemoryReplayStore(now?: () => number): ReplayStore;
    +declare function encryptHttpBody<T>(body: T, input: {
    +    keyring: EncryptionKeyring;
    +    method?: string;
    +    url: string | URL;
    +    requestId?: string;
    +    timestamp?: number;
    +}): Promise<EncryptedHttpEnvelope>;
    +declare function decryptHttpBody<T>(value: unknown, input: {
    +    keyring: EncryptionKeyring;
    +    method?: string;
    +    url: string | URL;
    +    maxAgeMs?: number;
    +    replayStore?: ReplayStore;
    +    now?: () => number;
    +    expectedRequestId?: string;
    +}): Promise<DecryptedHttpBody<T>>;
    +declare function createEncryptedRequest<T>(url: string | URL, body: T, input: Omit<RequestInit, "body"> & {
    +    keyring: EncryptionKeyring;
    +    requestId?: string;
    +}): Promise<Request>;
    +declare function decryptRequest<T>(request: Request, options: EncryptedHttpOptions): Promise<DecryptedHttpBody<T>>;
    +declare function encryptResponse<T>(body: T, request: Request, options: EncryptedHttpOptions & {
    +    status?: number;
    +    headers?: HeadersInit;
    +}): Promise<Response>;
    +declare function decryptEncryptedResponse<T>(response: Response, request: Request, options: EncryptedHttpOptions): Promise<DecryptedHttpBody<T>>;
    +declare function encryptedFetch<TRequest, TResponse>(url: string | URL, body: TRequest, input: Omit<RequestInit, "body"> & EncryptedHttpOptions): Promise<TResponse>;
    +declare function encryptedBody(options: EncryptedHttpOptions): Middleware;
    +declare function encryptedExchange(options: EncryptedHttpOptions & {
    +    encryptResponses?: boolean;
    +}): Middleware;
    +
     /**
      * @wrnexus/encryption — authenticated symmetric encryption (AES-256-GCM) via
      * WebCrypto, dependency-free. Use it to encrypt secrets, tokens, or database
    @@ -109,25 +180,40 @@ declare function decrypt(payload: string, key: string): Promise<string>;
     /** Derive a base64 AES key from a password + salt (PBKDF2, 100k iterations). */
     declare function deriveKey(password: string, salt: string): Promise<string>;
     
    -export { type EncryptionKey, type EncryptionKeyring, createKeyring, decrypt, deriveKey, encrypt, generateKey, hmacSign, hmacVerify, needsRotation, open, seal, sealedKeyId, sha256 };
    -

    Examples

    Copy-ready examples from the installed package documentation.

    Symmetric encryption of a secret at rest

    import { generateKey, encrypt, decrypt } from "@wrnexus/encryption";
    +export { type DecryptedHttpBody, ENCRYPTED_HTTP_CONTENT_TYPE, ENCRYPTED_HTTP_VERSION, type EncryptedHttpEnvelope, type EncryptedHttpOptions, type EncryptionKey, type EncryptionKeyring, type ReplayStore, createEncryptedRequest, createKeyring, createMemoryReplayStore, decrypt, decryptEncryptedResponse, decryptHttpBody, decryptRequest, deriveKey, encrypt, encryptHttpBody, encryptResponse, encryptedBody, encryptedExchange, encryptedFetch, generateKey, hmacSign, hmacVerify, needsRotation, open, seal, sealedKeyId, sha256 };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    ## Encrypted HTTP envelope

    import {
    +  createEncryptedRequest,
    +  createKeyring,
    +  createMemoryReplayStore,
    +  decryptEncryptedResponse,
    +  encryptedExchange,
    +} from "@wrnexus/encryption";
     
    -const key = await generateKey(); // store this safely (env/secret manager)
    +const keyring = createKeyring([{ id: "2026-08", secret: process.env.API_BODY_KEY!, active: true }]);
     
    -const box = await encrypt("card #1234", key); // opaque base64 string, safe to persist
    -const plain = await decrypt(box, key); // "card #1234"

    Deriving a key from a user password instead of a random key

    import { deriveKey, encrypt } from "@wrnexus/encryption";
    +const replayStore = createMemoryReplayStore();
     
    -const key = await deriveKey("correct horse battery staple", "per-user-salt");
    -const box = await encrypt("secret note", key);

    Hashing and webhook signature verification

    import { sha256, hmacSign, hmacVerify } from "@wrnexus/encryption";
    +// Server middleware.
    +app.use(
    +  encryptedExchange({
    +    keyring,
    +    replayStore,
    +    maxAgeMs: 60_000,
    +    maxBodyBytes: 1_048_576,
    +  }),
    +);
     
    -const digest = await sha256("some content"); // 64-char hex string
    -
    -const signature = await hmacSign(rawBody, webhookSecret);
    -const ok = await hmacVerify(rawBody, webhookSecret, incomingSignatureHeader);
    -if (!ok) throw new Error("Invalid webhook signature");
    - +// Controlled service/native client. +const request = await createEncryptedRequest( + "https://api.example.com/private/report", + { reportId: "report-1" }, + { method: "POST", keyring }, +); +const response = await fetch(request); +const result = await decryptEncryptedResponse(response, request, { keyring });

    Install @wrnexus/encryption

    bun add @wrnexus/encryption
    +
    - + } diff --git a/app/pages/packages/graphql.wrn b/app/pages/packages/graphql.wrn new file mode 100644 index 00000000..4c6a565e --- /dev/null +++ b/app/pages/packages/graphql.wrn @@ -0,0 +1,26 @@ +page wrnexusgraphql { + seo { + title = "@wrnexus/graphql" + description = "GraphQL schemas, routes, and framework plugin integration." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Data · Package reference

    @wrnexus/graphql

    GraphQL schemas, routes, and framework plugin integration.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/graphql@0.8.0

    Request preview access. Never put registry tokens in source control.

    Optional GraphQL endpoint plugin. Supply the executor from GraphQL.js, GraphQL Yoga, Mercurius, or another maintained engine; WRNexus owns bounded HTTP input, depth/alias limits, introspection policy, generic production errors and plugin route integration.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { G as GraphqlExecutionResult, a as GraphqlOptions, b as GraphqlRequest, c as createGraphqlHandler, default as graphqlPlugin } from './plugin.js';
    +import '@wrnexus/plugin';
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/graphql

    bun add @wrnexus/graphql

    Import @wrnexus/graphql

    import * as graphql from "@wrnexus/graphql";
    + +
    + + +
    + } +} diff --git a/app/pages/packages/helpers.wrn b/app/pages/packages/helpers.wrn index 3dc8fbf8..ecdff3a2 100644 --- a/app/pages/packages/helpers.wrn +++ b/app/pages/packages/helpers.wrn @@ -10,11 +10,11 @@ page wrnexushelpers {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/helpers

    Safe Context URL helpers and forward-auth login redirects.

    v0.7.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/helpers@0.7.0

    Request preview access. Never put registry tokens in source control.

    Safe convenience helpers for common WRNexusJS application flows. The package uses standard Context, URL, and Response values and has no runtime dependency beyond @wrnexus/core.

    +
    Tooling · Package reference

    @wrnexus/helpers

    Safe Context URL helpers and forward-auth login redirects.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/helpers@0.8.0

    Request preview access. Never put registry tokens in source control.

    Safe convenience helpers for common WRNexusJS application flows. The package uses standard Context, URL, and Response values and has no runtime dependency beyond @wrnexus/core.

    bun add @wrnexus/helpers

    The package is private, so the machine must be authenticated to the wrnexus npm organization.

    Usage

    @@ -156,7 +156,7 @@ export const GET = async (ctx: Context) => { };
    - + } diff --git a/app/pages/packages/i18n.wrn b/app/pages/packages/i18n.wrn index 3c307e49..457f267d 100644 --- a/app/pages/packages/i18n.wrn +++ b/app/pages/packages/i18n.wrn @@ -10,110 +10,76 @@ page wrnexusi18n {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/i18n

    Translation loading, locale resolution, and Intl formatting.

    v0.7.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/i18n@0.7.0

    Request preview access. Never put registry tokens in source control.

    Per-request translations plus locale-aware number, date, and currency formatting for WRNexusJS apps.
    -

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    -

    Overview

    -

    @wrnexus/i18n loads locale files from app/locales/<lang>.json, resolves the active language for each request (cookie → Accept-Language → default), and builds a t(key, params) translator used both in server code and in .wrn views. It also ships Intl-based formatting helpers and a tiny client runtime that wires up a language switcher. Translation lookup, language resolution, and HTML marker rewriting run server-side; only the small I18N_RUNTIME snippet runs in the browser.

    -
    bun add @wrnexus/i18n
    -
    Private package — the machine must be authenticated to the wrnexus npm org
    -
    (a read token in ~/.npmrc). Requires Bun (Node is not supported).
    -

    API

    -

    Loading & resolving

    -
    - -
    ExportSignatureDescription
    loadLocales(dir: string) => Record<string, Messages>Reads every <lang>.json in dir into a { lang: messages } map. Missing dir → {}; a bad file is warned and skipped.
    resolveI18n(messages: Record<string, Messages>, config?: I18nConfig) => ResolvedI18nMerges loaded messages + config into a resolved bundle (default lang, supported langs, messages).
    resolveLang`(i18n: ResolvedI18n, cookieValue: string \undefined, acceptLanguage: string \null) => string`Picks the active language: matching cookie → best Accept-Language tag (falls back to base tag, e.g. en-USen) → i18n.default.
    makeT(i18n: ResolvedI18n, lang: string) => TFunctionBuilds a translator resolving current language → default → the key itself, with {param} interpolation.
    -

    Types & constants

    -
    - -
    ExportKindNotes
    MessagestypeRecord<string, unknown> — a locale's messages (supports nested/dotted keys).
    I18nConfiginterface{ default?: string; locales?: string[] }.
    ResolvedI18ninterface{ default: string; langs: string[]; messages: Record<string, Messages> }.
    LANG_COOKIEconst"wire-lang" — the cookie the language is read from / written to.
    I18N_JS_HREFconst"/__wrnexus/i18n.js" — URL the client runtime is served at.
    -

    HTML & client runtime

    -
    - -
    ExportSignatureDescription
    translateHtml(html: string, t: TFunction) => stringRewrites markers in rendered HTML: t:<attr>="key"<attr>="<translation>" (attribute-escaped) and <tag data-t="key">…</tag> → element text becomes the translation (HTML-escaped). No-op unless a marker is present.
    renderI18nData(i18n: ResolvedI18n, lang: string) => stringJS snippet setting window.__wireI18n = { lang, langs, default } for the client switcher.
    I18N_RUNTIMEconst stringBrowser IIFE that binds [data-wire-lang-set="es"] clicks and select[data-wire-lang] changes to set the wire-lang cookie and reload. Exposes window.__wireLang.set(lang).
    -

    Formatting helpers (re-exported from ./format.ts)

    -
    - -
    ExportSignatureExample
    formatNumber(value: number, lang: string, options?: Intl.NumberFormatOptions) => string1234.5 → "1,234.5"
    formatCurrency(value: number, currency: string, lang: string) => string9.99, "USD" → "$9.99"
    formatDate`(value: Date \number \string, lang: string, options?: Intl.DateTimeFormatOptions) => string`defaults to { dateStyle: "medium" }
    formatRelativeTime(value: number, unit: Intl.RelativeTimeFormatUnit, lang: string) => string-3, "day" → "3 days ago" (numeric: "auto")
    plural(count: number, forms: Partial<Record<Intl.LDMLPluralRule, string>>, lang: string) => stringpicks CLDR form; # is replaced by count
    -

    Usage

    -

    Server: load, resolve, translate

    -
    import {
    -  loadLocales,
    -  resolveI18n,
    -  resolveLang,
    -  makeT,
    -  translateHtml,
    -  LANG_COOKIE,
    -} from "@wrnexus/i18n";
    +      
    Frontend · Package reference

    @wrnexus/i18n

    Translation loading, locale resolution, and Intl formatting.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/i18n@0.8.0

    Request preview access. Never put registry tokens in source control.

    Recursive locale loading, fallback resolution, SSR/browser translations, locale formatting, and language UI blocks for WRNexusJS.

    +

    Locale files

    +

    Both layouts can be used together:

    +
    app/locales/en.json
    +app/locales/en/common.json
    +app/locales/en/auth.json
    +app/locales/mr/common.json
    +

    Namespaced files become keys such as common.save and auth.signIn.

    +
    import { loadLocales, makeT, resolveI18n, resolveLang } from "@wrnexus/i18n";
     
    -// app/locales/en.json, app/locales/es.json
    -const messages = loadLocales("app/locales");
    -const i18n = resolveI18n(messages, { default: "en", locales: ["en", "es"] });
    +const i18n = resolveI18n(loadLocales("app/locales", { strict: true }), {
    +  default: "en",
    +  locales: ["en", "mr", "hi"],
    +  fallbacks: { "mr-IN": ["mr", "en"] },
    +  cookie: { name: "wire-lang", sameSite: "Lax", secure: true },
    +});
     
    -// Per request:
    -const lang = resolveLang(i18n, req.cookies?.[LANG_COOKIE], req.headers.get("accept-language"));
    +const lang = resolveLang(i18n, cookieValue, request.headers.get("accept-language"));
     const t = makeT(i18n, lang);
    -
    -t("nav.home"); // dotted key → "Home"
    -t("greeting", { name: "Ada" }); // "Hello, {name}" → "Hello, Ada"
    -
    -// After rendering a .wrn view, resolve translation markers in the HTML:
    -const finalHtml = translateHtml(renderedHtml, t);
    -

    app/locales/en.json:

    -
    {
    -  "nav": { "home": "Home" },
    -  "greeting": "Hello, {name}"
    -}
    -

    Views: translation markers

    -
    <h1 data-t="nav.home">Home</h1>
    +t("common.hello", { name: "Ajay" });
    +

    Resolution behavior

    +
      +
    • normalized BCP-47-style locale names
    • +
    • cookie preference
    • +
    • weighted Accept-Language
    • +
    • wildcard language ranges
    • +
    • regional base fallback
    • +
    • explicit fallback chains
    • +
    • configured default language
    • +
    • automatic RTL for Arabic, Hebrew, Persian, Urdu, and related languages
    • +
    +

    Locale JSON is size-limited and rejects prototype-pollution keys. Recursive namespace collisions are resolved safely.

    +

    Views and runtime

    +
    <h1 data-t="dashboard.title">Dashboard</h1>
     <input t:placeholder="search.placeholder" />
    -

    translateHtml replaces the element text for data-t and the attribute value for any t:<attr> (e.g. t:placeholder, t:aria-label).

    -

    Client: language switcher

    -
    import { renderI18nData, I18N_RUNTIME, I18N_JS_HREF } from "@wrnexus/i18n";
    -
    -// In the document <head>:
    -const head = `
    -  <script>${renderI18nData(i18n, lang)}</script>
    -  <script src="${I18N_JS_HREF}"></script>
    -`;
    -
    -// Serve I18N_RUNTIME at I18N_JS_HREF; then in markup:
    -// <button data-wire-lang-set="es">Español</button>
    -// <select data-wire-lang>…</select>
    -

    Formatting

    +

    Text and translated attributes are resolved during SSR. Active/fallback messages are serialized safely for the language runtime, which rebinds data-t markers after client navigation.

    +

    Enable i18nPlugin() to use:

    +
      +
    • <LanguageSwitcher />
    • +
    • <LocaleStatus />
    • +
    +

    LanguageSwitcher renders a native select[data-wire-lang]. The packaged runtime validates the selection against the configured locales, writes the configured language cookie, updates the document lang/dir attributes, emits wrnexus:language-change, and reloads so the next SSR request uses the same cookie. No application-owned browser script is required.

    +

    Formatting

    +
      +
    • formatNumber
    • +
    • formatCurrency
    • +
    • formatDate
    • +
    • formatRelativeTime
    • +
    • plural
    • +
    • createLocaleFormatter
    • +
    • translationCoverage
    • +

      Localization tooling can extract statically discoverable t("key"), i18n.t("key"), and data-i18n="key" usage, compare every locale with a reference, and create layout-stressing pseudo-locales:

      +
    import {
    -  formatNumber,
    -  formatCurrency,
    -  formatDate,
    -  formatRelativeTime,
    -  plural,
    +  auditLocaleKeys,
    +  createPseudoLocale,
    +  extractTranslationKeysFromFiles,
     } from "@wrnexus/i18n";
     
    -formatNumber(1234.5, lang); // "1,234.5"
    -formatCurrency(9.99, "USD", lang); // "$9.99"
    -formatDate(Date.now(), lang); // "Jul 4, 2026"
    -formatRelativeTime(-3, "day", lang); // "3 days ago"
    -plural(2, { one: "# item", other: "# items" }, lang); // "2 items"
    -

    Configuration

    -

    resolveI18n accepts an I18nConfig:

    -
      -
    • default — fallback language; used when nothing else matches. Ignored if it has
    • -

      no loaded messages, in which case the first supported language is used.

      -
    • locales — explicit supported-language list; defaults to the loaded locale names.
    • -
    -

    Language resolution order at request time (resolveLang): a supported wire-lang cookie value → the first matching Accept-Language tag (or its base subtag) → the resolved default.

    -

    Requirements / Notes

    -
      -
    • Bun-only. Locale loading uses node:fs (existsSync, readdirSync,
    • -

      readFileSync) and node:path; formatting relies on the platform Intl APIs.

      -
    • Works with [@wrnexus/core](../core) — TFunction (the t(key, params) type)
    • -

      comes from core, and the resolved translator is exposed as ctx.t / ctx.lang in request handling.

      -
    • Nested message objects are supported: keys are looked up whole first, then split
    • -

      on . to walk the object tree.

      -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { TFunction } from '@wrnexus/core';
    +const used = extractTranslationKeysFromFiles(sourceFiles);
    +const coverage = auditLocaleKeys(messages, "en");
    +const enXA = createPseudoLocale(messages.en);
    +const arXB = createPseudoLocale(messages.en, { rtl: true });
    +

    Pseudo-localization preserves interpolation placeholders and markup tags. RTL pseudo output uses Unicode direction controls, while runtime direction detection continues to derive rtl from Arabic and other RTL language subtags.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { TFunction } from '@wrnexus/core';
    +export { I18nPluginOptions, i18nComponentsDir, default as i18nPlugin } from './plugin.js';
    +import '@wrnexus/plugin';
     
     /**
      * Locale-aware formatting helpers (Intl-based) + pluralization. Pair with the
    @@ -134,6 +100,25 @@ declare function formatRelativeTime(value: number, unit: Intl.RelativeTimeFormat
      */
     declare function plural(count: number, forms: Partial<Record<Intl.LDMLPluralRule, string>>, lang: string): string;
     
    +interface ExtractedTranslationKey {
    +    key: string;
    +    file?: string;
    +    offset: number;
    +}
    +declare function extractTranslationKeys(source: string, file?: string): ExtractedTranslationKey[];
    +declare function extractTranslationKeysFromFiles(files: Iterable<string>): ExtractedTranslationKey[];
    +declare function flattenMessageKeys(messages: Messages, prefix?: string): string[];
    +declare function auditLocaleKeys(messages: Record<string, Messages>, referenceLocale: string): Record<string, {
    +    missing: string[];
    +    extra: string[];
    +}>;
    +declare function pseudoLocalize(value: string, options?: {
    +    rtl?: boolean;
    +}): string;
    +declare function createPseudoLocale(messages: Messages, options?: {
    +    rtl?: boolean;
    +}): Messages;
    +
     declare function flattenMessages(messages: Messages, prefix?: string, output?: Record<string, string>): Record<string, string>;
     declare function localeFallbacks(locale: string, fallback?: string): string[];
     declare function translationCoverage(i18n: ResolvedI18n): Record<string, {
    @@ -150,108 +135,103 @@ interface LocaleFormatter {
         relative(value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions): string;
         list(values: string[], options?: Intl.ListFormatOptions): string;
     }
    -declare function createLocaleFormatter(locale: string, timeZone?: string): LocaleFormatter;
    -/** Lightweight plural templates: `{count, plural, one {# item} other {# items}}`. */
    +declare function createLocaleFormatter(locale: string, timeZone?: string, calendar?: string): LocaleFormatter;
    +/** ICU-style plural/select templates with exact values and recursive interpolation. */
     declare function formatMessage(template: string, params: Record<string, string | number>, locale: string): string;
     
     /**
    - * @wrnexus/i18n — translations for pages and API responses.
    - *
    - * Locales live in `app/locales/<lang>.json`. Per request the active language is
    - * resolved from the `wire-lang` cookie, then Accept-Language, then the default.
    - * `ctx.t(key, params)` translates on the server; in `.wrn` views `{t:key}` and
    - * `t:attr="key"` markers are resolved by `translateHtml` before the HTML is sent.
    + * @wrnexus/i18n — deterministic locale loading, fallback resolution, SSR
    + * translation markers, browser translation helpers, and UI language controls.
      */
     
     type Messages = Record<string, unknown>;
    -/** Load `<dir>/<lang>.json` files into a `{ lang: messages }` map. */
    -declare function loadLocales(dir: string): Record<string, Messages>;
    +interface LocaleLoadOptions {
    +    /** Throw on invalid JSON instead of warning and continuing. */
    +    strict?: boolean;
    +    /** Maximum JSON file size. Default 1 MiB. */
    +    maxFileBytes?: number;
    +}
    +interface I18nCookieConfig {
    +    name?: string;
    +    maxAge?: number;
    +    path?: string;
    +    sameSite?: "Strict" | "Lax" | "None";
    +    secure?: boolean;
    +}
     interface I18nConfig {
    -    /** Default language, used as the fallback and when nothing else matches. */
         default?: string;
    -    /** Explicit set of supported languages (defaults to the loaded locale names). */
         locales?: string[];
    +    /** Human-readable locale names used by package language controls. */
    +    labels?: Record<string, string>;
    +    /** Per-locale fallback override. Example: `{ "fr-CA": ["fr", "en"] }`. */
    +    fallbacks?: Record<string, string[]>;
    +    /** Locale direction overrides. Arabic/Hebrew/Persian/Urdu are RTL automatically. */
    +    direction?: Record<string, "ltr" | "rtl">;
    +    cookie?: I18nCookieConfig;
    +    strict?: boolean;
     }
     interface ResolvedI18n {
         default: string;
         langs: string[];
         messages: Record<string, Messages>;
    +    fallbacks: Record<string, string[]>;
    +    direction: Record<string, "ltr" | "rtl">;
    +    labels: Record<string, string>;
    +    cookie: Required<I18nCookieConfig>;
     }
     declare const LANG_COOKIE = "wire-lang";
     declare const I18N_JS_HREF = "/__wrnexus/i18n.js";
    -/** Merge loaded locale messages + config into a resolved i18n bundle. */
    +declare function normalizeLocale(locale: string): string;
    +/**
    + * Load both supported layouts:
    + * - `locales/en.json`
    + * - `locales/en/common.json`, `locales/en/auth.json`
    + *
    + * Namespaced files become `messages.en.common` and `messages.en.auth`.
    + */
    +declare function loadLocales(dir: string, options?: LocaleLoadOptions): Record<string, Messages>;
    +declare function localeDirection(locale: string, overrides?: Record<string, "ltr" | "rtl">): "ltr" | "rtl";
     declare function resolveI18n(messages: Record<string, Messages>, config?: I18nConfig): ResolvedI18n;
    -/** Build a `t()` for a language: current → default → the key itself. */
    +declare function lookupMessage(messages: Messages | undefined, key: string): string | undefined;
    +declare function interpolate(message: string, params?: Record<string, string | number>): string;
    +declare function translationChain(i18n: ResolvedI18n, locale: string): string[];
     declare function makeT(i18n: ResolvedI18n, lang: string): TFunction;
    -/** Resolve the active language from a cookie, Accept-Language, then default. */
    +/** Deeply apply tenant-specific translations without mutating the shared locale bundle. */
    +declare function withTenantMessages(i18n: ResolvedI18n, overrides: Record<string, Messages>): ResolvedI18n;
    +/** Load only common and route-specific messages for one locale. */
    +declare function loadRouteMessages(directory: string, locale: string, route: string): Messages;
    +declare function parseAcceptLanguage(value: string | null): string[];
     declare function resolveLang(i18n: ResolvedI18n, cookieValue: string | undefined, acceptLanguage: string | null): string;
    -/**
    - * Resolve translation markers in rendered HTML:
    - *   t:<attr>="key"        → <attr>="<translation>"   (e.g. t:placeholder, t:aria-label)
    - *   <tag data-t="key">…</tag> → element text becomes the translation
    - * Only runs when the HTML actually contains a marker.
    - */
     declare function translateHtml(html: string, t: TFunction): string;
    -/** `window.__wireI18n = { lang, langs }` for the client language switcher. */
     declare function renderI18nData(i18n: ResolvedI18n, lang: string): string;
    -/**
    - * Client runtime: binds `[data-wire-lang-set="es"]` elements to set the
    - * `wire-lang` cookie and reload, so the server re-renders in the new language.
    - */
     declare const I18N_RUNTIME: string;
     
    -export { I18N_JS_HREF, I18N_RUNTIME, type I18nConfig, LANG_COOKIE, type LocaleFormatter, type Messages, type ResolvedI18n, createLocaleFormatter, flattenMessages, formatCurrency, formatDate, formatMessage, formatNumber, formatRelativeTime, loadLocales, localeFallbacks, makeT, plural, renderI18nData, resolveI18n, resolveLang, translateHtml, translationCoverage };
    -

    Examples

    Copy-ready examples from the installed package documentation.

    Server: load, resolve, translate

    import {
    -  loadLocales,
    -  resolveI18n,
    -  resolveLang,
    -  makeT,
    -  translateHtml,
    -  LANG_COOKIE,
    -} from "@wrnexus/i18n";
    +export { type ExtractedTranslationKey, I18N_JS_HREF, I18N_RUNTIME, type I18nConfig, type I18nCookieConfig, LANG_COOKIE, type LocaleFormatter, type LocaleLoadOptions, type Messages, type ResolvedI18n, auditLocaleKeys, createLocaleFormatter, createPseudoLocale, extractTranslationKeys, extractTranslationKeysFromFiles, flattenMessageKeys, flattenMessages, formatCurrency, formatDate, formatMessage, formatNumber, formatRelativeTime, interpolate, loadLocales, loadRouteMessages, localeDirection, localeFallbacks, lookupMessage, makeT, normalizeLocale, parseAcceptLanguage, plural, pseudoLocalize, renderI18nData, resolveI18n, resolveLang, translateHtml, translationChain, translationCoverage, withTenantMessages };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Namespaced files become keys such as common.save and auth.signIn.

    import { loadLocales, makeT, resolveI18n, resolveLang } from "@wrnexus/i18n";
     
    -// app/locales/en.json, app/locales/es.json
    -const messages = loadLocales("app/locales");
    -const i18n = resolveI18n(messages, { default: "en", locales: ["en", "es"] });
    +const i18n = resolveI18n(loadLocales("app/locales", { strict: true }), {
    +  default: "en",
    +  locales: ["en", "mr", "hi"],
    +  fallbacks: { "mr-IN": ["mr", "en"] },
    +  cookie: { name: "wire-lang", sameSite: "Lax", secure: true },
    +});
     
    -// Per request:
    -const lang = resolveLang(i18n, req.cookies?.[LANG_COOKIE], req.headers.get("accept-language"));
    +const lang = resolveLang(i18n, cookieValue, request.headers.get("accept-language"));
     const t = makeT(i18n, lang);
    -
    -t("nav.home"); // dotted key → "Home"
    -t("greeting", { name: "Ada" }); // "Hello, {name}" → "Hello, Ada"
    -
    -// After rendering a .wrn view, resolve translation markers in the HTML:
    -const finalHtml = translateHtml(renderedHtml, t);

    Server: load, resolve, translate

    {
    -  "nav": { "home": "Home" },
    -  "greeting": "Hello, {name}"
    -}

    Views: translation markers

    <h1 data-t="nav.home">Home</h1>
    -<input t:placeholder="search.placeholder" />

    Client: language switcher

    import { renderI18nData, I18N_RUNTIME, I18N_JS_HREF } from "@wrnexus/i18n";
    -
    -// In the document <head>:
    -const head = `
    -  <script>${renderI18nData(i18n, lang)}</script>
    -  <script src="${I18N_JS_HREF}"></script>
    -`;
    -
    -// Serve I18N_RUNTIME at I18N_JS_HREF; then in markup:
    -// <button data-wire-lang-set="es">Español</button>
    -// <select data-wire-lang>…</select>

    Formatting

    import {
    -  formatNumber,
    -  formatCurrency,
    -  formatDate,
    -  formatRelativeTime,
    -  plural,
    +t("common.hello", { name: "Ajay" });

    ## Views and runtime

    <h1 data-t="dashboard.title">Dashboard</h1>
    +<input t:placeholder="search.placeholder" />

    reference, and create layout-stressing pseudo-locales

    import {
    +  auditLocaleKeys,
    +  createPseudoLocale,
    +  extractTranslationKeysFromFiles,
     } from "@wrnexus/i18n";
     
    -formatNumber(1234.5, lang); // "1,234.5"
    -formatCurrency(9.99, "USD", lang); // "$9.99"
    -formatDate(Date.now(), lang); // "Jul 4, 2026"
    -formatRelativeTime(-3, "day", lang); // "3 days ago"
    -plural(2, { one: "# item", other: "# items" }, lang); // "2 items"
    - +const used = extractTranslationKeysFromFiles(sourceFiles); +const coverage = auditLocaleKeys(messages, "en"); +const enXA = createPseudoLocale(messages.en); +const arXB = createPseudoLocale(messages.en, { rtl: true });
    +
    - + } diff --git a/app/pages/packages/identity.wrn b/app/pages/packages/identity.wrn new file mode 100644 index 00000000..4fbeebf0 --- /dev/null +++ b/app/pages/packages/identity.wrn @@ -0,0 +1,240 @@ +page wrnexusidentity { + seo { + title = "@wrnexus/identity" + description = "Portable identity records, claims, and account linking." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Security · Package reference

    @wrnexus/identity

    Portable identity records, claims, and account linking.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/identity@0.8.0

    Request preview access. Never put registry tokens in source control.

    Enterprise identity and governance for WRNexusJS: OIDC discovery, signed SAML adapter flows, LDAP/Active Directory synchronization adapters, SCIM provisioning, scoped API keys, service accounts, approval workflows, consent history, retention, subject export/deletion and audit.

    +

    The package complements @wrnexus/auth (passkeys, MFA, devices, sessions, OAuth and audited impersonation) and @wrnexus/authz (RBAC, ABAC and policy decisions). Protocol-specific SAML and directory parsing is supplied through adapters so applications can select a maintained vendor SDK without weakening framework validation, replay protection or governance auditing.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface OidcMetadata {
    +    issuer: string;
    +    authorization_endpoint: string;
    +    token_endpoint: string;
    +    userinfo_endpoint?: string;
    +    jwks_uri: string;
    +    scopes_supported?: string[];
    +}
    +declare function discoverOidc(issuer: string, options?: {
    +    fetch?: typeof fetch;
    +}): Promise<OidcMetadata>;
    +declare function oidcAuthorizationUrl(metadata: OidcMetadata, input: {
    +    clientId: string;
    +    redirectUri: string;
    +    state: string;
    +    nonce: string;
    +    codeChallenge: string;
    +    scopes?: string[];
    +}): string;
    +interface EnterpriseIdentity {
    +    externalId: string;
    +    username: string;
    +    displayName?: string;
    +    email?: string;
    +    groups: string[];
    +    active: boolean;
    +    attributes?: Record<string, unknown>;
    +}
    +interface SamlAssertion {
    +    id: string;
    +    issuer: string;
    +    audience: string;
    +    recipient: string;
    +    expiresAt: number;
    +    identity: EnterpriseIdentity;
    +}
    +interface SamlAdapter {
    +    createLoginRequest(input: {
    +        requestId: string;
    +        callbackUrl: string;
    +        relayState: string;
    +    }): Promise<string> | string;
    +    verifySignedResponse(response: string): Promise<SamlAssertion>;
    +}
    +interface ReplayStore {
    +    consume(id: string, expiresAt: number): Promise<boolean>;
    +}
    +declare function memoryReplayStore(now?: () => number): ReplayStore;
    +declare function createSamlFederation(options: {
    +    adapter: SamlAdapter;
    +    issuer: string;
    +    audience: string;
    +    recipient: string;
    +    replayStore?: ReplayStore;
    +    now?: () => number;
    +}): {
    +    login: (input: {
    +        requestId: string;
    +        callbackUrl: string;
    +        relayState: string;
    +    }) => Promise<string> | string;
    +    callback(encodedResponse: string): Promise<EnterpriseIdentity>;
    +};
    +interface DirectoryAdapter {
    +    kind: "ldap" | "active-directory";
    +    search(input: {
    +        baseDn: string;
    +        filter: string;
    +        attributes: string[];
    +        signal?: AbortSignal;
    +    }): Promise<EnterpriseIdentity[]>;
    +    authenticate?(username: string, password: string, signal?: AbortSignal): Promise<EnterpriseIdentity | null>;
    +}
    +declare function syncDirectory(adapter: DirectoryAdapter, options: {
    +    baseDn: string;
    +    filter?: string;
    +    attributes?: string[];
    +    signal?: AbortSignal;
    +    upsert: (identity: EnterpriseIdentity) => void | Promise<void>;
    +    disableMissing?: (externalIds: string[]) => void | Promise<void>;
    +}): Promise<{
    +    provider: "ldap" | "active-directory";
    +    synchronized: number;
    +}>;
    +interface ScimUser extends EnterpriseIdentity {
    +    id: string;
    +    /** RFC 7643 field accepted at the HTTP boundary. */
    +    userName?: string;
    +    schemas?: string[];
    +}
    +interface ScimStore {
    +    list(): Promise<ScimUser[]>;
    +    get(id: string): Promise<ScimUser | null>;
    +    create(user: Omit<ScimUser, "id">): Promise<ScimUser>;
    +    update(id: string, user: Partial<ScimUser>): Promise<ScimUser | null>;
    +    delete(id: string): Promise<boolean>;
    +}
    +declare function memoryScimStore(): ScimStore;
    +declare function createScimHandler(options: {
    +    store: ScimStore;
    +    bearerToken: string;
    +    basePath?: string;
    +    maxBodyBytes?: number;
    +}): (request: Request) => Promise<Response>;
    +interface MachineCredential {
    +    id: string;
    +    ownerId: string;
    +    kind: "api-key" | "service-account";
    +    name: string;
    +    scopes: string[];
    +    secretHash: string;
    +    createdAt: number;
    +    expiresAt?: number;
    +    revokedAt?: number;
    +}
    +declare function createMachineIdentityManager(now?: () => number): {
    +    issue(input: {
    +        ownerId: string;
    +        name: string;
    +        scopes: string[];
    +        kind?: MachineCredential["kind"];
    +        expiresAt?: number;
    +    }): Promise<{
    +        secret: string;
    +        credential: {
    +            secretHash: string;
    +            id: string;
    +            ownerId: string;
    +            kind: "api-key" | "service-account";
    +            name: string;
    +            scopes: string[];
    +            createdAt: number;
    +            expiresAt?: number;
    +            revokedAt?: number;
    +        };
    +    }>;
    +    authenticate(secret: string, requiredScope?: string): Promise<{
    +        secretHash: string;
    +        id: string;
    +        ownerId: string;
    +        kind: "api-key" | "service-account";
    +        name: string;
    +        scopes: string[];
    +        createdAt: number;
    +        expiresAt?: number;
    +        revokedAt?: number;
    +    } | null>;
    +    revoke(id: string): boolean;
    +    list(ownerId: string): {
    +        secretHash: string;
    +        id: string;
    +        ownerId: string;
    +        kind: "api-key" | "service-account";
    +        name: string;
    +        scopes: string[];
    +        createdAt: number;
    +        expiresAt?: number;
    +        revokedAt?: number;
    +    }[];
    +};
    +interface GovernanceEvent {
    +    id: string;
    +    type: string;
    +    subjectId: string;
    +    actorId?: string;
    +    createdAt: number;
    +    data?: Record<string, unknown>;
    +}
    +declare function createGovernance(options?: {
    +    now?: () => number;
    +    audit?: (event: GovernanceEvent) => void | Promise<void>;
    +    exportSubject?: (subjectId: string) => unknown | Promise<unknown>;
    +    deleteSubject?: (subjectId: string) => void | Promise<void>;
    +}): {
    +    consent(subjectId: string, purpose: string, granted: boolean, version: string): Promise<{
    +        granted: boolean;
    +        version: string;
    +        at: number;
    +    }>;
    +    consents(subjectId: string): {
    +        [k: string]: {
    +            granted: boolean;
    +            version: string;
    +            at: number;
    +        };
    +    };
    +    request(subjectId: string, action: "export" | "delete"): Promise<{
    +        id: `${string}-${string}-${string}-${string}-${string}`;
    +        subjectId: string;
    +        action: "export" | "delete";
    +        status: "pending";
    +        requestedAt: number;
    +    }>;
    +    decide(id: string, actorId: string, approved: boolean): Promise<{
    +        decision: {
    +            status: "approved" | "rejected";
    +            decidedAt: number;
    +            decidedBy: string;
    +            id: string;
    +            subjectId: string;
    +            action: "export" | "delete";
    +            requestedAt: number;
    +        };
    +        result: unknown;
    +    }>;
    +    enforceRetention(records: Array<{
    +        subjectId: string;
    +        createdAt: number;
    +    }>, maxAgeMs: number, remove: (record: {
    +        subjectId: string;
    +        createdAt: number;
    +    }) => void | Promise<void>): Promise<number>;
    +};
    +
    +export { type DirectoryAdapter, type EnterpriseIdentity, type GovernanceEvent, type MachineCredential, type OidcMetadata, type ReplayStore, type SamlAdapter, type SamlAssertion, type ScimStore, type ScimUser, createGovernance, createMachineIdentityManager, createSamlFederation, createScimHandler, discoverOidc, memoryReplayStore, memoryScimStore, oidcAuthorizationUrl, syncDirectory };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/identity

    bun add @wrnexus/identity

    Import @wrnexus/identity

    import * as identity from "@wrnexus/identity";
    + +
    + + +
    + } +} diff --git a/app/pages/packages/image.wrn b/app/pages/packages/image.wrn new file mode 100644 index 00000000..b3d297f2 --- /dev/null +++ b/app/pages/packages/image.wrn @@ -0,0 +1,226 @@ +page wrnexusimage { + seo { + title = "@wrnexus/image" + description = "Responsive image optimization, loaders, placeholders, and components." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Frontend · Package reference

    @wrnexus/image

    Responsive image optimization, loaders, placeholders, and components.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/image@0.8.0

    Request preview access. Never put registry tokens in source control.

    Secure responsive-image planning, loader adapters, picture sources, preload hints, placeholders, and performance auditing for WRNexusJS.

    +

    Build-time conversion is available through optimizeImage. It normalizes and bounds width/format variants, prevents variant explosions, writes deterministic filenames, and returns a manifest with dimensions and byte sizes:

    +
    import { optimizeImage } from "@wrnexus/image";
    +
    +const manifest = await optimizeImage("public/hero.jpg", {
    +  outputDir: "public/generated/images",
    +  widths: [480, 960, 1440],
    +  formats: ["avif", "webp"],
    +  quality: 80,
    +});
    +

    Install the optional sharp peer (bun add sharp) for the default AVIF/WebP processor. Build systems can instead supply an ImageProcessor adapter, which also makes transformation pipelines deterministic in tests.

    +

    Helper API

    +
    import {
    +  createResponsiveImage,
    +  createPicture,
    +  createCdnImageLoader,
    +  createPathImageLoader,
    +  createBlurPlaceholder,
    +  imagePreload,
    +  auditImage,
    +} from "@wrnexus/image";
    +
    +const loader = createCdnImageLoader("https://images.example.com/transform");
    +const picture = createPicture({
    +  src: "/hero.jpg",
    +  alt: "Product dashboard",
    +  width: 1600,
    +  height: 900,
    +  widths: [480, 768, 1200, 1600],
    +  formats: ["avif", "webp"],
    +  sizes: "(max-width: 768px) 100vw, 1200px",
    +  fetchPriority: "high",
    +  loader,
    +});
    +

    Remote loaders require HTTPS. Source URLs are validated, dimensions and quality are bounded, placeholder colors are restricted to safe CSS colors, and preload attributes are escaped.

    +

    Components

    +

    Enable imagePlugin() and use:

    +
      +
    • <OptimizedImage />
    • +
    • <Picture />
    • +
    • <ImageCard />
    • +
    +

    The package-owned blocks compose @wrnexus/ui where a complete UI block is appropriate while keeping the low-level image element lightweight.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { ImagePluginOptions, imageComponentsDir, default as imagePlugin } from './plugin.js';
    +import '@wrnexus/plugin';
    +
    +interface ImageProcessorResult {
    +    data: Uint8Array;
    +    width: number;
    +    height: number;
    +}
    +interface ImageProcessor {
    +    transform(input: string, options: {
    +        width: number;
    +        format: Exclude<ImageFormat, "original">;
    +        quality: number;
    +    }): Promise<ImageProcessorResult>;
    +}
    +interface OptimizeImageOptions {
    +    outputDir: string;
    +    widths: number[];
    +    formats?: Array<Exclude<ImageFormat, "original">>;
    +    quality?: number;
    +    maxVariants?: number;
    +    processor?: ImageProcessor;
    +}
    +interface OptimizedImageVariant {
    +    path: string;
    +    width: number;
    +    height: number;
    +    format: Exclude<ImageFormat, "original">;
    +    bytes: number;
    +}
    +interface OptimizedImageManifest {
    +    source: string;
    +    variants: OptimizedImageVariant[];
    +}
    +declare function optimizeImage(input: string, options: OptimizeImageOptions): Promise<OptimizedImageManifest>;
    +
    +type ImageFormat = "avif" | "webp" | "jpeg" | "png" | "original";
    +interface ImageLoaderInput {
    +    src: string;
    +    width: number;
    +    quality?: number;
    +    format?: ImageFormat;
    +}
    +type ImageLoader = (input: ImageLoaderInput) => string;
    +interface ImagePolicy {
    +    remoteHosts?: string[];
    +    allowedProtocols?: string[];
    +    maxWidth?: number;
    +    maxQuality?: number;
    +}
    +interface ResponsiveImageOptions extends ImagePolicy {
    +    src: string;
    +    alt: string;
    +    width: number;
    +    height: number;
    +    widths?: number[];
    +    sizes?: string;
    +    quality?: number;
    +    format?: ImageFormat;
    +    loading?: "eager" | "lazy";
    +    fetchPriority?: "high" | "low" | "auto";
    +    decoding?: "async" | "sync" | "auto";
    +    loader?: ImageLoader;
    +    class?: string;
    +}
    +interface ResponsiveImageAttributes {
    +    src: string;
    +    srcset?: string;
    +    sizes?: string;
    +    alt: string;
    +    width: string;
    +    height: string;
    +    loading: "eager" | "lazy";
    +    decoding: "async" | "sync" | "auto";
    +    fetchpriority?: "high" | "low" | "auto";
    +    class?: string;
    +}
    +interface ImageAuditInput {
    +    src: string;
    +    width?: number;
    +    height?: number;
    +    renderedWidth?: number;
    +    bytes?: number;
    +    loading?: string;
    +    fetchPriority?: string;
    +    isLcp?: boolean;
    +}
    +interface ImageAuditIssue {
    +    code: string;
    +    severity: "error" | "warning" | "info";
    +    message: string;
    +}
    +declare const defaultImageLoader: ImageLoader;
    +declare function createResponsiveImage(options: ResponsiveImageOptions): ResponsiveImageAttributes;
    +declare function auditImage(input: ImageAuditInput): ImageAuditIssue[];
    +interface PictureSource {
    +    type: string;
    +    srcset: string;
    +    sizes?: string;
    +}
    +interface PicturePlan {
    +    image: ResponsiveImageAttributes;
    +    sources: PictureSource[];
    +}
    +declare function normalizeImageWidths(widths: readonly number[], options?: {
    +    min?: number;
    +    max?: number;
    +}): number[];
    +declare function createCdnImageLoader(baseUrl: string, options?: {
    +    sourceParam?: string;
    +    widthParam?: string;
    +    qualityParam?: string;
    +    formatParam?: string;
    +}): ImageLoader;
    +declare function createPathImageLoader(prefix?: string): ImageLoader;
    +declare function createPicture(options: ResponsiveImageOptions & {
    +    formats?: ImageFormat[];
    +}): PicturePlan;
    +declare function createBlurPlaceholder(options?: {
    +    width?: number;
    +    height?: number;
    +    color?: string;
    +    accent?: string;
    +}): string;
    +declare function imagePreload(image: ResponsiveImageAttributes, options?: {
    +    as?: string;
    +    type?: string;
    +    crossOrigin?: "anonymous" | "use-credentials";
    +}): string;
    +declare function imageCacheKey(input: ImageLoaderInput): string;
    +
    +export { type ImageAuditInput, type ImageAuditIssue, type ImageFormat, type ImageLoader, type ImageLoaderInput, type ImagePolicy, type ImageProcessor, type ImageProcessorResult, type OptimizeImageOptions, type OptimizedImageManifest, type OptimizedImageVariant, type PicturePlan, type PictureSource, type ResponsiveImageAttributes, type ResponsiveImageOptions, auditImage, createBlurPlaceholder, createCdnImageLoader, createPathImageLoader, createPicture, createResponsiveImage, defaultImageLoader, imageCacheKey, imagePreload, normalizeImageWidths, optimizeImage };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    filenames, and returns a manifest with dimensions and byte sizes

    import { optimizeImage } from "@wrnexus/image";
    +
    +const manifest = await optimizeImage("public/hero.jpg", {
    +  outputDir: "public/generated/images",
    +  widths: [480, 960, 1440],
    +  formats: ["avif", "webp"],
    +  quality: 80,
    +});

    ## Helper API

    import {
    +  createResponsiveImage,
    +  createPicture,
    +  createCdnImageLoader,
    +  createPathImageLoader,
    +  createBlurPlaceholder,
    +  imagePreload,
    +  auditImage,
    +} from "@wrnexus/image";
    +
    +const loader = createCdnImageLoader("https://images.example.com/transform");
    +const picture = createPicture({
    +  src: "/hero.jpg",
    +  alt: "Product dashboard",
    +  width: 1600,
    +  height: 900,
    +  widths: [480, 768, 1200, 1600],
    +  formats: ["avif", "webp"],
    +  sizes: "(max-width: 768px) 100vw, 1200px",
    +  fetchPriority: "high",
    +  loader,
    +});
    + +
    + + +
    + } +} diff --git a/app/pages/packages/jwt.wrn b/app/pages/packages/jwt.wrn index 6335eb0c..5c40c9b0 100644 --- a/app/pages/packages/jwt.wrn +++ b/app/pages/packages/jwt.wrn @@ -10,11 +10,11 @@ page wrnexusjwt {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/jwt

    HS256 JWT signing, verification, and bearer authentication.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/jwt@0.7.0

    Request preview access. Never put registry tokens in source control.

    Dependency-free JSON Web Tokens (HS256) via Web Crypto, plus a bearer-token auth middleware for WRNexusJS.
    +
    Security · Package reference

    @wrnexus/jwt

    HS256 JWT signing, verification, and bearer authentication.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/jwt@0.8.0

    Request preview access. Never put registry tokens in source control.

    Dependency-free JSON Web Tokens (HS256) via Web Crypto, plus a bearer-token auth middleware for WRNexusJS.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/jwt signs and verifies stateless JSON Web Tokens using the HS256 (HMAC-SHA-256) algorithm. It has no runtime dependencies — signing and verification are implemented directly on the standard Web Crypto API (crypto.subtle), which Bun provides natively. It runs server-side and pairs with the session-based auth in @wrnexus/core, giving you a stateless option for API and mobile clients. Reach for it when you need bearer-token auth rather than cookie sessions.

    @@ -87,7 +87,46 @@ app.use(jwtAuth({ secret: process.env.JWT_SECRET!, required: false }))

    are not supported.

  • Integrates with [@wrnexus/core](../core) for Context, Middleware, and
  • ctx.user; it complements the framework's cookie/session auth with a stateless bearer-token flow for API and mobile clients.

    -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context, Middleware } from '@wrnexus/core';
    +
    +
    +
    import {
    +  createAccessToken,
    +  createRefreshToken,
    +  verifyAccessToken,
    +  verifyRefreshToken,
    +  extractBearerToken,
    +  requireScopes,
    +  jwtCookie,
    +} from "@wrnexus/jwt";
    +

    The helpers add explicit type: "access" | "refresh" claims, scope checks, refresh-token family metadata, no-store token responses, and secure cookie defaults. __Host- cookies are rejected unless they use Path=/ and Secure; SameSite=None is rejected without Secure.

    +

    0.8 helper kit

    +
    import {
    +  createTokenPair,
    +  verifyAccessToken,
    +  verifyRefreshToken,
    +  extractBearerToken,
    +  readJwtCookie,
    +  jwtCookie,
    +  clearJwtCookie,
    +  requireScopes,
    +} from "@wrnexus/jwt";
    +
    +const pair = await createTokenPair(user.id, {
    +  accessSecret: process.env.JWT_ACCESS_SECRET!,
    +  refreshSecret: process.env.JWT_REFRESH_SECRET!,
    +  scopes: ["profile:read"],
    +  family: sessionFamily,
    +});
    +

    The helper kit validates __Host- cookie invariants, cookie names and paths, SameSite=None security, typed access/refresh token types, scope requirements, and no-store token responses. In addition to local HS256 secrets/keyrings, the package verifies standards-based RS256 tokens through bounded remote JWKS caches:

    +
    import { createRemoteJwks, verifyJwtWithJwks } from "@wrnexus/jwt";
    +
    +const jwks = createRemoteJwks("https://issuer.example/.well-known/jwks.json");
    +const claims = await verifyJwtWithJwks(token, jwks, {
    +  issuer: "https://issuer.example",
    +  audience: "my-api",
    +  maxAge: 300,
    +});
    +

    JWKS URLs must use HTTPS. Responses have key-count/byte limits, accept only RS256 signing RSA keys, deduplicate concurrent refreshes, cache imported public keys, and force an immediate refresh for an unknown kid so issuer rotation does not wait for cache expiry. Never use decoded-but-unverified claims for an authorization decision.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context, Middleware } from '@wrnexus/core';
     
     interface JwtKey {
         id: string;
    @@ -107,6 +146,91 @@ declare function createJwtKeyring(keys: JwtKey[]): JwtKeyring;
     declare function signWithKeyring(claims: JwtClaims, keyring: JwtKeyring, options?: SignOptions): Promise<string>;
     declare function verifyWithKeyring<T extends JwtClaims = JwtClaims>(token: string, keyring: JwtKeyring, options?: VerifyOptions): Promise<T>;
     
    +interface AccessTokenClaims extends JwtClaims {
    +    sub: string;
    +    type: "access";
    +    scopes?: string[];
    +}
    +interface RefreshTokenClaims extends JwtClaims {
    +    sub: string;
    +    type: "refresh";
    +    family?: string;
    +}
    +declare function extractBearerToken(value: Headers | Request | Context | string | null | undefined): string | undefined;
    +declare function tryVerifyJwt<T extends JwtClaims = JwtClaims>(token: string | undefined, secret: string, options?: VerifyOptions): Promise<T | null>;
    +declare function assertJwtClaims<T extends JwtClaims>(claims: T, requirements?: {
    +    subject?: boolean;
    +    type?: string;
    +    required?: string[];
    +}): T;
    +declare function tokenScopes(claims: JwtClaims): string[];
    +declare function hasScopes(claims: JwtClaims, required: readonly string[], mode?: "all" | "any"): boolean;
    +declare function requireScopes(required: readonly string[], mode?: "all" | "any"): Middleware;
    +declare function createAccessToken(subject: string, secret: string, options?: Omit<SignOptions, "expiresIn"> & {
    +    expiresIn?: number;
    +    scopes?: string[];
    +    claims?: JwtClaims;
    +}): Promise<string>;
    +declare function createRefreshToken(subject: string, secret: string, options?: Omit<SignOptions, "expiresIn"> & {
    +    expiresIn?: number;
    +    family?: string;
    +    claims?: JwtClaims;
    +}): Promise<string>;
    +declare function verifyAccessToken(token: string, secret: string, options?: VerifyOptions): Promise<AccessTokenClaims>;
    +declare function verifyRefreshToken(token: string, secret: string, options?: VerifyOptions): Promise<RefreshTokenClaims>;
    +declare function readJwtCookie(value: Headers | Request | string | null | undefined, name?: string): string | undefined;
    +declare function jwtCookie(token: string, options?: {
    +    name?: string;
    +    maxAge?: number;
    +    secure?: boolean;
    +    sameSite?: "Strict" | "Lax" | "None";
    +    path?: string;
    +}): string;
    +declare function clearJwtCookie(options?: Omit<Parameters<typeof jwtCookie>[1], "maxAge">): string;
    +interface JwtTokenPair {
    +    accessToken: string;
    +    refreshToken: string;
    +    tokenType: "Bearer";
    +    expiresIn: number;
    +}
    +declare function createTokenPair(subject: string, input: {
    +    accessSecret: string;
    +    refreshSecret?: string;
    +    accessExpiresIn?: number;
    +    refreshExpiresIn?: number;
    +    scopes?: string[];
    +    family?: string;
    +    accessOptions?: Omit<SignOptions, "expiresIn">;
    +    refreshOptions?: Omit<SignOptions, "expiresIn">;
    +}): Promise<JwtTokenPair>;
    +declare function jwtResponse(accessToken: string, input?: {
    +    refreshToken?: string;
    +    expiresIn?: number;
    +    tokenType?: string;
    +    scope?: string[];
    +}): Response;
    +
    +interface RemoteJwksOptions {
    +    fetch?: typeof fetch;
    +    cacheTtlMs?: number;
    +    maxKeys?: number;
    +    maxBytes?: number;
    +    now?: () => number;
    +}
    +interface RemoteJwks {
    +    resolve(kid: string, alg: string): Promise<CryptoKey>;
    +    refresh(): Promise<void>;
    +    clear(): void;
    +    stats(): {
    +        fetches: number;
    +        hits: number;
    +        keys: number;
    +        expiresAt: number;
    +    };
    +}
    +declare function createRemoteJwks(url: string, options?: RemoteJwksOptions): RemoteJwks;
    +declare function verifyJwtWithJwks<T extends JwtClaims = JwtClaims>(token: string, jwks: RemoteJwks, options?: VerifyOptions): Promise<T>;
    +
     /**
      * @wrnexus/jwt — dependency-free JSON Web Tokens (HS256) via WebCrypto, plus a
      * bearer-token auth middleware. Pairs with the session auth in @wrnexus/core for
    @@ -165,7 +289,7 @@ interface JwtAuthOptions {
      */
     declare function jwtAuth(options: JwtAuthOptions): Middleware;
     
    -export { type JwtAuthOptions, type JwtClaims, JwtError, type JwtKey, type JwtKeyring, type SignOptions, type VerifyOptions, createJwtKeyring, decodeJwt, jwtAuth, signJwt, signWithKeyring, verifyJwt, verifyWithKeyring };
    +export { type AccessTokenClaims, type JwtAuthOptions, type JwtClaims, JwtError, type JwtKey, type JwtKeyring, type JwtTokenPair, type RefreshTokenClaims, type RemoteJwks, type RemoteJwksOptions, type SignOptions, type VerifyOptions, assertJwtClaims, clearJwtCookie, createAccessToken, createJwtKeyring, createRefreshToken, createRemoteJwks, createTokenPair, decodeJwt, extractBearerToken, hasScopes, jwtAuth, jwtCookie, jwtResponse, readJwtCookie, requireScopes, signJwt, signWithKeyring, tokenScopes, tryVerifyJwt, verifyAccessToken, verifyJwt, verifyJwtWithJwks, verifyRefreshToken, verifyWithKeyring };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Typical usage

    import { signJwt, verifyJwt, jwtAuth, JwtError } from "@wrnexus/jwt";
     
     const secret = process.env.JWT_SECRET!;
    @@ -190,9 +314,9 @@ app.use(jwtAuth({ secret: process.env.JWT_SECRET! }));
     
     // Optional auth — populate ctx.user when present, but don't 401
     app.use(jwtAuth({ secret: process.env.JWT_SECRET!, required: false }));
    - +
    - + } diff --git a/app/pages/packages/language-server.wrn b/app/pages/packages/language-server.wrn new file mode 100644 index 00000000..cd6f5c67 --- /dev/null +++ b/app/pages/packages/language-server.wrn @@ -0,0 +1,164 @@ +page wrnexuslanguageserver { + seo { + title = "@wrnexus/language-server" + description = "Editor-neutral language intelligence for WRN files." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Tooling · Package reference

    @wrnexus/language-server

    Editor-neutral language intelligence for WRN files.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/language-server@0.8.0

    Request preview access. Never put registry tokens in source control.

    Editor-neutral Language Server Protocol support for .wrn files. It uses the canonical @wrnexus/syntax parser, diagnostics, accessibility rules, and formatter.

    +
    bunx wrnexus-language-server --stdio
    +

    Capabilities include syntax, accessibility and TypeScript expression diagnostics, formatting, completion, hover, document symbols, go-to-definition, references, rename, and quick fixes. The custom wrnexus/virtualDocument request returns the mapped TypeScript representation of an open .wrn document for editor TypeScript plugins and safe refactoring tools. Any LSP 3.x client can launch the stdio command. Example Neovim configuration:

    +
    vim.lsp.start({
    +  name = "wrnexus",
    +  cmd = { "bunx", "wrnexus-language-server", "--stdio" },
    +  root_dir = vim.fs.root(0, { "wrnexus.config.ts", "package.json", ".git" }),
    +})
    +

    JetBrains users can register the same command through an LSP client/plugin. The server does not require VS Code and never reads environment secrets or sends source over a network.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface WorkspaceCompletionItem {
    +    label: string;
    +    kind: number;
    +    detail: string;
    +    insertText?: string;
    +    data?: Record<string, unknown>;
    +}
    +declare function workspaceCompletionItems(root: string): WorkspaceCompletionItem[];
    +declare function clearWorkspaceIndexCache(root?: string): void;
    +declare function extractComponentRefactor(document: TextDocument, range: Range, name: string): {
    +    documentChanges: ({
    +        kind: string;
    +        uri: string;
    +        textDocument?: undefined;
    +        edits?: undefined;
    +    } | {
    +        textDocument: {
    +            uri: string;
    +            version: number | null;
    +        };
    +        edits: {
    +            range: Range;
    +            newText: string;
    +        }[];
    +        kind?: undefined;
    +        uri?: undefined;
    +    })[];
    +};
    +declare function htmlToWrn(html: string, name?: string): string;
    +
    +interface Position {
    +    line: number;
    +    character: number;
    +}
    +interface Range {
    +    start: Position;
    +    end: Position;
    +}
    +interface TextDocument {
    +    uri: string;
    +    text: string;
    +    version?: number;
    +}
    +declare const WRN_COMPLETIONS: readonly ["page", "component", "layout", "props", "outputs", "state", "computed", "effect", "watch", "lifecycle", "load", "action", "api", "realtime", "view", "style", "runtime", "hydrate"];
    +declare function offsetAt(text: string, position: Position): number;
    +declare function positionAt(text: string, requestedOffset: number): Position;
    +declare function wordAt(text: string, position: Position): {
    +    word: string;
    +    range: Range;
    +} | null;
    +declare function documentDiagnostics(document: TextDocument): {
    +    range: {
    +        start: {
    +            line: number;
    +            character: number;
    +        };
    +        end: {
    +            line: number;
    +            character: number;
    +        };
    +    };
    +    severity: number;
    +    code: string;
    +    source: string;
    +    message: string;
    +}[];
    +/** TypeScript representation consumed by editor TypeScript plugins and safe refactoring tools. */
    +declare function virtualTypeScriptDocument(document: TextDocument): {
    +    uri: string;
    +    languageId: "typescript";
    +    text: string;
    +    mappings: Array<{
    +        virtualStartLine: number;
    +        virtualEndLine: number;
    +        sourceStartLine: number;
    +        sourceStartColumn: number;
    +    }>;
    +};
    +declare function formatDocument(document: TextDocument, tabSize?: number, insertSpaces?: boolean): {
    +    range: {
    +        start: {
    +            line: number;
    +            character: number;
    +        };
    +        end: Position;
    +    };
    +    newText: string;
    +}[];
    +declare function documentSymbols(document: TextDocument): {
    +    name: string;
    +    kind: number;
    +    range: {
    +        start: Position;
    +        end: Position;
    +    };
    +    selectionRange: {
    +        start: Position;
    +        end: Position;
    +    };
    +}[];
    +declare function symbolLocations(document: TextDocument, position: Position): {
    +    uri: string;
    +    range: {
    +        start: Position;
    +        end: Position;
    +    };
    +}[];
    +declare function definitionLocation(document: TextDocument, position: Position): {
    +    uri: string;
    +    range: {
    +        start: Position;
    +        end: Position;
    +    };
    +} | null;
    +declare function hover(document: TextDocument, position: Position): {
    +    contents: {
    +        kind: string;
    +        value: string;
    +    };
    +    range: Range;
    +} | null;
    +declare function completionItems(): {
    +    label: "page" | "component" | "layout" | "props" | "outputs" | "state" | "computed" | "effect" | "watch" | "lifecycle" | "load" | "action" | "api" | "realtime" | "view" | "style" | "runtime" | "hydrate";
    +    kind: number;
    +    detail: string;
    +}[];
    +
    +export { type Position, type Range, type TextDocument, WRN_COMPLETIONS, type WorkspaceCompletionItem, clearWorkspaceIndexCache, completionItems, definitionLocation, documentDiagnostics, documentSymbols, extractComponentRefactor, formatDocument, hover, htmlToWrn, offsetAt, positionAt, symbolLocations, virtualTypeScriptDocument, wordAt, workspaceCompletionItems };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    @wrnexus/syntax parser, diagnostics, accessibility rules, and formatter.

    bunx wrnexus-language-server --stdio

    stdio command. Example Neovim configuration

    vim.lsp.start({
    +  name = "wrnexus",
    +  cmd = { "bunx", "wrnexus-language-server", "--stdio" },
    +  root_dir = vim.fs.root(0, { "wrnexus.config.ts", "package.json", ".git" }),
    +})
    + +
    + + +
    + } +} diff --git a/app/pages/packages/mcp.wrn b/app/pages/packages/mcp.wrn new file mode 100644 index 00000000..7689be72 --- /dev/null +++ b/app/pages/packages/mcp.wrn @@ -0,0 +1,50 @@ +page wrnexusmcp { + seo { + title = "@wrnexus/mcp" + description = "Model Context Protocol tools for WRNexus projects." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Tooling · Package reference

    @wrnexus/mcp

    Model Context Protocol tools for WRNexus projects.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mcp@0.8.0

    Request preview access. Never put registry tokens in source control.

    Editor-neutral Model Context Protocol server for AI development tools.

    +
    bunx wrnexus-mcp --root=.
    +

    It exposes current routes, components with props/events, database schema files, compiler diagnostics, runtime errors, dev-server health, framework documentation and installed packages. Files are resolved inside the configured application root and returned as bounded structured JSON.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface McpTool {
    +    name: string;
    +    description: string;
    +    inputSchema: {
    +        type: "object";
    +        properties?: Record<string, unknown>;
    +        additionalProperties?: boolean;
    +    };
    +}
    +interface McpServerOptions {
    +    maxFiles?: number;
    +    maxFileBytes?: number;
    +    fetch?: typeof fetch;
    +    devServerUrl?: string;
    +    runtimeErrors?: () => unknown[] | Promise<unknown[]>;
    +}
    +interface McpServer {
    +    tools(): McpTool[];
    +    call(name: string, args?: Record<string, unknown>): Promise<unknown>;
    +    handle(message: unknown): Promise<Record<string, unknown> | null>;
    +}
    +declare function createFrameworkMcpServer(appRoot: string, options?: McpServerOptions): McpServer;
    +
    +export { type McpServer, type McpServerOptions, type McpTool, createFrameworkMcpServer };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Editor-neutral Model Context Protocol server for AI development tools.

    bunx wrnexus-mcp --root=.

    Install @wrnexus/mcp

    bun add @wrnexus/mcp
    + +
    + + +
    + } +} diff --git a/app/pages/packages/mobile.wrn b/app/pages/packages/mobile.wrn index dc18ab7a..985a6181 100644 --- a/app/pages/packages/mobile.wrn +++ b/app/pages/packages/mobile.wrn @@ -10,11 +10,11 @@ page wrnexusmobile {
    W WRNexusJS - +
    -
    Native · Package reference

    @wrnexus/mobile

    SSR-safe compatibility access to Capacitor plugins.

    v0.7.0Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mobile@0.7.0

    Request preview access. Never put registry tokens in source control.

    SSR-safe access to Capacitor plugins from WRNexusJS browser code.
    +
    Native · Package reference

    @wrnexus/mobile

    SSR-safe compatibility access to Capacitor plugins.

    v0.8.0Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/mobile@0.8.0

    Request preview access. Never put registry tokens in source control.

    SSR-safe access to Capacitor plugins from WRNexusJS browser code.

    Overview

    @wrnexus/mobile keeps optional native imports out of server rendering while giving browser-owned modules one consistent registry for Capacitor plugins. During SSR, mobile.isNative() is false and mobile.platform() is "web".

    Install a plugin through the WRNexusJS CLI so the web and native projects stay aligned:

    @@ -61,6 +61,14 @@ const status = network ? await network.getStatus() : { connected: true, con
  • isNative() and platform() report the current Capacitor environment.
  • Unavailable required plugins throw MobileUnavailableError with an actionable message.

    +

    The package also provides portable application-facing primitives:

    +
      +
    • listenDeepLinks normalizes initial and live links with an allowed-scheme list.
    • +
    • PushNotifications performs permission gating and validates registrations.
    • +
    • SecureStorage namespaces and validates keys over an application-supplied encrypted
    • +

      Keychain/Keystore adapter; it does not mislabel browser localStorage as secure.

      +
    • OfflineQueue persists bounded sync batches through a pluggable durable store.
    • +

    Requirements / Notes

    • Capacitor plugin imports must remain in browser-owned modules.
    • @@ -74,6 +82,42 @@ interface DeepLink { query: URLSearchParams; } declare function parseDeepLink(value: string, schemes?: string[]): DeepLink | null; +interface DeepLinkSource { + current?(): Promise<string | undefined>; + subscribe(listener: (url: string) => void): void | (() => void); +} +/** Normalize initial and live native links and ignore malformed/unapproved schemes. */ +declare function listenDeepLinks(source: DeepLinkSource, listener: (link: DeepLink) => void, schemes?: string[]): () => void; +interface PushRegistration { + token: string; + platform?: string; +} +interface PushAdapter { + permission(): Promise<"granted" | "denied" | "prompt" | "unavailable">; + requestPermission?(): Promise<"granted" | "denied">; + register(): Promise<PushRegistration>; + subscribe?(listener: (notification: unknown) => void): () => void; +} +declare class PushNotifications { + private readonly adapter; + constructor(adapter: PushAdapter); + register(): Promise<PushRegistration>; + subscribe(listener: (notification: unknown) => void): () => void; +} +interface SecureStorageAdapter { + get(key: string): Promise<string | null>; + set(key: string, value: string): Promise<void>; + remove(key: string): Promise<void>; +} +declare class SecureStorage { + #private; + private readonly adapter; + private readonly namespace; + constructor(adapter: SecureStorageAdapter, namespace?: string); + get(key: string): Promise<string | null>; + set(key: string, value: string): Promise<void>; + remove(key: string): Promise<void>; +} interface OfflineTask<T = unknown> { id: string; type: string; @@ -141,7 +185,7 @@ declare const mobile: { whenNative: typeof whenNative; }; -export { type CapacitorBridge, type DeepLink, type MobileEnvironment, type MobilePlatform, MobileUnavailableError, OfflineQueue, type OfflineTask, type OfflineTaskStore, invoke, isNative, memoryOfflineTaskStore, mobile, mobileEnvironment, parseDeepLink, platform, plugin, registerPlugin, requirePlugin, whenNative }; +export { type CapacitorBridge, type DeepLink, type DeepLinkSource, type MobileEnvironment, type MobilePlatform, MobileUnavailableError, OfflineQueue, type OfflineTask, type OfflineTaskStore, type PushAdapter, PushNotifications, type PushRegistration, SecureStorage, type SecureStorageAdapter, invoke, isNative, listenDeepLinks, memoryOfflineTaskStore, mobile, mobileEnvironment, parseDeepLink, platform, plugin, registerPlugin, requirePlugin, whenNative };

    Examples

    Copy-ready examples from the installed package documentation.

    Register and invoke a Capacitor plugin

    import { Camera, CameraResultType } from "@capacitor/camera";
     import { mobile } from "@wrnexus/mobile";
     
    @@ -169,7 +213,7 @@ const network = mobile.plugin<NetworkPlugin>("Network");
     const status = network ? await network.getStatus() : { connected: true, connectionType: "unknown" };
    - + } diff --git a/app/pages/packages/native.wrn b/app/pages/packages/native.wrn index ca39816a..0c2bd808 100644 --- a/app/pages/packages/native.wrn +++ b/app/pages/packages/native.wrn @@ -10,11 +10,11 @@ page wrnexusnative {
    W WRNexusJS - +
    -
    Native · Package reference

    @wrnexus/native

    Cross-platform browser and Capacitor capability registry.

    v0.7.0Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/native@0.7.0

    Request preview access. Never put registry tokens in source control.

    Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.
    +
    Native · Package reference

    @wrnexus/native

    Cross-platform browser and Capacitor capability registry.

    v0.8.0Private registryNative

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/native@0.8.0

    Request preview access. Never put registry tokens in source control.

    Cross-platform capabilities for browsers, Capacitor WebViews, and compiled native apps.

    Overview

    @wrnexus/native exposes capabilities by name so application code can ask what the current platform supports before presenting an action. Browser capabilities use Web APIs; mobile capabilities use installed Capacitor plugins. platform() returns "server" during SSR, "browser" on the web, and the Capacitor platform in a native WebView.

    bun add @wrnexus/native
    @@ -64,6 +64,7 @@ const position = await native.run(
  • isMobile() and platform() report the current target safely during SSR.
  • Built-ins include camera, clipboard.write, share, geolocation, network, haptics, storage, filesystem, notifications, and device information.

    +

    defineNativeManifest declares required capabilities and typed permissions, while PermissionManager normalizes permission query/request flows across platform adapters.

    Requirements / Notes

    Use supports() before showing optional controls. Mobile capabilities require their matching Capacitor plugins to be installed and registered by the application.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { N as NativePlatform, a as NativeCapability, b as NativeRunOptions, c as NativeTarget } from './types-CDShWg0i.js';
     export { d as NativeAdapter, e as NativeBrowserRuntime } from './types-CDShWg0i.js';
    @@ -81,10 +82,11 @@ declare function supports(name: string, target?: NativeTarget): boolean;
     declare function run<TResult = unknown>(name: string, options?: unknown, runOptions?: NativeRunOptions): Promise<TResult>;
     declare function clearRegistry(): void;
     
    +type NativePermission = "camera" | "geolocation" | "microphone" | "notifications" | "photos" | "storage" | (string & {});
     interface NativeCapabilityManifestEntry {
         name: string;
         description?: string;
    -    permissions?: string[];
    +    permissions?: NativePermission[];
         targets?: NativeTarget[];
         optional?: boolean;
     }
    @@ -100,14 +102,14 @@ declare function inspectNativeCapabilities(target?: NativeTarget): Array<
     }>;
     declare function missingNativeCapabilities(manifest: NativeCapabilityManifest, target?: NativeTarget): NativeCapabilityManifestEntry[];
     interface PermissionAdapter {
    -    query(name: string): Promise<"granted" | "denied" | "prompt" | "unavailable">;
    -    request?(name: string): Promise<"granted" | "denied">;
    +    query(name: NativePermission): Promise<"granted" | "denied" | "prompt" | "unavailable">;
    +    request?(name: NativePermission): Promise<"granted" | "denied">;
     }
     declare class PermissionManager {
         private readonly adapter;
         constructor(adapter: PermissionAdapter);
    -    query(name: string): Promise<"denied" | "granted" | "prompt" | "unavailable">;
    -    ensure(name: string): Promise<boolean>;
    +    query(name: NativePermission): Promise<"denied" | "granted" | "prompt" | "unavailable">;
    +    ensure(name: NativePermission): Promise<boolean>;
     }
     
     declare const native: {
    @@ -119,7 +121,7 @@ declare const native: {
         supports: typeof supports;
     };
     
    -export { NativeCapability, type NativeCapabilityManifest, type NativeCapabilityManifestEntry, NativePlatform, NativeRunOptions, NativeTarget, NativeUnavailableError, type PermissionAdapter, PermissionManager, clearRegistry, defineNativeManifest, inspectNativeCapabilities, isMobile, missingNativeCapabilities, native, platform, register, registered, run, supports };
    +export { NativeCapability, type NativeCapabilityManifest, type NativeCapabilityManifestEntry, type NativePermission, NativePlatform, NativeRunOptions, NativeTarget, NativeUnavailableError, type PermissionAdapter, PermissionManager, clearRegistry, defineNativeManifest, inspectNativeCapabilities, isMobile, missingNativeCapabilities, native, platform, register, registered, run, supports };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Share a page when the platform supports it

    import { native } from "@wrnexus/native";
     
     export async function shareCurrentPage() {
    @@ -152,7 +154,7 @@ const position = await native.run(
     );
    - + } diff --git a/app/pages/packages/oauth.wrn b/app/pages/packages/oauth.wrn index 0578c820..376b2cac 100644 --- a/app/pages/packages/oauth.wrn +++ b/app/pages/packages/oauth.wrn @@ -10,11 +10,11 @@ page wrnexusoauth {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/oauth

    OAuth 2.0, PKCE, provider presets, and profile mapping.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/oauth@0.7.0

    Request preview access. Never put registry tokens in source control.

    Dependency-free OAuth 2.0 sign-in for any provider, with PKCE and presets for Google, GitHub, and Discord.
    +
    Security · Package reference

    @wrnexus/oauth

    OAuth 2.0, PKCE, provider presets, and profile mapping.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/oauth@0.8.0

    Request preview access. Never put registry tokens in source control.

    Dependency-free OAuth 2.0 sign-in for any provider, with PKCE and presets for Google, GitHub, and Discord.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/oauth implements the OAuth 2.0 Authorization Code flow (with PKCE) for server-side sign-in. It ships ready-made provider presets and a defineProvider helper for custom providers, then gives you two flow functions — startAuth (build the redirect) and completeAuth (exchange the code and fetch the user's profile). It has no runtime dependencies: it uses the platform fetch and WebCrypto only. Pairs naturally with @wrnexus/core's logIn to establish a session once you have a normalized profile.

    @@ -145,8 +145,23 @@ const gitlab = defineProvider({
  • The flow is stateless by design: you are responsible for storing state and
  • verifier between startAuth and completeAuth (session or signed cookie).

  • Pairs with [@wrnexus/core](../core) — feed the normalized OAuthProfile into
  • -

    logIn to establish a session.

    -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface OAuthStateRecord {
    +

    logIn to establish a session. OIDC integrations can combine strict discovery with the rotating JWKS verifier:

    + +
    import { createRemoteJwks } from "@wrnexus/jwt";
    +import { discoverOidc, verifyOidcIdToken } from "@wrnexus/oauth";
    +
    +const metadata = await discoverOidc("https://issuer.example");
    +const jwks = createRemoteJwks(metadata.jwks_uri);
    +const claims = await verifyOidcIdToken(idToken, {
    +  issuer: metadata.issuer,
    +  clientId: "client-id",
    +  jwks,
    +  nonce: expectedNonce,
    +  accessToken,
    +});
    +

    Discovery requires an exact normalized issuer and HTTPS endpoints without URL credentials/fragments. ID-token verification checks the RS256 signature, expiry/not-before, issuer, audience, required OIDC claims, nonce, multi-audience azp, optional token age, and optional at_hash binding.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { JwtClaims, RemoteJwks } from '@wrnexus/jwt';
    +
    +interface OAuthStateRecord {
         state: string;
         verifier: string;
         redirectUri: string;
    @@ -171,6 +186,28 @@ interface OidcDiscovery {
         revocation_endpoint?: string;
     }
     declare function discoverOidc(issuer: string, fetchImpl?: typeof fetch): Promise<OidcDiscovery>;
    +interface OidcIdTokenClaims extends JwtClaims {
    +    sub: string;
    +    iss: string;
    +    aud: string | string[];
    +    exp: number;
    +    iat: number;
    +    nonce?: string;
    +    azp?: string;
    +    at_hash?: string;
    +}
    +interface VerifyOidcIdTokenOptions {
    +    issuer: string;
    +    clientId: string;
    +    jwks: RemoteJwks;
    +    nonce?: string;
    +    accessToken?: string;
    +    now?: number;
    +    clockTolerance?: number;
    +    maxAge?: number;
    +}
    +declare function validateOidcClaims(claims: JwtClaims, options: Pick<VerifyOidcIdTokenOptions, "clientId" | "nonce">): asserts claims is OidcIdTokenClaims;
    +declare function verifyOidcIdToken(token: string, options: VerifyOidcIdTokenOptions): Promise<OidcIdTokenClaims>;
     declare function validateOAuthReturnTo(value: string | undefined, origin: string, fallback?: string): string;
     
     /**
    @@ -262,7 +299,7 @@ declare function exchangeCode(provider: OAuthProvider, options: CompleteAuthOpti
     /** Fetch + normalize the user's profile from the provider. */
     declare function fetchProfile(provider: OAuthProvider, tokens: OAuthTokens, fetchImpl?: FetchLike): Promise<OAuthProfile>;
     
    -export { type CompleteAuthOptions, type OAuthProfile, type OAuthProvider, type OAuthStateRecord, type OAuthStateStore, type OAuthTokens, type OidcDiscovery, type ProviderCredentials, type StartAuthOptions, type StartAuthResult, completeAuth, createOAuthState, defineProvider, discord, discoverOidc, exchangeCode, fetchProfile, github, google, memoryOAuthStateStore, randomToken, refreshOAuthTokens, startAuth, validateOAuthReturnTo };
    +export { type CompleteAuthOptions, type OAuthProfile, type OAuthProvider, type OAuthStateRecord, type OAuthStateStore, type OAuthTokens, type OidcDiscovery, type OidcIdTokenClaims, type ProviderCredentials, type StartAuthOptions, type StartAuthResult, type VerifyOidcIdTokenOptions, completeAuth, createOAuthState, defineProvider, discord, discoverOidc, exchangeCode, fetchProfile, github, google, memoryOAuthStateStore, randomToken, refreshOAuthTokens, startAuth, validateOAuthReturnTo, validateOidcClaims, verifyOidcIdToken };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Typical usage

    import { google, startAuth, completeAuth } from "@wrnexus/oauth";
     import { logIn } from "@wrnexus/core";
     
    @@ -313,7 +350,7 @@ const gitlab = defineProvider({
     });
    - + } diff --git a/app/pages/packages/observability.wrn b/app/pages/packages/observability.wrn new file mode 100644 index 00000000..c5e39c8d --- /dev/null +++ b/app/pages/packages/observability.wrn @@ -0,0 +1,133 @@ +page wrnexusobservability { + seo { + title = "@wrnexus/observability" + description = "Structured logging, tracing, health, and integration adapters." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Runtime · Package reference

    @wrnexus/observability

    Structured logging, tracing, health, and integration adapters.

    v0.8.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/observability@0.8.0

    Request preview access. Never put registry tokens in source control.

    Open-standard traces, metrics, logs, health checks, Web Vitals, error reporting and profiling.

    +

    Use createOperationTracer() for database, cache, queue, realtime, server-action or custom application spans. Export through OTLP, Prometheus, Zipkin/Jaeger, or the Sentry-compatible error reporter; Grafana can consume the Prometheus or OTLP signals.

    +

    Privacy-conscious counters, gauges, histograms, HTTP middleware, Web Vitals ingestion, browser collection, and exporter adapters. Request bodies and user identifiers are not collected by default.

    +
    export default {
    +  observability: { enabled: true, serverTiming: true, sampleRate: 0.1, webVitals: true },
    +};
    +

    Traces, correlated logs, and OTLP

    +
    import {
    +  createOtlpMetricExporter,
    +  createOtlpTraceExporter,
    +  createStructuredLogger,
    +  metricsMiddleware,
    +  traceMiddleware,
    +} from "@wrnexus/observability";
    +
    +const traces = createOtlpTraceExporter("https://collector.example/v1/traces", {
    +  serviceName: "checkout",
    +  headers: { authorization: `Bearer ${process.env.OTLP_TOKEN}` },
    +});
    +
    +export const tracing = traceMiddleware({
    +  serviceName: "checkout",
    +  sampleRate: 0.1,
    +  exporter: traces,
    +  onExportError(error) {
    +    console.error("trace export failed", error);
    +  },
    +});
    +
    +export const metrics = metricsMiddleware();
    +export const metricExporter = createOtlpMetricExporter("https://collector.example/v1/metrics", {
    +  serviceName: "checkout",
    +});
    +
    +export const logger = createStructuredLogger({ service: "checkout" });
    +// Request middleware can create a correlated child from ctx.locals.
    +logger
    +  .child({
    +    traceId: ctx.locals.traceId,
    +    spanId: ctx.locals.spanId,
    +    requestId: ctx.locals.requestId,
    +  })
    +  .info("order accepted", { orderId });
    +

    The tracing middleware accepts and validates W3C traceparent, creates a child server span, stores correlation identifiers in ctx.locals, installs the framework tracer on ctx.tracer, and returns traceparent plus x-request-id. Export failures are isolated from application responses when onExportError is configured.

    +

    Liveness and readiness

    +
    import { HealthRegistry } from "@wrnexus/core";
    +import { createLivenessHandler, createReadinessHandler } from "@wrnexus/observability";
    +
    +const health = new HealthRegistry();
    +health.register("database", async () =>
    +  (await db.ping()) ? { status: "up" } : { status: "down" },
    +);
    +
    +export const live = createLivenessHandler();
    +export const ready = createReadinessHandler(health);
    +

    Liveness reports whether the process can answer requests. Readiness returns HTTP 503 when a registered dependency is down. Dependency messages and details are hidden unless exposeDetails: true is explicitly selected for a trusted endpoint.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { MetricLabels, MetricPoint, MetricsRegistry } from './metrics.js';
    +export { MetricExporter, MetricsMiddlewareOptions, WebVitalRecord, WebVitalsHandlerOptions, createHttpMetricExporter, createOtlpMetricExporter, createWebVitalsHandler, defaultMetrics, metricsMiddleware } from './server.js';
    +export { WebVitalsClientOptions, webVitalsClient } from './client.js';
    +export { SpanExporter, SpanRecord, TraceContext, TraceMiddlewareOptions, createOtlpTraceExporter, formatTraceparent, parseTraceparent, traceMiddleware } from './trace.js';
    +export { HealthHandlerOptions, createLivenessHandler, createReadinessHandler } from './health.js';
    +export { LogLevel, LogRecord, StructuredLogger, StructuredLoggerOptions, createStructuredLogger } from './logging.js';
    +export { ErrorReporter, FrameworkSpanKind, LogExporter, OperationTracer, createJaegerExporter, createOperationTracer, createOtlpLogExporter, createPerformanceProfiler, createPrometheusPushExporter, createSentryCompatibleReporter, createZipkinExporter, renderPrometheus } from './integrations.js';
    +import '@wrnexus/core';
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Privacy-conscious counters, gauges, histograms, HTTP middleware, Web Vitals ingestion, browser collection, and exporter adapters. Request bodies and user identifiers are not collected by default.

    export default {
    +  observability: { enabled: true, serverTiming: true, sampleRate: 0.1, webVitals: true },
    +};

    ## Traces, correlated logs, and OTLP

    import {
    +  createOtlpMetricExporter,
    +  createOtlpTraceExporter,
    +  createStructuredLogger,
    +  metricsMiddleware,
    +  traceMiddleware,
    +} from "@wrnexus/observability";
    +
    +const traces = createOtlpTraceExporter("https://collector.example/v1/traces", {
    +  serviceName: "checkout",
    +  headers: { authorization: `Bearer ${process.env.OTLP_TOKEN}` },
    +});
    +
    +export const tracing = traceMiddleware({
    +  serviceName: "checkout",
    +  sampleRate: 0.1,
    +  exporter: traces,
    +  onExportError(error) {
    +    console.error("trace export failed", error);
    +  },
    +});
    +
    +export const metrics = metricsMiddleware();
    +export const metricExporter = createOtlpMetricExporter("https://collector.example/v1/metrics", {
    +  serviceName: "checkout",
    +});
    +
    +export const logger = createStructuredLogger({ service: "checkout" });
    +// Request middleware can create a correlated child from ctx.locals.
    +logger
    +  .child({
    +    traceId: ctx.locals.traceId,
    +    spanId: ctx.locals.spanId,
    +    requestId: ctx.locals.requestId,
    +  })
    +  .info("order accepted", { orderId });

    ## Liveness and readiness

    import { HealthRegistry } from "@wrnexus/core";
    +import { createLivenessHandler, createReadinessHandler } from "@wrnexus/observability";
    +
    +const health = new HealthRegistry();
    +health.register("database", async () =>
    +  (await db.ping()) ? { status: "up" } : { status: "down" },
    +);
    +
    +export const live = createLivenessHandler();
    +export const ready = createReadinessHandler(health);
    + +
    + + +
    + } +} diff --git a/app/pages/packages/playground.wrn b/app/pages/packages/playground.wrn new file mode 100644 index 00000000..c46f6257 --- /dev/null +++ b/app/pages/packages/playground.wrn @@ -0,0 +1,66 @@ +page wrnexusplayground { + seo { + title = "@wrnexus/playground" + description = "Interactive framework examples and executable playground utilities." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Tooling · Package reference

    @wrnexus/playground

    Interactive framework examples and executable playground utilities.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/playground@0.8.0

    Request preview access. Never put registry tokens in source control.

    A deployable, shareable .wrn playground with diagnostics, generated JavaScript, safe SSR-shaped HTML, sandboxed preview, reactive/UI examples, and version adapters.

    +

    Run wrnexus playground, or deploy createPlaygroundHandler().

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface PlaygroundCompilation {
    +    source: string;
    +    generated: string;
    +    client: string;
    +    html: string;
    +    interactiveHtml: string;
    +    diagnostics: Array<{
    +        code: string;
    +        message: string;
    +        severity: string;
    +    }>;
    +    version: string;
    +}
    +interface PlaygroundVersionAdapter {
    +    version: string;
    +    compile(source: string): Promise<Omit<PlaygroundCompilation, "source" | "version">>;
    +}
    +declare function compilePlayground(source: string, version?: string): PlaygroundCompilation;
    +declare function encodePlaygroundShare(source: string): string;
    +declare function decodePlaygroundShare(value: string): string;
    +declare function comparePlaygroundVersions(source: string, adapters: PlaygroundVersionAdapter[]): Promise<{
    +    current: PlaygroundCompilation;
    +    comparisons: {
    +        generated: string;
    +        client: string;
    +        html: string;
    +        interactiveHtml: string;
    +        diagnostics: Array<{
    +            code: string;
    +            message: string;
    +            severity: string;
    +        }>;
    +        version: string;
    +    }[];
    +}>;
    +declare function createPlaygroundHandler(options?: {
    +    versions?: PlaygroundVersionAdapter[];
    +    examples?: Record<string, string>;
    +}): (request: Request) => Promise<Response>;
    +
    +export { type PlaygroundCompilation, type PlaygroundVersionAdapter, comparePlaygroundVersions, compilePlayground, createPlaygroundHandler, decodePlaygroundShare, encodePlaygroundShare };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/playground

    bun add @wrnexus/playground

    Import @wrnexus/playground

    import * as playground from "@wrnexus/playground";
    + +
    + + +
    + } +} diff --git a/app/pages/packages/plugin.wrn b/app/pages/packages/plugin.wrn index e16b0120..6d16016a 100644 --- a/app/pages/packages/plugin.wrn +++ b/app/pages/packages/plugin.wrn @@ -10,17 +10,54 @@ page wrnexusplugin {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/plugin

    Plugin contracts, lifecycle hooks, composition, and framework integration.

    v0.7.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/plugin@0.7.0

    Request preview access. Never put registry tokens in source control.

    Deterministic WRNexusJS plugin contracts for configuration, AST/code transforms, diagnostics, development servers, production builds, and DevToolbar extensions.

    -

    Use definePlugin() and declare enforce, before, or after when ordering matters. Duplicate names and dependency cycles are rejected.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { PageAst, WrnDiagnostic } from '@wrnexus/syntax';
    -import { WrnexusPlugin, PluginInput, PluginContext, PluginRunner } from './types.js';
    -export { ClientRuntimeDefinition, ClientRuntimeInject, ClientRuntimeLoad, ClientRuntimeType, PackageAssetDefinition, PackageMigrationDefinition, PackagePluginManifest, PackageRouteDefinition, PackageStyleDefinition, PluginCommand, PluginContributions, PluginDevToolbarPanel, PluginOrder, TransformContext, WrnexusPackageManifest } from './types.js';
    +      
    Core · Package reference

    @wrnexus/plugin

    Plugin contracts, lifecycle hooks, composition, and framework integration.

    v0.8.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/plugin@0.8.0

    Request preview access. Never put registry tokens in source control.

    Least-privilege package permissions

    +

    Package manifests declare every framework capability they register:

    +
    {
    +  "wrnexus": {
    +    "permissions": ["routes", "migrations"],
    +    "routes": [{ "kind": "api", "path": "/api/example", "entry": "./route.ts" }]
    +  }
    +}
    +

    Applications can enable fail-closed grants:

    +
    export default {
    +  pluginPermissions: {
    +    enforce: true,
    +    grants: { "example-plugin": ["routes"] },
    +  },
    +};
    +

    Discovery rejects used-but-undeclared capabilities with WRN-PLUGIN-PERMISSION-UNDECLARED and ungranted capabilities with WRN-PLUGIN-PERMISSION-DENIED. Permissions cover components, browser runtime, assets, styles, routes, middleware, migrations, config, transforms, diagnostics/tooling, and server/build hooks.

    +

    Compatibility matrices

    +

    Manifests can add compatibility: { bunMin: "1.3.0", os: ["linux", "darwin"] } alongside runtimes and requires. Use testPluginCompatibility(manifest, targets) in a package test to exercise the complete support matrix. Runtime discovery enforces the same Bun minimum, OS, runtime, and capability declarations used by the test kit.

    +

    Deterministic WRNexusJS plugin contracts for configuration, AST/code transforms, diagnostics, development servers, production builds, and DevToolbar extensions.

    +

    Use definePlugin() and declare enforce, before, or after when ordering matters. Duplicate names and dependency cycles are rejected.

    +

    Complete lifecycle and contributions

    +

    Plugins may implement setup, configure, configResolved, transformAst, transformCode, diagnostics, routes, configureServer, buildStart, buildEnd, render, deploy, shutdown, and hmrUpdate. The runner preserves resolved plugin order for every hook and executes setup exactly once.

    +

    In addition to components, routes, middleware, assets, styles, runtimes, and migrations, plugins can contribute directives, cliCommands, virtualModules, deploymentAdapters, configSchemas, documentation, and typeDefinitions. Names are collision checked. Configuration schemas run after configuration resolution, CLI commands are callable as normal wrnexus commands, directives participate in AST transformation, and production builds materialize virtual modules and invoke matching contributed adapters.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { PageAst, WrnDiagnostic } from '@wrnexus/syntax';
    +import { WrnexusPackageManifest, WrnexusPlugin, PluginInput, PluginContext, PluginRunner } from './types.js';
    +export { ClientRuntimeDefinition, ClientRuntimeInject, ClientRuntimeLoad, ClientRuntimeType, PackageAssetDefinition, PackageMigrationDefinition, PackagePluginManifest, PackageRouteDefinition, PackageStyleDefinition, PluginCliCommand, PluginCommand, PluginConfigSchema, PluginContributions, PluginDeploymentAdapter, PluginDevToolbarPanel, PluginDirective, PluginOrder, PluginPermission, PluginVirtualModule, TransformContext } from './types.js';
     export { assertContributionId, contentTypeForPath, defaultClientRuntimePath, defaultPackageAssetPath, definePackageManifest, normalizeClientRuntime, normalizePackageAsset, validateStyleIds } from './manifest.js';
     export { DiscoverPluginOptions, discoverPlugins } from './discovery.js';
     
    +interface PluginCompatibilityTarget {
    +    runtime: "bun" | "node" | "edge" | "worker" | "service-worker" | "browser";
    +    version?: string;
    +    os?: "win32" | "linux" | "darwin" | string;
    +    capabilities?: readonly string[];
    +}
    +interface PluginCompatibilityResult {
    +    target: PluginCompatibilityTarget;
    +    ok: boolean;
    +    issues: Array<{
    +        code: "WRN-PLUGIN-MATRIX-RUNTIME" | "WRN-PLUGIN-MATRIX-VERSION" | "WRN-PLUGIN-MATRIX-OS" | "WRN-PLUGIN-MATRIX-CAPABILITY";
    +        message: string;
    +    }>;
    +}
    +declare function testPluginCompatibility(manifest: WrnexusPackageManifest, targets: readonly PluginCompatibilityTarget[]): PluginCompatibilityResult[];
    +
     declare function definePlugin(plugin: WrnexusPlugin): WrnexusPlugin;
     declare function flattenPlugins(input: PluginInput, output?: WrnexusPlugin[]): WrnexusPlugin[];
     
    @@ -28,18 +65,21 @@ declare function flattenPlugins(input: PluginInput, output?: WrnexusPlugin[]): W
     declare function resolvePlugins(input: PluginInput): WrnexusPlugin[];
     declare function createPluginRunner(input: PluginInput, context: PluginContext): PluginRunner;
     
    -export { PluginContext, PluginInput, PluginRunner, WrnexusPlugin, createPluginRunner, definePlugin, flattenPlugins, resolvePlugins };
    -

    Examples

    Copy-ready examples from the installed package documentation.

    Define an ordered plugin

    import { definePlugin } from "@wrnexus/plugin";
    -
    -export default definePlugin({
    -  name: "analytics",
    -  enforce: "post",
    -});

    Resolve plugin execution order

    import { resolvePlugins } from "@wrnexus/plugin";
    -
    -const ordered = resolvePlugins([corePlugin, analyticsPlugin]);
    - +export { type PluginCompatibilityResult, type PluginCompatibilityTarget, PluginContext, PluginInput, PluginRunner, WrnexusPackageManifest, WrnexusPlugin, createPluginRunner, definePlugin, flattenPlugins, resolvePlugins, testPluginCompatibility }; +

    Examples

    Copy-ready examples from the installed package documentation.

    Package manifests declare every framework capability they register

    {
    +  "wrnexus": {
    +    "permissions": ["routes", "migrations"],
    +    "routes": [{ "kind": "api", "path": "/api/example", "entry": "./route.ts" }]
    +  }
    +}

    Applications can enable fail-closed grants

    export default {
    +  pluginPermissions: {
    +    enforce: true,
    +    grants: { "example-plugin": ["routes"] },
    +  },
    +};
    +
    - + } diff --git a/app/pages/packages/pubsub.wrn b/app/pages/packages/pubsub.wrn index d6b2f08b..c5e6c441 100644 --- a/app/pages/packages/pubsub.wrn +++ b/app/pages/packages/pubsub.wrn @@ -10,11 +10,11 @@ page wrnexuspubsub {
    W WRNexusJS - +
    -
    Realtime · Package reference

    @wrnexus/pubsub

    In-process and Redis-backed publish/subscribe.

    v0.7.0Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pubsub@0.7.0

    Request preview access. Never put registry tokens in source control.

    Topic-based publish/subscribe with a pluggable driver — in-process by default, Redis for cross-process messaging.
    +
    Realtime · Package reference

    @wrnexus/pubsub

    In-process and Redis-backed publish/subscribe.

    v0.8.0Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pubsub@0.8.0

    Request preview access. Never put registry tokens in source control.

    Topic-based publish/subscribe with a pluggable driver — in-process by default, Redis for cross-process messaging.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/pubsub is a small server-side pub/sub bus. You publish messages to a topic and subscribe with topic patterns; handlers fire for matching topics. The default driver keeps everything in-process, and you can swap in the Redis driver (@wrnexus/pubsub/redis) to fan messages out across processes or hosts. It also backs @wrnexus/core's realtime bridge for horizontal scaling.

    @@ -27,12 +27,14 @@ page wrnexuspubsub {
    interface PubSub {
       publish<T = unknown>(topic: string, message: T): Promise<void>;
       subscribe<T = unknown>(pattern: string, handler: Handler<T>): () => void;
    +  close(): Promise<void>;
     }
     
     type Handler<T = unknown> = (message: T, topic: string) => void | Promise<void>;
      -
    • publish(topic, message) — resolves once the driver has dispatched the message.
    • +
    • publish(topic, message) — resolves once the driver and in-memory async handlers finish.
    • subscribe(pattern, handler) — returns an unsubscribe function.
    • +
    • close() — idempotently rejects new work, clears local subscriptions, and closes the driver.

    Pattern matching

    Subscription patterns match in three ways:

    @@ -49,13 +51,15 @@ type Handler<T = unknown> = (message: T, topic: string) => void | Promi }

    @wrnexus/pubsub/redisredisDriver(url?)

    A cross-process driver backed by Redis. It speaks RESP over a raw TCP socket via Bun.connect, so it adds no npm dependency. url defaults to $REDIS_URL, then redis://localhost:6379. The URL may carry a password and a database index (e.g. redis://:secret@host:6379/2).

    -
    function redisDriver(url?: string): PubSubDriver & { close(): void };
    +
    function redisDriver(url?: string, options?: RedisDriverOptions): PubSubDriver & { close(): void };
    • Exact topics use Redis SUBSCRIBE; wildcard patterns (ns:*, *) use
    • PSUBSCRIBE, whose glob semantics line up with this library's matching.

    • Messages are JSON-stringified on publish and JSON.parsed on receipt; a payload
    • that isn't valid JSON is delivered as the raw string.

    • close() tears down both the subscriber and publisher connections.
    • +
    • Lost sockets reconnect with bounded exponential backoff and active subscriptions
    • +

      are replayed. maxPending bounds unavailable-connection writes (default 1000); reconnectDelayMs and reconnectMaxDelayMs tune recovery (100ms/5000ms).

    RESP codec (internal)

    redis.ts uses a minimal RESP implementation exported from resp.ts (encodeCommand, parseReply, concat, and the RespValue type). These are implementation details of the Redis driver, not part of the public package entry.

    @@ -85,8 +89,8 @@ bus.subscribe("order:*", (msg, topic) => { await bus.publish("order:created", { id: 7 }); -// on shutdown -driver.close(); +// on shutdown (also closes the driver) +await bus.close();

    Requirements / Notes

    • Bun-only. The Redis driver depends on Bun.connect; it throws
    • @@ -139,17 +143,34 @@ type Handler<T = unknown> = (message: T, topic: string) => void | Promi interface PubSubDriver { publish(topic: string, message: unknown): void | Promise<void>; subscribe(pattern: string, handler: Handler): () => void; + close?(): void | Promise<void>; } interface PubSub { publish<T = unknown>(topic: string, message: T): Promise<void>; subscribe<T = unknown>(pattern: string, handler: Handler<T>): () => void; + /** Stop new work, remove subscriptions, and close the backing driver. */ + close(): Promise<void>; } /** In-process pub/sub driver (default). */ declare function memoryDriver(): PubSubDriver; /** Create a pub/sub bus over a driver (in-memory by default). */ declare function createPubSub(driver?: PubSubDriver): PubSub; -export { type Handler, type MessageEnvelope, PresenceChannel, type PresenceMember, type PubSub, type PubSubDriver, type ResilientPubSubOptions, createPubSub, createResilientPubSub, memoryDriver }; +interface NatsClient { + publish(subject: string, data: Uint8Array): void | Promise<void>; + subscribe(subject: string, handler: (data: Uint8Array, subject: string) => void): () => void; + close?(): void | Promise<void>; +} +declare function natsDriver(client: NatsClient): PubSubDriver; +interface KafkaClient { + publish(topic: string, value: string): void | Promise<void>; + subscribe(pattern: string, handler: (value: string, topic: string) => void): () => void; + close?(): void | Promise<void>; +} +/** Kafka adapter contract; consumer-group/rebalance policy remains owned by the selected client. */ +declare function kafkaDriver(client: KafkaClient): PubSubDriver; + +export { type Handler, type KafkaClient, type MessageEnvelope, type NatsClient, PresenceChannel, type PresenceMember, type PubSub, type PubSubDriver, type ResilientPubSubOptions, createPubSub, createResilientPubSub, kafkaDriver, memoryDriver, natsDriver };

    Examples

    Copy-ready examples from the installed package documentation.

    In-process (default)

    import { createPubSub } from "@wrnexus/pubsub";
     
     const bus = createPubSub();
    @@ -172,11 +193,11 @@ bus.subscribe("order:*", (msg, topic) => {
     
     await bus.publish("order:created", { id: 7 });
     
    -// on shutdown
    -driver.close();
    +// on shutdown (also closes the driver) +await bus.close();
    - + } diff --git a/app/pages/packages/pwa.wrn b/app/pages/packages/pwa.wrn new file mode 100644 index 00000000..d1a8d67f --- /dev/null +++ b/app/pages/packages/pwa.wrn @@ -0,0 +1,183 @@ +page wrnexuspwa { + seo { + title = "@wrnexus/pwa" + description = "Progressive Web App manifests, service workers, and offline strategies." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Frontend · Package reference

    @wrnexus/pwa

    Progressive Web App manifests, service workers, and offline strategies.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/pwa@0.8.0

    Request preview access. Never put registry tokens in source control.

    Official PWA primitives for manifests, service workers, offline pages and precaching, runtime caching, background synchronization, push notifications, install/update events, offline mutation stores, and conflict resolution. createOfflineQueue() accepts a durable IndexedDB-style store and retries requests with stable idempotency headers.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    interface IndexedDbMigration {
    +    version: number;
    +    migrate(db: IDBDatabase, transaction: IDBTransaction): void;
    +}
    +declare function openPwaDatabase(name: string, migrations: IndexedDbMigration[], factory?: IDBFactory): Promise<IDBDatabase>;
    +declare function indexedDbOfflineQueueStore(db: IDBDatabase, storeName?: string): OfflineQueueStore;
    +declare const offlineQueueMigration: IndexedDbMigration;
    +interface StoredPushSubscription {
    +    id: string;
    +    userId: string;
    +    endpoint: string;
    +    expirationTime?: number | null;
    +    keys: {
    +        p256dh: string;
    +        auth: string;
    +    };
    +    createdAt: number;
    +}
    +interface PushSubscriptionStore {
    +    put(value: StoredPushSubscription): Promise<void>;
    +    remove(id: string): Promise<void>;
    +    list(userId: string): Promise<StoredPushSubscription[]>;
    +}
    +declare function memoryPushSubscriptionStore(): PushSubscriptionStore;
    +interface PushSqlClient {
    +    query<T = Record<string, unknown>>(sql: string, parameters?: unknown[]): Promise<{
    +        rows: T[];
    +    }>;
    +}
    +declare function postgresPushSubscriptionStore(db: PushSqlClient): PushSubscriptionStore;
    +declare const POSTGRES_PUSH_SUBSCRIPTION_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_push_subscriptions (id text PRIMARY KEY,user_id text NOT NULL,endpoint text NOT NULL,expiration_time bigint,p256dh text NOT NULL,auth text NOT NULL,created_at bigint NOT NULL); CREATE INDEX IF NOT EXISTS wrnexus_push_user ON wrnexus_push_subscriptions (user_id);";
    +declare function createPushSubscriptionService(store: PushSubscriptionStore, options?: {
    +    now?: () => number;
    +    maxPerUser?: number;
    +}): {
    +    subscribe(userId: string, value: {
    +        endpoint: string;
    +        expirationTime?: number | null;
    +        keys: {
    +            p256dh: string;
    +            auth: string;
    +        };
    +    }): Promise<{
    +        keys: {
    +            p256dh: string;
    +            auth: string;
    +        };
    +        createdAt: number;
    +        endpoint: string;
    +        expirationTime?: number | null;
    +        id: string;
    +        userId: string;
    +    }>;
    +    unsubscribe: (id: string) => Promise<void>;
    +    list: (userId: string) => Promise<StoredPushSubscription[]>;
    +};
    +declare function renderOfflineQueueReview(items: OfflineMutation[], conflicts?: Array<{
    +    id: string;
    +    message: string;
    +}>): string;
    +declare const PWA_REVIEW_RUNTIME = "document.addEventListener(\"click\",event=>{const button=event.target.closest(\"[data-pwa-retry],[data-pwa-remove],[data-pwa-client],[data-pwa-server]\");if(!button)return;const action=button.hasAttribute(\"data-pwa-retry\")?\"retry\":button.hasAttribute(\"data-pwa-remove\")?\"remove\":button.hasAttribute(\"data-pwa-client\")?\"client\":\"server\";const id=button.getAttribute(\"data-pwa-\"+action);dispatchEvent(new CustomEvent(\"wrnexus:pwa-review\",{detail:{action,id}}))});";
    +
    +type RuntimeCacheStrategy = "network-first" | "cache-first" | "stale-while-revalidate";
    +interface RuntimeCacheRule {
    +    pattern: string;
    +    strategy: RuntimeCacheStrategy;
    +    cacheName?: string;
    +    methods?: string[];
    +}
    +interface ServiceWorkerOptions {
    +    cacheName?: string;
    +    offlineUrl?: string;
    +    startUrl?: string;
    +    cacheUrls?: string[];
    +    runtimeCaching?: RuntimeCacheRule[];
    +    backgroundSyncTag?: string;
    +}
    +interface WebManifestOptions {
    +    name: string;
    +    shortName?: string;
    +    description?: string;
    +    id?: string;
    +    startUrl?: string;
    +    scope?: string;
    +    display?: "standalone" | "fullscreen" | "minimal-ui" | "browser";
    +    themeColor?: string;
    +    backgroundColor?: string;
    +    icons?: Array<{
    +        src: string;
    +        sizes: string;
    +        type?: string;
    +        purpose?: string;
    +    }>;
    +    shortcuts?: unknown[];
    +    screenshots?: unknown[];
    +    categories?: string[];
    +    lang?: string;
    +}
    +declare function createWebManifest(options: WebManifestOptions): {
    +    id: string;
    +    name: string;
    +    short_name: string;
    +    description: string | undefined;
    +    start_url: string;
    +    scope: string;
    +    display: "standalone" | "fullscreen" | "minimal-ui" | "browser";
    +    theme_color: string;
    +    background_color: string;
    +    icons: {
    +        src: string;
    +        sizes: string;
    +        type?: string;
    +        purpose?: string;
    +    }[];
    +    shortcuts: unknown[];
    +    screenshots: unknown[];
    +    categories: string[];
    +    lang: string;
    +};
    +declare function generateServiceWorker(options?: ServiceWorkerOptions): string;
    +interface OfflineMutation<T = unknown> {
    +    id: string;
    +    createdAt: number;
    +    updatedAt: number;
    +    endpoint: string;
    +    method: string;
    +    payload: T;
    +    attempts: number;
    +}
    +interface OfflineQueueStore {
    +    list(): Promise<OfflineMutation[]>;
    +    put(item: OfflineMutation): Promise<void>;
    +    remove(id: string): Promise<void>;
    +}
    +declare function memoryOfflineQueueStore(): OfflineQueueStore;
    +type ConflictResolution<T> = {
    +    action: "client" | "server" | "merge";
    +    value: T;
    +};
    +declare function resolveOfflineConflict<T extends object>(client: T, server: T, strategy?: "client-wins" | "server-wins" | "last-write-wins" | ((client: T, server: T) => T)): ConflictResolution<T>;
    +declare function createOfflineQueue(options?: {
    +    store?: OfflineQueueStore;
    +    fetch?: (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
    +    maxItems?: number;
    +    now?: () => number;
    +}): {
    +    enqueue<T>(input: Omit<OfflineMutation<T>, "id" | "createdAt" | "updatedAt" | "attempts">): Promise<OfflineMutation<T>>;
    +    list: () => Promise<OfflineMutation<unknown>[]>;
    +    sync(): Promise<{
    +        id: string;
    +        ok: boolean;
    +        status?: number;
    +    }[]>;
    +    remove: (id: string) => Promise<void>;
    +};
    +declare function pwaClientRuntime(serviceWorkerUrl?: string): string;
    +declare function subscribeToPush(registration: ServiceWorkerRegistration, publicKey: Uint8Array): Promise<PushSubscription>;
    +
    +export { type ConflictResolution, type IndexedDbMigration, type OfflineMutation, type OfflineQueueStore, POSTGRES_PUSH_SUBSCRIPTION_SCHEMA, PWA_REVIEW_RUNTIME, type PushSqlClient, type PushSubscriptionStore, type RuntimeCacheRule, type RuntimeCacheStrategy, type ServiceWorkerOptions, type StoredPushSubscription, type WebManifestOptions, createOfflineQueue, createPushSubscriptionService, createWebManifest, generateServiceWorker, indexedDbOfflineQueueStore, memoryOfflineQueueStore, memoryPushSubscriptionStore, offlineQueueMigration, openPwaDatabase, postgresPushSubscriptionStore, pwaClientRuntime, renderOfflineQueueReview, resolveOfflineConflict, subscribeToPush };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/pwa

    bun add @wrnexus/pwa

    Import @wrnexus/pwa

    import * as pwa from "@wrnexus/pwa";
    + +
    + + +
    + } +} diff --git a/app/pages/packages/queue.wrn b/app/pages/packages/queue.wrn index a054b528..ef05e8a4 100644 --- a/app/pages/packages/queue.wrn +++ b/app/pages/packages/queue.wrn @@ -10,11 +10,11 @@ page wrnexusqueue {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/queue

    Background jobs with delay, concurrency, retry, and repetition.

    v0.7.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/queue@0.7.0

    Request preview access. Never put registry tokens in source control.

    A background job queue with delays, retries + exponential backoff, recurring jobs, and concurrent workers.
    +
    Data · Package reference

    @wrnexus/queue

    Background jobs with delay, concurrency, retry, and repetition.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/queue@0.8.0

    Request preview access. Never put registry tokens in source control.

    A background job queue with delays, retries + exponential backoff, recurring jobs, and concurrent workers.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/queue is a server-side in-process job queue. You register named workers, enqueue jobs (optionally delayed or recurring), and let the queue poll and run them on a timer — with per-job retry limits and doubling backoff between attempts. The default store lives in memory; the design allows a pluggable driver to back it with Redis/SQL for durability across restarts. Reach for it when you need to defer work (emails, webhooks, cleanup) off the request path without a heavyweight external broker. Tests can drive it deterministically via drain().

    @@ -29,18 +29,21 @@ page wrnexusqueue {

    QueueOptions

    -
    OptionTypeDefaultDescription
    maxAttemptsnumber3Default max attempts per job before it is dead-lettered.
    backoffMsnumber1000Base retry backoff in ms; doubles per attempt.
    pollMsnumber250Poll interval used once start() is called (ms).
    onFailed(job: Job, error: unknown) => voidCalled when a job exhausts its attempts.
    now() => numberDate.nowClock injection for deterministic tests.
    +maxAttemptsnumber3Default max attempts per job before it is dead-lettered.backoffMsnumber1000Base retry backoff in ms; doubles per attempt.pollMsnumber250Poll interval used once start() is called (ms).onFailed(job: Job, error: unknown) => void—Called when a job exhausts its attempts.concurrencynumberunlimitedMaximum jobs claimed by one drain() call.capacitynumberunlimitedMaximum queued plus active jobs before adds reject.now() => numberDate.nowClock injection for deterministic tests.

    Queue

    The object returned by createQueue.

    -
    MethodSignatureDescription
    addadd<T>(name, data: T, options?: AddOptions): Promise<Job<T>>Enqueue a job under a worker name. Returns the created job.
    processprocess<T>(name, handler: JobHandler<T>): voidRegister the worker that runs jobs of the given name.
    draindrain(now?: number): Promise<number>Run every job whose runAt ≤ now, once. Returns how many ran.
    startstart(): voidBegin polling every pollMs. No-op if already started.
    stopstop(): voidStop the poll timer.
    sizesize(): numberNumber of jobs currently queued.
    +addadd<T>(name, data: T, options?: AddOptions): Promise<Job<T>>Enqueue a job under a worker name. Returns the created job.processprocess<T>(name, handler: JobHandler<T>): voidRegister the worker that runs jobs of the given name.draindrain(now?: number): Promise<number>Run every job whose runAt ≤ now, once. Returns how many ran.startstart(): voidBegin polling every pollMs. No-op if already started.stopstop(): voidStop the poll timer.shutdownshutdown({ force? }): Promise<void>Stop accepting jobs and await active work; force aborts it.sizesize(): numberNumber of jobs currently queued.get/listget(id) / list(name?)Inspect defensive copies of pending jobs.cancelcancel(id): booleanRemove queued work or abort an active handler.failedfailed(): Job[]Inspect exhausted jobs in the dead-letter collection.retryretry(id): Promise<boolean>Reset and requeue a dead-lettered job.

    AddOptions

    -
    OptionTypeDescription
    delayMsnumberDelay before the job becomes runnable (ms).
    maxAttemptsnumberMax attempts before dead-lettering. Defaults to the queue's maxAttempts.
    repeatnumberRe-enqueue this job this many ms after each successful run (recurring).
    +delayMsnumberDelay before the job becomes runnable (ms).maxAttemptsnumberMax attempts before dead-lettering. Defaults to the queue's maxAttempts.repeatnumberRe-enqueue this job this many ms after each successful run (recurring).prioritynumberHigher values are selected first among due jobs.idempotencyKeystringReturn the matching pending job instead of enqueueing a duplicate.

    JobHandler<T>

    -
    type JobHandler<T = unknown> = (job: Job<T>) => void | Promise<void>;
    +
    type JobHandler<T = unknown> = (
    +  job: Job<T>,
    +  context: { signal: AbortSignal },
    +) => void | Promise<void>;

    Job<T>

    interface Job<T = unknown> {
       id: string; // e.g. "job_1"
    @@ -66,6 +69,9 @@ queue.process<{ to: string }>("email", async (job) =&g
     await queue.add("email", { to: "a@b.com" }, { delayMs: 5000, maxAttempts: 3 });
     
     queue.start(); // begin polling; queue.stop() to halt
    +

    Use context.signal in network/database calls so forced shutdown and active cancellation finish promptly. For process termination, prefer await queue.shutdown(); use { force: true } only after your grace period.

    +

    Durable queue

    +

    createDurableQueue({ store }) retains jobs until their handler succeeds and supports atomic leases when a driver implements QueueStore.claim. It exposes the same cancellation/shutdown behavior plus list, failed, and retry. The included memoryQueueStore() is useful for tests; production Redis/SQL drivers should make claim() atomic to prevent two workers executing one job.

    Recurring jobs

    Pass repeat to re-enqueue a job a fixed interval after each successful run:

    queue.process("heartbeat", async () => ping());
    @@ -89,6 +95,20 @@ await queue.add("task", {}, { delayMs: 5000 });
     
     clock = 5000;
     const ran = await queue.drain(); // => 1
    +

    Durable workflows and approvals

    +

    createWorkflowEngine(store) executes dependency-ordered steps and persists every transition, result, progress update, failure, cancellation, and approval record. Approval steps pause safely and can resume after a process restart because the snapshot lives in the supplied WorkflowStore.

    +
    const workflow = defineDurableWorkflow({
    +  name: "publish-report",
    +  steps: [
    +    { name: "build", run: buildReport },
    +    { name: "approve", dependsOn: ["build"], approval: true, run: (report) => report },
    +    { name: "publish", dependsOn: ["approve"], run: publishReport },
    +  ],
    +});
    +
    +const run = await engine.start(workflow, input);
    +await engine.approve(workflow, run.id, "approve", currentUser.id);
    +

    Use memoryWorkflowStore() for tests. Production stores implement the small get, put, and list contract using the same transactional database or durable service as the application.

    Retry & backoff behavior

    • On a thrown handler error, the job is retried while attempts < maxAttempts.
    • @@ -105,7 +125,9 @@ const ran = await queue.drain(); // => 1
    • The default store is in-process, so queued jobs do not survive a restart; a
    • pluggable driver is intended for backing it with Redis/SQL for durability.

    • Works alongside @wrnexus/core for offloading work from the request path.
    • -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    /**
    +

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { ExecutionContext } from '@wrnexus/core';
    +
    +/**
      * Persistence contract for the durable queue.
      *
      * Distributed drivers should implement `claim()` atomically and exclude leased
    @@ -126,20 +148,142 @@ interface DurableQueueOptions {
         workerId?: string;
         maxAttempts?: number;
         concurrency?: number;
    +    capacity?: number;
         leaseMs?: number;
         backoff?: (attempt: number) => number;
         now?: () => number;
         onDeadLetter?: (job: Job, error: unknown) => void | Promise<void>;
    +    context?: (job: Job, signal: AbortSignal) => ExecutionContext;
     }
     interface DurableQueue {
         add<T>(name: string, data: T, options?: AddOptions): Promise<Job<T>>;
         process<T>(name: string, handler: JobHandler<T>): void;
         drain(): Promise<number>;
    +    cancel(id: string): Promise<boolean>;
    +    shutdown(options?: {
    +        force?: boolean;
    +    }): Promise<void>;
    +    list(name?: string): Promise<Job[]>;
         failed(): Job[];
         retry(id: string): Promise<boolean>;
     }
     declare function createDurableQueue(options?: DurableQueueOptions): DurableQueue;
     
    +interface RedisQueueClient {
    +    get(key: string): Promise<string | null>;
    +    set(key: string, value: string, options?: {
    +        NX?: boolean;
    +        PX?: number;
    +    }): Promise<unknown>;
    +    del(...keys: string[]): Promise<unknown>;
    +    zadd(key: string, score: number, member: string): Promise<unknown>;
    +    zrem(key: string, member: string): Promise<unknown>;
    +    zrangebyscore(key: string, min: number, max: number, options?: {
    +        limit: [number, number];
    +    }): Promise<string[]>;
    +    smembers(key: string): Promise<string[]>;
    +    sadd(key: string, member: string): Promise<unknown>;
    +    srem(key: string, member: string): Promise<unknown>;
    +}
    +/** Redis-backed queue store using only the common client command surface. */
    +declare function redisQueueStore(client: RedisQueueClient, prefix?: string): QueueStore;
    +interface SqlQueueClient {
    +    query<T = Record<string, unknown>>(sql: string, parameters?: unknown[]): Promise<{
    +        rows: T[];
    +    }>;
    +}
    +/** PostgreSQL store with atomic SKIP LOCKED leasing and JSON payloads. */
    +declare function postgresQueueStore(db: SqlQueueClient, table?: string): QueueStore;
    +declare const POSTGRES_QUEUE_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_jobs (\n  id text PRIMARY KEY, name text NOT NULL, payload jsonb NOT NULL, run_at bigint NOT NULL,\n  priority integer NOT NULL DEFAULT 0, lease_owner text, lease_until bigint\n); CREATE INDEX IF NOT EXISTS wrnexus_jobs_due ON wrnexus_jobs (run_at, priority DESC);";
    +
    +interface ScheduledJob<T = unknown> {
    +    name: string;
    +    data: T;
    +    everyMs: number;
    +    options?: AddOptions;
    +}
    +interface QueueScheduler {
    +    start(): void;
    +    stop(): void;
    +    tick(now?: number): Promise<number>;
    +    snapshot(): {
    +        running: boolean;
    +        schedules: number;
    +        nextRuns: Record<string, number>;
    +    };
    +}
    +/** Restart-safe scheduler when used with a durable queue and stable idempotency buckets. */
    +declare function createQueueScheduler(queue: DurableQueue, schedules: ScheduledJob[], options?: {
    +    pollMs?: number;
    +    now?: () => number;
    +}): QueueScheduler;
    +declare function addBatch<T>(queue: DurableQueue, name: string, values: T[], options?: AddOptions): Promise<Job<T>[]>;
    +interface QueueDashboardSnapshot {
    +    generatedAt: number;
    +    pending: number;
    +    failed: number;
    +    byName: Record<string, number>;
    +    oldestRunAt?: number;
    +}
    +declare function queueDashboardSnapshot(queue: DurableQueue): Promise<QueueDashboardSnapshot>;
    +declare function renderQueueDashboard(snapshot: QueueDashboardSnapshot): string;
    +/** Long-running scheduler/worker loop suitable for a dedicated process or container. */
    +declare function runQueueDaemon(queue: DurableQueue, scheduler: QueueScheduler, options?: {
    +    signal?: AbortSignal;
    +    pollMs?: number;
    +    onError?: (error: unknown) => void;
    +}): Promise<void>;
    +
    +type WorkflowStatus = "pending" | "running" | "waiting-approval" | "completed" | "failed" | "cancelled";
    +interface WorkflowStep$1<I = unknown, O = unknown> {
    +    name: string;
    +    dependsOn?: string[];
    +    approval?: boolean;
    +    run(input: I, context: WorkflowRunContext): O | Promise<O>;
    +}
    +interface WorkflowRunContext {
    +    workflowId: string;
    +    step: string;
    +    results: Readonly<Record<string, unknown>>;
    +    signal: AbortSignal;
    +    progress(value: number, message?: string): void;
    +}
    +interface WorkflowSnapshot {
    +    id: string;
    +    name: string;
    +    status: WorkflowStatus;
    +    input: unknown;
    +    results: Record<string, unknown>;
    +    completed: string[];
    +    waitingFor?: string;
    +    progress: number;
    +    message?: string;
    +    error?: string;
    +    updatedAt: number;
    +}
    +interface WorkflowStore {
    +    get(id: string): Promise<WorkflowSnapshot | null>;
    +    put(snapshot: WorkflowSnapshot): Promise<void>;
    +    list(): Promise<WorkflowSnapshot[]>;
    +}
    +declare function memoryWorkflowStore(): WorkflowStore;
    +interface WorkflowDefinition<I = unknown> {
    +    name: string;
    +    steps: WorkflowStep$1<any, any>[];
    +    /** Compile-time input marker; definitions do not store runtime input values. */
    +    readonly __input?: I;
    +}
    +interface WorkflowEngine {
    +    start<I>(definition: WorkflowDefinition<I>, input: I, id?: string): Promise<WorkflowSnapshot>;
    +    resume<I>(definition: WorkflowDefinition<I>, id: string): Promise<WorkflowSnapshot>;
    +    approve<I>(definition: WorkflowDefinition<I>, id: string, step: string, actor: string): Promise<WorkflowSnapshot>;
    +    cancel(id: string): Promise<boolean>;
    +    get(id: string): Promise<WorkflowSnapshot | null>;
    +    list(): Promise<WorkflowSnapshot[]>;
    +}
    +declare function createWorkflowEngine(store?: WorkflowStore): WorkflowEngine;
    +declare function defineDurableWorkflow<I>(definition: WorkflowDefinition<I>): WorkflowDefinition<I>;
    +
     /**
      * @wrnexus/queue — a background job queue with delays, retries + backoff, and
      * concurrent workers. The default store is in-process; a pluggable driver lets
    @@ -165,7 +309,13 @@ interface Job<T = unknown> {
         idempotencyKey?: string;
         createdAt: number;
     }
    -type JobHandler<T = unknown> = (job: Job<T>) => void | Promise<void>;
    +interface JobContext {
    +    /** Aborted when an active job is cancelled or the queue is force-stopped. */
    +    signal: AbortSignal;
    +    /** The same trusted context shape used by HTTP, actions, realtime and webhooks. */
    +    execution: ExecutionContext;
    +}
    +type JobHandler<T = unknown> = (job: Job<T>, context: JobContext) => void | Promise<void>;
     interface AddOptions {
         /** Delay before the job becomes runnable (ms). */
         delayMs?: number;
    @@ -189,8 +339,11 @@ interface QueueOptions {
         onFailed?: (job: Job, error: unknown) => void;
         /** Maximum jobs executed in one drain. Default: unlimited. */
         concurrency?: number;
    +    /** Maximum queued + active jobs. Adds reject once this limit is reached. */
    +    capacity?: number;
         /** Clock injection (tests). Default Date.now. */
         now?: () => number;
    +    context?: (job: Job, signal: AbortSignal) => ExecutionContext;
     }
     interface Queue {
         add<T>(name: string, data: T, options?: AddOptions): Promise<Job<T>>;
    @@ -199,10 +352,16 @@ interface Queue {
         drain(now?: number): Promise<number>;
         start(): void;
         stop(): void;
    +    /** Stop accepting work and wait for active handlers (or abort them). */
    +    shutdown(options?: {
    +        force?: boolean;
    +    }): Promise<void>;
         size(): number;
         get(id: string): Job | undefined;
         list(name?: string): Job[];
         cancel(id: string): boolean;
    +    failed(): Job[];
    +    retry(id: string): Promise<boolean>;
     }
     interface JobDefinition<I> {
         name: string;
    @@ -222,7 +381,7 @@ declare function defineWorkflow<T>(name: string, steps: Array<WorkflowS
     declare function cronToInterval(cron: string): number;
     declare function createQueue(options?: QueueOptions): Queue;
     
    -export { type AddOptions, type DurableQueue, type DurableQueueOptions, type Job, type JobDefinition, type JobHandler, type Queue, type QueueOptions, type QueueStore, type WorkflowStep, createDurableQueue, createQueue, cronToInterval, defineJob, defineWorkflow, memoryQueueStore };
    +export { type AddOptions, type DurableQueue, type DurableQueueOptions, type Job, type JobContext, type JobDefinition, type JobHandler, POSTGRES_QUEUE_SCHEMA, type Queue, type QueueDashboardSnapshot, type QueueOptions, type QueueScheduler, type QueueStore, type RedisQueueClient, type ScheduledJob, type SqlQueueClient, type WorkflowDefinition, type WorkflowEngine, type WorkflowRunContext, type WorkflowSnapshot, type WorkflowStatus, type WorkflowStep, type WorkflowStore, addBatch, createDurableQueue, createQueue, createQueueScheduler, createWorkflowEngine, cronToInterval, defineDurableWorkflow, defineJob, defineWorkflow, memoryQueueStore, memoryWorkflowStore, postgresQueueStore, queueDashboardSnapshot, redisQueueStore, renderQueueDashboard, runQueueDaemon };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Register workers, enqueue jobs, then start the poller

    import { createQueue } from "@wrnexus/queue";
     
     const queue = createQueue({ maxAttempts: 3, backoffMs: 1000 });
    @@ -249,10 +408,20 @@ queue.process("task", async () => {
     await queue.add("task", {}, { delayMs: 5000 });
     
     clock = 5000;
    -const ran = await queue.drain(); // => 1
    - +const ran = await queue.drain(); // => 1

    Durable workflows and approvals

    const workflow = defineDurableWorkflow({
    +  name: "publish-report",
    +  steps: [
    +    { name: "build", run: buildReport },
    +    { name: "approve", dependsOn: ["build"], approval: true, run: (report) => report },
    +    { name: "publish", dependsOn: ["approve"], run: publishReport },
    +  ],
    +});
    +
    +const run = await engine.start(workflow, input);
    +await engine.approve(workflow, run.id, "approve", currentUser.id);
    +
    - + } diff --git a/app/pages/packages/reactive.wrn b/app/pages/packages/reactive.wrn index f153e5e6..6baa7806 100644 --- a/app/pages/packages/reactive.wrn +++ b/app/pages/packages/reactive.wrn @@ -10,11 +10,11 @@ page wrnexusreactive {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/reactive

    Small type-safe reactive signal primitives.

    v0.7.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/reactive@0.7.0

    Request preview access. Never put registry tokens in source control.

    Tiny, type-safe reactive primitives (signals) with zero dependencies.
    +
    Frontend · Package reference

    @wrnexus/reactive

    Small type-safe reactive signal primitives.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/reactive@0.8.0

    Request preview access. Never put registry tokens in source control.

    Tiny, type-safe reactive primitives (signals) with zero dependencies.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/reactive is the seed of WRNexusJS's reactivity layer: a minimal signal primitive that holds a value, notifies subscribers when it changes, and hands back an unsubscribe function. It is deliberately small and framework-agnostic — it powers nothing on its own, but is shaped so client islands (and later the .wrn compiler's state blocks) can build reactive bindings on top of it. Reach for it when you need observable state without pulling in a full reactivity library.

    @@ -133,7 +133,57 @@ interface ReactiveScope { } declare function createScope(): ReactiveScope; -export { type Cleanup, type ReactiveScope, type ReadonlySignal, type Resource, type ResourceOptions, type ResourceStatus, type Signal, type Subscriber, type Unsubscribe, type WatchOptions, batch, computed, createScope, effect, resource, signal, untrack, watch }; +interface HistorySignal<T> extends Signal<T> { + undo(): boolean; + redo(): boolean; + canUndo(): boolean; + canRedo(): boolean; + clearHistory(): void; +} +declare function historySignal<T>(initial: T, options?: { + limit?: number; + equals?: (left: T, right: T) => boolean; +}): HistorySignal<T>; +interface UrlStateOptions<T> { + url?: URL; + parameter: string; + parse?: (value: string | null) => T; + serialize?: (value: T) => string | null; + replace?: (url: URL) => void; +} +declare function urlSignal<T>(initial: T, options: UrlStateOptions<T>): Signal<T>; +interface ReactiveContext<T> { + provide<R>(value: T, run: () => R): R; + use(): T; +} +declare function createContextProvider<T>(defaultValue?: T): ReactiveContext<T>; +declare function mountPortal(content: Node | string, target: Element): () => void; +declare function transition(update: () => void, options?: { + className?: string; + target?: Element; + durationMs?: number; + signal?: AbortSignal; +}): Promise<void>; +interface TimelineStep { + durationMs: number; + delayMs?: number; + easing?: (progress: number) => number; + update(progress: number): void; +} +interface AnimationTimeline { + play(options?: { + reverse?: boolean; + signal?: AbortSignal; + }): Promise<void>; + cancel(reason?: unknown): void; + readonly running: boolean; +} +declare function createTimeline(steps: TimelineStep[], options?: { + now?: () => number; + frame?: (callback: () => void) => unknown; +}): AnimationTimeline; + +export { type AnimationTimeline, type Cleanup, type HistorySignal, type ReactiveContext, type ReactiveScope, type ReadonlySignal, type Resource, type ResourceOptions, type ResourceStatus, type Signal, type Subscriber, type TimelineStep, type Unsubscribe, type UrlStateOptions, type WatchOptions, batch, computed, createContextProvider, createScope, createTimeline, effect, historySignal, mountPortal, resource, signal, transition, untrack, urlSignal, watch };

    Examples

    Copy-ready examples from the installed package documentation.

    Typical usage

    import { signal } from "@wrnexus/reactive";
     
     const count = signal(0);
    @@ -156,7 +206,7 @@ const user: Signal<{ name: string } | null> = signal(null);
     user.set({ name: "Ada" });
    - + } diff --git a/app/pages/packages/realtime.wrn b/app/pages/packages/realtime.wrn new file mode 100644 index 00000000..013c7e64 --- /dev/null +++ b/app/pages/packages/realtime.wrn @@ -0,0 +1,274 @@ +page wrnexusrealtime { + seo { + title = "@wrnexus/realtime" + description = "Rooms, presence, messaging, history, streams, and UI components." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Realtime · Package reference

    @wrnexus/realtime

    Rooms, presence, messaging, history, streams, and UI components.

    v0.8.0Private registryRealtime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/realtime@0.8.0

    Request preview access. Never put registry tokens in source control.

    Typed rooms, secure message envelopes, browser room helpers, presence utilities, and complete realtime UI blocks for WRNexusJS.

    +

    Server rooms

    +
    import { defineRoom } from "@wrnexus/realtime";
    +
    +export default defineRoom("support", {
    +  async authorize(context) {
    +    return Boolean(context.user);
    +  },
    +  message(client, message) {
    +    client.broadcast(message);
    +  },
    +});
    +

    The package re-exports the hardened realtime registry from @wrnexus/core, including authentication, origin checks, quotas, message-size limits, schema validation hooks, and room authorization.

    +

    Messages and browser helpers

    +
    import {
    +  createRealtimeMessage,
    +  createPresenceEvent,
    +  createTypingEvent,
    +  connectRoom,
    +  sendRoomMessage,
    +} from "@wrnexus/realtime";
    +
    +const room = connectRoom("support", { query: { ticket: "T-100" } });
    +sendRoomMessage(
    +  room,
    +  createRealtimeMessage({
    +    type: "message",
    +    room: "support",
    +    data: { text: "Hello" },
    +  }),
    +);
    +

    Message IDs use Web Crypto. A runtime without secure randomness must provide an explicit message ID.

    +

    Components

    +

    Enable realtimePlugin() and use:

    +
      +
    • <RealtimeRoom />
    • +
    • <RealtimeMessageBubble />
    • +
    • <MessageComposer />
    • +
    • <RoomStatus />
    • +
    • <RoomMeta />
    • +
    • <PresenceList />
    • +
    • <TypingIndicator />
    • +
    +

    These package-owned blocks compose existing @wrnexus/ui components such as Card, Alert, Avatar, Badge, Button, Input, and ChatBubble.

    +

    Incoming messages can be bounded and constrained:

    +
    const message = parseRealtimeMessage(rawMessage, {
    +  maxBytes: 64 * 1024,
    +  maxDepth: 12,
    +  allowedTypes: ["message", "typing", "presence"],
    +  room: "support",
    +});
    +

    The parser rejects oversized payloads, circular/unsupported values, unsafe object keys, invalid message types, invalid room names, and room mismatches.

    +

    Replay, acknowledgements, SSE, and monitoring

    +

    createRealtimeHistory() keeps a bounded sequenced log per room. Clients acknowledge a sequence and resume(room, clientId) returns only missed events. A snapshot exposes room, message, acknowledgement, and sequence counts for monitoring without exposing payloads.

    +
    const history = createRealtimeHistory({ limitPerRoom: 100 });
    +const entry = history.publish("support", message);
    +history.acknowledge("support", clientId, entry.sequence);
    +const missed = history.resume("support", clientId);
    +

    realtimeSseResponse(stream, signal) converts the same sequenced envelope into standards-based Server-Sent Events with event IDs, event types, JSON data, cancellation, and no-cache headers.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { RawSocket, RealtimeBridge, RealtimeBus, RealtimeConnectMeta, RealtimeEnvelope, RealtimeHandler, RealtimeRegistry, RealtimeRegistryOptions, RealtimeSecurityOptions, RealtimeSocket, Room, RoomAuthInfo, RoomClient, RoomDefinition, RoomHandlers, Target, bridgeRealtime, createRealtimeRegistry, defineRoom, isRoomDefinition } from '@wrnexus/core';
    +export { RealtimePluginOptions, realtimeComponentsDir, default as realtimePlugin } from './plugin.js';
    +import '@wrnexus/plugin';
    +
    +type RealtimeMessageType = string;
    +interface RealtimeMessage<T = unknown> {
    +    id: string;
    +    type: RealtimeMessageType;
    +    room?: string;
    +    senderId?: string;
    +    senderName?: string;
    +    sentAt: string;
    +    data: T;
    +    meta?: Record<string, string | number | boolean | null>;
    +}
    +interface CreateRealtimeMessageOptions<T> {
    +    id?: string;
    +    type: string;
    +    room?: string;
    +    senderId?: string;
    +    senderName?: string;
    +    sentAt?: string | Date;
    +    data: T;
    +    meta?: Record<string, string | number | boolean | null>;
    +}
    +interface ParseRealtimeMessageOptions {
    +    maxBytes?: number;
    +    maxDepth?: number;
    +    allowedTypes?: readonly string[];
    +    room?: string;
    +}
    +interface RealtimePresence {
    +    userId: string;
    +    name?: string;
    +    avatar?: string;
    +    status?: "online" | "away" | "busy" | "offline";
    +    joinedAt?: string;
    +    lastSeenAt?: string;
    +    meta?: Record<string, string | number | boolean | null>;
    +}
    +interface RealtimeRoomMeta {
    +    id: string;
    +    name: string;
    +    description?: string;
    +    memberCount?: number;
    +    onlineCount?: number;
    +    createdAt?: string;
    +    updatedAt?: string;
    +    private?: boolean;
    +    tags?: string[];
    +}
    +declare function assertRealtimeRoomName(name: string): string;
    +declare function createRealtimeMessage<T>(options: CreateRealtimeMessageOptions<T>): RealtimeMessage<T>;
    +declare function isRealtimeMessage(value: unknown): value is RealtimeMessage;
    +declare function parseRealtimeMessage<T = unknown>(value: string | unknown, options?: ParseRealtimeMessageOptions): RealtimeMessage<T>;
    +declare function createPresenceEvent(action: "join" | "leave" | "update", presence: RealtimePresence, room?: string): RealtimeMessage<{
    +    action: "join" | "leave" | "update";
    +    presence: RealtimePresence;
    +}>;
    +declare function createTypingEvent(userId: string, typing: boolean, options?: {
    +    room?: string;
    +    name?: string;
    +}): RealtimeMessage<{
    +    userId: string;
    +    name?: string;
    +    typing: boolean;
    +}>;
    +declare function roomMemberSummary(members: readonly RealtimePresence[]): {
    +    total: number;
    +    online: number;
    +    away: number;
    +    busy: number;
    +};
    +
    +interface BrowserRoomConnection {
    +    readonly name: string;
    +    send(message: unknown): BrowserRoomConnection;
    +    on(type: string | ((message: unknown) => void), callback?: (message: unknown) => void): BrowserRoomConnection;
    +    close(): void;
    +}
    +interface WrnexusRealtimeWindow extends Window {
    +    wire?: {
    +        room?: (name: string, query?: string) => BrowserRoomConnection;
    +    };
    +}
    +declare function roomQuery(params: Record<string, string | number | boolean | null | undefined>): string;
    +declare function connectRoom(name: string, options?: {
    +    query?: Record<string, string | number | boolean | null | undefined>;
    +    window?: WrnexusRealtimeWindow;
    +}): BrowserRoomConnection;
    +declare function sendRoomMessage<T>(room: BrowserRoomConnection, message: RealtimeMessage<T> | T): BrowserRoomConnection;
    +
    +interface SequencedRealtimeMessage<T = unknown> {
    +    sequence: number;
    +    message: RealtimeMessage<T>;
    +}
    +interface RealtimeHistorySnapshot {
    +    rooms: number;
    +    messages: number;
    +    acknowledgements: number;
    +    oldestSequence?: number;
    +    latestSequence?: number;
    +}
    +interface RealtimeHistoryOptions {
    +    limitPerRoom?: number;
    +    maxClients?: number;
    +}
    +interface RealtimeHistory {
    +    publish<T>(room: string, message: RealtimeMessage<T>): SequencedRealtimeMessage<T>;
    +    replay(room: string, afterSequence?: number, limit?: number): SequencedRealtimeMessage[];
    +    acknowledge(room: string, clientId: string, sequence: number): void;
    +    acknowledged(room: string, clientId: string): number;
    +    resume(room: string, clientId: string, limit?: number): SequencedRealtimeMessage[];
    +    snapshot(): RealtimeHistorySnapshot;
    +    clear(room?: string): void;
    +}
    +declare function createRealtimeHistory(options?: RealtimeHistoryOptions): RealtimeHistory;
    +declare function createAcknowledgement(room: string, sequence: number, clientId: string): RealtimeMessage<{
    +    sequence: number;
    +    clientId: string;
    +}>;
    +declare function realtimeSseResponse(stream: ReadableStream<SequencedRealtimeMessage>, signal?: AbortSignal): Response;
    +
    +interface DatabaseChange<T = unknown> {
    +    table: string;
    +    operation: "insert" | "update" | "delete";
    +    key?: string | number;
    +    record?: T;
    +    occurredAt: number;
    +}
    +interface DatabaseChangeSource {
    +    subscribe(handler: (change: DatabaseChange) => void | Promise<void>): () => void;
    +}
    +declare function databaseChangeFeed(source: DatabaseChangeSource, publish: (topic: string, change: DatabaseChange) => void | Promise<void>, options?: {
    +    prefix?: string;
    +    allowTables?: string[];
    +}): () => void;
    +interface FileStreamFrame {
    +    streamId: string;
    +    index: number;
    +    total: number;
    +    bytes: Uint8Array;
    +}
    +declare function frameFileStream(streamId: string, bytes: Uint8Array, options?: {
    +    chunkBytes?: number;
    +    maxBytes?: number;
    +}): FileStreamFrame[];
    +declare function createFileStreamReceiver(options?: {
    +    maxBytes?: number;
    +    maxStreams?: number;
    +}): {
    +    accept(frame: FileStreamFrame): Uint8Array | null;
    +    snapshot: () => {
    +        activeStreams: number;
    +        bufferedBytes: number;
    +    };
    +};
    +
    +export { type BrowserRoomConnection, type CreateRealtimeMessageOptions, type DatabaseChange, type DatabaseChangeSource, type FileStreamFrame, type ParseRealtimeMessageOptions, type RealtimeHistory, type RealtimeHistoryOptions, type RealtimeHistorySnapshot, type RealtimeMessage, type RealtimeMessageType, type RealtimePresence, type RealtimeRoomMeta, type SequencedRealtimeMessage, type WrnexusRealtimeWindow, assertRealtimeRoomName, connectRoom, createAcknowledgement, createFileStreamReceiver, createPresenceEvent, createRealtimeHistory, createRealtimeMessage, createTypingEvent, databaseChangeFeed, frameFileStream, isRealtimeMessage, parseRealtimeMessage, realtimeSseResponse, roomMemberSummary, roomQuery, sendRoomMessage };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    ## Server rooms

    import { defineRoom } from "@wrnexus/realtime";
    +
    +export default defineRoom("support", {
    +  async authorize(context) {
    +    return Boolean(context.user);
    +  },
    +  message(client, message) {
    +    client.broadcast(message);
    +  },
    +});

    ## Messages and browser helpers

    import {
    +  createRealtimeMessage,
    +  createPresenceEvent,
    +  createTypingEvent,
    +  connectRoom,
    +  sendRoomMessage,
    +} from "@wrnexus/realtime";
    +
    +const room = connectRoom("support", { query: { ticket: "T-100" } });
    +sendRoomMessage(
    +  room,
    +  createRealtimeMessage({
    +    type: "message",
    +    room: "support",
    +    data: { text: "Hello" },
    +  }),
    +);

    Incoming messages can be bounded and constrained

    const message = parseRealtimeMessage(rawMessage, {
    +  maxBytes: 64 * 1024,
    +  maxDepth: 12,
    +  allowedTypes: ["message", "typing", "presence"],
    +  room: "support",
    +});

    message, acknowledgement, and sequence counts for monitoring without exposing payloads.

    const history = createRealtimeHistory({ limitPerRoom: 100 });
    +const entry = history.publish("support", message);
    +history.acknowledge("support", clientId, entry.sequence);
    +const missed = history.resume("support", clientId);
    + +
    + + +
    + } +} diff --git a/app/pages/packages/router.wrn b/app/pages/packages/router.wrn index d4a5dedc..0f53d9f5 100644 --- a/app/pages/packages/router.wrn +++ b/app/pages/packages/router.wrn @@ -10,11 +10,11 @@ page wrnexusrouter {
    W WRNexusJS - +
    -
    Core · Package reference

    @wrnexus/router

    Filesystem discovery, route matching, and typed route generation.

    v0.7.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/router@0.7.0

    Request preview access. Never put registry tokens in source control.

    File-based router that maps an app/ directory onto route tables and matches request paths against them.
    +
    Core · Package reference

    @wrnexus/router

    Filesystem discovery, route matching, and typed route generation.

    v0.8.0Private registryCore

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/router@0.8.0

    Request preview access. Never put registry tokens in source control.

    File-based router that maps an app/ directory onto route tables and matches request paths against them.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/router scans an application's app/ directory once at startup and builds route tables for pages, API endpoints, realtime channels, middleware, server-rendered .wrn components, layouts, and validation schemas. It also compiles URL patterns (/users/[id]) into RegExps and matches request paths against them. Request input is never turned into a file path, which makes the router immune to path traversal. This is a server-side package used by the WRNexusJS runtime to resolve incoming requests, plus a codegen helper for compile-time typed links.

    @@ -302,7 +302,7 @@ const routes = sortRoutes([{ raw: "/posts/[slug]", file: " const m = matchRoute(routes, "/posts/hello"); // { route, params: { slug: "hello" } }
    - + } diff --git a/app/pages/packages/security.wrn b/app/pages/packages/security.wrn new file mode 100644 index 00000000..471e8f12 --- /dev/null +++ b/app/pages/packages/security.wrn @@ -0,0 +1,66 @@ +page wrnexussecurity { + seo { + title = "@wrnexus/security" + description = "Security headers, CSRF protection, rate limits, and safe rendering." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Security · Package reference

    @wrnexus/security

    Security headers, CSRF protection, rate limits, and safe rendering.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/security@0.8.0

    Request preview access. Never put registry tokens in source control.

    Secure-by-default utilities for WRNexusJS: bounded HTML-safe serialization, prototype-pollution rejection, URL policy, secure cookies, request hardening, security presets, and SSRF-safe remote fetches.

    +
    import { safeFetch, securityPreset, setSecureCookie } from "@wrnexus/security";
    +
    +export default { security: securityPreset("strict") };
    +const response = await safeFetch(remoteUrl, { allowedHosts: ["api.example.com"] });
    +setSecureCookie(ctx, "__Host-session", sessionId);

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { S as SafeFetchOptions, a as SafeUrlPolicy, i as isPrivateAddress, b as isSafeUrl, s as safeFetch, c as sanitizeUrl, v as validateUrl } from './fetch-DNyX0J_D.js';
    +export { SecureSerializeOptions, secureJsonStringify, serializeForHtml } from './serialization.js';
    +import { CookieOptions, Context, RequestLimitsConfig, Middleware, SecurityConfig } from '@wrnexus/core';
    +export { TrustedHtmlPolicy, TrustedHtmlValue, createTrustedHtml, isTrustedHtml, unwrapTrustedHtml } from './trusted-html.js';
    +
    +declare class SecurityError extends Error {
    +    readonly code: string;
    +    readonly status: number;
    +    constructor(code: string, message: string, status?: number, options?: ErrorOptions);
    +}
    +
    +interface SafeObjectOptions {
    +    maxDepth?: number;
    +    maxKeys?: number;
    +    allowInstances?: boolean;
    +}
    +declare function isDangerousObjectKey(key: string): boolean;
    +declare function assertSafeObject(value: unknown, options?: SafeObjectOptions): void;
    +declare function safeMerge<T extends Record<string, unknown>>(target: T, ...sources: Array<Record<string, unknown> | undefined | null>): T;
    +
    +interface SecureCookieOptions extends CookieOptions {
    +    hostOnly?: boolean;
    +}
    +declare function secureCookieOptions(ctx: Pick<Context, "url">, options?: SecureCookieOptions): CookieOptions;
    +declare function setSecureCookie(ctx: Pick<Context, "url" | "cookies">, name: string, value: string, options?: SecureCookieOptions): void;
    +
    +type RequestHardeningOptions = RequestLimitsConfig;
    +declare function requestHardening(options?: RequestHardeningOptions): Middleware;
    +
    +type SecurityPreset = "balanced" | "strict" | "api";
    +declare function securityPreset(preset?: SecurityPreset): SecurityConfig;
    +
    +export { type RequestHardeningOptions, type SafeObjectOptions, type SecureCookieOptions, SecurityError, type SecurityPreset, assertSafeObject, isDangerousObjectKey, requestHardening, safeMerge, secureCookieOptions, securityPreset, setSecureCookie };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Secure-by-default utilities for WRNexusJS: bounded HTML-safe serialization, prototype-pollution rejection, URL policy, secure cookies, request hardening, security presets, and SSRF-safe remote fetches.

    import { safeFetch, securityPreset, setSecureCookie } from "@wrnexus/security";
    +
    +export default { security: securityPreset("strict") };
    +const response = await safeFetch(remoteUrl, { allowedHosts: ["api.example.com"] });
    +setSecureCookie(ctx, "__Host-session", sessionId);

    Install @wrnexus/security

    bun add @wrnexus/security
    + +
    + + +
    + } +} diff --git a/app/pages/packages/ssr.wrn b/app/pages/packages/ssr.wrn index 4f85014b..ee6383f6 100644 --- a/app/pages/packages/ssr.wrn +++ b/app/pages/packages/ssr.wrn @@ -10,11 +10,11 @@ page wrnexusssr {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/ssr

    Secure HTML document rendering and SEO metadata.

    v0.7.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ssr@0.7.0

    Request preview access. Never put registry tokens in source control.

    Server-side rendering: wraps a page's HTML body in a complete HTML document with a metadata-driven <head>.
    +
    Runtime · Package reference

    @wrnexus/ssr

    Secure HTML document rendering and SEO metadata.

    v0.8.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ssr@0.8.0

    Request preview access. Never put registry tokens in source control.

    Server-side rendering: wraps a page's HTML body in a complete HTML document with a metadata-driven <head>.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    Pages in WRNexusJS return an HTML string for the body. @wrnexus/ssr takes that body and produces a full HTML document — building the <head> from page metadata and global SEO defaults, resolving canonical/Open Graph/Twitter tags, and injecting module preloads and <script type="module"> tags. It is deliberately server-only: nothing in this package touches the DOM or ships to the browser, keeping server code genuinely server-only. Reach for it on the server when turning a rendered page body into a response document.

    @@ -121,6 +121,17 @@ interface ScriptAsset { attributes?: Record<string, string | boolean>; } type RenderScript = string | ScriptAsset; +interface PartialPrerenderResult { + shell: string; + regions: Array<{ + id: string; + html: string; + }>; +} +/** Extract compiler-emitted dynamic regions into a cacheable static shell. */ +declare function partialPrerender(html: string, startIndex?: number): PartialPrerenderResult; +/** Stream the static shell first, followed by inert region templates for client insertion. */ +declare function streamPartialDocument(result: PartialPrerenderResult, nonce?: string): ReadableStream<Uint8Array>; interface RenderOptions { /** Page metadata for the document head. */ meta: PageMeta; @@ -180,7 +191,7 @@ interface StreamRenderOptions extends Omit<RenderOptions, "body"> declare function renderDocumentStream(opts: StreamRenderOptions): ReadableStream<Uint8Array>; declare function streamDocumentResponse(opts: StreamRenderOptions, init?: ResponseInit): Response; -export { type RenderOptions, type RenderScript, type ScriptAsset, type StreamRenderOptions, extractWrnexusStyles, renderDocument, renderDocumentStream, streamDocumentResponse }; +export { type PartialPrerenderResult, type RenderOptions, type RenderScript, type ScriptAsset, type StreamRenderOptions, extractWrnexusStyles, partialPrerender, renderDocument, renderDocumentStream, streamDocumentResponse, streamPartialDocument };

    Examples

    Copy-ready examples from the installed package documentation.

    Render an SEO-ready application page

    import { renderDocument } from "@wrnexus/ssr";
     
     const html = renderDocument({
    @@ -213,7 +224,7 @@ return new Response(html, {
     return new Response(html, { headers: { "content-type": "text/html; charset=utf-8" } });
    - + } diff --git a/app/pages/packages/store.wrn b/app/pages/packages/store.wrn new file mode 100644 index 00000000..d44e7d33 --- /dev/null +++ b/app/pages/packages/store.wrn @@ -0,0 +1,69 @@ +page wrnexusstore { + seo { + title = "@wrnexus/store" + description = "Application state stores shared across server and browser runtimes." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Data · Package reference

    @wrnexus/store

    Application state stores shared across server and browser runtimes.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/store@0.8.0

    Request preview access. Never put registry tokens in source control.

    Typed global and page-scoped WRNexusJS stores with runtime-specific state, computed values, actions, lifecycle hooks, persistence, SSR isolation, and HMR support.

    +

    Use defineStore() to declare a store and createStoreContainer() to create an isolated request or browser container. Store definitions are framework helpers and do not require UI components.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { StoreMutation, StoreFunction, StoreDefinition, StoreInstance, StoreCombinedState } from './types.js';
    +export { PersistenceStorage, StoreActionContext, StoreActionDefinition, StoreInstanceCore, StoreKind, StoreLifecycleContext, StorePersistenceConfig, StoreRuntime } from './types.js';
    +
    +declare function defineStore<S extends object, C extends object = Record<string, never>, A extends Record<string, StoreFunction> = Record<string, StoreFunction>, CS extends object = Record<string, never>, SS extends object = Record<string, never>>(definition: StoreDefinition<S, C, A, CS, SS>): StoreDefinition<S, C, A, CS, SS>;
    +interface StoreContainerOptions {
    +    runtime: "server" | "client";
    +    request?: unknown;
    +    routeId?: string;
    +    hydration?: Record<string, unknown>;
    +    onMutation?: (mutation: StoreMutation) => void;
    +}
    +declare class StoreContainer {
    +    readonly runtime: "server" | "client";
    +    readonly request?: unknown;
    +    readonly routeId?: string;
    +    private readonly instances;
    +    private readonly hydration;
    +    private readonly onMutation?;
    +    private readonly lastMutations;
    +    constructor(options: StoreContainerOptions);
    +    use<S extends object, C extends object, A extends Record<string, StoreFunction>, CS extends object, SS extends object>(definition: StoreDefinition<S, C, A, CS, SS>): Promise<StoreInstance<StoreCombinedState<S, CS, SS>, C, A>>;
    +    serialize(): Record<string, unknown>;
    +    inspect(): Array<{
    +        name: string;
    +        kind: "global" | "page";
    +        state: Readonly<Record<string, unknown>>;
    +        computed: Readonly<Record<string, unknown>>;
    +        lastAction?: string;
    +        changed: string[];
    +        hydrationSource: "server" | "persistence" | "initial";
    +    }>;
    +    hotUpdate<S extends object, C extends object, A extends Record<string, StoreFunction>, CS extends object, SS extends object>(definition: StoreDefinition<S, C, A, CS, SS>): Promise<{
    +        preserved: string[];
    +        reset: string[];
    +    }>;
    +    disposePageStores(): Promise<void>;
    +    dispose(): Promise<void>;
    +}
    +declare function createStoreContainer(options: StoreContainerOptions): StoreContainer;
    +declare function createStoreInstance<S extends object, C extends object, A extends Record<string, StoreFunction>, CS extends object, SS extends object>(definition: StoreDefinition<S, C, A, CS, SS>, options: Omit<StoreContainerOptions, "hydration"> & {
    +    hydration?: unknown;
    +}): StoreInstance<StoreCombinedState<S, CS, SS>, C, A>;
    +
    +export { StoreCombinedState, StoreContainer, type StoreContainerOptions, StoreDefinition, StoreFunction, StoreInstance, StoreMutation, createStoreContainer, createStoreInstance, defineStore };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/store

    bun add @wrnexus/store

    Import @wrnexus/store

    import * as store from "@wrnexus/store";
    + +
    + + +
    + } +} diff --git a/app/pages/packages/styles.wrn b/app/pages/packages/styles.wrn index d719b342..6c809ccc 100644 --- a/app/pages/packages/styles.wrn +++ b/app/pages/packages/styles.wrn @@ -10,11 +10,18 @@ page wrnexusstyles {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/styles

    CSS pipeline, themes, fonts, profiles, and application config.

    v0.7.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/styles@0.7.0

    Request preview access. Never put registry tokens in source control.

    Global CSS bundling, the --wire-* design-token theme system, and the wrnexus.config.ts app-config loader for WRNexusJS apps.
    +
    Frontend · Package reference

    @wrnexus/styles

    CSS pipeline, themes, fonts, profiles, and application config.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/styles@0.8.0

    Request preview access. Never put registry tokens in source control.

    Reusable layers and presets

    +

    Compose local or package foundations in order; later layers override earlier ones and the application has final base-config precedence:

    +
    export default defineConfig({
    +  extends: ["@workroot/wrnexus-enterprise", "./layers/company"],
    +  profiles: { production: { port: 8080 } },
    +});
    +

    A directory layer exports wrnexus.layer.ts (JavaScript/MJS are supported). A package can provide that conventional file or declare wrnexus.layer in its package.json. Layers may extend other layers and carry the complete app configuration, including plugins that contribute layouts, components, routes, middleware, and migrations. plugins and head compose; other arrays intentionally replace earlier values. Cycles and missing/invalid entries fail with stable WRN-CONFIG-LAYER-* diagnostics. wrnexus config --explain lists every resolved layer source.

    +
    Global CSS bundling, the --wire-* design-token theme system, and the wrnexus.config.ts app-config loader for WRNexusJS apps.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    This package owns three server-side concerns that shape every page a WRNexusJS app renders:

    @@ -176,7 +183,7 @@ const themeJs = renderThemeRuntime(theme); // served at THEME_JS_HREFPeer package: @wrnexus/core supplies the SeoConfig and SecurityConfig types referenced by AppConfig.
  • The bundled global stylesheet, the theme stylesheet (THEME_CSS_HREF), and the theme runtime (THEME_JS_HREF) are wired into pages by the framework's server; this package only produces their contents.
  • Complete TypeScript API

    Generated from the exact installed package declarations.

    import { PerformanceBudgets, SeoConfig, SecurityConfig } from '@wrnexus/core';
    -import { PluginInput } from '@wrnexus/plugin';
    +import { PluginInput, PluginPermission } from '@wrnexus/plugin';
     import { StorageConfig } from '@wrnexus/uploader';
     
     /**
    @@ -191,7 +198,12 @@ import { StorageConfig } from '@wrnexus/uploader';
      * present before the first paint. The reserved token key `color-scheme` is
      * emitted as the native CSS property instead of a custom property.
      */
    -type ThemeTokens = Record<string, string>;
    +type ThemeSemanticColor = "primary" | "secondary" | "info" | "success" | "warning" | "danger" | "error";
    +type ThemeToken = "color-scheme" | "color-bg" | "color-background" | "color-foreground" | "color-surface" | "color-surface-2" | "color-surface-raised" | "color-surface-muted" | "color-text" | "color-text-muted" | "color-text-subtle" | "color-muted" | "color-border" | "color-border-strong" | "color-code-background" | "color-code-surface" | "color-code-text" | "color-code-muted" | "color-code-border" | `color-${ThemeSemanticColor}` | `color-${ThemeSemanticColor}-${"hover" | "active" | "contrast" | "soft" | "muted" | "text"}` | `color-on-${"primary" | "secondary"}` | "radius" | "radius-sm" | "shadow-1" | "shadow-sm" | "shadow-md" | "shadow-lg" | "space-section" | "space-section-sm" | "container-max" | "font-sans";
    +/** Known tokens get autocomplete while applications may add namespaced custom tokens. */
    +type ThemeTokens = Partial<Record<ThemeToken, string>> & Record<string, string>;
    +declare function defineThemeTokens<T extends ThemeTokens>(tokens: T): T;
    +declare function themeVar(token: ThemeToken, fallback?: string): string;
     declare const THEME_PALETTE_NAMES: readonly ["blue", "indigo", "violet", "emerald", "cyan", "rose", "amber", "slate"];
     type ThemePaletteName = (typeof THEME_PALETTE_NAMES)[number];
     /** Required semantic colors for a custom application palette. */
    @@ -345,6 +357,26 @@ declare function fontCspSources(fonts?: FontConfig): {
         font: string[];
     };
     
    +declare const CURRENT_COMPATIBILITY_DATE = "2026-08-02";
    +declare const CURRENT_FRAMEWORK_BEHAVIOUR = 1;
    +interface CompatibilityPolicy {
    +    compatibilityDate?: string;
    +    frameworkBehaviour?: number;
    +}
    +interface CompatibilityReport {
    +    configuredDate?: string;
    +    effectiveDate: string;
    +    currentDate: string;
    +    configuredBehaviour?: number;
    +    effectiveBehaviour: number;
    +    currentBehaviour: number;
    +    needsUpgrade: boolean;
    +    future: boolean;
    +    messages: string[];
    +}
    +declare function isCompatibilityDate(value: string): boolean;
    +declare function resolveCompatibility(policy: CompatibilityPolicy): CompatibilityReport;
    +
     /**
      * App configuration loader (`wrnexus.config.ts`).
      *
    @@ -453,6 +485,15 @@ interface PwaConfig {
         cacheUrls?: string[];
         /** Service-worker cache key. Change it to invalidate existing PWA caches. */
         cacheName?: string;
    +    /** Ordered URL rules for runtime caching. Patterns are regular-expression source strings. */
    +    runtimeCaching?: Array<{
    +        pattern: string;
    +        strategy: "network-first" | "cache-first" | "stale-while-revalidate";
    +        cacheName?: string;
    +        methods?: string[];
    +    }>;
    +    /** Background Sync tag used by the offline mutation queue. */
    +    backgroundSyncTag?: string;
     }
     type DevToolbarPosition = "bottom-center" | "bottom-left" | "bottom-right";
     interface DevToolbarConfig {
    @@ -548,9 +589,16 @@ interface CompatibilityConfig {
         legacyComponentDiscovery?: boolean;
         stringLayouts?: boolean;
     }
    -interface AppConfig {
    +interface AppConfig extends CompatibilityPolicy {
    +    /** Ordered reusable configuration layers; the application always has final precedence. */
    +    extends?: string | string[];
         /** Compiler/dev/build plugins, resolved in deterministic pre/normal/post order. */
         plugins?: PluginInput;
    +    /** Optional least-privilege enforcement for automatically discovered packages. */
    +    pluginPermissions?: {
    +        enforce?: boolean;
    +        grants?: Record<string, PluginPermission[]>;
    +    };
         /** WRN v0.6 explicit import and compatibility resolution. */
         imports?: ImportsConfig;
         /** TypeScript-backed .wrn type checking and declaration generation. */
    @@ -598,6 +646,17 @@ interface AppConfig {
         i18n?: {
             default?: string;
             locales?: string[];
    +        labels?: Record<string, string>;
    +        fallbacks?: Record<string, string[]>;
    +        direction?: Record<string, "ltr" | "rtl">;
    +        cookie?: {
    +            name?: string;
    +            maxAge?: number;
    +            path?: string;
    +            sameSite?: "Strict" | "Lax" | "None";
    +            secure?: boolean;
    +        };
    +        strict?: boolean;
         };
         /** Default database connection (driver + url); reached with `getDb()`. */
         db?: {
    @@ -647,6 +706,11 @@ declare function resolveProfile(options?: {
         explicit?: string;
         mode?: Mode;
     }): string;
    +interface ResolvedConfigLayers {
    +    config: AppConfig;
    +    sources: string[];
    +}
    +declare function resolveConfigLayers(appRoot: string, application: AppConfig): Promise<ResolvedConfigLayers>;
     /** Load the raw `wrnexus.config.*` (with the `profiles` map intact), or `{}`. */
     declare function loadRawConfig(appRoot: string): Promise<AppConfig>;
     /** Load `wrnexus.config.*`, applying the active profile's overrides. */
    @@ -746,7 +810,7 @@ declare function auditCssPerformance(source: string): CssPerformanceAuditIssue[]
      */
     declare function renderStyles(ctx: StyleProcessContext, styles?: StylesConfig): Promise<string>;
     
    -export { ACCENT_COOKIE, type AppConfig, type BuildConfig, type ConfigIssue, type ContrastResult, type CssPerformanceAuditIssue, type CssTokenAudit, type CustomThemePalette, DEFAULT_THEMES, type DevToolbarConfig, type ExperimentalConfig, type ExplainedConfig, type FontConfig, type FontDisplay, type GoogleFont, type LocalFontFace, type MobileConfig, type Mode, type NavigationConfig, type ObservabilityConfig, type PerformanceConfig, type PwaConfig, type ResolvedTheme, type StyleProcessContext, type StyleSource, type StylesConfig, type Mode as StylesMode, THEME_COOKIE, THEME_CSS_HREF, THEME_JS_HREF, THEME_PALETTES, THEME_PALETTE_NAMES, type TenancyConfig, type ThemeAccentConfig, type ThemeConfig, type ThemePaletteName, type ThemeTokens, auditCssPerformance, auditWireTokens, bundleCss, contrast, defineConfig, explainAppConfig, findStyleEntry, fontCspSources, headToString, loadAppConfig, loadEnv, loadRawConfig, normalizeStyleSources, renderFontHead, renderProductionFontHead, renderStyles, renderThemeCss, renderThemeRuntime, resolveAccentName, resolveProfile, resolveThemeConfig, resolveThemeName, tailwindSourceDirectives, validateAppConfig };
    +export { ACCENT_COOKIE, type AppConfig, type BuildConfig, CURRENT_COMPATIBILITY_DATE, CURRENT_FRAMEWORK_BEHAVIOUR, type CompatibilityPolicy, type CompatibilityReport, type ConfigIssue, type ContrastResult, type CssPerformanceAuditIssue, type CssTokenAudit, type CustomThemePalette, DEFAULT_THEMES, type DevToolbarConfig, type ExperimentalConfig, type ExplainedConfig, type FontConfig, type FontDisplay, type GoogleFont, type LocalFontFace, type MobileConfig, type Mode, type NavigationConfig, type ObservabilityConfig, type PerformanceConfig, type PwaConfig, type ResolvedConfigLayers, type ResolvedTheme, type StyleProcessContext, type StyleSource, type StylesConfig, type Mode as StylesMode, THEME_COOKIE, THEME_CSS_HREF, THEME_JS_HREF, THEME_PALETTES, THEME_PALETTE_NAMES, type TenancyConfig, type ThemeAccentConfig, type ThemeConfig, type ThemePaletteName, type ThemeSemanticColor, type ThemeToken, type ThemeTokens, auditCssPerformance, auditWireTokens, bundleCss, contrast, defineConfig, defineThemeTokens, explainAppConfig, findStyleEntry, fontCspSources, headToString, isCompatibilityDate, loadAppConfig, loadEnv, loadRawConfig, normalizeStyleSources, renderFontHead, renderProductionFontHead, renderStyles, renderThemeCss, renderThemeRuntime, resolveAccentName, resolveCompatibility, resolveConfigLayers, resolveProfile, resolveThemeConfig, resolveThemeName, tailwindSourceDirectives, themeVar, validateAppConfig };
     

    Examples

    Copy-ready examples from the installed package documentation.

    wrnexus.config.ts

    import type { AppConfig } from "@wrnexus/styles";
     
     export default {
    @@ -817,9 +881,9 @@ const themeJs = renderThemeRuntime(theme); // served at THEME_JS_HREF

    Rendering the theme

    <button data-wire-theme-toggle>Toggle theme</button>
     <button data-wire-theme-set="brand">Brand theme</button>
    - +
    - + } diff --git a/app/pages/packages/syntax.wrn b/app/pages/packages/syntax.wrn index c758d292..b0231303 100644 --- a/app/pages/packages/syntax.wrn +++ b/app/pages/packages/syntax.wrn @@ -10,13 +10,14 @@ page wrnexussyntax {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/syntax

    Editor syntax definitions and language tooling for .wrn files.

    v0.7.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/syntax@0.7.0

    Request preview access. Never put registry tokens in source control.

    Canonical WRN lexer, parser, AST, language metadata, source positions, and stable diagnostics. Framework tooling should import this package instead of implementing a separate .wrn parser.

    +
    Frontend · Package reference

    @wrnexus/syntax

    Editor syntax definitions and language tooling for .wrn files.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/syntax@0.8.0

    Request preview access. Never put registry tokens in source control.

    Canonical WRN lexer, parser, AST, language metadata, source positions, and stable diagnostics. Framework tooling should import this package instead of implementing a separate .wrn parser.

    See docs/WRN-LANGUAGE-SPEC-1.0.md in the WRNexusJS repository.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { LexError, Lexer } from './tokenizer.js';
    -export { A as ActionBlock, a as ApiBlock, b as Attr, C as ComputedDecl, D as DataApiBlock, c as DataMode, E as EffectBlock, d as EventDecl, F as FunctionParameterDecl, e as FunctionRuntime, L as LifecycleBlock, f as LoadBlock, M as ModeFunctionsBlock, O as OutputDecl, P as PageAst, g as ParseError, h as PersistDecl, i as PropDecl, R as RealtimeBlock, j as RealtimeHandler, k as RuntimeFunctionDecl, S as SeoBlock, l as StateDecl, m as StateRuntime, n as StoreKind, o as StoreLifecycleDecl, p as StructuredImportDecl, V as VOID_ELEMENTS, q as ViewNode, W as WatchBlock, r as parse, s as parseComputedDeclarations, t as parseHtmlView, u as parseOutputs, v as parsePersist, w as parseRuntimeFunctions, x as parseStateDeclarations, y as parseStoreLifecycle, z as parseStructuredImports, B as stripRuntimeFunctionModifiers } from './parser-BGaF5Zdu.js';
    +export { FormatWrnOptions, formatWrn } from './formatter.js';
    +export { A as ActionBlock, a as ApiBlock, b as Attr, C as ComputedDecl, D as DataApiBlock, c as DataMode, E as EffectBlock, d as EventDecl, F as FunctionParameterDecl, e as FunctionRuntime, L as LifecycleBlock, f as LoadBlock, M as ModeFunctionsBlock, O as OutputDecl, P as PageAst, g as ParseError, h as PersistDecl, i as PropDecl, R as RealtimeBlock, j as RealtimeHandler, k as RuntimeFunctionDecl, S as SeoBlock, l as StateDecl, m as StateRuntime, n as StoreKind, o as StoreLifecycleDecl, p as StructuredImportDecl, V as VOID_ELEMENTS, q as ViewNode, W as WatchBlock, r as parse, s as parseComputedDeclarations, t as parseHtmlView, u as parseOutputs, v as parsePersist, w as parseRuntimeFunctions, x as parseStateDeclarations, y as parseStoreLifecycle, z as parseStructuredImports, B as stripRuntimeFunctionModifiers } from './parser-CTLO4mcT.js';
     export { RuntimeType, eraseFunctionTypes, inferredRuntimeType, runtimeTypeOf, validateTypedInitializer } from './types.js';
     import { WrnDiagnostic } from './diagnostics.js';
     export { DiagnoseOptions, WrnDiagnosticSeverity, WrnSourcePosition, assertValidAst, classifyParseError, containsReadonlyPropMutation, diagnose, diagnosticFromError, formatDiagnostic, isHydrationStrategy, isRuntimeTarget, positionAt } from './diagnostics.js';
    @@ -48,7 +49,7 @@ const ast = parse('component Greeting { view { <p>Hello</p>
     const summary = diagnosticSummary(diagnose(source));
    - + } diff --git a/app/pages/packages/test.wrn b/app/pages/packages/test.wrn index 390c7164..63598f68 100644 --- a/app/pages/packages/test.wrn +++ b/app/pages/packages/test.wrn @@ -10,11 +10,11 @@ page wrnexustest {
    W WRNexusJS - +
    -
    Tooling · Package reference

    @wrnexus/test

    WRNexusJS-aware component, route, and browser testing utilities.

    v0.7.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/test@0.7.0

    Request preview access. Never put registry tokens in source control.

    Testing utilities for WRNexusJS apps — component rendering, reactive-DOM mounting, route handler calls, and a full in-process app harness, plus a one-import re-export of bun:test.
    +
    Tooling · Package reference

    @wrnexus/test

    WRNexusJS-aware component, route, and browser testing utilities.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/test@0.8.0

    Request preview access. Never put registry tokens in source control.

    Testing utilities for WRNexusJS apps — component rendering, reactive-DOM mounting, route handler calls, and a full in-process app harness, plus a one-import re-export of bun:test.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/test is the server-side test toolkit you reach for when writing tests for a WRNexusJS app. It runs under bun test (invoked via wrnexus test) and gives you a single import surface: the bun:test primitives (test, expect, mock, …) re-exported alongside WRNexusJS-aware helpers that compile .wrn components, hydrate server HTML in a DOM, invoke API route handlers, and boot the real app on an ephemeral port for integration tests.

    @@ -65,6 +65,15 @@ interface Harness { }

    Boots the app at projectRoot on an ephemeral port (port: 0) for integration tests covering pages, API routes, middleware, and the full request pipeline. Loads env and app config for the given profile (default "test") so it picks up your test database/env. The server runs in development mode with HMR disabled. Remember to await app.close() when done.

    Usage

    +

    The CLI supports focused suites by file or directory convention:

    +
    wrnexus test unit                 # *.unit.test.ts or test/unit/**
    +wrnexus test component            # *.component.test.ts or test/component/**
    +wrnexus test api                  # *.api.test.ts or test/api/**
    +wrnexus test accessibility        # *.a11y.test.ts / *.accessibility.test.ts
    +wrnexus test performance          # *.performance.test.ts / *.benchmark.test.ts
    +wrnexus test browser              # Playwright project when configured
    +wrnexus test visual               # Playwright tests tagged @visual
    +

    Pass the application directory after the level, for example wrnexus test component examples/basic-app. A focused command fails clearly when no matching suite exists instead of silently running unrelated tests.

    import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test";
     
     test("counter renders its label", async () => {
    @@ -138,6 +147,38 @@ declare class MemoryCookieJar {
         clear(): void;
     }
     
    +interface TransactionalDatabase {
    +    tx<T>(callback: (transaction: TransactionalDatabase) => Promise<T>): Promise<T>;
    +}
    +/** Run test work in a real transaction and always force rollback. */
    +declare function withDatabaseRollback<T>(db: TransactionalDatabase, run: (transaction: TransactionalDatabase) => T | Promise<T>): Promise<T>;
    +declare function createFactory<T extends Record<string, unknown>>(build: (sequence: number) => T): {
    +    build(overrides?: Partial<T>): T;
    +    buildMany(count: number, overrides?: Partial<T>): T[];
    +    reset(): void;
    +};
    +interface BrowserArtifactPage {
    +    screenshot(options: {
    +        path: string;
    +        fullPage?: boolean;
    +    }): Promise<unknown>;
    +    context(): {
    +        tracing?: {
    +            stop(options: {
    +                path: string;
    +            }): Promise<unknown>;
    +        };
    +    };
    +}
    +declare function captureBrowserArtifacts(page: BrowserArtifactPage, testName: string, options?: {
    +    root?: string;
    +    screenshot?: boolean;
    +    trace?: boolean;
    +}): Promise<{
    +    screenshot?: string;
    +    trace?: string;
    +}>;
    +
     /**
      * @wrnexus/test — testing utilities for WRNexusJS apps. Runs on `bun test` (via
      * `wrnexus test`). Import everything from one place:
    @@ -193,8 +234,14 @@ interface HarnessOptions {
      */
     declare function createHarness(projectRoot: string, options?: HarnessOptions): Promise<Harness>;
     
    -export { type Deferred, type Harness, type HarnessOptions, type JsonResponse, MemoryCookieJar, type TestRequestOptions, type WaitForOptions, callRoute, createHarness, deferred, expectProblem, mountHtml, readJsonResponse, renderComponent, testContext, testRequest, waitFor };
    -

    Examples

    Copy-ready examples from the installed package documentation.

    Typical usage

    import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test";
    +export { type BrowserArtifactPage, type Deferred, type Harness, type HarnessOptions, type JsonResponse, MemoryCookieJar, type TestRequestOptions, type TransactionalDatabase, type WaitForOptions, callRoute, captureBrowserArtifacts, createFactory, createHarness, deferred, expectProblem, mountHtml, readJsonResponse, renderComponent, testContext, testRequest, waitFor, withDatabaseRollback };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    The CLI supports focused suites by file or directory convention

    wrnexus test unit                 # *.unit.test.ts or test/unit/**
    +wrnexus test component            # *.component.test.ts or test/component/**
    +wrnexus test api                  # *.api.test.ts or test/api/**
    +wrnexus test accessibility        # *.a11y.test.ts / *.accessibility.test.ts
    +wrnexus test performance          # *.performance.test.ts / *.benchmark.test.ts
    +wrnexus test browser              # Playwright project when configured
    +wrnexus test visual               # Playwright tests tagged @visual

    suite exists instead of silently running unrelated tests.

    import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test";
     
     test("counter renders its label", async () => {
       const html = await renderComponent(SRC, { start: 3, label: "Hits" });
    @@ -220,7 +267,7 @@ test("health endpoint", async () => {
     });
    - + } diff --git a/app/pages/packages/tracking.wrn b/app/pages/packages/tracking.wrn index 0dec22e9..01abd9ab 100644 --- a/app/pages/packages/tracking.wrn +++ b/app/pages/packages/tracking.wrn @@ -10,11 +10,11 @@ page wrnexustracking {
    W WRNexusJS - +
    -
    Runtime · Package reference

    @wrnexus/tracking

    Error/event capture, middleware, filtering, and sinks.

    v0.7.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/tracking@0.7.0

    Request preview access. Never put registry tokens in source control.

    Error tracking for WRNexusJS apps: capture exceptions manually or via middleware and fan them out to pluggable sinks.
    +
    Runtime · Package reference

    @wrnexus/tracking

    Error/event capture, middleware, filtering, and sinks.

    v0.8.0Private registryRuntime

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/tracking@0.8.0

    Request preview access. Never put registry tokens in source control.

    Error tracking for WRNexusJS apps: capture exceptions manually or via middleware and fan them out to pluggable sinks.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/tracking is a small, server-side error-capture layer. You create a tracker with one or more sinks, then feed it errors — either manually with tracker.capture(err, context) or automatically by mounting tracker.middleware() in your request pipeline. A consoleSink is included; forwarding to Sentry, Datadog, or any other backend is just a matter of writing a tiny sink. Reach for it when you want a single, sink-agnostic place to route application errors. Sinks run best-effort — a throwing sink never breaks the request.

    @@ -199,7 +199,7 @@ const tracker = createTracker({ tracker.addSink(anotherSink); // add more sinks later
    - + } diff --git a/app/pages/packages/typecheck.wrn b/app/pages/packages/typecheck.wrn new file mode 100644 index 00000000..146b8fd6 --- /dev/null +++ b/app/pages/packages/typecheck.wrn @@ -0,0 +1,72 @@ +page wrnexustypecheck { + seo { + title = "@wrnexus/typecheck" + description = "WRN-aware TypeScript diagnostics and virtual documents." + } + + view { +
    + +
    + W WRNexusJS + + +
    + +
    +
    Tooling · Package reference

    @wrnexus/typecheck

    WRN-aware TypeScript diagnostics and virtual documents.

    v0.8.0Private registryTooling

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/typecheck@0.8.0

    Request preview access. Never put registry tokens in source control.

    Static type checking for .wrn declarations, props, state, outputs, functions, stores, and generated virtual TypeScript files.

    +

    The package is compiler tooling rather than a browser UI package, so its public kit consists of programmatic typecheck helpers and diagnostics.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { PageAst } from '@wrnexus/syntax';
    +export { componentContract, storeContract } from './contracts.js';
    +export { findAppRoot, loadApplicationTypes } from './project.js';
    +
    +interface WrnTypeDiagnostic {
    +    code: string;
    +    category: "error" | "warning" | "info";
    +    message: string;
    +    file: string;
    +    line: number;
    +    column: number;
    +    length: number;
    +    expected?: string;
    +    received?: string;
    +    hint?: string;
    +    related?: {
    +        file: string;
    +        line: number;
    +        column: number;
    +        message: string;
    +    };
    +}
    +interface TypecheckOptions {
    +    filePath?: string;
    +    appRoot?: string;
    +    strict?: boolean;
    +    noImplicitAny?: boolean;
    +    strictNullChecks?: boolean;
    +    checkRuntimeBoundaries?: boolean;
    +}
    +interface SourceMapping {
    +    virtualStartLine: number;
    +    virtualEndLine: number;
    +    sourceStartLine: number;
    +    sourceStartColumn: number;
    +}
    +interface VirtualTypeScriptModule {
    +    ast: PageAst;
    +    fileName: string;
    +    code: string;
    +    mappings: SourceMapping[];
    +}
    +declare function virtualTypeScriptModule(source: string, filePath?: string, appRoot?: string): VirtualTypeScriptModule;
    +declare function checkWrnSource(source: string, options?: TypecheckOptions): WrnTypeDiagnostic[];
    +declare function checkWrnFile(filePath: string, options?: Omit<TypecheckOptions, "filePath">): WrnTypeDiagnostic[];
    +
    +export { type TypecheckOptions, type VirtualTypeScriptModule, type WrnTypeDiagnostic, checkWrnFile, checkWrnSource, virtualTypeScriptModule };
    +

    Examples

    Copy-ready examples from the installed package documentation.

    Install @wrnexus/typecheck

    bun add @wrnexus/typecheck

    Import @wrnexus/typecheck

    import * as typecheck from "@wrnexus/typecheck";
    + +
    + + +
    + } +} diff --git a/app/pages/packages/ui.wrn b/app/pages/packages/ui.wrn index f96e657b..ba44f944 100644 --- a/app/pages/packages/ui.wrn +++ b/app/pages/packages/ui.wrn @@ -10,11 +10,11 @@ page wrnexusui {
    W WRNexusJS - +
    -
    Frontend · Package reference

    @wrnexus/ui

    Themeable server-rendered UI components and CSS.

    v0.7.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ui@0.7.0

    Request preview access. Never put registry tokens in source control.

    First-party Wire UI component library — a set of themeable .wrn components plus a single tokenized stylesheet.
    +
    Frontend · Package reference

    @wrnexus/ui

    Themeable server-rendered UI components and CSS.

    v0.8.0Private registryFrontend

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/ui@0.8.0

    Request preview access. Never put registry tokens in source control.

    First-party Wire UI component library — a set of themeable .wrn components plus a single tokenized stylesheet.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    Overview

    @wrnexus/ui ships a library of server-rendered .wrn components (layout, form controls, and feedback UI) together with one themeable stylesheet, ui.css. The components are auto-discovered by the framework router — you don't import them in code. Once the package's component directory is on the router's scan path, you mount any component in a page with data-component="<name>". Every visual is driven by var(--wire-*) theme tokens, so components restyle instantly when the theme changes. The tiny JS surface (src/index.ts) exists only so the toolchain (CLI build + dev server) can locate the component directory and stylesheet.

    @@ -155,7 +155,7 @@ const router = buildRouter(appDir, { componentDirs: [uiComponentsDir()]  </div>

    Explore the component library

    Browse interactive examples and complete component usage in the dedicated WRNexusJS component showcase.

    Browse all 108 components →

    - + } diff --git a/app/pages/packages/uploader.wrn b/app/pages/packages/uploader.wrn index f52e4718..11055a21 100644 --- a/app/pages/packages/uploader.wrn +++ b/app/pages/packages/uploader.wrn @@ -10,11 +10,11 @@ page wrnexusuploader {
    W WRNexusJS - +
    -
    Data · Package reference

    @wrnexus/uploader

    Validated local/S3 uploads and secure file serving.

    v0.7.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/uploader@0.7.0

    Request preview access. Never put registry tokens in source control.

    Config-driven file uploads + serving for WRNexusJS. Declare named storage stores (local disk or any S3-compatible backend) in wrnexus.config.ts, upload with one function call, drop a drag-and-drop widget on a page, and serve files back — public or private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the rest of the framework).

    +
    Data · Package reference

    @wrnexus/uploader

    Validated local/S3 uploads and secure file serving.

    v0.8.0Private registryData

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/uploader@0.8.0

    Request preview access. Never put registry tokens in source control.

    Config-driven file uploads + serving for WRNexusJS. Declare named storage stores (local disk or any S3-compatible backend) in wrnexus.config.ts, upload with one function call, drop a drag-and-drop widget on a page, and serve files back — public or private. Zero external dependencies (S3 is signed with a built-in AWS SigV4 implementation, like the rest of the framework).

    Usage

    Configure local and S3 stores

    // wrnexus.config.ts
    @@ -88,6 +88,7 @@ await getStore("docs").driver.delete(files[0].key);
    import { serveFromStore } from "@wrnexus/uploader"; export const GET = serveFromStore("docs"); // your middleware decides who gets in

    API

    +

    Uploads can participate in security and media pipelines without changing storage drivers. Pass a scan hook to reject malware/DLP findings before storage, and afterStore to enqueue image/video processing or indexing. If post-processing throws, WRNexus deletes the newly written object so a partially accepted upload is never left behind.

    ExportWhat
    handleUpload(opts)POST route handler → JSON { ok, files }
    upload(store, req, opts)Parse + validate + store; returns { files }
    serveFromStore(store)Route handler that streams an object back (gate it for private)
    getStore(name?) / hasStorage(name?)Reach a store's driver (put/get/delete/publicUrl)
    configureStorage(config, root)Build the registry (the framework calls this at startup)
    s3Driver / localDriver / signS3Lower-level building blocks
    @@ -97,7 +98,28 @@ export const GET = serveFromStore("docs"); // your middleware decides
  • SigV4 signing is implemented from scratch (no @aws-sdk); tested against local S3 semantics.
  • Live AWS/R2 connectivity depends on your credentials + bucket policy.

  • v1 buffers each file in memory up to its size cap (fine for images/docs up to tens of MB).
  • -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context } from '@wrnexus/core';
    +
    +

    Helper and component kit

    +

    Use formatFileSize, uploadAccept, uploadedFileMap, uploaderAttributes, and assertUploadedFiles to keep upload forms and server validation consistent.

    +

    Enable uploaderPlugin() for:

    +
      +
    • <UploadDropzone />
    • +
    • <UploadStatus />
    • +
    +

    The complete blocks compose Card, Alert, and Badge from @wrnexus/ui; the specialized upload runtime remains responsible for the native file input and secure transport behavior. Large files can use createResumableUploadManager. Sessions are bounded and expiring; chunks may arrive out of order, carry SHA-256 checksums, and are idempotent when retried. Conflicting retries reject, and the object is assembled only after every exact-sized chunk is present.

    +
    const uploads = createResumableUploadManager({
    +  driver: getStore("documents").driver,
    +  sessions: redisUploadSessionStore,
    +  chunkSize: 5 * 1024 * 1024,
    +  maxBytes: 500 * 1024 * 1024,
    +  accept: ["application/pdf"],
    +});
    +
    +const session = await uploads.create({ name: "report.pdf", size, type });
    +await uploads.uploadChunk(session.id, index, bytes, sha256);
    +

    The included memory session store is intended for one-process apps and tests. Multi-instance production deployments should implement ResumableSessionStore with shared durable storage and atomic session updates, and periodically call prune() for abandoned uploads.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    import { Context } from '@wrnexus/core';
    +export { UploaderPluginOptions, uploaderComponentsDir, default as uploaderPlugin } from './plugin.js';
    +import '@wrnexus/plugin';
     
     /**
      * Storage driver contract + config types.
    @@ -227,6 +249,25 @@ interface UploadOptions {
         accept?: string[];
         /** Key prefix, e.g. `"avatars"` → keys become `avatars/<yyyy>/<mm>/<rand>.<ext>`. */
         prefix?: string;
    +    /** Virus/DLP/content scanner invoked before bytes enter storage. Throw or return unsafe to reject. */
    +    scan?: (file: UploadScanInput) => UploadScanResult | Promise<UploadScanResult>;
    +    /** Image/video/indexing hook invoked after storage. Failure removes the just-written object. */
    +    afterStore?: (file: UploadedFile & {
    +        bytes: Uint8Array;
    +        store: Store;
    +    }) => void | Promise<void>;
    +}
    +interface UploadScanInput {
    +    name: string;
    +    type: string;
    +    size: number;
    +    bytes: Uint8Array;
    +    store: Store;
    +}
    +interface UploadScanResult {
    +    safe: boolean;
    +    reason?: string;
    +    scanner?: string;
     }
     /** A 4xx-carrying error so `handleUpload` can map it to a status. */
     declare class UploadError extends Error {
    @@ -401,7 +442,145 @@ interface SignedFileToken {
     declare function createSignedFileToken(input: SignedFileToken, secret: string): Promise<string>;
     declare function verifySignedFileToken(token: string, secret: string, now?: number): Promise<SignedFileToken | null>;
     
    -export { type LocalStoreConfig, type PutMeta, type S3StoreConfig, type SignedFileToken, type StorageConfig, type StorageDriver, type Store, type StoreAccess, type StoreConfig, type StoredObject, UPLOADS_PREFIX, UPLOAD_JS_HREF, UPLOAD_RUNTIME, UploadError, type UploadInspection, type UploadOptions, type UploadPolicy, UploadPolicyError, type UploadedFile, accepts, configureStorage, contentTypeOf, createSignedFileToken, encodeKey, enforceUploadPolicy, extForType, extOf, getStore, handleUpload, hasStorage, inspectUpload, localDriver, s3Driver, safeObjectKey, serveFromStore, serveStoredFile, sha256Hex, signS3, sniffContentType, storeNames, storedUrl, upload, verifySignedFileToken };
    +declare function formatFileSize(bytes: number, locale?: string): string;
    +declare function uploadAccept(value: string | readonly string[]): string;
    +declare function uploadedFileMap(files: readonly UploadedFile[]): Record<string, UploadedFile>;
    +declare function uploaderAttributes(options?: {
    +    store?: string;
    +    endpoint?: string;
    +    accept?: string | readonly string[];
    +    maxBytes?: number;
    +    multiple?: boolean;
    +    field?: string;
    +    label?: string;
    +}): Record<string, string | boolean>;
    +declare function assertUploadedFiles(files: readonly UploadedFile[], options?: {
    +    min?: number;
    +    max?: number;
    +}): readonly UploadedFile[];
    +
    +interface ResumableUploadSession {
    +    id: string;
    +    key: string;
    +    name: string;
    +    type: string;
    +    size: number;
    +    chunkSize: number;
    +    totalChunks: number;
    +    createdAt: number;
    +    expiresAt: number;
    +    chunks: Record<number, Uint8Array>;
    +    digests: Record<number, string>;
    +}
    +interface ResumableSessionStore {
    +    get(id: string): Promise<ResumableUploadSession | null>;
    +    put(session: ResumableUploadSession): Promise<void>;
    +    delete(id: string): Promise<void>;
    +    list(): Promise<ResumableUploadSession[]>;
    +}
    +declare function memoryResumableSessionStore(): ResumableSessionStore;
    +interface ResumableUploadManagerOptions {
    +    driver: StorageDriver;
    +    sessions?: ResumableSessionStore;
    +    maxBytes?: number;
    +    chunkSize?: number;
    +    maxSessions?: number;
    +    ttlMs?: number;
    +    accept?: string[];
    +    prefix?: string;
    +    publicUrl?: (key: string) => string | null;
    +    now?: () => number;
    +}
    +interface CreateResumableUpload {
    +    name: string;
    +    type?: string;
    +    size: number;
    +    chunkSize?: number;
    +}
    +interface ResumableChunkResult {
    +    receivedChunks: number;
    +    totalChunks: number;
    +    complete: boolean;
    +    file?: UploadedFile;
    +}
    +interface ResumableUploadManager {
    +    create(input: CreateResumableUpload): Promise<ResumableUploadSession>;
    +    uploadChunk(id: string, index: number, data: Uint8Array, sha256?: string): Promise<ResumableChunkResult>;
    +    status(id: string): Promise<{
    +        received: number[];
    +        totalChunks: number;
    +        expiresAt: number;
    +    } | null>;
    +    cancel(id: string): Promise<boolean>;
    +    prune(): Promise<number>;
    +}
    +declare function createResumableUploadManager(options: ResumableUploadManagerOptions): ResumableUploadManager;
    +
    +interface QuotaUsage {
    +    owner: string;
    +    bytes: number;
    +    objects: number;
    +    updatedAt: number;
    +}
    +interface QuotaStore {
    +    get(owner: string): Promise<QuotaUsage>;
    +    reserve(owner: string, bytes: number, limits: {
    +        bytes: number;
    +        objects?: number;
    +    }): Promise<boolean>;
    +    release(owner: string, bytes: number): Promise<void>;
    +}
    +declare function memoryQuotaStore(): QuotaStore;
    +interface QuotaSqlClient {
    +    query<T = any>(sql: string, parameters?: unknown[]): Promise<{
    +        rows: T[];
    +    }>;
    +}
    +/** PostgreSQL quota accounting using a single atomic conditional upsert. */
    +declare function postgresQuotaStore(db: QuotaSqlClient, table?: string): QuotaStore;
    +declare const POSTGRES_QUOTA_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_storage_quota (owner text PRIMARY KEY, bytes bigint NOT NULL DEFAULT 0, objects integer NOT NULL DEFAULT 0, updated_at bigint NOT NULL);";
    +interface MultipartObjectClient {
    +    create(key: string, meta: PutMeta): Promise<string>;
    +    uploadPart(uploadId: string, key: string, part: number, bytes: Uint8Array): Promise<string>;
    +    complete(uploadId: string, key: string, parts: Array<{
    +        part: number;
    +        etag: string;
    +    }>): Promise<void>;
    +    abort(uploadId: string, key: string): Promise<void>;
    +}
    +declare function multipartUpload(client: MultipartObjectClient, key: string, bytes: Uint8Array, meta: PutMeta, options?: {
    +    partBytes?: number;
    +    concurrency?: number;
    +}): Promise<void>;
    +interface TemporaryObject {
    +    key: string;
    +    expiresAt: number;
    +}
    +declare function createTemporaryObjectCleaner(driver: StorageDriver, options?: {
    +    now?: () => number;
    +    limit?: number;
    +}): {
    +    track(key: string, ttlMs: number): void;
    +    cleanup(at?: number): Promise<number>;
    +    snapshot: () => {
    +        tracked: number;
    +        nextExpiry: number | undefined;
    +    };
    +};
    +interface VideoTranscodeOptions {
    +    format: "mp4" | "webm";
    +    width?: number;
    +    height?: number;
    +    videoBitrateKbps?: number;
    +}
    +declare function ffmpegVideoTranscoder(options?: {
    +    executable?: string;
    +    spawn?: (args: string[]) => {
    +        exited: Promise<number>;
    +    };
    +}): (input: string, output: string, config: VideoTranscodeOptions) => Promise<void>;
    +
    +export { type CreateResumableUpload, type LocalStoreConfig, type MultipartObjectClient, POSTGRES_QUOTA_SCHEMA, type PutMeta, type QuotaSqlClient, type QuotaStore, type QuotaUsage, type ResumableChunkResult, type ResumableSessionStore, type ResumableUploadManager, type ResumableUploadManagerOptions, type ResumableUploadSession, type S3StoreConfig, type SignedFileToken, type StorageConfig, type StorageDriver, type Store, type StoreAccess, type StoreConfig, type StoredObject, type TemporaryObject, UPLOADS_PREFIX, UPLOAD_JS_HREF, UPLOAD_RUNTIME, UploadError, type UploadInspection, type UploadOptions, type UploadPolicy, UploadPolicyError, type UploadScanInput, type UploadScanResult, type UploadedFile, type VideoTranscodeOptions, accepts, assertUploadedFiles, configureStorage, contentTypeOf, createResumableUploadManager, createSignedFileToken, createTemporaryObjectCleaner, encodeKey, enforceUploadPolicy, extForType, extOf, ffmpegVideoTranscoder, formatFileSize, getStore, handleUpload, hasStorage, inspectUpload, localDriver, memoryQuotaStore, memoryResumableSessionStore, multipartUpload, postgresQuotaStore, s3Driver, safeObjectKey, serveFromStore, serveStoredFile, sha256Hex, signS3, sniffContentType, storeNames, storedUrl, upload, uploadAccept, uploadedFileMap, uploaderAttributes, verifySignedFileToken };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Configure local and S3 stores

    // wrnexus.config.ts
     import type { AppConfig } from "@wrnexus/styles";
     
    @@ -451,9 +630,9 @@ await getStore("docs").driver.delete(files[0].key);

    Serve private files behind application authentication

    // app/api/files/[key].ts
     import { serveFromStore } from "@wrnexus/uploader";
     export const GET = serveFromStore("docs"); // your middleware decides who gets in
    - +
    - + } diff --git a/app/pages/packages/validation.wrn b/app/pages/packages/validation.wrn index 0a431eee..e7ac76b7 100644 --- a/app/pages/packages/validation.wrn +++ b/app/pages/packages/validation.wrn @@ -10,12 +10,25 @@ page wrnexusvalidation {
    W WRNexusJS - +
    -
    Security · Package reference

    @wrnexus/validation

    Typed schemas, coercion, validation, and browser descriptors.

    v0.7.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/validation@0.7.0

    Request preview access. Never put registry tokens in source control.

    One fluent schema, validated on the server (API bodies, env vars) and mirrored to an eval-free browser validator for forms.
    +
    Security · Package reference

    @wrnexus/validation

    Typed schemas, coercion, validation, and browser descriptors.

    v0.8.0Private registrySecurity

    Install the package

    After WorkRoot approves private registry access, install the release-aligned package:

    bun add @wrnexus/validation@0.8.0

    Request preview access. Never put registry tokens in source control.

    One fluent schema, validated on the server (API bodies, env vars) and mirrored to an eval-free browser validator for forms.

    Part of the WRNexusJS framework — an SSR-first, Bun-native full-stack web framework.

    +

    Boundary contracts

    +

    Use ContractRegistry with defineContract or defineEvent to publish the same schema descriptors for APIs, actions, webhooks, realtime, queues, cron, pub/sub, plugins, configuration, and environment variables.

    +
    import { ContractRegistry, defineEvent, v } from "@wrnexus/validation";
    +
    +export const contracts = new ContractRegistry().register(
    +  defineEvent({
    +    name: "user.created",
    +    version: 1,
    +    consumers: ["notification-worker", "audit-service"],
    +    payload: v.object({ userId: v.string().uuid(), createdAt: v.string().date() }),
    +  }),
    +);
    +

    Export the registry from app/contracts.ts, then accept a baseline with wrnexus contracts snapshot. CI can run wrnexus contracts check; removed contracts/fields, required-field additions, type changes, narrowed enums, and tighter validation fail with stable WRN-CONTRACT-* diagnostics and list known consumers. A generated wrnexus.contracts.json can be used instead of a module.

    Overview

    Define a schema once with the fluent v builder, then reuse it in three places: .parse() runs server-side and returns coerced values plus per-field errors; .describe() emits a plain-JSON SchemaDescriptor that the browser runtime interprets (no eval, no bundled validator); and helpers like parseBody and parseEnv wire schemas straight into API routes and startup config. The server rule logic (applyRule/checkField) and the client runtime (VALIDATE_RUNTIME) mirror each other exactly, so a form validates identically in both places. Schemas are conventionally kept in app/schemas/.

    bun add @wrnexus/validation
    @@ -128,7 +141,46 @@ const head = `<script>${renderSchemasScript({ signup: signupSche
  • Refinements (refine) run only server-side and are never serialized — client and server agree on every other rule because both interpret the same RuleDescriptor list.
  • No runtime dependencies. Ships as TypeScript source (src/index.ts) executed directly by Bun.
  • Pairs with the WRNexusJS server (@wrnexus/core) for route handlers and the SSR layer that injects renderSchemasScript / VALIDATE_RUNTIME.
  • -

    Complete TypeScript API

    Generated from the exact installed package declarations.

    /**
    +
    +

    Helper and component kit

    +

    The public helper API includes parseOrThrow, ValidationError, validationResponse, firstValidationError, validationSummary, and schemaFieldNames.

    +

    Schema output is inferred automatically by ObjectSchema, parseOrThrow, parseBody, parseEnv, and asyncSchema. Use InferSchema<typeof schema> when a named output type is useful:

    +
    const accountSchema = v.object({
    +  email: v.string().email(),
    +  attempts: v.number().integer(),
    +});
    +
    +type AccountInput = InferSchema<typeof accountSchema>;
    +const account = parseOrThrow(accountSchema, input);
    +// account.email: string
    +// account.attempts: number
    +

    Enable validationPlugin() for:

    +
      +
    • <ValidationSummary />
    • +
    • <FieldError />
    • +
    +

    The summary block composes Alert from @wrnexus/ui, while FieldError remains a lightweight accessible field-level primitive. Schemas can drive external contracts without maintaining a second definition:

    +
    import {
    +  localizeDescriptor,
    +  openApiRequestBody,
    +  parseDescriptor,
    +  toJsonSchema,
    +} from "@wrnexus/validation";
    +
    +const jsonSchema = toJsonSchema(contactSchema, {
    +  id: "urn:example:contact",
    +  title: "Contact request",
    +});
    +const requestBody = openApiRequestBody(contactSchema);
    +
    +const mr = localizeDescriptor(contactSchema, (key, params) =>
    +  translations.t(`validation.${key}`, params),
    +);
    +const result = parseDescriptor(mr, input);
    +

    JSON Schema output targets draft 2020-12, closes unknown object properties, and maps lengths/ranges/formats/enums/patterns/integer rules. OpenAPI request bodies reuse the same properties. Localized descriptors preserve explicit custom messages and fill default required, type-coercion, and rule messages; the same descriptor is consumable by server parsing and the eval-free browser runtime.

    Complete TypeScript API

    Generated from the exact installed package declarations.

    export { ValidationPluginOptions, validationComponentsDir, default as validationPlugin } from './plugin.js';
    +import '@wrnexus/plugin';
    +
    +/**
      * Client-side validation. `renderSchemasScript` bakes the discovered schema
      * descriptors into `window.__wireSchemas`; `VALIDATE_RUNTIME` is a generic,
      * eval-free validator that reads them and validates every `form[data-schema]`
    @@ -146,16 +198,16 @@ interface AsyncValidationContext<T> {
         signal?: AbortSignal;
     }
     type AsyncRefinement<T> = (context: AsyncValidationContext<T>) => void | Promise<void>;
    -declare class AsyncObjectSchema<T extends Record<string, unknown> = Record<string, unknown>> {
    +declare class AsyncObjectSchema<T extends object = Record<string, unknown>> {
         #private;
    -    readonly base: ObjectSchema;
    -    constructor(base: ObjectSchema);
    +    readonly base: ObjectSchema<T>;
    +    constructor(base: ObjectSchema<T>);
         refine(refinement: AsyncRefinement<T>): this;
         describe(): SchemaDescriptor;
         parse(input: unknown, signal?: AbortSignal): Promise<ParseResult<T>>;
     }
    -declare function asyncSchema<T extends Record<string, unknown> = Record<string, unknown>>(schema: ObjectSchema): AsyncObjectSchema<T>;
    -declare function parseBodyAsync<T extends Record<string, unknown>>(schema: AsyncObjectSchema<T>, request: Request, signal?: AbortSignal): Promise<{
    +declare function asyncSchema<T extends object>(schema: ObjectSchema<T>): AsyncObjectSchema<T>;
    +declare function parseBodyAsync<T extends object>(schema: AsyncObjectSchema<T>, request: Request, signal?: AbortSignal): Promise<{
         ok: true;
         value: T;
     } | {
    @@ -170,6 +222,99 @@ interface OpenApiSchema {
     declare function schemaToOpenApi(schema: ObjectSchema | AsyncObjectSchema): OpenApiSchema;
     declare function mergeValidationResults<T>(...results: ParseResult<T>[]): ParseResult<T>;
     
    +declare class ValidationError<T = Record<string, unknown>> extends Error {
    +    readonly result: ParseResult<T>;
    +    constructor(result: ParseResult<T>);
    +}
    +declare function parseOrThrow<T extends object>(schema: ObjectSchema<T>, input: unknown): T;
    +declare function validationResponse(result: ParseResult, options?: {
    +    successStatus?: number;
    +    failureStatus?: number;
    +}): Response;
    +declare function firstValidationError(errors: Record<string, string>): string | null;
    +declare function validationSummary(errors: Record<string, string>): Array<{
    +    field: string;
    +    message: string;
    +}>;
    +declare function schemaFieldNames(schema: ObjectSchema | SchemaDescriptor): string[];
    +
    +interface JsonSchemaDocument {
    +    $schema: "https://json-schema.org/draft/2020-12/schema";
    +    $id?: string;
    +    title?: string;
    +    type: "object";
    +    properties: Record<string, Record<string, unknown>>;
    +    required?: string[];
    +    additionalProperties: false;
    +}
    +declare function toJsonSchema(schema: ObjectSchema | SchemaDescriptor, options?: {
    +    id?: string;
    +    title?: string;
    +}): JsonSchemaDocument;
    +declare function openApiRequestBody(schema: ObjectSchema | SchemaDescriptor, options?: {
    +    description?: string;
    +    required?: boolean;
    +    contentTypes?: string[];
    +}): {
    +    required: boolean;
    +    content: {
    +        [k: string]: {
    +            schema: {
    +                $id?: string;
    +                title?: string;
    +                type: "object";
    +                properties: Record<string, Record<string, unknown>>;
    +                required?: string[];
    +                additionalProperties: false;
    +            };
    +        };
    +    };
    +    description?: string | undefined;
    +};
    +type ValidationMessageKey = "required" | "number" | `rule.${RuleDescriptor["kind"]}`;
    +type ValidationMessageTranslator = (key: ValidationMessageKey, params: Record<string, unknown>) => string;
    +declare function localizeDescriptor(schema: ObjectSchema | SchemaDescriptor, translate: ValidationMessageTranslator): SchemaDescriptor;
    +declare function parseDescriptor<T = Record<string, unknown>>(descriptor: SchemaDescriptor, source: Record<string, unknown>): ParseResult<T>;
    +
    +type ContractKind = "api" | "action" | "webhook" | "realtime" | "queue" | "cron" | "pubsub" | "plugin" | "config" | "env";
    +interface ContractDefinition<T extends object = Record<string, unknown>> {
    +    kind: ContractKind;
    +    name: string;
    +    version: number;
    +    payload: ObjectSchema<T> | SchemaDescriptor;
    +    consumers?: string[];
    +    description?: string;
    +}
    +interface ContractRecord {
    +    kind: ContractKind;
    +    name: string;
    +    version: number;
    +    payload: SchemaDescriptor;
    +    consumers: string[];
    +    description?: string;
    +}
    +interface ContractSnapshot {
    +    format: 1;
    +    contracts: ContractRecord[];
    +}
    +interface ContractIssue {
    +    code: "WRN-CONTRACT-REMOVED" | "WRN-CONTRACT-FIELD-REMOVED" | "WRN-CONTRACT-FIELD-REQUIRED" | "WRN-CONTRACT-FIELD-TYPE" | "WRN-CONTRACT-RULE-TIGHTENED";
    +    contract: string;
    +    field?: string;
    +    message: string;
    +    consumers: string[];
    +}
    +declare function defineContract<T extends object>(definition: ContractDefinition<T>): ContractDefinition<T>;
    +declare function defineEvent<T extends object>(definition: Omit<ContractDefinition<T>, "kind"> & {
    +    kind?: "realtime" | "pubsub";
    +}): ContractDefinition<T>;
    +declare class ContractRegistry {
    +    private readonly records;
    +    register<T extends object>(definition: ContractDefinition<T>): this;
    +    snapshot(): ContractSnapshot;
    +}
    +declare function checkContractCompatibility(previous: ContractSnapshot, current: ContractSnapshot): ContractIssue[];
    +
     /**
      * @wrnexus/validation — one schema, validated on the server (API) and the browser
      * (forms). A schema is a fluent builder; `.parse()` runs server-side and returns
    @@ -218,6 +363,8 @@ interface FieldDescriptor {
         optional?: boolean;
         /** Message used when a required field is empty. Defaults to "Required". */
         requiredMessage?: string;
    +    /** Message used when coercion to the declared type fails. */
    +    typeMessage?: string;
         label?: string;
         /** Trim string input before validating. */
         trim?: boolean;
    @@ -274,7 +421,9 @@ declare abstract class FieldSchema {
         runRefinements(value: unknown): string | null;
         describe(): FieldDescriptor;
     }
    -declare class StringSchema extends FieldSchema {
    +declare class StringSchema<TValue extends string = string> extends FieldSchema {
    +    /** Type-only marker used to preserve literal unions through schema inference. */
    +    readonly __value: TValue;
         readonly type: "string";
         private _trim;
         email(message?: string): this;
    @@ -282,16 +431,18 @@ declare class StringSchema extends FieldSchema {
         uuid(message?: string): this;
         date(message?: string): this;
         length(n: number, message?: string): this;
    -    oneOf(values: string[], message?: string): this;
    +    oneOf<const TValues extends readonly string[]>(values: TValues, message?: string): StringSchema<TValues extends readonly [string, ...string[]] ? TValues[number] : TValue>;
         trim(): this;
         pattern(re: RegExp, message?: string): this;
         describe(): FieldDescriptor;
     }
    -declare class NumberSchema extends FieldSchema {
    +declare class NumberSchema<TValue extends number = number> extends FieldSchema {
    +    /** Type-only marker used to preserve numeric literal unions through schema inference. */
    +    readonly __value: TValue;
         readonly type: "number";
         integer(message?: string): this;
         positive(message?: string): this;
    -    oneOf(values: number[], message?: string): this;
    +    oneOf<const TValues extends readonly number[]>(values: TValues, message?: string): NumberSchema<TValues extends readonly [number, ...number[]] ? TValues[number] : TValue>;
     }
     declare class BooleanSchema extends FieldSchema {
         readonly type: "boolean";
    @@ -299,27 +450,37 @@ declare class BooleanSchema extends FieldSchema {
     declare class UnknownSchema extends FieldSchema {
         readonly type: "unknown";
     }
    -type AnyFieldSchema = StringSchema | NumberSchema | BooleanSchema | UnknownSchema;
    -declare class ObjectSchema {
    +type AnyFieldSchema = StringSchema<string> | NumberSchema<number> | BooleanSchema | UnknownSchema;
    +/** Infer the runtime value produced by a field schema. */
    +type InferFieldValue<TField extends FieldSchema> = TField extends StringSchema<infer TValue> ? TValue : TField extends NumberSchema<infer TValue> ? TValue : TField extends BooleanSchema ? boolean : unknown;
    +/** Infer the validated object produced by a field map. */
    +type InferObjectFields<TFields extends Record<string, FieldSchema>> = {
    +    [K in keyof TFields]: InferFieldValue<TFields[K]>;
    +};
    +/** Infer the object value produced by an object schema. */
    +type InferSchema<TSchema extends ObjectSchema> = TSchema extends ObjectSchema<infer TValue> ? TValue : never;
    +declare class ObjectSchema<TValue extends object = Record<string, unknown>> {
         private readonly fields;
    +    /** Type-only marker used by helper functions to infer validated output. */
    +    readonly __output: TValue;
         constructor(fields: Record<string, FieldSchema>);
         /** Return a defensive copy of the schema fields. */
         getFields(): Readonly<Record<string, FieldSchema>>;
         /** Create a new schema with fields added or replaced. The original is unchanged. */
    -    extend(fields: Record<string, FieldSchema>): ObjectSchema;
    +    extend<TFields extends Record<string, FieldSchema>>(fields: TFields): ObjectSchema<Omit<TValue, keyof TFields> & InferObjectFields<TFields>>;
         /** Create a new schema containing fields from both schemas. */
    -    merge(schema: ObjectSchema): ObjectSchema;
    +    merge<TOther extends object>(schema: ObjectSchema<TOther>): ObjectSchema<TValue & TOther>;
         /** Validate an input object; returns coerced values + per-field errors. */
    -    parse(input: unknown): ParseResult;
    +    parse(input: unknown): ParseResult<TValue>;
         describe(): SchemaDescriptor;
     }
     /** The fluent schema builder. */
     declare const v: {
    -    string: () => StringSchema;
    -    number: () => NumberSchema;
    +    string: () => StringSchema<string>;
    +    number: () => NumberSchema<number>;
         boolean: () => BooleanSchema;
         unknown: () => UnknownSchema;
    -    object: (fields: Record<string, FieldSchema>) => ObjectSchema;
    +    object: <TFields extends Record<string, FieldSchema>>(fields: TFields) => ObjectSchema<InferObjectFields<TFields>>;
     };
     /**
      * Validate environment variables against a schema at startup. Values are read
    @@ -333,14 +494,14 @@ declare const v: {
      *     PORT: v.number(),
      *   }));
      */
    -declare function parseEnv<T = Record<string, unknown>>(schema: ObjectSchema, source?: Record<string, string | undefined>): T;
    +declare function parseEnv<T extends object>(schema: ObjectSchema<T>, source?: Record<string, string | undefined>): T;
     /** A 400 response carrying field errors, for API routes. */
     declare function invalid(errors: Record<string, string>): Response;
     /**
      * Parse a request's JSON body against a schema. On failure returns
      * `{ ok: false, response }` (a ready 400); on success `{ ok: true, value }`.
      */
    -declare function parseBody<T = Record<string, unknown>>(schema: ObjectSchema, req: Request): Promise<{
    +declare function parseBody<T extends object>(schema: ObjectSchema<T>, req: Request): Promise<{
         ok: true;
         value: T;
     } | {
    @@ -348,7 +509,7 @@ declare function parseBody<T = Record<string, unknown>>(schema: Obje
         response: Response;
     }>;
     
    -export { type AnyFieldSchema, AsyncObjectSchema, type AsyncRefinement, type AsyncValidationContext, BooleanSchema, type FieldDescriptor, FieldSchema, NumberSchema, ObjectSchema, type OpenApiSchema, type ParseResult, type RuleDescriptor, type SchemaDescriptor, StringSchema, UnknownSchema, VALIDATE_RUNTIME, applyRule, asyncSchema, checkField, invalid, mergeValidationResults, parseBody, parseBodyAsync, parseEnv, renderSchemasScript, schemaToOpenApi, v };
    +export { type AnyFieldSchema, AsyncObjectSchema, type AsyncRefinement, type AsyncValidationContext, BooleanSchema, type ContractDefinition, type ContractIssue, type ContractKind, type ContractRecord, ContractRegistry, type ContractSnapshot, type FieldDescriptor, FieldSchema, type InferFieldValue, type InferObjectFields, type InferSchema, type JsonSchemaDocument, NumberSchema, ObjectSchema, type OpenApiSchema, type ParseResult, type RuleDescriptor, type SchemaDescriptor, StringSchema, UnknownSchema, VALIDATE_RUNTIME, ValidationError, type ValidationMessageKey, type ValidationMessageTranslator, applyRule, asyncSchema, checkContractCompatibility, checkField, defineContract, defineEvent, firstValidationError, invalid, localizeDescriptor, mergeValidationResults, openApiRequestBody, parseBody, parseBodyAsync, parseDescriptor, parseEnv, parseOrThrow, renderSchemasScript, schemaFieldNames, schemaToOpenApi, toJsonSchema, v, validationResponse, validationSummary };
     

    Examples

    Copy-ready examples from the installed package documentation.

    Define a schema and validate an API body

    import { v, parseBody } from "@wrnexus/validation";
     
     export const signupSchema = v.object({
    @@ -382,9 +543,9 @@ import { signupSchema } from "./app/schemas/signup.ts";
     const head = `<script>${renderSchemasScript({ signup: signupSchema.describe() })}</script>
     <script>${VALIDATE_RUNTIME}</script>`;
     // render a <form data-schema="signup"> with [data-error="email"] etc.
    - +
    - + } diff --git a/app/pages/releases/0.2.15.wrn b/app/pages/releases/0.2.15.wrn index 91d98f0c..7bbba1f6 100644 --- a/app/pages/releases/0.2.15.wrn +++ b/app/pages/releases/0.2.15.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0215 { seo { title = "Release 0.2.15" @@ -5,13 +9,58 @@ page Release0215 { canonical = "https://wrnexusjs.dev/releases/0.2.15" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.15

    Released 2026-07-12 in this documentation repository. Twenty-five installed packages are aligned to this version. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.15

    Released 2026-07-12 in this documentation repository. Twenty-five installed packages are aligned to this version. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.17.wrn b/app/pages/releases/0.2.17.wrn index 3e6a9aac..4b25c11f 100644 --- a/app/pages/releases/0.2.17.wrn +++ b/app/pages/releases/0.2.17.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0217 { seo { title = "Release 0.2.17" @@ -5,13 +9,58 @@ page Release0217 { canonical = "https://wrnexusjs.dev/releases/0.2.17" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.17

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.17

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.18.wrn b/app/pages/releases/0.2.18.wrn index 963408a8..1ab66643 100644 --- a/app/pages/releases/0.2.18.wrn +++ b/app/pages/releases/0.2.18.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0218 { seo { title = "Release 0.2.18" @@ -5,13 +9,58 @@ page Release0218 { canonical = "https://wrnexusjs.dev/releases/0.2.18" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.18

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.18

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.19.wrn b/app/pages/releases/0.2.19.wrn index 78108967..6bf95b3b 100644 --- a/app/pages/releases/0.2.19.wrn +++ b/app/pages/releases/0.2.19.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0219 { seo { title = "Release 0.2.19" @@ -5,13 +9,58 @@ page Release0219 { canonical = "https://wrnexusjs.dev/releases/0.2.19" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.19

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.19

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.20.wrn b/app/pages/releases/0.2.20.wrn index a571ed87..55938585 100644 --- a/app/pages/releases/0.2.20.wrn +++ b/app/pages/releases/0.2.20.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0220 { seo { title = "Release 0.2.20" @@ -5,13 +9,58 @@ page Release0220 { canonical = "https://wrnexusjs.dev/releases/0.2.20" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.20

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.20

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.21.wrn b/app/pages/releases/0.2.21.wrn index 31e32045..84e54e06 100644 --- a/app/pages/releases/0.2.21.wrn +++ b/app/pages/releases/0.2.21.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0221 { seo { title = "Release 0.2.21" @@ -5,13 +9,58 @@ page Release0221 { canonical = "https://wrnexusjs.dev/releases/0.2.21" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.21

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.21

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.22.wrn b/app/pages/releases/0.2.22.wrn index 37738a87..7bd6a1fa 100644 --- a/app/pages/releases/0.2.22.wrn +++ b/app/pages/releases/0.2.22.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0222 { seo { title = "Release 0.2.22" @@ -5,13 +9,58 @@ page Release0222 { canonical = "https://wrnexusjs.dev/releases/0.2.22" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.22

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.22

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.23.wrn b/app/pages/releases/0.2.23.wrn index 8adc5cf7..a3dfb699 100644 --- a/app/pages/releases/0.2.23.wrn +++ b/app/pages/releases/0.2.23.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0223 { seo { title = "Release 0.2.23" @@ -5,13 +9,58 @@ page Release0223 { canonical = "https://wrnexusjs.dev/releases/0.2.23" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.23

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.23

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.24.wrn b/app/pages/releases/0.2.24.wrn index 19d2b690..08f7dc4f 100644 --- a/app/pages/releases/0.2.24.wrn +++ b/app/pages/releases/0.2.24.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0224 { seo { title = "Release 0.2.24" @@ -5,13 +9,58 @@ page Release0224 { canonical = "https://wrnexusjs.dev/releases/0.2.24" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.24

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.24

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.25.wrn b/app/pages/releases/0.2.25.wrn index f4d11e7f..56a653af 100644 --- a/app/pages/releases/0.2.25.wrn +++ b/app/pages/releases/0.2.25.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0225 { seo { title = "Release 0.2.25" @@ -5,13 +9,58 @@ page Release0225 { canonical = "https://wrnexusjs.dev/releases/0.2.25" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.25

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.25

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.26.wrn b/app/pages/releases/0.2.26.wrn index 70ea8dcc..0ce04ff8 100644 --- a/app/pages/releases/0.2.26.wrn +++ b/app/pages/releases/0.2.26.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0226 { seo { title = "Release 0.2.26" @@ -5,13 +9,58 @@ page Release0226 { canonical = "https://wrnexusjs.dev/releases/0.2.26" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.26

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.26

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.27.wrn b/app/pages/releases/0.2.27.wrn index 7ac695ea..92e70e6e 100644 --- a/app/pages/releases/0.2.27.wrn +++ b/app/pages/releases/0.2.27.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0227 { seo { title = "Release 0.2.27" @@ -5,13 +9,58 @@ page Release0227 { canonical = "https://wrnexusjs.dev/releases/0.2.27" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.27

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.27

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.28.wrn b/app/pages/releases/0.2.28.wrn index 449bfb64..b34bc1c3 100644 --- a/app/pages/releases/0.2.28.wrn +++ b/app/pages/releases/0.2.28.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0228 { seo { title = "Release 0.2.28" @@ -5,13 +9,58 @@ page Release0228 { canonical = "https://wrnexusjs.dev/releases/0.2.28" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.28

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.28

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.29.wrn b/app/pages/releases/0.2.29.wrn index 4eb95bfe..5dd3ebc8 100644 --- a/app/pages/releases/0.2.29.wrn +++ b/app/pages/releases/0.2.29.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0229 { seo { title = "Release 0.2.29" @@ -5,13 +9,58 @@ page Release0229 { canonical = "https://wrnexusjs.dev/releases/0.2.29" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.29

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.29

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.30.wrn b/app/pages/releases/0.2.30.wrn index 69993e1f..99832133 100644 --- a/app/pages/releases/0.2.30.wrn +++ b/app/pages/releases/0.2.30.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0230 { seo { title = "Release 0.2.30" @@ -5,13 +9,58 @@ page Release0230 { canonical = "https://wrnexusjs.dev/releases/0.2.30" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.30

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.30

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.31.wrn b/app/pages/releases/0.2.31.wrn index 8446f250..a5e6b842 100644 --- a/app/pages/releases/0.2.31.wrn +++ b/app/pages/releases/0.2.31.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0231 { seo { title = "Release 0.2.31" @@ -5,13 +9,58 @@ page Release0231 { canonical = "https://wrnexusjs.dev/releases/0.2.31" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.31

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.31

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.32.wrn b/app/pages/releases/0.2.32.wrn index 675d4734..b4ffe9c3 100644 --- a/app/pages/releases/0.2.32.wrn +++ b/app/pages/releases/0.2.32.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0232 { seo { title = "Release 0.2.32" @@ -5,13 +9,58 @@ page Release0232 { canonical = "https://wrnexusjs.dev/releases/0.2.32" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.32

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.32

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.33.wrn b/app/pages/releases/0.2.33.wrn index 8c629a7d..43ee29b6 100644 --- a/app/pages/releases/0.2.33.wrn +++ b/app/pages/releases/0.2.33.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0233 { seo { title = "Release 0.2.33" @@ -5,13 +9,58 @@ page Release0233 { canonical = "https://wrnexusjs.dev/releases/0.2.33" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.33

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.33

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.34.wrn b/app/pages/releases/0.2.34.wrn index 277180bf..947d88ee 100644 --- a/app/pages/releases/0.2.34.wrn +++ b/app/pages/releases/0.2.34.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0234 { seo { title = "Release 0.2.34" @@ -5,13 +9,58 @@ page Release0234 { canonical = "https://wrnexusjs.dev/releases/0.2.34" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.34

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.34

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.35.wrn b/app/pages/releases/0.2.35.wrn index 054448f6..2c255202 100644 --- a/app/pages/releases/0.2.35.wrn +++ b/app/pages/releases/0.2.35.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0235 { seo { title = "Release 0.2.35" @@ -5,13 +9,58 @@ page Release0235 { canonical = "https://wrnexusjs.dev/releases/0.2.35" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.35

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.35

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.36.wrn b/app/pages/releases/0.2.36.wrn index 6a674ad7..a4074af6 100644 --- a/app/pages/releases/0.2.36.wrn +++ b/app/pages/releases/0.2.36.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0236 { seo { title = "Release 0.2.36" @@ -5,13 +9,58 @@ page Release0236 { canonical = "https://wrnexusjs.dev/releases/0.2.36" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.36

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.36

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.37.wrn b/app/pages/releases/0.2.37.wrn index 41643775..a6e72f58 100644 --- a/app/pages/releases/0.2.37.wrn +++ b/app/pages/releases/0.2.37.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0237 { seo { title = "Release 0.2.37" @@ -5,13 +9,58 @@ page Release0237 { canonical = "https://wrnexusjs.dev/releases/0.2.37" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.37

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.37

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.38.wrn b/app/pages/releases/0.2.38.wrn index ca3c938c..12a004b9 100644 --- a/app/pages/releases/0.2.38.wrn +++ b/app/pages/releases/0.2.38.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0238 { seo { title = "Release 0.2.38" @@ -5,13 +9,58 @@ page Release0238 { canonical = "https://wrnexusjs.dev/releases/0.2.38" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.38

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.38

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.39.wrn b/app/pages/releases/0.2.39.wrn index aa806f2d..770f39d6 100644 --- a/app/pages/releases/0.2.39.wrn +++ b/app/pages/releases/0.2.39.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0239 { seo { title = "Release 0.2.39" @@ -5,13 +9,58 @@ page Release0239 { canonical = "https://wrnexusjs.dev/releases/0.2.39" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.39

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.39

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.40.wrn b/app/pages/releases/0.2.40.wrn index f7af6c08..317ded84 100644 --- a/app/pages/releases/0.2.40.wrn +++ b/app/pages/releases/0.2.40.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0240 { seo { title = "Release 0.2.40" @@ -5,13 +9,58 @@ page Release0240 { canonical = "https://wrnexusjs.dev/releases/0.2.40" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.40

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.40

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.41.wrn b/app/pages/releases/0.2.41.wrn index b420468c..eba7d74a 100644 --- a/app/pages/releases/0.2.41.wrn +++ b/app/pages/releases/0.2.41.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0241 { seo { title = "Release 0.2.41" @@ -5,13 +9,58 @@ page Release0241 { canonical = "https://wrnexusjs.dev/releases/0.2.41" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.41

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.41

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.42.wrn b/app/pages/releases/0.2.42.wrn index 29d03142..f561f265 100644 --- a/app/pages/releases/0.2.42.wrn +++ b/app/pages/releases/0.2.42.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0242 { seo { title = "Release 0.2.42" @@ -5,13 +9,58 @@ page Release0242 { canonical = "https://wrnexusjs.dev/releases/0.2.42" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.42

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.42

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.43.wrn b/app/pages/releases/0.2.43.wrn index 0829e91e..16a90511 100644 --- a/app/pages/releases/0.2.43.wrn +++ b/app/pages/releases/0.2.43.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0243 { seo { title = "Release 0.2.43" @@ -5,13 +9,58 @@ page Release0243 { canonical = "https://wrnexusjs.dev/releases/0.2.43" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.43

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.43

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.44.wrn b/app/pages/releases/0.2.44.wrn index 65d8ca6b..7428ac72 100644 --- a/app/pages/releases/0.2.44.wrn +++ b/app/pages/releases/0.2.44.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0244 { seo { title = "Release 0.2.44" @@ -5,13 +9,58 @@ page Release0244 { canonical = "https://wrnexusjs.dev/releases/0.2.44" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.44

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.44

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.45.wrn b/app/pages/releases/0.2.45.wrn index e12d3ba9..c579e36b 100644 --- a/app/pages/releases/0.2.45.wrn +++ b/app/pages/releases/0.2.45.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0245 { seo { title = "Release 0.2.45" @@ -5,13 +9,58 @@ page Release0245 { canonical = "https://wrnexusjs.dev/releases/0.2.45" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.45

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.45

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.46.wrn b/app/pages/releases/0.2.46.wrn index 1ea0cf86..9d5f673a 100644 --- a/app/pages/releases/0.2.46.wrn +++ b/app/pages/releases/0.2.46.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0246 { seo { title = "Release 0.2.46" @@ -5,13 +9,58 @@ page Release0246 { canonical = "https://wrnexusjs.dev/releases/0.2.46" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.46

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.46

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.47.wrn b/app/pages/releases/0.2.47.wrn index 0d0c3dfa..88ac06b6 100644 --- a/app/pages/releases/0.2.47.wrn +++ b/app/pages/releases/0.2.47.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0247 { seo { title = "Release 0.2.47" @@ -5,13 +9,58 @@ page Release0247 { canonical = "https://wrnexusjs.dev/releases/0.2.47" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.47

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.47

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.48.wrn b/app/pages/releases/0.2.48.wrn index e09457c3..ea252765 100644 --- a/app/pages/releases/0.2.48.wrn +++ b/app/pages/releases/0.2.48.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0248 { seo { title = "Release 0.2.48" @@ -5,13 +9,58 @@ page Release0248 { canonical = "https://wrnexusjs.dev/releases/0.2.48" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.48

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.48

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.49.wrn b/app/pages/releases/0.2.49.wrn index e276d662..8a0765f6 100644 --- a/app/pages/releases/0.2.49.wrn +++ b/app/pages/releases/0.2.49.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0249 { seo { title = "Release 0.2.49" @@ -5,13 +9,58 @@ page Release0249 { canonical = "https://wrnexusjs.dev/releases/0.2.49" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.49

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.49

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.50.wrn b/app/pages/releases/0.2.50.wrn index d91ae857..51a36a9f 100644 --- a/app/pages/releases/0.2.50.wrn +++ b/app/pages/releases/0.2.50.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0250 { seo { title = "Release 0.2.50" @@ -5,13 +9,58 @@ page Release0250 { canonical = "https://wrnexusjs.dev/releases/0.2.50" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.50

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.50

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.51.wrn b/app/pages/releases/0.2.51.wrn index f827dce1..7c765ca6 100644 --- a/app/pages/releases/0.2.51.wrn +++ b/app/pages/releases/0.2.51.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0251 { seo { title = "Release 0.2.51" @@ -5,13 +9,58 @@ page Release0251 { canonical = "https://wrnexusjs.dev/releases/0.2.51" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.51

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.51

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.52.wrn b/app/pages/releases/0.2.52.wrn index d01ee1ac..d4fb98fd 100644 --- a/app/pages/releases/0.2.52.wrn +++ b/app/pages/releases/0.2.52.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0252 { seo { title = "Release 0.2.52" @@ -5,13 +9,58 @@ page Release0252 { canonical = "https://wrnexusjs.dev/releases/0.2.52" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.52

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.52

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.53.wrn b/app/pages/releases/0.2.53.wrn index 6d51d425..9ea984b0 100644 --- a/app/pages/releases/0.2.53.wrn +++ b/app/pages/releases/0.2.53.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0253 { seo { title = "Release 0.2.53" @@ -5,13 +9,58 @@ page Release0253 { canonical = "https://wrnexusjs.dev/releases/0.2.53" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.53

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.53

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.54.wrn b/app/pages/releases/0.2.54.wrn index b4d64799..7a0dacf7 100644 --- a/app/pages/releases/0.2.54.wrn +++ b/app/pages/releases/0.2.54.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0254 { seo { title = "Release 0.2.54" @@ -5,13 +9,58 @@ page Release0254 { canonical = "https://wrnexusjs.dev/releases/0.2.54" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.54

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.54

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.55.wrn b/app/pages/releases/0.2.55.wrn index 42215a8c..cffd015c 100644 --- a/app/pages/releases/0.2.55.wrn +++ b/app/pages/releases/0.2.55.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0255 { seo { title = "Release 0.2.55" @@ -5,13 +9,58 @@ page Release0255 { canonical = "https://wrnexusjs.dev/releases/0.2.55" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.55

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.55

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.56.wrn b/app/pages/releases/0.2.56.wrn index 1d5bb6da..585e9dc8 100644 --- a/app/pages/releases/0.2.56.wrn +++ b/app/pages/releases/0.2.56.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0256 { seo { title = "Release 0.2.56" @@ -5,13 +9,58 @@ page Release0256 { canonical = "https://wrnexusjs.dev/releases/0.2.56" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.56

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.56

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.57.wrn b/app/pages/releases/0.2.57.wrn index 0b7de4a1..c068a1e9 100644 --- a/app/pages/releases/0.2.57.wrn +++ b/app/pages/releases/0.2.57.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0257 { seo { title = "Release 0.2.57" @@ -5,13 +9,58 @@ page Release0257 { canonical = "https://wrnexusjs.dev/releases/0.2.57" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.57

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.57

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.58.wrn b/app/pages/releases/0.2.58.wrn index e51daa7a..19aeb061 100644 --- a/app/pages/releases/0.2.58.wrn +++ b/app/pages/releases/0.2.58.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0258 { seo { title = "Release 0.2.58" @@ -5,13 +9,58 @@ page Release0258 { canonical = "https://wrnexusjs.dev/releases/0.2.58" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.58

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.58

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.59.wrn b/app/pages/releases/0.2.59.wrn index fa3e2d55..6511dc45 100644 --- a/app/pages/releases/0.2.59.wrn +++ b/app/pages/releases/0.2.59.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0259 { seo { title = "Release 0.2.59" @@ -5,13 +9,58 @@ page Release0259 { canonical = "https://wrnexusjs.dev/releases/0.2.59" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.59

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.59

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.60.wrn b/app/pages/releases/0.2.60.wrn index fb3b9959..5fe868d8 100644 --- a/app/pages/releases/0.2.60.wrn +++ b/app/pages/releases/0.2.60.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0260 { seo { title = "Release 0.2.60" @@ -5,13 +9,58 @@ page Release0260 { canonical = "https://wrnexusjs.dev/releases/0.2.60" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.60

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.60

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.61.wrn b/app/pages/releases/0.2.61.wrn index 192ed752..fe0ffb46 100644 --- a/app/pages/releases/0.2.61.wrn +++ b/app/pages/releases/0.2.61.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0261 { seo { title = "Release 0.2.61" @@ -5,13 +9,58 @@ page Release0261 { canonical = "https://wrnexusjs.dev/releases/0.2.61" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.61

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.61

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.62.wrn b/app/pages/releases/0.2.62.wrn index f7a8c45f..4adb87bf 100644 --- a/app/pages/releases/0.2.62.wrn +++ b/app/pages/releases/0.2.62.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0262 { seo { title = "Release 0.2.62" @@ -5,13 +9,58 @@ page Release0262 { canonical = "https://wrnexusjs.dev/releases/0.2.62" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.62

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.62

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.63.wrn b/app/pages/releases/0.2.63.wrn index 724ff58f..3511ef63 100644 --- a/app/pages/releases/0.2.63.wrn +++ b/app/pages/releases/0.2.63.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0263 { seo { title = "Release 0.2.63" @@ -5,13 +9,58 @@ page Release0263 { canonical = "https://wrnexusjs.dev/releases/0.2.63" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.63

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.63

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.64.wrn b/app/pages/releases/0.2.64.wrn index 03e00d35..ad5b8be7 100644 --- a/app/pages/releases/0.2.64.wrn +++ b/app/pages/releases/0.2.64.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0264 { seo { title = "Release 0.2.64" @@ -5,13 +9,60 @@ page Release0264 { canonical = "https://wrnexusjs.dev/releases/0.2.64" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.64

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.64

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.65.wrn b/app/pages/releases/0.2.65.wrn index 1fa800ea..7611bec8 100644 --- a/app/pages/releases/0.2.65.wrn +++ b/app/pages/releases/0.2.65.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0265 { seo { title = "Release 0.2.65" @@ -5,13 +9,60 @@ page Release0265 { canonical = "https://wrnexusjs.dev/releases/0.2.65" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.65

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.65

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.66.wrn b/app/pages/releases/0.2.66.wrn index be5ebc50..a899bac4 100644 --- a/app/pages/releases/0.2.66.wrn +++ b/app/pages/releases/0.2.66.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0266 { seo { title = "Release 0.2.66" @@ -5,13 +9,60 @@ page Release0266 { canonical = "https://wrnexusjs.dev/releases/0.2.66" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.66

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.66

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.67.wrn b/app/pages/releases/0.2.67.wrn index 66938815..7e425270 100644 --- a/app/pages/releases/0.2.67.wrn +++ b/app/pages/releases/0.2.67.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0267 { seo { title = "Release 0.2.67" @@ -5,13 +9,60 @@ page Release0267 { canonical = "https://wrnexusjs.dev/releases/0.2.67" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.67

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.67

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.68.wrn b/app/pages/releases/0.2.68.wrn index 0bba1e46..2c27106b 100644 --- a/app/pages/releases/0.2.68.wrn +++ b/app/pages/releases/0.2.68.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0268 { seo { title = "Release 0.2.68" @@ -5,13 +9,60 @@ page Release0268 { canonical = "https://wrnexusjs.dev/releases/0.2.68" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.68

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.68

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.69.wrn b/app/pages/releases/0.2.69.wrn index 90abde39..9974cdc0 100644 --- a/app/pages/releases/0.2.69.wrn +++ b/app/pages/releases/0.2.69.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0269 { seo { title = "Release 0.2.69" @@ -5,13 +9,60 @@ page Release0269 { canonical = "https://wrnexusjs.dev/releases/0.2.69" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.69

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.69

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.70.wrn b/app/pages/releases/0.2.70.wrn index 0de39a2c..4cb80653 100644 --- a/app/pages/releases/0.2.70.wrn +++ b/app/pages/releases/0.2.70.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0270 { seo { title = "Release 0.2.70" @@ -5,13 +9,60 @@ page Release0270 { canonical = "https://wrnexusjs.dev/releases/0.2.70" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.70

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.70

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.71.wrn b/app/pages/releases/0.2.71.wrn index d9b15da1..b19cd2cc 100644 --- a/app/pages/releases/0.2.71.wrn +++ b/app/pages/releases/0.2.71.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0271 { seo { title = "Release 0.2.71" @@ -5,13 +9,60 @@ page Release0271 { canonical = "https://wrnexusjs.dev/releases/0.2.71" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.71

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.71

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.72.wrn b/app/pages/releases/0.2.72.wrn index 9852078c..3471475c 100644 --- a/app/pages/releases/0.2.72.wrn +++ b/app/pages/releases/0.2.72.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0272 { seo { title = "Release 0.2.72" @@ -5,13 +9,60 @@ page Release0272 { canonical = "https://wrnexusjs.dev/releases/0.2.72" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.72

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.72

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.73.wrn b/app/pages/releases/0.2.73.wrn index 9568aeb9..2bd5a915 100644 --- a/app/pages/releases/0.2.73.wrn +++ b/app/pages/releases/0.2.73.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0273 { seo { title = "Release 0.2.73" @@ -5,13 +9,60 @@ page Release0273 { canonical = "https://wrnexusjs.dev/releases/0.2.73" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.73

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.73

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.74.wrn b/app/pages/releases/0.2.74.wrn index c4d8b037..980e1685 100644 --- a/app/pages/releases/0.2.74.wrn +++ b/app/pages/releases/0.2.74.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0274 { seo { title = "Release 0.2.74" @@ -5,13 +9,60 @@ page Release0274 { canonical = "https://wrnexusjs.dev/releases/0.2.74" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.74

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.74

    Released 2026-07-13. All 26 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.75.wrn b/app/pages/releases/0.2.75.wrn index c91918a1..63199143 100644 --- a/app/pages/releases/0.2.75.wrn +++ b/app/pages/releases/0.2.75.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0275 { seo { title = "Release 0.2.75" @@ -5,13 +9,60 @@ page Release0275 { canonical = "https://wrnexusjs.dev/releases/0.2.75" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.75

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.75

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.76.wrn b/app/pages/releases/0.2.76.wrn index 937d10b3..9c2b7ee0 100644 --- a/app/pages/releases/0.2.76.wrn +++ b/app/pages/releases/0.2.76.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0276 { seo { title = "Release 0.2.76" @@ -5,13 +9,60 @@ page Release0276 { canonical = "https://wrnexusjs.dev/releases/0.2.76" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.76

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.76

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.77.wrn b/app/pages/releases/0.2.77.wrn index aaece36d..af401ce9 100644 --- a/app/pages/releases/0.2.77.wrn +++ b/app/pages/releases/0.2.77.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0277 { seo { title = "Release 0.2.77" @@ -5,13 +9,60 @@ page Release0277 { canonical = "https://wrnexusjs.dev/releases/0.2.77" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.77

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.77

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.78.wrn b/app/pages/releases/0.2.78.wrn index cae1b55b..cb0eacfa 100644 --- a/app/pages/releases/0.2.78.wrn +++ b/app/pages/releases/0.2.78.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0278 { seo { title = "Release 0.2.78" @@ -5,13 +9,60 @@ page Release0278 { canonical = "https://wrnexusjs.dev/releases/0.2.78" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.78

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.78

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.2.79.wrn b/app/pages/releases/0.2.79.wrn index 9f08449f..f3421ea7 100644 --- a/app/pages/releases/0.2.79.wrn +++ b/app/pages/releases/0.2.79.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0279 { seo { title = "Release 0.2.79" @@ -5,13 +9,60 @@ page Release0279 { canonical = "https://wrnexusjs.dev/releases/0.2.79" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.2.79

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.2.79

    Released 2026-07-13. All 27 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.0.wrn b/app/pages/releases/0.3.0.wrn index 9293fd74..aa7fdb47 100644 --- a/app/pages/releases/0.3.0.wrn +++ b/app/pages/releases/0.3.0.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release030 { seo { title = "Release 0.3.0" @@ -5,13 +9,60 @@ page Release030 { canonical = "https://wrnexusjs.dev/releases/0.3.0" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.0

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.0

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.1.wrn b/app/pages/releases/0.3.1.wrn index c37dd4a2..5fc3eb99 100644 --- a/app/pages/releases/0.3.1.wrn +++ b/app/pages/releases/0.3.1.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release031 { seo { title = "Release 0.3.1" @@ -5,13 +9,60 @@ page Release031 { canonical = "https://wrnexusjs.dev/releases/0.3.1" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.1

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.1

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.2.wrn b/app/pages/releases/0.3.2.wrn index 31cd0cd5..b1f20082 100644 --- a/app/pages/releases/0.3.2.wrn +++ b/app/pages/releases/0.3.2.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release032 { seo { title = "Release 0.3.2" @@ -5,13 +9,60 @@ page Release032 { canonical = "https://wrnexusjs.dev/releases/0.3.2" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.2

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.2

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.3.wrn b/app/pages/releases/0.3.3.wrn index c41e631d..95c2e59b 100644 --- a/app/pages/releases/0.3.3.wrn +++ b/app/pages/releases/0.3.3.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release033 { seo { title = "Release 0.3.3" @@ -5,13 +9,60 @@ page Release033 { canonical = "https://wrnexusjs.dev/releases/0.3.3" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.3

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.3

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.4.wrn b/app/pages/releases/0.3.4.wrn index a6dd30cb..63e9fa31 100644 --- a/app/pages/releases/0.3.4.wrn +++ b/app/pages/releases/0.3.4.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release034 { seo { title = "Release 0.3.4" @@ -5,13 +9,60 @@ page Release034 { canonical = "https://wrnexusjs.dev/releases/0.3.4" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.4

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.4

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.5.wrn b/app/pages/releases/0.3.5.wrn index e035ef99..2374f39f 100644 --- a/app/pages/releases/0.3.5.wrn +++ b/app/pages/releases/0.3.5.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release035 { seo { title = "Release 0.3.5" @@ -5,13 +9,60 @@ page Release035 { canonical = "https://wrnexusjs.dev/releases/0.3.5" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.5

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.5

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.3.6.wrn b/app/pages/releases/0.3.6.wrn index 032f4985..d55112f3 100644 --- a/app/pages/releases/0.3.6.wrn +++ b/app/pages/releases/0.3.6.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release036 { seo { title = "Release 0.3.6" @@ -5,13 +9,60 @@ page Release036 { canonical = "https://wrnexusjs.dev/releases/0.3.6" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.3.6

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.3.6

    Released 2026-07-13. All 29 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.4.0.wrn b/app/pages/releases/0.4.0.wrn index 00820f6c..bca3ebe8 100644 --- a/app/pages/releases/0.4.0.wrn +++ b/app/pages/releases/0.4.0.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release040 { seo { title = "Release 0.4.0" @@ -5,13 +9,60 @@ page Release040 { canonical = "https://wrnexusjs.dev/releases/0.4.0" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.4.0

    Released 2026-07-13. All 30 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.4.0

    Released 2026-07-13. All 30 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.5.0.wrn b/app/pages/releases/0.5.0.wrn index 7f550455..eb2a78c5 100644 --- a/app/pages/releases/0.5.0.wrn +++ b/app/pages/releases/0.5.0.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release050 { seo { title = "Release 0.5.0" @@ -5,13 +9,60 @@ page Release050 { canonical = "https://wrnexusjs.dev/releases/0.5.0" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.5.0

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.5.0

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.5.1.wrn b/app/pages/releases/0.5.1.wrn index 864dc3d2..ec923e8c 100644 --- a/app/pages/releases/0.5.1.wrn +++ b/app/pages/releases/0.5.1.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release051 { seo { title = "Release 0.5.1" @@ -5,13 +9,60 @@ page Release051 { canonical = "https://wrnexusjs.dev/releases/0.5.1" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.5.1

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.5.1

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.5.10.wrn b/app/pages/releases/0.5.10.wrn index beaacd07..e3702977 100644 --- a/app/pages/releases/0.5.10.wrn +++ b/app/pages/releases/0.5.10.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0510 { seo { title = "Release 0.5.10" @@ -5,13 +9,60 @@ page Release0510 { canonical = "https://wrnexusjs.dev/releases/0.5.10" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.5.10

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.5.10

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.5.11.wrn b/app/pages/releases/0.5.11.wrn index 4c20b7ec..5fa43483 100644 --- a/app/pages/releases/0.5.11.wrn +++ b/app/pages/releases/0.5.11.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0511 { seo { title = "Release 0.5.11" @@ -5,13 +9,60 @@ page Release0511 { canonical = "https://wrnexusjs.dev/releases/0.5.11" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.5.11

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.5.11

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.5.12.wrn b/app/pages/releases/0.5.12.wrn index 5e496487..286fc963 100644 --- a/app/pages/releases/0.5.12.wrn +++ b/app/pages/releases/0.5.12.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0512 { seo { title = "Release 0.5.12" @@ -5,13 +9,60 @@ page Release0512 { canonical = "https://wrnexusjs.dev/releases/0.5.12" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.5.12

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.5.12

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.5.13.wrn b/app/pages/releases/0.5.13.wrn index 403c5d55..71b1d36f 100644 --- a/app/pages/releases/0.5.13.wrn +++ b/app/pages/releases/0.5.13.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release0513 { seo { title = "Release 0.5.13" @@ -5,13 +9,60 @@ page Release0513 { canonical = "https://wrnexusjs.dev/releases/0.5.13" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.5.13

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.5.13

    Released 2026-07-13. All 31 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.6.0.wrn b/app/pages/releases/0.6.0.wrn index 8445fee8..510b3b7d 100644 --- a/app/pages/releases/0.6.0.wrn +++ b/app/pages/releases/0.6.0.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release060 { seo { title = "Release 0.6.0" @@ -5,13 +9,60 @@ page Release060 { canonical = "https://wrnexusjs.dev/releases/0.6.0" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.6.0

    Released 2026-07-13. All 33 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.6.0

    Released 2026-07-13. All 33 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.7.0.wrn b/app/pages/releases/0.7.0.wrn index c09ad8f2..b9765e63 100644 --- a/app/pages/releases/0.7.0.wrn +++ b/app/pages/releases/0.7.0.wrn @@ -1,3 +1,7 @@ +import { + BackToTop, + } from "@wrnexus/ui" + page Release070 { seo { title = "Release 0.7.0" @@ -5,13 +9,60 @@ page Release070 { canonical = "https://wrnexusjs.dev/releases/0.7.0" } view { - -
    -
    W WRNexusJS
    - -

    WRNexusJS 0.7.0

    Released 2026-07-13. All 38 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    - - -
    - } -} \ No newline at end of file + +
    +
    + + + W WRNexusJS +
    + +
    +

    WRNexusJS 0.7.0

    Released 2026-07-13. All 38 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    +
    + + +
    + } + } diff --git a/app/pages/releases/0.8.0.wrn b/app/pages/releases/0.8.0.wrn new file mode 100644 index 00000000..daab3470 --- /dev/null +++ b/app/pages/releases/0.8.0.wrn @@ -0,0 +1,17 @@ +page Release080 { + seo { + title = "Release 0.8.0" + description = "WRNexusJS 0.8.0 release notes." + canonical = "https://wrnexusjs.dev/releases/0.8.0" + } + view { + +
    +
    W WRNexusJS
    + +

    WRNexusJS 0.8.0

    Released 2026-07-13. All 46 installed packages are aligned to this version. Highlights include the new helpers package, reliable workspace app addition, and browser SSO redirects through forward authentication. See the changelog, upgrade guide, and package references.

    + + +
    + } +} \ No newline at end of file diff --git a/app/pages/roadmap.wrn b/app/pages/roadmap.wrn index 074a4e8a..bea3fc92 100644 --- a/app/pages/roadmap.wrn +++ b/app/pages/roadmap.wrn @@ -7,10 +7,10 @@ page Roadmap { view {
    -
    W WRNexusJS
    +
    W WRNexusJS

    Roadmap

    Roadmap items are direction, not delivery commitments. Dates require explicit owner approval.

    Now

    • Private preview onboarding and accurate package references
    • Runnable documentation fixtures and link/accessibility checks
    • License, support, and disclosure owner decisions

    Next

    • Durable queue driver guidance
    • Expanded database/auth/realtime examples
    • Versioned release notes and migration fixtures

    Later / exploration

    • Historical documentation selector
    • Maintained reproducible benchmarks
    • Broader mobile/native coverage
    - +
    } diff --git a/app/pages/search.wrn b/app/pages/search.wrn index 34ea127b..b564e397 100644 --- a/app/pages/search.wrn +++ b/app/pages/search.wrn @@ -7,10 +7,10 @@ page Search { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -

    Search documentation

    This build-time index is local and sends no query to a third party. Use your browser’s find command to filter this compact index.

    Core documentation

    Get started · Packages · Components · Language · Architecture

    Guides

    Project structure · Routing · Pages and components · Server data · API routes · Middleware · Forms and validation · Authentication · Authorization · Application security · Database · Uploads · Realtime · Pub/sub · Queues · Testing · Workspaces and gateway · Deployment · Configuration and profiles · Internationalization and themes · Mobile · Observability · Upgrading · Troubleshooting

    Package APIs

    @wrnexus/ai · @wrnexus/authz · @wrnexus/compiler · @wrnexus/core · @wrnexus/csr · @wrnexus/db · @wrnexus/dev-server · @wrnexus/encryption · @wrnexus/helpers · @wrnexus/i18n · @wrnexus/jwt · @wrnexus/mobile · @wrnexus/native · @wrnexus/oauth · @wrnexus/pubsub · @wrnexus/queue · @wrnexus/reactive · @wrnexus/router · @wrnexus/ssr · @wrnexus/styles · @wrnexus/test · @wrnexus/tracking · @wrnexus/ui · @wrnexus/uploader · @wrnexus/validation · @wrnexus/dev-toolbar · @wrnexus/syntax · @wrnexus/plugin · @wrnexus/captcha · @wrnexus/auth · @wrnexus/store · @wrnexus/typecheck · @wrnexus/security · @wrnexus/cache · @wrnexus/image · @wrnexus/observability · @wrnexus/benchmark · @wrnexus/cli

    - +

    Search documentation

    This build-time index is local and sends no query to a third party. Use your browser’s find command to filter this compact index.

    Core documentation

    Get started · Packages · Components · Language · Architecture

    Guides

    Project structure · Routing · Pages and components · Server data · API routes · Middleware · Forms and validation · Authentication · Authorization · Application security · Database · Uploads · Realtime · Pub/sub · Queues · Testing · Workspaces and gateway · Deployment · Configuration and profiles · Internationalization and themes · Mobile · Observability · Upgrading · Troubleshooting

    Package APIs

    @wrnexus/ai · @wrnexus/authz · @wrnexus/compiler · @wrnexus/core · @wrnexus/csr · @wrnexus/db · @wrnexus/dev-server · @wrnexus/encryption · @wrnexus/helpers · @wrnexus/i18n · @wrnexus/jwt · @wrnexus/mobile · @wrnexus/native · @wrnexus/oauth · @wrnexus/pubsub · @wrnexus/queue · @wrnexus/reactive · @wrnexus/router · @wrnexus/ssr · @wrnexus/styles · @wrnexus/test · @wrnexus/tracking · @wrnexus/ui · @wrnexus/uploader · @wrnexus/validation · @wrnexus/dev-toolbar · @wrnexus/syntax · @wrnexus/plugin · @wrnexus/captcha · @wrnexus/auth · @wrnexus/store · @wrnexus/typecheck · @wrnexus/security · @wrnexus/cache · @wrnexus/image · @wrnexus/observability · @wrnexus/benchmark · @wrnexus/realtime · @wrnexus/content · @wrnexus/graphql · @wrnexus/identity · @wrnexus/language-server · @wrnexus/mcp · @wrnexus/playground · @wrnexus/pwa · @wrnexus/cli

    +
    } diff --git a/app/pages/security.wrn b/app/pages/security.wrn index 446db465..72c037d3 100644 --- a/app/pages/security.wrn +++ b/app/pages/security.wrn @@ -7,10 +7,10 @@ page Security { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -

    Security

    WRNexusJS provides primitives for CSP, CSRF, Trusted Types, sessions, validation, authorization, encryption, upload restrictions, request limits, and WebSocket-origin checks. Applications remain responsible for correct configuration, business authorization, secrets, dependencies, data protection, and operations.

    Supported releases

    Only the current private-preview release 0.7.0 is documented here. A formal old-release support window is not yet published.

    Report a vulnerability

    Use WorkRoot’s approved private contact path at workroot.in. Do not publish exploit details or secrets. Include affected version, impact, reproduction, and a safe contact method. Response targets, encryption key, bounty, audit, and certification are not currently claimed.

    Deployment controls

    Use restrictive CSP and permissions policies, HSTS only on HTTPS production origins, MIME sniffing protection, restrictive referrers, explicit CORS, secure cookies, CSRF validation, request limits, and origin checks. See application security.

    - +

    Security

    WRNexusJS provides primitives for CSP, CSRF, Trusted Types, sessions, validation, authorization, encryption, upload restrictions, request limits, and WebSocket-origin checks. Applications remain responsible for correct configuration, business authorization, secrets, dependencies, data protection, and operations.

    Supported releases

    Only the current private-preview release 0.8.0 is documented here. A formal old-release support window is not yet published.

    Report a vulnerability

    Use WorkRoot’s approved private contact path at workroot.in. Do not publish exploit details or secrets. Include affected version, impact, reproduction, and a safe contact method. Response targets, encryption key, bounty, audit, and certification are not currently claimed.

    Deployment controls

    Use restrictive CSP and permissions policies, HSTS only on HTTPS production origins, MIME sniffing protection, restrictive referrers, explicit CORS, secure cookies, CSRF validation, request limits, and origin checks. See application security.

    +
    } diff --git a/app/pages/showcase.wrn b/app/pages/showcase.wrn index 6fb87782..77a21e29 100644 --- a/app/pages/showcase.wrn +++ b/app/pages/showcase.wrn @@ -7,10 +7,10 @@ page Showcase { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -

    Showcase

    Only confirmed public properties are listed; no customer or traffic claims are made.

    WorkRoot

    Creator/company site demonstrating a public WRNexusJS deployment. Exact deployed version and infrastructure notes await owner confirmation.

    WRNexusJS docs

    This documentation portal, built and verified against WRNexusJS 0.7.0 on Bun.

    Screenshots are intentionally deferred until approved assets and alt text are available.

    - +

    Showcase

    Only confirmed public properties are listed; no customer or traffic claims are made.

    WorkRoot

    Creator/company site demonstrating a public WRNexusJS deployment. Exact deployed version and infrastructure notes await owner confirmation.

    WRNexusJS docs

    This documentation portal, built and verified against WRNexusJS 0.8.0 on Bun.

    Screenshots are intentionally deferred until approved assets and alt text are available.

    +
    } diff --git a/app/pages/support.wrn b/app/pages/support.wrn index 21ae3098..4c6123af 100644 --- a/app/pages/support.wrn +++ b/app/pages/support.wrn @@ -7,10 +7,10 @@ page Support { view {
    -
    W WRNexusJS
    +
    W WRNexusJS

    Support

    WRNexusJS has no public Discord, public issue tracker, or guaranteed community support channel listed by this repository. Preview access and support begin through WorkRoot’s public contact path.

    Include WRNexusJS version, Bun version, OS, a minimal reproduction, expected and actual behavior, and sanitized logs. Never include registry tokens, credentials, session cookies, or private data.

    Support scope, service levels, and commercial terms require owner confirmation.

    - +
    } diff --git a/app/pages/tutorial.wrn b/app/pages/tutorial.wrn index 56f23bea..6b9666cb 100644 --- a/app/pages/tutorial.wrn +++ b/app/pages/tutorial.wrn @@ -7,9 +7,9 @@ page Tutorial { view {
    -
    W WRNexusJS
    +
    W WRNexusJS
    -
    Preview · runnable-project extraction pending

    Secure task board

    This tutorial connects the installed 0.7.0 APIs into one design. Snippets are limited to declarations and README patterns verified in the installed packages; a CI-compiled standalone fixture remains on the roadmap.

    Application shape

    A .wrn page renders tasks from an SSR API binding. A shared validation schema protects mutations. Session middleware identifies users, authorization policies gate updates, and a realtime room broadcasts changes.

    Schema and create route

    import { v, parseBody } from "@wrnexus/validation";
    +      
    Preview · runnable-project extraction pending

    Secure task board

    This tutorial connects the installed 0.8.0 APIs into one design. Snippets are limited to declarations and README patterns verified in the installed packages; a CI-compiled standalone fixture remains on the roadmap.

    Application shape

    A .wrn page renders tasks from an SSR API binding. A shared validation schema protects mutations. Session middleware identifies users, authorization policies gate updates, and a realtime room broadcasts changes.

    Schema and create route

    import { v, parseBody } from "@wrnexus/validation";
     const task = v.object({ title: v.string().trim().min(3).max(120) });
     export const POST = async (ctx) => {
       const parsed = await parseBody(task, ctx.req);
    @@ -23,7 +23,7 @@ export const POST = async (ctx) => {
         </ul></main>
       }
     }

    Production checklist

    • Choose SQLite for local development or configure the supported PostgreSQL driver.
    • Run migrations before accepting traffic.
    • Enable session authentication and enforce authorization on every mutation.
    • Validate upload types and sizes; keep private objects behind authenticated routes.
    • Use Redis pub/sub when realtime rooms span processes.
    • Treat the default queue as non-durable until a production driver is selected.

    Follow the focused database, authentication, authorization, realtime, and upload guides.

    - +
    } diff --git a/app/routes.gen.ts b/app/routes.gen.ts index 248c8ee5..ac2b1c27 100644 --- a/app/routes.gen.ts +++ b/app/routes.gen.ts @@ -1,53 +1,593 @@ -// AUTO-GENERATED by `wrnexus dev` — do not edit. -// Typed routes: a compile-time map of every page path to its [param] types, -// plus an href() builder that fills params and rejects unknown paths. +// AUTO-GENERATED by `wrnexus dev` - do not edit. +// Typed routes support required, optional, and catch-all parameters. export interface Routes { "/": Record; + "/404": Record; + "/access": Record; "/architecture": Record; + "/benchmarks": Record; + "/changelog": Record; + "/examples": Record; "/getting-started": Record; + "/guides/api-routes": Record; + "/guides/authentication": Record; + "/guides/authorization": Record; + "/guides/configuration-and-profiles": Record; + "/guides/database": Record; + "/guides/deployment": Record; + "/guides/forms-and-validation": Record; + "/guides/i18n-and-themes": Record; + "/guides/middleware": Record; + "/guides/mobile": Record; + "/guides/observability": Record; + "/guides/pages-and-components": Record; + "/guides/project-structure": Record; + "/guides/pubsub": Record; + "/guides/queues": Record; + "/guides/realtime": Record; + "/guides/routing": Record; + "/guides/security": Record; + "/guides/server-data": Record; + "/guides/testing": Record; + "/guides/troubleshooting": Record; + "/guides/upgrading": Record; + "/guides/uploads": Record; + "/guides/workspaces-and-gateway": Record; "/language": Record; + "/license": Record; "/packages": Record; "/packages/ai": Record; + "/packages/auth": Record; "/packages/authz": Record; + "/packages/benchmark": Record; + "/packages/cache": Record; + "/packages/captcha": Record; "/packages/cli": Record; "/packages/compiler": Record; + "/packages/content": Record; "/packages/core": Record; "/packages/csr": Record; "/packages/db": Record; "/packages/dev-server": Record; + "/packages/dev-toolbar": Record; "/packages/encryption": Record; + "/packages/graphql": Record; + "/packages/helpers": Record; "/packages/i18n": Record; + "/packages/identity": Record; + "/packages/image": Record; "/packages/jwt": Record; + "/packages/language-server": Record; + "/packages/mcp": Record; "/packages/mobile": Record; "/packages/native": Record; "/packages/oauth": Record; + "/packages/observability": Record; + "/packages/playground": Record; + "/packages/plugin": Record; "/packages/pubsub": Record; + "/packages/pwa": Record; "/packages/queue": Record; "/packages/reactive": Record; + "/packages/realtime": Record; "/packages/router": Record; + "/packages/security": Record; "/packages/ssr": Record; + "/packages/store": Record; "/packages/styles": Record; + "/packages/syntax": Record; "/packages/test": Record; "/packages/tracking": Record; + "/packages/typecheck": Record; "/packages/ui": Record; "/packages/uploader": Record; "/packages/validation": Record; + "/releases/0.2.15": Record; + "/releases/0.2.17": Record; + "/releases/0.2.18": Record; + "/releases/0.2.19": Record; + "/releases/0.2.20": Record; + "/releases/0.2.21": Record; + "/releases/0.2.22": Record; + "/releases/0.2.23": Record; + "/releases/0.2.24": Record; + "/releases/0.2.25": Record; + "/releases/0.2.26": Record; + "/releases/0.2.27": Record; + "/releases/0.2.28": Record; + "/releases/0.2.29": Record; + "/releases/0.2.30": Record; + "/releases/0.2.31": Record; + "/releases/0.2.32": Record; + "/releases/0.2.33": Record; + "/releases/0.2.34": Record; + "/releases/0.2.35": Record; + "/releases/0.2.36": Record; + "/releases/0.2.37": Record; + "/releases/0.2.38": Record; + "/releases/0.2.39": Record; + "/releases/0.2.40": Record; + "/releases/0.2.41": Record; + "/releases/0.2.42": Record; + "/releases/0.2.43": Record; + "/releases/0.2.44": Record; + "/releases/0.2.45": Record; + "/releases/0.2.46": Record; + "/releases/0.2.47": Record; + "/releases/0.2.48": Record; + "/releases/0.2.49": Record; + "/releases/0.2.50": Record; + "/releases/0.2.51": Record; + "/releases/0.2.52": Record; + "/releases/0.2.53": Record; + "/releases/0.2.54": Record; + "/releases/0.2.55": Record; + "/releases/0.2.56": Record; + "/releases/0.2.57": Record; + "/releases/0.2.58": Record; + "/releases/0.2.59": Record; + "/releases/0.2.60": Record; + "/releases/0.2.61": Record; + "/releases/0.2.62": Record; + "/releases/0.2.63": Record; + "/releases/0.2.64": Record; + "/releases/0.2.65": Record; + "/releases/0.2.66": Record; + "/releases/0.2.67": Record; + "/releases/0.2.68": Record; + "/releases/0.2.69": Record; + "/releases/0.2.70": Record; + "/releases/0.2.71": Record; + "/releases/0.2.72": Record; + "/releases/0.2.73": Record; + "/releases/0.2.74": Record; + "/releases/0.2.75": Record; + "/releases/0.2.76": Record; + "/releases/0.2.77": Record; + "/releases/0.2.78": Record; + "/releases/0.2.79": Record; + "/releases/0.3.0": Record; + "/releases/0.3.1": Record; + "/releases/0.3.2": Record; + "/releases/0.3.3": Record; + "/releases/0.3.4": Record; + "/releases/0.3.5": Record; + "/releases/0.3.6": Record; + "/releases/0.4.0": Record; + "/releases/0.5.0": Record; + "/releases/0.5.1": Record; + "/releases/0.5.10": Record; + "/releases/0.5.11": Record; + "/releases/0.5.12": Record; + "/releases/0.5.13": Record; + "/releases/0.6.0": Record; + "/releases/0.7.0": Record; + "/releases/0.8.0": Record; + "/roadmap": Record; + "/search": Record; + "/security": Record; + "/showcase": Record; + "/support": Record; + "/tutorial": Record; +} + +export interface RouteNames { + "index": "/"; + "404": "/404"; + "access": "/access"; + "architecture": "/architecture"; + "benchmarks": "/benchmarks"; + "changelog": "/changelog"; + "examples": "/examples"; + "getting.started": "/getting-started"; + "guides.api.routes": "/guides/api-routes"; + "guides.authentication": "/guides/authentication"; + "guides.authorization": "/guides/authorization"; + "guides.configuration.and.profiles": "/guides/configuration-and-profiles"; + "guides.database": "/guides/database"; + "guides.deployment": "/guides/deployment"; + "guides.forms.and.validation": "/guides/forms-and-validation"; + "guides.i18n.and.themes": "/guides/i18n-and-themes"; + "guides.middleware": "/guides/middleware"; + "guides.mobile": "/guides/mobile"; + "guides.observability": "/guides/observability"; + "guides.pages.and.components": "/guides/pages-and-components"; + "guides.project.structure": "/guides/project-structure"; + "guides.pubsub": "/guides/pubsub"; + "guides.queues": "/guides/queues"; + "guides.realtime": "/guides/realtime"; + "guides.routing": "/guides/routing"; + "guides.security": "/guides/security"; + "guides.server.data": "/guides/server-data"; + "guides.testing": "/guides/testing"; + "guides.troubleshooting": "/guides/troubleshooting"; + "guides.upgrading": "/guides/upgrading"; + "guides.uploads": "/guides/uploads"; + "guides.workspaces.and.gateway": "/guides/workspaces-and-gateway"; + "language": "/language"; + "license": "/license"; + "packages": "/packages"; + "packages.ai": "/packages/ai"; + "packages.auth": "/packages/auth"; + "packages.authz": "/packages/authz"; + "packages.benchmark": "/packages/benchmark"; + "packages.cache": "/packages/cache"; + "packages.captcha": "/packages/captcha"; + "packages.cli": "/packages/cli"; + "packages.compiler": "/packages/compiler"; + "packages.content": "/packages/content"; + "packages.core": "/packages/core"; + "packages.csr": "/packages/csr"; + "packages.db": "/packages/db"; + "packages.dev.server": "/packages/dev-server"; + "packages.dev.toolbar": "/packages/dev-toolbar"; + "packages.encryption": "/packages/encryption"; + "packages.graphql": "/packages/graphql"; + "packages.helpers": "/packages/helpers"; + "packages.i18n": "/packages/i18n"; + "packages.identity": "/packages/identity"; + "packages.image": "/packages/image"; + "packages.jwt": "/packages/jwt"; + "packages.language.server": "/packages/language-server"; + "packages.mcp": "/packages/mcp"; + "packages.mobile": "/packages/mobile"; + "packages.native": "/packages/native"; + "packages.oauth": "/packages/oauth"; + "packages.observability": "/packages/observability"; + "packages.playground": "/packages/playground"; + "packages.plugin": "/packages/plugin"; + "packages.pubsub": "/packages/pubsub"; + "packages.pwa": "/packages/pwa"; + "packages.queue": "/packages/queue"; + "packages.reactive": "/packages/reactive"; + "packages.realtime": "/packages/realtime"; + "packages.router": "/packages/router"; + "packages.security": "/packages/security"; + "packages.ssr": "/packages/ssr"; + "packages.store": "/packages/store"; + "packages.styles": "/packages/styles"; + "packages.syntax": "/packages/syntax"; + "packages.test": "/packages/test"; + "packages.tracking": "/packages/tracking"; + "packages.typecheck": "/packages/typecheck"; + "packages.ui": "/packages/ui"; + "packages.uploader": "/packages/uploader"; + "packages.validation": "/packages/validation"; + "releases.0.2.15": "/releases/0.2.15"; + "releases.0.2.17": "/releases/0.2.17"; + "releases.0.2.18": "/releases/0.2.18"; + "releases.0.2.19": "/releases/0.2.19"; + "releases.0.2.20": "/releases/0.2.20"; + "releases.0.2.21": "/releases/0.2.21"; + "releases.0.2.22": "/releases/0.2.22"; + "releases.0.2.23": "/releases/0.2.23"; + "releases.0.2.24": "/releases/0.2.24"; + "releases.0.2.25": "/releases/0.2.25"; + "releases.0.2.26": "/releases/0.2.26"; + "releases.0.2.27": "/releases/0.2.27"; + "releases.0.2.28": "/releases/0.2.28"; + "releases.0.2.29": "/releases/0.2.29"; + "releases.0.2.30": "/releases/0.2.30"; + "releases.0.2.31": "/releases/0.2.31"; + "releases.0.2.32": "/releases/0.2.32"; + "releases.0.2.33": "/releases/0.2.33"; + "releases.0.2.34": "/releases/0.2.34"; + "releases.0.2.35": "/releases/0.2.35"; + "releases.0.2.36": "/releases/0.2.36"; + "releases.0.2.37": "/releases/0.2.37"; + "releases.0.2.38": "/releases/0.2.38"; + "releases.0.2.39": "/releases/0.2.39"; + "releases.0.2.40": "/releases/0.2.40"; + "releases.0.2.41": "/releases/0.2.41"; + "releases.0.2.42": "/releases/0.2.42"; + "releases.0.2.43": "/releases/0.2.43"; + "releases.0.2.44": "/releases/0.2.44"; + "releases.0.2.45": "/releases/0.2.45"; + "releases.0.2.46": "/releases/0.2.46"; + "releases.0.2.47": "/releases/0.2.47"; + "releases.0.2.48": "/releases/0.2.48"; + "releases.0.2.49": "/releases/0.2.49"; + "releases.0.2.50": "/releases/0.2.50"; + "releases.0.2.51": "/releases/0.2.51"; + "releases.0.2.52": "/releases/0.2.52"; + "releases.0.2.53": "/releases/0.2.53"; + "releases.0.2.54": "/releases/0.2.54"; + "releases.0.2.55": "/releases/0.2.55"; + "releases.0.2.56": "/releases/0.2.56"; + "releases.0.2.57": "/releases/0.2.57"; + "releases.0.2.58": "/releases/0.2.58"; + "releases.0.2.59": "/releases/0.2.59"; + "releases.0.2.60": "/releases/0.2.60"; + "releases.0.2.61": "/releases/0.2.61"; + "releases.0.2.62": "/releases/0.2.62"; + "releases.0.2.63": "/releases/0.2.63"; + "releases.0.2.64": "/releases/0.2.64"; + "releases.0.2.65": "/releases/0.2.65"; + "releases.0.2.66": "/releases/0.2.66"; + "releases.0.2.67": "/releases/0.2.67"; + "releases.0.2.68": "/releases/0.2.68"; + "releases.0.2.69": "/releases/0.2.69"; + "releases.0.2.70": "/releases/0.2.70"; + "releases.0.2.71": "/releases/0.2.71"; + "releases.0.2.72": "/releases/0.2.72"; + "releases.0.2.73": "/releases/0.2.73"; + "releases.0.2.74": "/releases/0.2.74"; + "releases.0.2.75": "/releases/0.2.75"; + "releases.0.2.76": "/releases/0.2.76"; + "releases.0.2.77": "/releases/0.2.77"; + "releases.0.2.78": "/releases/0.2.78"; + "releases.0.2.79": "/releases/0.2.79"; + "releases.0.3.0": "/releases/0.3.0"; + "releases.0.3.1": "/releases/0.3.1"; + "releases.0.3.2": "/releases/0.3.2"; + "releases.0.3.3": "/releases/0.3.3"; + "releases.0.3.4": "/releases/0.3.4"; + "releases.0.3.5": "/releases/0.3.5"; + "releases.0.3.6": "/releases/0.3.6"; + "releases.0.4.0": "/releases/0.4.0"; + "releases.0.5.0": "/releases/0.5.0"; + "releases.0.5.1": "/releases/0.5.1"; + "releases.0.5.10": "/releases/0.5.10"; + "releases.0.5.11": "/releases/0.5.11"; + "releases.0.5.12": "/releases/0.5.12"; + "releases.0.5.13": "/releases/0.5.13"; + "releases.0.6.0": "/releases/0.6.0"; + "releases.0.7.0": "/releases/0.7.0"; + "releases.0.8.0": "/releases/0.8.0"; + "roadmap": "/roadmap"; + "search": "/search"; + "security": "/security"; + "showcase": "/showcase"; + "support": "/support"; + "tutorial": "/tutorial"; +} + +export interface RouteQueries { + [path: string]: Record; } export type RoutePath = keyof Routes; +export type RouteName = keyof RouteNames; +export type RouteQuery

    = P extends keyof RouteQueries + ? RouteQueries[P] + : Record; +type RouteValue = string | readonly string[] | undefined; + +function encodeRouteValue(value: RouteValue, catchAll: boolean): string { + if (value === undefined) return ""; + const values = Array.isArray(value) ? value : catchAll ? String(value).split("/") : [String(value)]; + return values.map((part) => encodeURIComponent(part)).join("/"); +} + +function buildHref(path: string, params: Record = {}): string { + const output: string[] = []; + for (const segment of path.split("/").filter(Boolean)) { + let name: string | undefined; + let optional = false; + let catchAll = false; + if (segment.startsWith("[[") && segment.endsWith("]]")) { + optional = true; + name = segment.slice(2, -2); + } else if (segment.startsWith("[") && segment.endsWith("]")) { + name = segment.slice(1, -1); + if (name.endsWith("?")) { + optional = true; + name = name.slice(0, -1); + } + } + if (!name) { + output.push(segment); + continue; + } + if (name.startsWith("...")) { + catchAll = true; + name = name.slice(3); + } + const value = params[name]; + if (value === undefined && optional) continue; + if (value === undefined) throw new Error(`WRN-ROUTE-MISSING-PARAM: Missing route parameter '${name}'.`); + output.push(encodeRouteValue(value, catchAll)); + } + return "/" + output.filter(Boolean).join("/"); +} export function href

    ( path: P, - ...args: Routes[P] extends Record ? [] : [params: Routes[P]] + ...args: keyof Routes[P] extends never + ? [] + : Record extends Routes[P] + ? [params?: Routes[P]] + : [params: Routes[P]] ): string { - const params = (args[0] ?? {}) as Record; - return String(path) - .split("/") - .map((seg) => - seg.startsWith("[") && seg.endsWith("]") - ? encodeURIComponent(params[seg.slice(1, -1)] ?? "") - : seg, - ) - .join("/"); + const params = (args[0] ?? {}) as Record; + return buildHref(String(path), params); +} + +export function route( + name: N, + ...args: keyof Routes[RouteNames[N]] extends never + ? [params?: Routes[RouteNames[N]], query?: RouteQuery] + : Record extends Routes[RouteNames[N]] + ? [params?: Routes[RouteNames[N]], query?: RouteQuery] + : [params: Routes[RouteNames[N]], query?: RouteQuery] +): string { + const paths: Record = { + "404": "/404", + "index": "/", + "access": "/access", + "architecture": "/architecture", + "benchmarks": "/benchmarks", + "changelog": "/changelog", + "examples": "/examples", + "getting.started": "/getting-started", + "guides.api.routes": "/guides/api-routes", + "guides.authentication": "/guides/authentication", + "guides.authorization": "/guides/authorization", + "guides.configuration.and.profiles": "/guides/configuration-and-profiles", + "guides.database": "/guides/database", + "guides.deployment": "/guides/deployment", + "guides.forms.and.validation": "/guides/forms-and-validation", + "guides.i18n.and.themes": "/guides/i18n-and-themes", + "guides.middleware": "/guides/middleware", + "guides.mobile": "/guides/mobile", + "guides.observability": "/guides/observability", + "guides.pages.and.components": "/guides/pages-and-components", + "guides.project.structure": "/guides/project-structure", + "guides.pubsub": "/guides/pubsub", + "guides.queues": "/guides/queues", + "guides.realtime": "/guides/realtime", + "guides.routing": "/guides/routing", + "guides.security": "/guides/security", + "guides.server.data": "/guides/server-data", + "guides.testing": "/guides/testing", + "guides.troubleshooting": "/guides/troubleshooting", + "guides.upgrading": "/guides/upgrading", + "guides.uploads": "/guides/uploads", + "guides.workspaces.and.gateway": "/guides/workspaces-and-gateway", + "language": "/language", + "license": "/license", + "packages": "/packages", + "packages.ai": "/packages/ai", + "packages.auth": "/packages/auth", + "packages.authz": "/packages/authz", + "packages.benchmark": "/packages/benchmark", + "packages.cache": "/packages/cache", + "packages.captcha": "/packages/captcha", + "packages.cli": "/packages/cli", + "packages.compiler": "/packages/compiler", + "packages.content": "/packages/content", + "packages.core": "/packages/core", + "packages.csr": "/packages/csr", + "packages.db": "/packages/db", + "packages.dev.server": "/packages/dev-server", + "packages.dev.toolbar": "/packages/dev-toolbar", + "packages.encryption": "/packages/encryption", + "packages.graphql": "/packages/graphql", + "packages.helpers": "/packages/helpers", + "packages.i18n": "/packages/i18n", + "packages.identity": "/packages/identity", + "packages.image": "/packages/image", + "packages.jwt": "/packages/jwt", + "packages.language.server": "/packages/language-server", + "packages.mcp": "/packages/mcp", + "packages.mobile": "/packages/mobile", + "packages.native": "/packages/native", + "packages.oauth": "/packages/oauth", + "packages.observability": "/packages/observability", + "packages.playground": "/packages/playground", + "packages.plugin": "/packages/plugin", + "packages.pubsub": "/packages/pubsub", + "packages.pwa": "/packages/pwa", + "packages.queue": "/packages/queue", + "packages.reactive": "/packages/reactive", + "packages.realtime": "/packages/realtime", + "packages.router": "/packages/router", + "packages.security": "/packages/security", + "packages.ssr": "/packages/ssr", + "packages.store": "/packages/store", + "packages.styles": "/packages/styles", + "packages.syntax": "/packages/syntax", + "packages.test": "/packages/test", + "packages.tracking": "/packages/tracking", + "packages.typecheck": "/packages/typecheck", + "packages.ui": "/packages/ui", + "packages.uploader": "/packages/uploader", + "packages.validation": "/packages/validation", + "releases.0.2.15": "/releases/0.2.15", + "releases.0.2.17": "/releases/0.2.17", + "releases.0.2.18": "/releases/0.2.18", + "releases.0.2.19": "/releases/0.2.19", + "releases.0.2.20": "/releases/0.2.20", + "releases.0.2.21": "/releases/0.2.21", + "releases.0.2.22": "/releases/0.2.22", + "releases.0.2.23": "/releases/0.2.23", + "releases.0.2.24": "/releases/0.2.24", + "releases.0.2.25": "/releases/0.2.25", + "releases.0.2.26": "/releases/0.2.26", + "releases.0.2.27": "/releases/0.2.27", + "releases.0.2.28": "/releases/0.2.28", + "releases.0.2.29": "/releases/0.2.29", + "releases.0.2.30": "/releases/0.2.30", + "releases.0.2.31": "/releases/0.2.31", + "releases.0.2.32": "/releases/0.2.32", + "releases.0.2.33": "/releases/0.2.33", + "releases.0.2.34": "/releases/0.2.34", + "releases.0.2.35": "/releases/0.2.35", + "releases.0.2.36": "/releases/0.2.36", + "releases.0.2.37": "/releases/0.2.37", + "releases.0.2.38": "/releases/0.2.38", + "releases.0.2.39": "/releases/0.2.39", + "releases.0.2.40": "/releases/0.2.40", + "releases.0.2.41": "/releases/0.2.41", + "releases.0.2.42": "/releases/0.2.42", + "releases.0.2.43": "/releases/0.2.43", + "releases.0.2.44": "/releases/0.2.44", + "releases.0.2.45": "/releases/0.2.45", + "releases.0.2.46": "/releases/0.2.46", + "releases.0.2.47": "/releases/0.2.47", + "releases.0.2.48": "/releases/0.2.48", + "releases.0.2.49": "/releases/0.2.49", + "releases.0.2.50": "/releases/0.2.50", + "releases.0.2.51": "/releases/0.2.51", + "releases.0.2.52": "/releases/0.2.52", + "releases.0.2.53": "/releases/0.2.53", + "releases.0.2.54": "/releases/0.2.54", + "releases.0.2.55": "/releases/0.2.55", + "releases.0.2.56": "/releases/0.2.56", + "releases.0.2.57": "/releases/0.2.57", + "releases.0.2.58": "/releases/0.2.58", + "releases.0.2.59": "/releases/0.2.59", + "releases.0.2.60": "/releases/0.2.60", + "releases.0.2.61": "/releases/0.2.61", + "releases.0.2.62": "/releases/0.2.62", + "releases.0.2.63": "/releases/0.2.63", + "releases.0.2.64": "/releases/0.2.64", + "releases.0.2.65": "/releases/0.2.65", + "releases.0.2.66": "/releases/0.2.66", + "releases.0.2.67": "/releases/0.2.67", + "releases.0.2.68": "/releases/0.2.68", + "releases.0.2.69": "/releases/0.2.69", + "releases.0.2.70": "/releases/0.2.70", + "releases.0.2.71": "/releases/0.2.71", + "releases.0.2.72": "/releases/0.2.72", + "releases.0.2.73": "/releases/0.2.73", + "releases.0.2.74": "/releases/0.2.74", + "releases.0.2.75": "/releases/0.2.75", + "releases.0.2.76": "/releases/0.2.76", + "releases.0.2.77": "/releases/0.2.77", + "releases.0.2.78": "/releases/0.2.78", + "releases.0.2.79": "/releases/0.2.79", + "releases.0.3.0": "/releases/0.3.0", + "releases.0.3.1": "/releases/0.3.1", + "releases.0.3.2": "/releases/0.3.2", + "releases.0.3.3": "/releases/0.3.3", + "releases.0.3.4": "/releases/0.3.4", + "releases.0.3.5": "/releases/0.3.5", + "releases.0.3.6": "/releases/0.3.6", + "releases.0.4.0": "/releases/0.4.0", + "releases.0.5.0": "/releases/0.5.0", + "releases.0.5.1": "/releases/0.5.1", + "releases.0.5.10": "/releases/0.5.10", + "releases.0.5.11": "/releases/0.5.11", + "releases.0.5.12": "/releases/0.5.12", + "releases.0.5.13": "/releases/0.5.13", + "releases.0.6.0": "/releases/0.6.0", + "releases.0.7.0": "/releases/0.7.0", + "releases.0.8.0": "/releases/0.8.0", + "roadmap": "/roadmap", + "search": "/search", + "security": "/security", + "showcase": "/showcase", + "support": "/support", + "tutorial": "/tutorial" +} as Record; + const output = buildHref(paths[name], (args[0] ?? {}) as Record); + const query = args[1]; + if (!query) return output; + const search = new URLSearchParams(); + for (const [key, value] of Object.entries(query)) + if (value !== undefined && value !== null) search.set(key, String(value)); + const text = search.toString(); + return text ? `${output}?${text}` : output; } diff --git a/app/types/wrnexus.generated.d.ts b/app/types/wrnexus.generated.d.ts new file mode 100644 index 00000000..0a6b4daa --- /dev/null +++ b/app/types/wrnexus.generated.d.ts @@ -0,0 +1,42 @@ +// AUTO-GENERATED by `wrnexus generate types` - do not edit. +declare namespace WRNexusGenerated { + type ApiContract = T extends import("@wrnexus/core").DefinedEndpoint + ? { input: I; output: O } + : T extends (...args: infer A) => infer R + ? { input: A extends [any, infer I, ...any[]] ? I : unknown; output: Awaited } + : { input: unknown; output: unknown }; + type MiddlewareContext = T extends (ctx: infer C, ...args: any[]) => any ? C : never; + type QueryContract = T extends (db: any, args: infer A, ...rest: any[]) => infer R + ? { args: A; result: Awaited } + : T extends (db: any, ...rest: any[]) => infer R + ? { args: Record; result: Awaited } + : never; + type RealtimeMessage = T extends import("@wrnexus/core").RoomDefinition ? M : unknown; + type QueuePayload = T extends import("@wrnexus/queue").JobDefinition ? I : unknown; + type RouteName = "404" | "access" | "architecture" | "benchmarks" | "changelog" | "examples" | "getting.started" | "guides.api.routes" | "guides.authentication" | "guides.authorization" | "guides.configuration.and.profiles" | "guides.database" | "guides.deployment" | "guides.forms.and.validation" | "guides.i18n.and.themes" | "guides.middleware" | "guides.mobile" | "guides.observability" | "guides.pages.and.components" | "guides.project.structure" | "guides.pubsub" | "guides.queues" | "guides.realtime" | "guides.routing" | "guides.security" | "guides.server.data" | "guides.testing" | "guides.troubleshooting" | "guides.upgrading" | "guides.uploads" | "guides.workspaces.and.gateway" | "index" | "language" | "license" | "packages" | "packages.ai" | "packages.auth" | "packages.authz" | "packages.benchmark" | "packages.cache" | "packages.captcha" | "packages.cli" | "packages.compiler" | "packages.content" | "packages.core" | "packages.csr" | "packages.db" | "packages.dev.server" | "packages.dev.toolbar" | "packages.encryption" | "packages.graphql" | "packages.helpers" | "packages.i18n" | "packages.identity" | "packages.image" | "packages.jwt" | "packages.language.server" | "packages.mcp" | "packages.mobile" | "packages.native" | "packages.oauth" | "packages.observability" | "packages.playground" | "packages.plugin" | "packages.pubsub" | "packages.pwa" | "packages.queue" | "packages.reactive" | "packages.realtime" | "packages.router" | "packages.security" | "packages.ssr" | "packages.store" | "packages.styles" | "packages.syntax" | "packages.test" | "packages.tracking" | "packages.typecheck" | "packages.ui" | "packages.uploader" | "packages.validation" | "releases.0.2.15" | "releases.0.2.17" | "releases.0.2.18" | "releases.0.2.19" | "releases.0.2.20" | "releases.0.2.21" | "releases.0.2.22" | "releases.0.2.23" | "releases.0.2.24" | "releases.0.2.25" | "releases.0.2.26" | "releases.0.2.27" | "releases.0.2.28" | "releases.0.2.29" | "releases.0.2.30" | "releases.0.2.31" | "releases.0.2.32" | "releases.0.2.33" | "releases.0.2.34" | "releases.0.2.35" | "releases.0.2.36" | "releases.0.2.37" | "releases.0.2.38" | "releases.0.2.39" | "releases.0.2.40" | "releases.0.2.41" | "releases.0.2.42" | "releases.0.2.43" | "releases.0.2.44" | "releases.0.2.45" | "releases.0.2.46" | "releases.0.2.47" | "releases.0.2.48" | "releases.0.2.49" | "releases.0.2.50" | "releases.0.2.51" | "releases.0.2.52" | "releases.0.2.53" | "releases.0.2.54" | "releases.0.2.55" | "releases.0.2.56" | "releases.0.2.57" | "releases.0.2.58" | "releases.0.2.59" | "releases.0.2.60" | "releases.0.2.61" | "releases.0.2.62" | "releases.0.2.63" | "releases.0.2.64" | "releases.0.2.65" | "releases.0.2.66" | "releases.0.2.67" | "releases.0.2.68" | "releases.0.2.69" | "releases.0.2.70" | "releases.0.2.71" | "releases.0.2.72" | "releases.0.2.73" | "releases.0.2.74" | "releases.0.2.75" | "releases.0.2.76" | "releases.0.2.77" | "releases.0.2.78" | "releases.0.2.79" | "releases.0.3.0" | "releases.0.3.1" | "releases.0.3.2" | "releases.0.3.3" | "releases.0.3.4" | "releases.0.3.5" | "releases.0.3.6" | "releases.0.4.0" | "releases.0.5.0" | "releases.0.5.1" | "releases.0.5.10" | "releases.0.5.11" | "releases.0.5.12" | "releases.0.5.13" | "releases.0.6.0" | "releases.0.7.0" | "releases.0.8.0" | "roadmap" | "search" | "security" | "showcase" | "support" | "tutorial"; + type ApiRoute = never; + type RealtimeRoute = never; + type EnvironmentKey = never; + type TranslationKey = never; + type QueueName = never; + type CacheKey = never; + interface Components { + + } + interface ApiContracts { + + } + interface MiddlewareContexts { + + } + interface DatabaseQueries { + + } + interface RealtimeMessages { + + } + interface QueuePayloads { + + } + type ApplicationConfig = (typeof import("../../wrnexus.config.ts"))["default"]; +} diff --git a/app/types/wrnexus.plugins.generated.d.ts b/app/types/wrnexus.plugins.generated.d.ts new file mode 100644 index 00000000..b82c221b --- /dev/null +++ b/app/types/wrnexus.plugins.generated.d.ts @@ -0,0 +1,2 @@ +// AUTO-GENERATED plugin type aggregation - do not edit. + diff --git a/bun.lock b/bun.lock index e0ae87b2..59dde31d 100644 --- a/bun.lock +++ b/bun.lock @@ -7,50 +7,58 @@ "dependencies": { "@iconify-json/lucide": "^1.2.118", "@iconify/tailwind4": "^1.2.3", - "@wrnexus/ai": "^0.7.0", - "@wrnexus/auth": "^0.7.0", - "@wrnexus/authz": "^0.7.0", - "@wrnexus/benchmark": "^0.7.0", - "@wrnexus/cache": "^0.7.0", - "@wrnexus/captcha": "^0.7.0", - "@wrnexus/compiler": "^0.7.0", - "@wrnexus/core": "^0.7.0", - "@wrnexus/csr": "^0.7.0", - "@wrnexus/db": "^0.7.0", - "@wrnexus/dev-server": "^0.7.0", - "@wrnexus/dev-toolbar": "^0.7.0", - "@wrnexus/encryption": "^0.7.0", - "@wrnexus/helpers": "^0.7.0", - "@wrnexus/i18n": "^0.7.0", - "@wrnexus/image": "^0.7.0", - "@wrnexus/jwt": "^0.7.0", - "@wrnexus/mobile": "^0.7.0", - "@wrnexus/native": "^0.7.0", - "@wrnexus/oauth": "^0.7.0", - "@wrnexus/observability": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/pubsub": "^0.7.0", - "@wrnexus/queue": "^0.7.0", - "@wrnexus/reactive": "^0.7.0", - "@wrnexus/router": "^0.7.0", - "@wrnexus/security": "^0.7.0", - "@wrnexus/ssr": "^0.7.0", - "@wrnexus/store": "^0.7.0", - "@wrnexus/styles": "^0.7.0", - "@wrnexus/syntax": "^0.7.0", - "@wrnexus/test": "^0.7.0", - "@wrnexus/tracking": "^0.7.0", - "@wrnexus/typecheck": "^0.7.0", - "@wrnexus/ui": "^0.7.0", - "@wrnexus/uploader": "^0.7.0", - "@wrnexus/validation": "^0.7.0", + "@wrnexus/ai": "^0.8.0", + "@wrnexus/auth": "^0.8.0", + "@wrnexus/authz": "^0.8.0", + "@wrnexus/benchmark": "^0.8.0", + "@wrnexus/cache": "^0.8.0", + "@wrnexus/captcha": "^0.8.0", + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/content": "^0.8.0", + "@wrnexus/core": "^0.8.0", + "@wrnexus/csr": "^0.8.0", + "@wrnexus/db": "^0.8.0", + "@wrnexus/dev-server": "^0.8.0", + "@wrnexus/dev-toolbar": "^0.8.0", + "@wrnexus/encryption": "^0.8.0", + "@wrnexus/graphql": "^0.8.0", + "@wrnexus/helpers": "^0.8.0", + "@wrnexus/i18n": "^0.8.0", + "@wrnexus/identity": "^0.8.0", + "@wrnexus/image": "^0.8.0", + "@wrnexus/jwt": "^0.8.0", + "@wrnexus/language-server": "^0.8.0", + "@wrnexus/mcp": "^0.8.0", + "@wrnexus/mobile": "^0.8.0", + "@wrnexus/native": "^0.8.0", + "@wrnexus/oauth": "^0.8.0", + "@wrnexus/observability": "^0.8.0", + "@wrnexus/playground": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/pubsub": "^0.8.0", + "@wrnexus/pwa": "^0.8.0", + "@wrnexus/queue": "^0.8.0", + "@wrnexus/reactive": "^0.8.0", + "@wrnexus/realtime": "^0.8.0", + "@wrnexus/router": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/ssr": "^0.8.0", + "@wrnexus/store": "^0.8.0", + "@wrnexus/styles": "^0.8.0", + "@wrnexus/syntax": "^0.8.0", + "@wrnexus/test": "^0.8.0", + "@wrnexus/tracking": "^0.8.0", + "@wrnexus/typecheck": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/uploader": "^0.8.0", + "@wrnexus/validation": "^0.8.0", }, "devDependencies": { "@eslint/js": "^9.0.0", "@tailwindcss/cli": "^4.0.0", "@types/bun": "latest", "@types/node": "^26.1.1", - "@wrnexus/cli": "^0.7.0", + "@wrnexus/cli": "^0.8.0", "eslint": "^9.0.0", "prettier": "latest", "tailwindcss": "^4.0.0", @@ -112,6 +120,8 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="], + "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="], @@ -140,6 +150,30 @@ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="], + "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "@peculiar/asn1-x509-attr": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA=="], + + "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg=="], + + "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ=="], + + "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.8.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.8.0", "@peculiar/asn1-pkcs8": "^2.8.0", "@peculiar/asn1-rsa": "^2.8.0", "@peculiar/asn1-schema": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg=="], + + "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA=="], + + "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.8.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.8.0", "@peculiar/asn1-pfx": "^2.8.0", "@peculiar/asn1-pkcs8": "^2.8.0", "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "@peculiar/asn1-x509-attr": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ=="], + + "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg=="], + + "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.8.0", "", { "dependencies": { "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q=="], + + "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg=="], + + "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.8.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.8.0", "@peculiar/asn1-x509": "^2.8.0", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA=="], + + "@peculiar/utils": ["@peculiar/utils@2.0.3", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ=="], + + "@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="], + "@tailwindcss/cli": ["@tailwindcss/cli@4.3.2", "", { "dependencies": { "@parcel/watcher": "2.5.1", "@tailwindcss/node": "4.3.2", "@tailwindcss/oxide": "4.3.2", "enhanced-resolve": "5.21.6", "mri": "^1.2.0", "picocolors": "^1.1.1", "tailwindcss": "4.3.2" }, "bin": { "tailwindcss": "./dist/index.mjs" } }, "sha512-Fzt+HrIZHDlkRYKdLMBeufaroaPvwCBG70sMLdmurdeadNMO/LxbmT8Sbb+P83ep0iAlAImettb7Y+rO+37rXw=="], "@tailwindcss/node": ["@tailwindcss/node@4.3.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "5.21.6", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.2" } }, "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg=="], @@ -198,81 +232,97 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.63.0", "", { "dependencies": { "@typescript-eslint/types": "8.63.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw=="], - "@wrnexus/ai": ["@wrnexus/ai@0.7.0", "", {}, "sha512-tJGbCrKsDUHrmAsboBdHZ2zkUGgdffQhyCaPN2BNL88vozuHAFKEl6fOdbADXzu9EZPH4cFMV5Ew54QAUQS1Xw=="], + "@wrnexus/ai": ["@wrnexus/ai@0.8.0", "", {}, "sha512-23uGl/rugZBtxOYm0w1bb6o1UirG/Bu8bSahfD4yzeIRy1cPhtRtk411qa+Wz/jxz+/0A+9BKGwkuwevlPk/qQ=="], - "@wrnexus/auth": ["@wrnexus/auth@0.7.0", "", { "dependencies": { "@wrnexus/authz": "^0.7.0", "@wrnexus/captcha": "^0.7.0", "@wrnexus/core": "^0.7.0", "@wrnexus/db": "^0.7.0", "@wrnexus/encryption": "^0.7.0", "@wrnexus/jwt": "^0.7.0", "@wrnexus/oauth": "^0.7.0", "@wrnexus/plugin": "^0.7.0", "@wrnexus/queue": "^0.7.0", "@wrnexus/ui": "^0.7.0", "@wrnexus/validation": "^0.7.0" } }, "sha512-GD6XEXMmu/H6XcK6a4hmF72ItB1/pdlmMPWe4RPU+w40blfZyiN3GaYhjdE3Cxb9C86uMo3Phrm65NKrMU6ptA=="], + "@wrnexus/auth": ["@wrnexus/auth@0.8.0", "", { "dependencies": { "@wrnexus/authz": "^0.8.0", "@wrnexus/captcha": "^0.8.0", "@wrnexus/core": "^0.8.0", "@wrnexus/db": "^0.8.0", "@wrnexus/encryption": "^0.8.0", "@wrnexus/jwt": "^0.8.0", "@wrnexus/oauth": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/queue": "^0.8.0", "@wrnexus/ui": "^0.8.0", "@wrnexus/validation": "^0.8.0" } }, "sha512-ytAN9FfFu6sjjIwo5G8rNaP/TbmPb8wIGYLUBfanJorfbh61uMB7rlxDqybO+Lz6/PeiAVNB6C2JxGxMiKhzsw=="], - "@wrnexus/authz": ["@wrnexus/authz@0.7.0", "", {}, "sha512-l3hIHlE1suHJDt31e1+/WW1OHyomSdfzx89rNyvrZbfej4rYPpB2H7YQYtLa1uwJUehcWCdqy9gEnJZclhDbJg=="], + "@wrnexus/authz": ["@wrnexus/authz@0.8.0", "", {}, "sha512-LuwMFqSmYCf52ZD6wotCoy8rtd3PsQ/dno39/P7o8iEY6361bekd6cnChS5AJ+1YMyOgMo0jA/fQLR4z65lWSA=="], - "@wrnexus/benchmark": ["@wrnexus/benchmark@0.7.0", "", {}, "sha512-0VFTdjKDPq815qHmUFDMaRxPe13Z5yuyXOTSFs2rRluwY+ujphYcofVX2AKcyXiu120hL/6Vf1gMS2C8YWcoAg=="], + "@wrnexus/benchmark": ["@wrnexus/benchmark@0.8.0", "", {}, "sha512-KiVBJSfb8KeV5nGDyR5DOdaZySILN/Js6dRNlHLu6sKRkbLca7nnr4DJhRenCQnh7heQzbVHDR5iCvY71vprmg=="], - "@wrnexus/cache": ["@wrnexus/cache@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-uRnwH45yM2Y93TI/fFEphZqKWi2B8dnJnAsxdB+lhgYb3PKDS3RHx3wgSjbolXFCIMjvhM5hEGFwSFy22DnFQw=="], + "@wrnexus/cache": ["@wrnexus/cache@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-VkigRb0KnV8+UIoL85mhlY4u30BD56l1u+gikJWuQ4YUTNWn/QC5ExilPTest30VEcAe2O3nVAcDEZZNpr5vfg=="], - "@wrnexus/captcha": ["@wrnexus/captcha@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0", "@wrnexus/plugin": "^0.7.0", "@wrnexus/validation": "^0.7.0" } }, "sha512-l5YtUklzUqQzilB3bGrsGewWHc0gd04RF1OuRbN9Uhys4s1ZUGgWeZHMdPDd6+fe8mqSgXnac0pliRgcQbeBKQ=="], + "@wrnexus/captcha": ["@wrnexus/captcha@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/ui": "^0.8.0", "@wrnexus/validation": "^0.8.0" } }, "sha512-s8moegsHkZb6PokJULQWOEFHsMWpJOG84PPMmu3SovJOpdeE1wJCmk1E/jxu91DyCHt+ECt3LW4hhFF7hZwexA=="], - "@wrnexus/cli": ["@wrnexus/cli@0.7.0", "", { "dependencies": { "@wrnexus/compiler": "^0.7.0", "@wrnexus/core": "^0.7.0", "@wrnexus/csr": "^0.7.0", "@wrnexus/db": "^0.7.0", "@wrnexus/dev-server": "^0.7.0", "@wrnexus/i18n": "^0.7.0", "@wrnexus/plugin": "^0.7.0", "@wrnexus/router": "^0.7.0", "@wrnexus/styles": "^0.7.0", "@wrnexus/syntax": "^0.7.0", "@wrnexus/ui": "^0.7.0", "@wrnexus/validation": "^0.7.0" }, "bin": { "wrnexus": "dist/index.js" } }, "sha512-Fo8p4XI0Eocjn9CgaNNfk1o1iywvvnIaMaMZ2MDcj6H/eysG4uW/4WMwa5XXQY3GzAmaiOFdurl5tXPhcTuC9A=="], + "@wrnexus/cli": ["@wrnexus/cli@0.8.0", "", { "dependencies": { "@wrnexus/compiler": "^0.8.0", "@wrnexus/core": "^0.8.0", "@wrnexus/csr": "^0.8.0", "@wrnexus/db": "^0.8.0", "@wrnexus/dev-server": "^0.8.0", "@wrnexus/i18n": "^0.8.0", "@wrnexus/mcp": "^0.8.0", "@wrnexus/playground": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/router": "^0.8.0", "@wrnexus/security": "^0.8.0", "@wrnexus/styles": "^0.8.0", "@wrnexus/syntax": "^0.8.0", "@wrnexus/typecheck": "^0.8.0", "@wrnexus/ui": "^0.8.0", "@wrnexus/validation": "^0.8.0", "selfsigned": "^5.5.0" }, "bin": { "wrnexus": "dist/index.js" } }, "sha512-6BOf//IY17Gz/C2kzGVHTn0bF5zMAtJWxofVAW96L/pwJQWHzxioqOpNWLVk1bHh6m2Jh59NOzwWtuR3xBpGTQ=="], - "@wrnexus/compiler": ["@wrnexus/compiler@0.7.0", "", { "dependencies": { "@wrnexus/store": "^0.7.0", "@wrnexus/syntax": "^0.7.0" } }, "sha512-iS3oaIiwTeffdriC2PlLS9MTOX4CU5lRDq6uO0ExbB/wvZ7qnBnT2mpliyZGPF5m7BKadPf77rr8dDtIg8C9iQ=="], + "@wrnexus/compiler": ["@wrnexus/compiler@0.8.0", "", { "dependencies": { "@wrnexus/csr": "^0.8.0", "@wrnexus/store": "^0.8.0", "@wrnexus/syntax": "^0.8.0", "@wrnexus/validation": "^0.8.0" } }, "sha512-xRIUer9UrzfXxebLIvEkeIHiZ1VhRhb8/ium/m0ehqyLllLf1oOH8mFT3g6tdnwZs8B4UJXlwdrIfbBs/xWrvg=="], - "@wrnexus/core": ["@wrnexus/core@0.7.0", "", {}, "sha512-HsQ1jHLMy+W+9H2BV7ilpAkbA2cCBJ3TEI8H6wTSC51j9C0HRZHtX1wlg0pDBsQEDwumpKFwvr3IxH9HVlpl5A=="], + "@wrnexus/content": ["@wrnexus/content@0.8.0", "", {}, "sha512-vE0LR53Pgu7ZVAxJF+QuiyGnlmL/1R9ZJ1fApRHTB6szCSFk1gaNvENiXH0H7LOYWEVvUXI9ITiC1cONfyHNRA=="], - "@wrnexus/csr": ["@wrnexus/csr@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-7EofnItpvQRZSvRi4nFjxOQiPMlbyFKgkhRlDo0lpElqslm+Kr1pRj1ux5wzSQZnb/XUMcaA45l5CX7poZq+eQ=="], + "@wrnexus/core": ["@wrnexus/core@0.8.0", "", {}, "sha512-4lz7E8uWraMjx4XOl5AfY1gizPiF6MOmKueWmJIbEhtg8pRetU5Sl3H1u4Ngmt1ZE/WkSUihLrtgurb6kQwTTg=="], - "@wrnexus/db": ["@wrnexus/db@0.7.0", "", {}, "sha512-Weh8V5SrJEHKXQwMWYVyTkPdtrF5HV59jn0Z6VuZsKsEh0hAIhKbqGT2nAKHqddWaUjwxNt+hRQltx2lX/9MMQ=="], + "@wrnexus/csr": ["@wrnexus/csr@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-wlS4yW/tBGHGe0Dv7IJ7AoL+ZOXosKlRVK7t9z0+4cpI8d18/WpX73AqNjTqYYYczGMUXS0M1DMgtPDRpuhVGg=="], - "@wrnexus/dev-server": ["@wrnexus/dev-server@0.7.0", "", { "dependencies": { "@wrnexus/compiler": "^0.7.0", "@wrnexus/core": "^0.7.0", "@wrnexus/csr": "^0.7.0", "@wrnexus/db": "^0.7.0", "@wrnexus/dev-toolbar": "^0.7.0", "@wrnexus/i18n": "^0.7.0", "@wrnexus/observability": "^0.7.0", "@wrnexus/plugin": "^0.7.0", "@wrnexus/pubsub": "^0.7.0", "@wrnexus/router": "^0.7.0", "@wrnexus/security": "^0.7.0", "@wrnexus/ssr": "^0.7.0", "@wrnexus/store": "^0.7.0", "@wrnexus/styles": "^0.7.0", "@wrnexus/ui": "^0.7.0", "@wrnexus/uploader": "^0.7.0", "@wrnexus/validation": "^0.7.0" } }, "sha512-NE7sU68s2GMp3eWPPYLVLGIIZZVDJxfLXr98yFFQq2XniAaDuHz9NBO8CIzamWlWtFhKcLKbgwYMkyLfOukd3A=="], + "@wrnexus/db": ["@wrnexus/db@0.8.0", "", {}, "sha512-uFRv2BRSqRrHygab5nQnT/CZ5KMq8KrRoNiVXWoye40txFZklabMlqGhAR+WsWx7URuBqjPE+Pufz2gBpZOStQ=="], - "@wrnexus/dev-toolbar": ["@wrnexus/dev-toolbar@0.7.0", "", {}, "sha512-iqI47nhtKmuSvu3cyju/Mg343+evqBnD4Ek2TQg+kvxhnEfVNmPKBZ6CRZGC3Qq+C8j0TuCUVD3Sb88hiV0+Qw=="], + "@wrnexus/dev-server": ["@wrnexus/dev-server@0.8.0", "", { "dependencies": { "@wrnexus/cache": "^0.8.0", "@wrnexus/compiler": "^0.8.0", "@wrnexus/core": "^0.8.0", "@wrnexus/csr": "^0.8.0", "@wrnexus/db": "^0.8.0", "@wrnexus/dev-toolbar": "^0.8.0", "@wrnexus/i18n": "^0.8.0", "@wrnexus/observability": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/pubsub": "^0.8.0", "@wrnexus/pwa": "^0.8.0", "@wrnexus/router": "^0.8.0", "@wrnexus/security": "^0.8.0", "@wrnexus/ssr": "^0.8.0", "@wrnexus/store": "^0.8.0", "@wrnexus/styles": "^0.8.0", "@wrnexus/ui": "^0.8.0", "@wrnexus/uploader": "^0.8.0", "@wrnexus/validation": "^0.8.0" } }, "sha512-WYX5ahqLl2TUf/H4y16dsu7JLGumFZykU3dZQ7AMsrZ9wdZNMiDKzHWIfZmQaL5cqILTIv1bPv3PpvYQAP1rIw=="], - "@wrnexus/encryption": ["@wrnexus/encryption@0.7.0", "", {}, "sha512-eLMVjHZbK0+2wJBdyPzCx3JQd8btgtvzcWQ+1XSMPmnxvsxVhVjxe2COgey8mRd2aUeltTvgJEqAIQ3AM9nlMw=="], + "@wrnexus/dev-toolbar": ["@wrnexus/dev-toolbar@0.8.0", "", {}, "sha512-efkTX27nYnKiqej+DKTMt/1T4JgEUeBzNF4GOuT1i5IA4M2X1DFH84sq4A+Oc2d+mzEjRklmQgYqQmjVmJ0skg=="], - "@wrnexus/helpers": ["@wrnexus/helpers@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-G9Fo5L23Xnp+cY0Q3fWcEtWpNNak5+/Wr2i+OZxxSjiHbKQtNi29kZ/HVROOGe978KAw8GTk6rycwUA4Ul568A=="], + "@wrnexus/encryption": ["@wrnexus/encryption@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-JpibmlHuTX6dII6mYDCjj55CdN9nubD+SMEqQEi3Lw2jOZrLMaBcytrKhivpE8z3EnegTVurxlzi190+SUTTeQ=="], - "@wrnexus/i18n": ["@wrnexus/i18n@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-1vOxW/07E2HqlvQHn+sJOQDlapcX1KXcdbge5yMvIUtDd1eTxuQfeo99svfgYxmoPzKqt8cDc5fU7O18Wvdedw=="], + "@wrnexus/graphql": ["@wrnexus/graphql@0.8.0", "", { "dependencies": { "@wrnexus/plugin": "^0.8.0" } }, "sha512-7urjt+17g2z9K0OUohG+0B1jEnYPpt6EF4d8JcHkhdwEGdqi8NFHxH4ymzcN4fmf5tmglRKnJkvq+X3i+65jKw=="], - "@wrnexus/image": ["@wrnexus/image@0.7.0", "", { "dependencies": { "@wrnexus/security": "^0.7.0" } }, "sha512-nxOHnhMHGOnW4dAYHH2hlpWCPhnDccqKPbrJZOWTk4ljxYI7PS4BHlH89FddeL1gdRqMu1dxrgyk/2N7SsF0Dg=="], + "@wrnexus/helpers": ["@wrnexus/helpers@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-xmXU5xVJzoR+GXdoX1rmfUqEv/0A278SpMj4hBqSDAioqS9edqJFyPqyCFPK/4M/ZZphihk46N1kkn3ySiqJsw=="], - "@wrnexus/jwt": ["@wrnexus/jwt@0.7.0", "", {}, "sha512-2oA6dWUgz05QnmjpnfSV+j7nfJ+Cx0E2u74r7xrrFGnvqCSHxUofDaQq7LpOeQW7tkTBFHsinmsTpp3x7ie8vQ=="], + "@wrnexus/i18n": ["@wrnexus/i18n@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/ui": "^0.8.0" } }, "sha512-ZzanKCaKuKLiFOQ5nbvd/LQiXqs4E7tXQMjBuJJzZN0WJAZNrr3vhYUtvoZVO9e0TCUPRosGOp5G8lVx/j/tRw=="], - "@wrnexus/mobile": ["@wrnexus/mobile@0.7.0", "", { "dependencies": { "@wrnexus/native": "^0.7.0" } }, "sha512-1Q1gJrwUtqJrS0B7aDdvor/CU88iTmFw7BinUY87bzqwMo1/ZJI0kdYFIZyFDFJeJr0TEtoepPA9n5TxnzRL/Q=="], + "@wrnexus/identity": ["@wrnexus/identity@0.8.0", "", { "dependencies": { "@wrnexus/auth": "^0.8.0", "@wrnexus/authz": "^0.8.0", "@wrnexus/oauth": "^0.8.0" } }, "sha512-mcLqMyG4i8H6mSEUCJOxOjOz6Njhz+EbkRZd8wxc6iLEkoHf676dVT7maEIOOUoof62Is0F5ZFkM58lJ8pC35w=="], - "@wrnexus/native": ["@wrnexus/native@0.7.0", "", {}, "sha512-dkcrc6+ulkjt4p2/yL7jpY2iALWy+OkOUORAnF5AmUNQEHcDH7kDR3+k1QexI9h6FcB0T/DqTTUBLVqYN2y7Qw=="], + "@wrnexus/image": ["@wrnexus/image@0.8.0", "", { "dependencies": { "@wrnexus/plugin": "^0.8.0", "@wrnexus/security": "^0.8.0", "@wrnexus/ui": "^0.8.0" } }, "sha512-IUAhEIrdM1PuIo2DBZ3j1UGd0iSmq1cD1gJxR7K+vkesH1hCMegvAbT0mebJHe3eavvHAKZnrfJDEG/NFMDEBg=="], - "@wrnexus/oauth": ["@wrnexus/oauth@0.7.0", "", {}, "sha512-xgjUwHUdgNfk0s+AD9c+i0WcaGIOa2iv+uDJyFaNymSB1MCkYMxKx2NwLfIteb+uiyowCD335i4He5edzx579g=="], + "@wrnexus/jwt": ["@wrnexus/jwt@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-PsoopDSMblOpzGH3gP/UnGLVw0wBYLG4ozIn6C9NwsYm/e9tdbGJYibf5nWV1PCnqcKIgNjkXIAQa1jzhJHHSA=="], - "@wrnexus/observability": ["@wrnexus/observability@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-EmMoVVsFl/IznDX4jR/xQAg/Nubgo47FROkglQhblakQ2T0bmkED8DOc433Ow1fDJwJsigF/GoDVmFzfIQlJJA=="], + "@wrnexus/language-server": ["@wrnexus/language-server@0.8.0", "", { "dependencies": { "@wrnexus/syntax": "^0.8.0", "@wrnexus/typecheck": "^0.8.0" }, "bin": { "wrnexus-language-server": "dist/server.js" } }, "sha512-Io5kak0s0ETp1WOkljjTEJzGZnipfsl0XgrbRC/ywF/Jwn6iXCdjBcImffWXfFGcfcjEP5AaWXQetoiAUAKz8w=="], - "@wrnexus/plugin": ["@wrnexus/plugin@0.7.0", "", { "dependencies": { "@wrnexus/syntax": "^0.7.0" } }, "sha512-tD/D0LC2WBPR57dz0Ztd5JiGOaWGPnraBPjYtQ13nV3AEmzoRvJmgRqTj496rbIbpytbES7yfHbBsvwbUz6kmg=="], + "@wrnexus/mcp": ["@wrnexus/mcp@0.8.0", "", { "bin": { "wrnexus-mcp": "dist/stdio.js" } }, "sha512-vodjH/86rNbZAGC6ppM6UKyBkTm0UDAgmhEZ4YVLCbD8ewcsDEzh007+QpQD99f/mMEJYePRQqn4PmaGuChI9g=="], - "@wrnexus/pubsub": ["@wrnexus/pubsub@0.7.0", "", {}, "sha512-wYz4xiaFLDJnJMv8tPKHFGmQXbeAag/n9ITK+6S/QJXyWdkzlHjmviYE81slmauqcqr1p40hZ3j7qYtdKyZ5fA=="], + "@wrnexus/mobile": ["@wrnexus/mobile@0.8.0", "", { "dependencies": { "@wrnexus/native": "^0.8.0" } }, "sha512-aC8pD5YzIJSdPY5GQmVr0IY19l0ljDA7ZtZLFP43AwSYzR+LEYu9zYln7pp6M+I/aOxN/dxRP/pzwLsPTjMSnA=="], - "@wrnexus/queue": ["@wrnexus/queue@0.7.0", "", {}, "sha512-6ti38dKNCCeIvzjUkdPt3nKv5MCQtNF6AhMkeIAlX2l26Wgf4+iPGovz+yf+k3doN35+UFnQ1fg/zjZdC9K5Wg=="], + "@wrnexus/native": ["@wrnexus/native@0.8.0", "", {}, "sha512-vslU63cozqEwIDNdtvt4Q27VPq5U4SZgJIGCN4meMnBfH1ID/XSwXJ3at6j5NbLvq/vu1nJVxNtAh5JBhxkFSA=="], - "@wrnexus/reactive": ["@wrnexus/reactive@0.7.0", "", {}, "sha512-TVQmoXE8kiAdmUvVKiEFqWpW1WiklZ7BxW2A3z7esoQRzgBCrnSSsbjETm4GDNJUQJZaCg6NGV29QvuHZiGzDA=="], + "@wrnexus/oauth": ["@wrnexus/oauth@0.8.0", "", { "dependencies": { "@wrnexus/jwt": "^0.8.0" } }, "sha512-OZ949JONJ1lgqtNeSDFfsjh3azUj0DQyJTqzxwZ1oP4ruwbPO98NhdqgCXyRUA+dXU1i3lpuCf/zY7Pv4krYWQ=="], - "@wrnexus/router": ["@wrnexus/router@0.7.0", "", { "dependencies": { "@wrnexus/compiler": "^0.7.0", "@wrnexus/core": "^0.7.0" } }, "sha512-82VowxOouJjHj4O7sy3NDWmwdQb4BqZwK9a9mj03ULBrXuAFkbDeY/stHIPKE1K6K+ICH2E2qAF4o1eXgWVxeQ=="], + "@wrnexus/observability": ["@wrnexus/observability@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-r/vtxHDBdJVqrPN5qr8prKbMv0gPF0I8CLWT9/UOpj/qjMgBX4UmsUbmI7SW1itrgvsZFYf4vh2vIlJY7GHz7A=="], - "@wrnexus/security": ["@wrnexus/security@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-XfnjwhbrDcwdDQzTMNyCwM9ODWVtzgL7IjsTix3bWd3zmEigkiyNxpCNxMoX79m0ATzi7YzBOriJ5o5hg8RGJQ=="], + "@wrnexus/playground": ["@wrnexus/playground@0.8.0", "", { "dependencies": { "@wrnexus/compiler": "^0.8.0", "@wrnexus/syntax": "^0.8.0" } }, "sha512-8t84X8H4NWVmf20nsCspOY3WII3+o95a9eTn0ZjQFRBwaAdfngwdddvPrUae+xnyZqNddyH219B2Ed1G48VN6Q=="], - "@wrnexus/ssr": ["@wrnexus/ssr@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0", "@wrnexus/security": "^0.7.0", "@wrnexus/store": "^0.7.0" } }, "sha512-1hRaXCDG16aBP7PlVGCRqXw9JHjMlxZUwqI9QiMgeJ+Z0lHU1zNjqepo4xN8Rmug3oUQ0rSpGYj7CxN1QWFgdw=="], + "@wrnexus/plugin": ["@wrnexus/plugin@0.8.0", "", { "dependencies": { "@wrnexus/syntax": "^0.8.0" } }, "sha512-NIWvCAzv6R0DALdtxU0/RlpbQUPIwezg6PK1d5JNekHREdfkftmX/+Ka25wah1ktUmGO29CywzxQ9bBAG/AgQw=="], - "@wrnexus/store": ["@wrnexus/store@0.7.0", "", {}, "sha512-yrlVX1q1NRDWvQ6tDj7BGxy/IGzjPjhESqnZtWN7KnR53TsFT+yxhVZdnyJxVSp/IipvJh0u2bgK4H/ZDYEozg=="], + "@wrnexus/pubsub": ["@wrnexus/pubsub@0.8.0", "", {}, "sha512-DyikECFdar10y0UoIQRHgfOzt3WfcoX8xpMH1uPCuXIo0AVuNpUMOtOJNynWHHAQ3TdjoJbDX8u/PwZVDfLAiw=="], - "@wrnexus/styles": ["@wrnexus/styles@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0", "@wrnexus/plugin": "^0.7.0", "@wrnexus/uploader": "^0.7.0" } }, "sha512-PiSlWNlg+kJ2P4kpHD1q/yDteSzCdpsvyeUmC4uRS724orubAkmQe2yk4e+CRr3MoQnxvHzefo+NamJcdrJwGg=="], + "@wrnexus/pwa": ["@wrnexus/pwa@0.8.0", "", {}, "sha512-bs8mVtv4dXzbZIlkONpysINVwkL9ir1jdzuQVWSr3naCe+bknKRvCeIw0Y9DqoxvpEVzAsIMLLR3vLbjCNIIFA=="], - "@wrnexus/syntax": ["@wrnexus/syntax@0.7.0", "", {}, "sha512-pygjZXLoQtHiP5DcxRX++GbZInmNzuoNtXmGgYWVH0oVMzPPYXUtyCX5O7tzY7hEqLhs+TG7CCyWIoum1rbkJg=="], + "@wrnexus/queue": ["@wrnexus/queue@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-PLM8KY/5R+3lwoDc2TK9PdEs7aOjCkdkfvK1nlz0ylbT0ej+LsfLFDTlAYifS0qrSJT9r88JWwswvJYUu7OnGg=="], - "@wrnexus/test": ["@wrnexus/test@0.7.0", "", {}, "sha512-3sYKNC6WUuwFoFAoDnZxVPCIwBU3CTkXbme9yd6c51eaksiNkPJJsQxANx83c/AM2k6z9BeH04ESUPgedm4GFg=="], + "@wrnexus/reactive": ["@wrnexus/reactive@0.8.0", "", {}, "sha512-jkW7W5YxTmKbdcUiahgDl8laAZR7O8l0DSW0x4+Oj0G1jWuNP7/eEIXtIHtX9MC2UEGhK0dv5S78zTp/bMD/9A=="], - "@wrnexus/tracking": ["@wrnexus/tracking@0.7.0", "", {}, "sha512-Q6cbKFD+0lW1PV8gPtXXZb1bS2w8wcKyCloOS2kRJR808LoIE6Y3XLWcL090w9HXmT2lBLVytriVl0LL19fe8g=="], + "@wrnexus/realtime": ["@wrnexus/realtime@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/ui": "^0.8.0" } }, "sha512-NPZmkf3eyHpkMyLQ80Bu1Fq1/6geiGtL4amVV+ZQaUW7zvdFlrgWsM3fbyMJ9k1iLs/UoeOUCaWe++UXnuZPzA=="], - "@wrnexus/typecheck": ["@wrnexus/typecheck@0.7.0", "", { "dependencies": { "@wrnexus/syntax": "^0.7.0", "typescript": "^5.5.0" } }, "sha512-49BcKK+5vNJ3JO3kHuGvFYRhjQli1n9GCSg6ppTUq7pg95AB4Amtn8VrYOIhMKxbu/bmRJAvUAjfW/aLnZwJ6A=="], + "@wrnexus/router": ["@wrnexus/router@0.8.0", "", { "dependencies": { "@wrnexus/compiler": "^0.8.0", "@wrnexus/core": "^0.8.0" } }, "sha512-7asmgW1zPf4uYjiDo7fhM2BQnGKNIearyIEV154QGppaA2OmGHN02bxWC0sd2tPWHY2qJLRCV221dUnE0kMtzg=="], - "@wrnexus/ui": ["@wrnexus/ui@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-31/8YOOl9iGckZ37C6s7gIwm1Xkq+YTkClNNC3VgM6/kn2BvGKKURiS9qngy2QznMmZ7jmRnwHOQmbTjldcJfA=="], + "@wrnexus/security": ["@wrnexus/security@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-PDFTFYX9HE4lBiS1+/UTcIgMr93m1VZ3M9EyRy0cvufOzXsoT6M1jlwoUEz56rjeZw1bT7ZDD1RLRmtUZRfkVw=="], - "@wrnexus/uploader": ["@wrnexus/uploader@0.7.0", "", { "dependencies": { "@wrnexus/core": "^0.7.0" } }, "sha512-YrT6KUWjR3ElO4DCTTSdXnZBEL+r3GDSpeXEZOpIZByd+6/vgsMPWbVSfqNZi9ZS2oYeUJtF9tKPAtQlOA8WGg=="], + "@wrnexus/ssr": ["@wrnexus/ssr@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/security": "^0.8.0", "@wrnexus/store": "^0.8.0" } }, "sha512-yBidB8GKrmUSviPNW48BJHikKkiu3I3zlymTIK/1bAuVTT89FUfS5jU5rNGHjvthJbahuqOJxLiG0vTcLKQpxw=="], - "@wrnexus/validation": ["@wrnexus/validation@0.7.0", "", {}, "sha512-nlIStY1coiCJDunGW1ilBuZqTAkiz7vlICAHe+h7sOhHJ2zd0FXVnwuN4yKR+RAn7pT9r3e/QG5NG8+/J5RsfQ=="], + "@wrnexus/store": ["@wrnexus/store@0.8.0", "", {}, "sha512-T4nv6iNRf9Kw2mambBUMy5wteZfpwns6fVEuMpdaQtKceZ6MzXiaqWdeKU02mDHSnBW9W+GuIKNolZNZSZDT+w=="], + + "@wrnexus/styles": ["@wrnexus/styles@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/uploader": "^0.8.0" } }, "sha512-BjXyzI7qGWScyR9/+2Py3MrEu1p7lJOYu0UnXjKX20HOFfFGbKKPTdjsI1JHiFp15XtFejfDvvWB7bclnWjvcA=="], + + "@wrnexus/syntax": ["@wrnexus/syntax@0.8.0", "", {}, "sha512-RjkfeKBQ/Pj9UgAJ3DMcmEkZFZb80o56vVXy0CgvzPE/NrrOZJPpOgeRza07vHQ3ewdATSUXG85BS/pt2FNBNQ=="], + + "@wrnexus/test": ["@wrnexus/test@0.8.0", "", {}, "sha512-4Q4oAUsZNLSiJOxUYnTp9umrR8r+DBijSxI0ZakwF7iK9cps70r6TaAeDNfoDbv2XTgyeL/z6Ixj5EXLuOKaQw=="], + + "@wrnexus/tracking": ["@wrnexus/tracking@0.8.0", "", {}, "sha512-SZopBuL8vtw/gYFe/CUCGyJFAc4Q/bhOXVEHE81OPx9Af5lfsrx7Rzb+ktHUcpGwSxJ2uEJuPhkV4YWJYHHFyg=="], + + "@wrnexus/typecheck": ["@wrnexus/typecheck@0.8.0", "", { "dependencies": { "@wrnexus/syntax": "^0.8.0", "typescript": "^5.5.0" } }, "sha512-ie8t9iYC1KjxyXipvyKXfkM5tDDSv9K7trFyRGD6m1cUzvZsqAzq9QcdxmbR8ypcxdGfNff5i+mz+NFujeZAPQ=="], + + "@wrnexus/ui": ["@wrnexus/ui@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0" } }, "sha512-KtYHZV50lDeOixZaS688UrulSRU39DTnl6gF+NhMBSdoIDqlX+FcAay7ccgzLN6B/6PlLBuQMsONGavzCZ8J8g=="], + + "@wrnexus/uploader": ["@wrnexus/uploader@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/ui": "^0.8.0" } }, "sha512-BcCzcIwnRsr7NnRYZVhrBXaqNkgI4dB8woWNgsujrYU0G43+oQ9tkLlSciY+vl8y0One/D9uTq+tjm3q1jlFMw=="], + + "@wrnexus/validation": ["@wrnexus/validation@0.8.0", "", { "dependencies": { "@wrnexus/core": "^0.8.0", "@wrnexus/plugin": "^0.8.0", "@wrnexus/ui": "^0.8.0" } }, "sha512-07RE6Jm7ZK1U+i3OvDYt7mOJC+Q7u7lUnCffT02yFDW06oQ+hxiadVVR+fgNHOJEevCgZwyOaKJzVPTC5Qoumw=="], "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="], @@ -284,6 +334,8 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "asn1js": ["asn1js@3.0.10", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.5", "tslib": "^2.8.1" } }, "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg=="], + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], @@ -294,6 +346,8 @@ "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "bytestreamjs": ["bytestreamjs@2.0.1", "", {}, "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -478,16 +532,26 @@ "picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "pkijs": ["pkijs@3.4.0", "", { "dependencies": { "@noble/hashes": "1.4.0", "asn1js": "^3.0.6", "bytestreamjs": "^2.0.1", "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw=="], + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "prettier": ["prettier@3.9.5", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], + + "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="], + + "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], + "selfsigned": ["selfsigned@5.5.0", "", { "dependencies": { "@peculiar/x509": "^1.14.2", "pkijs": "^3.3.3" } }, "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew=="], + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -514,6 +578,10 @@ "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsyringe": ["tsyringe@4.10.0", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], @@ -556,6 +624,8 @@ "tinyglobby/picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], + "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="], "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], diff --git a/docs/documentation-coverage-matrix.md b/docs/documentation-coverage-matrix.md index 46327ef3..2a41addc 100644 --- a/docs/documentation-coverage-matrix.md +++ b/docs/documentation-coverage-matrix.md @@ -1,42 +1,50 @@ # Documentation coverage matrix -| Area | Package reference | Concept guide | Runnable fixture | Tests | Stability | Limitation | -| ---------------------- | ----------------------- | ---------------------------- | ---------------- | ------------------ | ------------ | ------------------------ | -| @wrnexus/ai | /packages/ai | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/auth | /packages/auth | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/authz | /packages/authz | /guides/authorization | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/benchmark | /packages/benchmark | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/cache | /packages/cache | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/captcha | /packages/captcha | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/cli | /packages/cli | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/compiler | /packages/compiler | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/core | /packages/core | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/csr | /packages/csr | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/db | /packages/db | /guides/db | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/dev-server | /packages/dev-server | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/dev-toolbar | /packages/dev-toolbar | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/encryption | /packages/encryption | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/helpers | /packages/helpers | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/i18n | /packages/i18n | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/image | /packages/image | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/jwt | /packages/jwt | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/mobile | /packages/mobile | /guides/mobile | Planned | Generator coverage | Experimental | No standalone CI fixture | -| @wrnexus/native | /packages/native | Architecture/package guide | Planned | Generator coverage | Experimental | No standalone CI fixture | -| @wrnexus/oauth | /packages/oauth | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/observability | /packages/observability | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/plugin | /packages/plugin | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/pubsub | /packages/pubsub | /guides/pubsub | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/queue | /packages/queue | /guides/queues | Planned | Generator coverage | Experimental | No standalone CI fixture | -| @wrnexus/reactive | /packages/reactive | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/router | /packages/router | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/security | /packages/security | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/ssr | /packages/ssr | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/store | /packages/store | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/styles | /packages/styles | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/syntax | /packages/syntax | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/test | /packages/test | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/tracking | /packages/tracking | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/typecheck | /packages/typecheck | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/ui | /packages/ui | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/uploader | /packages/uploader | /guides/uploads | Planned | Generator coverage | Preview | No standalone CI fixture | -| @wrnexus/validation | /packages/validation | /guides/forms-and-validation | Planned | Generator coverage | Preview | No standalone CI fixture | +| Area | Package reference | Concept guide | Runnable fixture | Tests | Stability | Limitation | +| ------------------------ | ------------------------- | ---------------------------- | ---------------- | ------------------ | ------------ | ------------------------ | +| @wrnexus/ai | /packages/ai | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/auth | /packages/auth | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/authz | /packages/authz | /guides/authorization | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/benchmark | /packages/benchmark | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/cache | /packages/cache | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/captcha | /packages/captcha | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/cli | /packages/cli | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/compiler | /packages/compiler | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/content | /packages/content | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/core | /packages/core | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/csr | /packages/csr | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/db | /packages/db | /guides/db | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/dev-server | /packages/dev-server | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/dev-toolbar | /packages/dev-toolbar | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/encryption | /packages/encryption | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/graphql | /packages/graphql | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/helpers | /packages/helpers | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/i18n | /packages/i18n | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/identity | /packages/identity | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/image | /packages/image | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/jwt | /packages/jwt | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/language-server | /packages/language-server | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/mcp | /packages/mcp | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/mobile | /packages/mobile | /guides/mobile | Planned | Generator coverage | Experimental | No standalone CI fixture | +| @wrnexus/native | /packages/native | Architecture/package guide | Planned | Generator coverage | Experimental | No standalone CI fixture | +| @wrnexus/oauth | /packages/oauth | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/observability | /packages/observability | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/playground | /packages/playground | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/plugin | /packages/plugin | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/pubsub | /packages/pubsub | /guides/pubsub | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/pwa | /packages/pwa | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/queue | /packages/queue | /guides/queues | Planned | Generator coverage | Experimental | No standalone CI fixture | +| @wrnexus/reactive | /packages/reactive | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/realtime | /packages/realtime | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/router | /packages/router | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/security | /packages/security | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/ssr | /packages/ssr | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/store | /packages/store | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/styles | /packages/styles | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/syntax | /packages/syntax | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/test | /packages/test | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/tracking | /packages/tracking | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/typecheck | /packages/typecheck | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/ui | /packages/ui | Architecture/package guide | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/uploader | /packages/uploader | /guides/uploads | Planned | Generator coverage | Preview | No standalone CI fixture | +| @wrnexus/validation | /packages/validation | /guides/forms-and-validation | Planned | Generator coverage | Preview | No standalone CI fixture | diff --git a/docs/release-access-status.md b/docs/release-access-status.md index 332a7f0c..a76acfd8 100644 --- a/docs/release-access-status.md +++ b/docs/release-access-status.md @@ -2,6 +2,6 @@ ## Decision: Mode B — Private Developer Preview -Active version: 0.7.0, derived from package.json#wrnexus.version. All 38 installed @wrnexus packages resolve to 0.7.0 and npm reports restricted access. The repository remote is a private WorkRoot Git service and no public license file exists. +Active version: 0.8.0, derived from package.json#wrnexus.version. All 46 installed @wrnexus packages resolve to 0.8.0 and npm reports restricted access. The repository remote is a private WorkRoot Git service and no public license file exists. -External users cannot execute an installation without approved private registry credentials. The truthful CTA is Request preview access. After approval, the canonical command is bunx @wrnexus/cli@0.7.0 create my-app. Tokens must never appear in documentation or source. +External users cannot execute an installation without approved private registry credentials. The truthful CTA is Request preview access. After approval, the canonical command is bunx @wrnexus/cli@0.8.0 create my-app. Tokens must never appear in documentation or source. diff --git a/docs/site-audit.md b/docs/site-audit.md index 68f41196..3ce489f7 100644 --- a/docs/site-audit.md +++ b/docs/site-audit.md @@ -1,18 +1,18 @@ # WRNexusJS site audit -Date: 2026-07-13. Baseline: Bun 1.3.14, framework 0.7.0. +Date: 2026-07-13. Baseline: Bun 1.3.14, framework 0.8.0. ## Baseline results - authenticated private-registry installation: pass. -- docs generation: pass (38 package pages plus portal and guide pages). +- docs generation: pass (46 package pages plus portal and guide pages). - tests, lint, formatting, and production build are required by the release check. - package access remains restricted/private. - repository: private WorkRoot Git remote; no public license file exists. ## Findings -Package documentation, discovery assets, and AI-readable references are generated from the installed release. The 0.7.0 portal includes the helpers package, workspace app addition, and safe forward-auth login redirect guidance. +Package documentation, discovery assets, and AI-readable references are generated from the installed release. The 0.8.0 portal includes the helpers package, workspace app addition, and safe forward-auth login redirect guidance. ## Audit limitations diff --git a/package-lock.json b/package-lock.json index d74e93ba..292b8bf4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,50 +10,58 @@ "dependencies": { "@iconify-json/lucide": "^1.2.118", "@iconify/tailwind4": "^1.2.3", - "@wrnexus/ai": "^0.7.0", - "@wrnexus/auth": "^0.7.0", - "@wrnexus/authz": "^0.7.0", - "@wrnexus/benchmark": "^0.7.0", - "@wrnexus/cache": "^0.7.0", - "@wrnexus/captcha": "^0.7.0", - "@wrnexus/compiler": "^0.7.0", - "@wrnexus/core": "^0.7.0", - "@wrnexus/csr": "^0.7.0", - "@wrnexus/db": "^0.7.0", - "@wrnexus/dev-server": "^0.7.0", - "@wrnexus/dev-toolbar": "^0.7.0", - "@wrnexus/encryption": "^0.7.0", - "@wrnexus/helpers": "^0.7.0", - "@wrnexus/i18n": "^0.7.0", - "@wrnexus/image": "^0.7.0", - "@wrnexus/jwt": "^0.7.0", - "@wrnexus/mobile": "^0.7.0", - "@wrnexus/native": "^0.7.0", - "@wrnexus/oauth": "^0.7.0", - "@wrnexus/observability": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/pubsub": "^0.7.0", - "@wrnexus/queue": "^0.7.0", - "@wrnexus/reactive": "^0.7.0", - "@wrnexus/router": "^0.7.0", - "@wrnexus/security": "^0.7.0", - "@wrnexus/ssr": "^0.7.0", - "@wrnexus/store": "^0.7.0", - "@wrnexus/styles": "^0.7.0", - "@wrnexus/syntax": "^0.7.0", - "@wrnexus/test": "^0.7.0", - "@wrnexus/tracking": "^0.7.0", - "@wrnexus/typecheck": "^0.7.0", - "@wrnexus/ui": "^0.7.0", - "@wrnexus/uploader": "^0.7.0", - "@wrnexus/validation": "^0.7.0" + "@wrnexus/ai": "^0.8.0", + "@wrnexus/auth": "^0.8.0", + "@wrnexus/authz": "^0.8.0", + "@wrnexus/benchmark": "^0.8.0", + "@wrnexus/cache": "^0.8.0", + "@wrnexus/captcha": "^0.8.0", + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/content": "^0.8.0", + "@wrnexus/core": "^0.8.0", + "@wrnexus/csr": "^0.8.0", + "@wrnexus/db": "^0.8.0", + "@wrnexus/dev-server": "^0.8.0", + "@wrnexus/dev-toolbar": "^0.8.0", + "@wrnexus/encryption": "^0.8.0", + "@wrnexus/graphql": "^0.8.0", + "@wrnexus/helpers": "^0.8.0", + "@wrnexus/i18n": "^0.8.0", + "@wrnexus/identity": "^0.8.0", + "@wrnexus/image": "^0.8.0", + "@wrnexus/jwt": "^0.8.0", + "@wrnexus/language-server": "^0.8.0", + "@wrnexus/mcp": "^0.8.0", + "@wrnexus/mobile": "^0.8.0", + "@wrnexus/native": "^0.8.0", + "@wrnexus/oauth": "^0.8.0", + "@wrnexus/observability": "^0.8.0", + "@wrnexus/playground": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/pubsub": "^0.8.0", + "@wrnexus/pwa": "^0.8.0", + "@wrnexus/queue": "^0.8.0", + "@wrnexus/reactive": "^0.8.0", + "@wrnexus/realtime": "^0.8.0", + "@wrnexus/router": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/ssr": "^0.8.0", + "@wrnexus/store": "^0.8.0", + "@wrnexus/styles": "^0.8.0", + "@wrnexus/syntax": "^0.8.0", + "@wrnexus/test": "^0.8.0", + "@wrnexus/tracking": "^0.8.0", + "@wrnexus/typecheck": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/uploader": "^0.8.0", + "@wrnexus/validation": "^0.8.0" }, "devDependencies": { "@eslint/js": "^9.0.0", "@tailwindcss/cli": "^4.0.0", "@types/bun": "latest", "@types/node": "^26.1.1", - "@wrnexus/cli": "^0.7.0", + "@wrnexus/cli": "^0.8.0", "eslint": "^9.0.0", "prettier": "latest", "tailwindcss": "^4.0.0", @@ -361,6 +369,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.1", "dev": true, @@ -684,6 +705,175 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.8.0.tgz", + "integrity": "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.8.0.tgz", + "integrity": "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.8.0.tgz", + "integrity": "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.8.0.tgz", + "integrity": "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-rsa": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.8.0.tgz", + "integrity": "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.8.0.tgz", + "integrity": "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.8.0", + "@peculiar/asn1-pfx": "^2.8.0", + "@peculiar/asn1-pkcs8": "^2.8.0", + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "@peculiar/asn1-x509-attr": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.8.0.tgz", + "integrity": "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", + "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.8.0.tgz", + "integrity": "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.8.0.tgz", + "integrity": "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.8.0", + "@peculiar/asn1-x509": "^2.8.0", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", + "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-cms": "^2.6.0", + "@peculiar/asn1-csr": "^2.6.0", + "@peculiar/asn1-ecc": "^2.6.0", + "@peculiar/asn1-pkcs9": "^2.6.0", + "@peculiar/asn1-rsa": "^2.6.0", + "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-x509": "^2.6.0", + "pvtsutils": "^1.3.6", + "reflect-metadata": "^0.2.2", + "tslib": "^2.8.1", + "tsyringe": "^4.10.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@tailwindcss/cli": { "version": "4.3.2", "dev": true, @@ -1313,99 +1503,105 @@ } }, "node_modules/@wrnexus/ai": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/ai/-/ai-0.7.0.tgz", - "integrity": "sha512-tJGbCrKsDUHrmAsboBdHZ2zkUGgdffQhyCaPN2BNL88vozuHAFKEl6fOdbADXzu9EZPH4cFMV5Ew54QAUQS1Xw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/ai/-/ai-0.8.0.tgz", + "integrity": "sha512-23uGl/rugZBtxOYm0w1bb6o1UirG/Bu8bSahfD4yzeIRy1cPhtRtk411qa+Wz/jxz+/0A+9BKGwkuwevlPk/qQ==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/auth": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/auth/-/auth-0.7.0.tgz", - "integrity": "sha512-GD6XEXMmu/H6XcK6a4hmF72ItB1/pdlmMPWe4RPU+w40blfZyiN3GaYhjdE3Cxb9C86uMo3Phrm65NKrMU6ptA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/auth/-/auth-0.8.0.tgz", + "integrity": "sha512-ytAN9FfFu6sjjIwo5G8rNaP/TbmPb8wIGYLUBfanJorfbh61uMB7rlxDqybO+Lz6/PeiAVNB6C2JxGxMiKhzsw==", "license": "MIT", "dependencies": { - "@wrnexus/authz": "^0.7.0", - "@wrnexus/captcha": "^0.7.0", - "@wrnexus/core": "^0.7.0", - "@wrnexus/db": "^0.7.0", - "@wrnexus/encryption": "^0.7.0", - "@wrnexus/jwt": "^0.7.0", - "@wrnexus/oauth": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/queue": "^0.7.0", - "@wrnexus/ui": "^0.7.0", - "@wrnexus/validation": "^0.7.0" + "@wrnexus/authz": "^0.8.0", + "@wrnexus/captcha": "^0.8.0", + "@wrnexus/core": "^0.8.0", + "@wrnexus/db": "^0.8.0", + "@wrnexus/encryption": "^0.8.0", + "@wrnexus/jwt": "^0.8.0", + "@wrnexus/oauth": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/queue": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/validation": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/authz": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/authz/-/authz-0.7.0.tgz", - "integrity": "sha512-l3hIHlE1suHJDt31e1+/WW1OHyomSdfzx89rNyvrZbfej4rYPpB2H7YQYtLa1uwJUehcWCdqy9gEnJZclhDbJg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/authz/-/authz-0.8.0.tgz", + "integrity": "sha512-LuwMFqSmYCf52ZD6wotCoy8rtd3PsQ/dno39/P7o8iEY6361bekd6cnChS5AJ+1YMyOgMo0jA/fQLR4z65lWSA==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/benchmark": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/benchmark/-/benchmark-0.7.0.tgz", - "integrity": "sha512-0VFTdjKDPq815qHmUFDMaRxPe13Z5yuyXOTSFs2rRluwY+ujphYcofVX2AKcyXiu120hL/6Vf1gMS2C8YWcoAg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/benchmark/-/benchmark-0.8.0.tgz", + "integrity": "sha512-KiVBJSfb8KeV5nGDyR5DOdaZySILN/Js6dRNlHLu6sKRkbLca7nnr4DJhRenCQnh7heQzbVHDR5iCvY71vprmg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/cache": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/cache/-/cache-0.7.0.tgz", - "integrity": "sha512-uRnwH45yM2Y93TI/fFEphZqKWi2B8dnJnAsxdB+lhgYb3PKDS3RHx3wgSjbolXFCIMjvhM5hEGFwSFy22DnFQw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/cache/-/cache-0.8.0.tgz", + "integrity": "sha512-VkigRb0KnV8+UIoL85mhlY4u30BD56l1u+gikJWuQ4YUTNWn/QC5ExilPTest30VEcAe2O3nVAcDEZZNpr5vfg==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/captcha": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/captcha/-/captcha-0.7.0.tgz", - "integrity": "sha512-l5YtUklzUqQzilB3bGrsGewWHc0gd04RF1OuRbN9Uhys4s1ZUGgWeZHMdPDd6+fe8mqSgXnac0pliRgcQbeBKQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/captcha/-/captcha-0.8.0.tgz", + "integrity": "sha512-s8moegsHkZb6PokJULQWOEFHsMWpJOG84PPMmu3SovJOpdeE1wJCmk1E/jxu91DyCHt+ECt3LW4hhFF7hZwexA==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/validation": "^0.7.0" + "@wrnexus/core": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/validation": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/cli": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/cli/-/cli-0.7.0.tgz", - "integrity": "sha512-Fo8p4XI0Eocjn9CgaNNfk1o1iywvvnIaMaMZ2MDcj6H/eysG4uW/4WMwa5XXQY3GzAmaiOFdurl5tXPhcTuC9A==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/cli/-/cli-0.8.0.tgz", + "integrity": "sha512-6BOf//IY17Gz/C2kzGVHTn0bF5zMAtJWxofVAW96L/pwJQWHzxioqOpNWLVk1bHh6m2Jh59NOzwWtuR3xBpGTQ==", "dev": true, "license": "MIT", "dependencies": { - "@wrnexus/compiler": "^0.7.0", - "@wrnexus/core": "^0.7.0", - "@wrnexus/csr": "^0.7.0", - "@wrnexus/db": "^0.7.0", - "@wrnexus/dev-server": "^0.7.0", - "@wrnexus/i18n": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/router": "^0.7.0", - "@wrnexus/styles": "^0.7.0", - "@wrnexus/syntax": "^0.7.0", - "@wrnexus/ui": "^0.7.0", - "@wrnexus/validation": "^0.7.0" + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/core": "^0.8.0", + "@wrnexus/csr": "^0.8.0", + "@wrnexus/db": "^0.8.0", + "@wrnexus/dev-server": "^0.8.0", + "@wrnexus/i18n": "^0.8.0", + "@wrnexus/mcp": "^0.8.0", + "@wrnexus/playground": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/router": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/styles": "^0.8.0", + "@wrnexus/syntax": "^0.8.0", + "@wrnexus/typecheck": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/validation": "^0.8.0", + "selfsigned": "^5.5.0" }, "bin": { "wrnexus": "dist/index.js" @@ -1415,316 +1611,435 @@ } }, "node_modules/@wrnexus/compiler": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/compiler/-/compiler-0.7.0.tgz", - "integrity": "sha512-iS3oaIiwTeffdriC2PlLS9MTOX4CU5lRDq6uO0ExbB/wvZ7qnBnT2mpliyZGPF5m7BKadPf77rr8dDtIg8C9iQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/compiler/-/compiler-0.8.0.tgz", + "integrity": "sha512-xRIUer9UrzfXxebLIvEkeIHiZ1VhRhb8/ium/m0ehqyLllLf1oOH8mFT3g6tdnwZs8B4UJXlwdrIfbBs/xWrvg==", "license": "MIT", "dependencies": { - "@wrnexus/store": "^0.7.0", - "@wrnexus/syntax": "^0.7.0" + "@wrnexus/csr": "^0.8.0", + "@wrnexus/store": "^0.8.0", + "@wrnexus/syntax": "^0.8.0", + "@wrnexus/validation": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, + "node_modules/@wrnexus/content": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/content/-/content-0.8.0.tgz", + "integrity": "sha512-vE0LR53Pgu7ZVAxJF+QuiyGnlmL/1R9ZJ1fApRHTB6szCSFk1gaNvENiXH0H7LOYWEVvUXI9ITiC1cONfyHNRA==", + "license": "MIT", + "engines": { + "bun": ">=1.3.0" + } + }, "node_modules/@wrnexus/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/core/-/core-0.7.0.tgz", - "integrity": "sha512-HsQ1jHLMy+W+9H2BV7ilpAkbA2cCBJ3TEI8H6wTSC51j9C0HRZHtX1wlg0pDBsQEDwumpKFwvr3IxH9HVlpl5A==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/core/-/core-0.8.0.tgz", + "integrity": "sha512-4lz7E8uWraMjx4XOl5AfY1gizPiF6MOmKueWmJIbEhtg8pRetU5Sl3H1u4Ngmt1ZE/WkSUihLrtgurb6kQwTTg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/csr": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/csr/-/csr-0.7.0.tgz", - "integrity": "sha512-7EofnItpvQRZSvRi4nFjxOQiPMlbyFKgkhRlDo0lpElqslm+Kr1pRj1ux5wzSQZnb/XUMcaA45l5CX7poZq+eQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/csr/-/csr-0.8.0.tgz", + "integrity": "sha512-wlS4yW/tBGHGe0Dv7IJ7AoL+ZOXosKlRVK7t9z0+4cpI8d18/WpX73AqNjTqYYYczGMUXS0M1DMgtPDRpuhVGg==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/db": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/db/-/db-0.7.0.tgz", - "integrity": "sha512-Weh8V5SrJEHKXQwMWYVyTkPdtrF5HV59jn0Z6VuZsKsEh0hAIhKbqGT2nAKHqddWaUjwxNt+hRQltx2lX/9MMQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/db/-/db-0.8.0.tgz", + "integrity": "sha512-uFRv2BRSqRrHygab5nQnT/CZ5KMq8KrRoNiVXWoye40txFZklabMlqGhAR+WsWx7URuBqjPE+Pufz2gBpZOStQ==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/dev-server": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/dev-server/-/dev-server-0.7.0.tgz", - "integrity": "sha512-NE7sU68s2GMp3eWPPYLVLGIIZZVDJxfLXr98yFFQq2XniAaDuHz9NBO8CIzamWlWtFhKcLKbgwYMkyLfOukd3A==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/dev-server/-/dev-server-0.8.0.tgz", + "integrity": "sha512-WYX5ahqLl2TUf/H4y16dsu7JLGumFZykU3dZQ7AMsrZ9wdZNMiDKzHWIfZmQaL5cqILTIv1bPv3PpvYQAP1rIw==", "license": "MIT", "dependencies": { - "@wrnexus/compiler": "^0.7.0", - "@wrnexus/core": "^0.7.0", - "@wrnexus/csr": "^0.7.0", - "@wrnexus/db": "^0.7.0", - "@wrnexus/dev-toolbar": "^0.7.0", - "@wrnexus/i18n": "^0.7.0", - "@wrnexus/observability": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/pubsub": "^0.7.0", - "@wrnexus/router": "^0.7.0", - "@wrnexus/security": "^0.7.0", - "@wrnexus/ssr": "^0.7.0", - "@wrnexus/store": "^0.7.0", - "@wrnexus/styles": "^0.7.0", - "@wrnexus/ui": "^0.7.0", - "@wrnexus/uploader": "^0.7.0", - "@wrnexus/validation": "^0.7.0" + "@wrnexus/cache": "^0.8.0", + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/core": "^0.8.0", + "@wrnexus/csr": "^0.8.0", + "@wrnexus/db": "^0.8.0", + "@wrnexus/dev-toolbar": "^0.8.0", + "@wrnexus/i18n": "^0.8.0", + "@wrnexus/observability": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/pubsub": "^0.8.0", + "@wrnexus/pwa": "^0.8.0", + "@wrnexus/router": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/ssr": "^0.8.0", + "@wrnexus/store": "^0.8.0", + "@wrnexus/styles": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/uploader": "^0.8.0", + "@wrnexus/validation": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/dev-toolbar": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/dev-toolbar/-/dev-toolbar-0.7.0.tgz", - "integrity": "sha512-iqI47nhtKmuSvu3cyju/Mg343+evqBnD4Ek2TQg+kvxhnEfVNmPKBZ6CRZGC3Qq+C8j0TuCUVD3Sb88hiV0+Qw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/dev-toolbar/-/dev-toolbar-0.8.0.tgz", + "integrity": "sha512-efkTX27nYnKiqej+DKTMt/1T4JgEUeBzNF4GOuT1i5IA4M2X1DFH84sq4A+Oc2d+mzEjRklmQgYqQmjVmJ0skg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/encryption": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/encryption/-/encryption-0.7.0.tgz", - "integrity": "sha512-eLMVjHZbK0+2wJBdyPzCx3JQd8btgtvzcWQ+1XSMPmnxvsxVhVjxe2COgey8mRd2aUeltTvgJEqAIQ3AM9nlMw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/encryption/-/encryption-0.8.0.tgz", + "integrity": "sha512-JpibmlHuTX6dII6mYDCjj55CdN9nubD+SMEqQEi3Lw2jOZrLMaBcytrKhivpE8z3EnegTVurxlzi190+SUTTeQ==", "license": "MIT", + "dependencies": { + "@wrnexus/core": "^0.8.0" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/graphql": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/graphql/-/graphql-0.8.0.tgz", + "integrity": "sha512-7urjt+17g2z9K0OUohG+0B1jEnYPpt6EF4d8JcHkhdwEGdqi8NFHxH4ymzcN4fmf5tmglRKnJkvq+X3i+65jKw==", + "license": "MIT", + "dependencies": { + "@wrnexus/plugin": "^0.8.0" + }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/helpers": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/helpers/-/helpers-0.7.0.tgz", - "integrity": "sha512-G9Fo5L23Xnp+cY0Q3fWcEtWpNNak5+/Wr2i+OZxxSjiHbKQtNi29kZ/HVROOGe978KAw8GTk6rycwUA4Ul568A==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/helpers/-/helpers-0.8.0.tgz", + "integrity": "sha512-xmXU5xVJzoR+GXdoX1rmfUqEv/0A278SpMj4hBqSDAioqS9edqJFyPqyCFPK/4M/ZZphihk46N1kkn3ySiqJsw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/i18n": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/i18n/-/i18n-0.7.0.tgz", - "integrity": "sha512-1vOxW/07E2HqlvQHn+sJOQDlapcX1KXcdbge5yMvIUtDd1eTxuQfeo99svfgYxmoPzKqt8cDc5fU7O18Wvdedw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/i18n/-/i18n-0.8.0.tgz", + "integrity": "sha512-ZzanKCaKuKLiFOQ5nbvd/LQiXqs4E7tXQMjBuJJzZN0WJAZNrr3vhYUtvoZVO9e0TCUPRosGOp5G8lVx/j/tRw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/ui": "^0.8.0" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/identity": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/identity/-/identity-0.8.0.tgz", + "integrity": "sha512-mcLqMyG4i8H6mSEUCJOxOjOz6Njhz+EbkRZd8wxc6iLEkoHf676dVT7maEIOOUoof62Is0F5ZFkM58lJ8pC35w==", + "license": "MIT", + "dependencies": { + "@wrnexus/auth": "^0.8.0", + "@wrnexus/authz": "^0.8.0", + "@wrnexus/oauth": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/image": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/image/-/image-0.7.0.tgz", - "integrity": "sha512-nxOHnhMHGOnW4dAYHH2hlpWCPhnDccqKPbrJZOWTk4ljxYI7PS4BHlH89FddeL1gdRqMu1dxrgyk/2N7SsF0Dg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/image/-/image-0.8.0.tgz", + "integrity": "sha512-IUAhEIrdM1PuIo2DBZ3j1UGd0iSmq1cD1gJxR7K+vkesH1hCMegvAbT0mebJHe3eavvHAKZnrfJDEG/NFMDEBg==", "license": "MIT", "dependencies": { - "@wrnexus/security": "^0.7.0" + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/ui": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/jwt": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/jwt/-/jwt-0.7.0.tgz", - "integrity": "sha512-2oA6dWUgz05QnmjpnfSV+j7nfJ+Cx0E2u74r7xrrFGnvqCSHxUofDaQq7LpOeQW7tkTBFHsinmsTpp3x7ie8vQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/jwt/-/jwt-0.8.0.tgz", + "integrity": "sha512-PsoopDSMblOpzGH3gP/UnGLVw0wBYLG4ozIn6C9NwsYm/e9tdbGJYibf5nWV1PCnqcKIgNjkXIAQa1jzhJHHSA==", "license": "MIT", + "dependencies": { + "@wrnexus/core": "^0.8.0" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/language-server": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/language-server/-/language-server-0.8.0.tgz", + "integrity": "sha512-Io5kak0s0ETp1WOkljjTEJzGZnipfsl0XgrbRC/ywF/Jwn6iXCdjBcImffWXfFGcfcjEP5AaWXQetoiAUAKz8w==", + "license": "MIT", + "dependencies": { + "@wrnexus/syntax": "^0.8.0", + "@wrnexus/typecheck": "^0.8.0" + }, + "bin": { + "wrnexus-language-server": "dist/server.js" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/mcp": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/mcp/-/mcp-0.8.0.tgz", + "integrity": "sha512-vodjH/86rNbZAGC6ppM6UKyBkTm0UDAgmhEZ4YVLCbD8ewcsDEzh007+QpQD99f/mMEJYePRQqn4PmaGuChI9g==", + "license": "MIT", + "bin": { + "wrnexus-mcp": "dist/stdio.js" + }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/mobile": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/mobile/-/mobile-0.7.0.tgz", - "integrity": "sha512-1Q1gJrwUtqJrS0B7aDdvor/CU88iTmFw7BinUY87bzqwMo1/ZJI0kdYFIZyFDFJeJr0TEtoepPA9n5TxnzRL/Q==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/mobile/-/mobile-0.8.0.tgz", + "integrity": "sha512-aC8pD5YzIJSdPY5GQmVr0IY19l0ljDA7ZtZLFP43AwSYzR+LEYu9zYln7pp6M+I/aOxN/dxRP/pzwLsPTjMSnA==", "license": "MIT", "dependencies": { - "@wrnexus/native": "^0.7.0" + "@wrnexus/native": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/native": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/native/-/native-0.7.0.tgz", - "integrity": "sha512-dkcrc6+ulkjt4p2/yL7jpY2iALWy+OkOUORAnF5AmUNQEHcDH7kDR3+k1QexI9h6FcB0T/DqTTUBLVqYN2y7Qw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/native/-/native-0.8.0.tgz", + "integrity": "sha512-vslU63cozqEwIDNdtvt4Q27VPq5U4SZgJIGCN4meMnBfH1ID/XSwXJ3at6j5NbLvq/vu1nJVxNtAh5JBhxkFSA==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/oauth": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/oauth/-/oauth-0.7.0.tgz", - "integrity": "sha512-xgjUwHUdgNfk0s+AD9c+i0WcaGIOa2iv+uDJyFaNymSB1MCkYMxKx2NwLfIteb+uiyowCD335i4He5edzx579g==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/oauth/-/oauth-0.8.0.tgz", + "integrity": "sha512-OZ949JONJ1lgqtNeSDFfsjh3azUj0DQyJTqzxwZ1oP4ruwbPO98NhdqgCXyRUA+dXU1i3lpuCf/zY7Pv4krYWQ==", "license": "MIT", + "dependencies": { + "@wrnexus/jwt": "^0.8.0" + }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/observability": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/observability/-/observability-0.7.0.tgz", - "integrity": "sha512-EmMoVVsFl/IznDX4jR/xQAg/Nubgo47FROkglQhblakQ2T0bmkED8DOc433Ow1fDJwJsigF/GoDVmFzfIQlJJA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/observability/-/observability-0.8.0.tgz", + "integrity": "sha512-r/vtxHDBdJVqrPN5qr8prKbMv0gPF0I8CLWT9/UOpj/qjMgBX4UmsUbmI7SW1itrgvsZFYf4vh2vIlJY7GHz7A==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/playground": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/playground/-/playground-0.8.0.tgz", + "integrity": "sha512-8t84X8H4NWVmf20nsCspOY3WII3+o95a9eTn0ZjQFRBwaAdfngwdddvPrUae+xnyZqNddyH219B2Ed1G48VN6Q==", + "license": "MIT", + "dependencies": { + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/syntax": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/plugin": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/plugin/-/plugin-0.7.0.tgz", - "integrity": "sha512-tD/D0LC2WBPR57dz0Ztd5JiGOaWGPnraBPjYtQ13nV3AEmzoRvJmgRqTj496rbIbpytbES7yfHbBsvwbUz6kmg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/plugin/-/plugin-0.8.0.tgz", + "integrity": "sha512-NIWvCAzv6R0DALdtxU0/RlpbQUPIwezg6PK1d5JNekHREdfkftmX/+Ka25wah1ktUmGO29CywzxQ9bBAG/AgQw==", "license": "MIT", "dependencies": { - "@wrnexus/syntax": "^0.7.0" + "@wrnexus/syntax": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/pubsub": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/pubsub/-/pubsub-0.7.0.tgz", - "integrity": "sha512-wYz4xiaFLDJnJMv8tPKHFGmQXbeAag/n9ITK+6S/QJXyWdkzlHjmviYE81slmauqcqr1p40hZ3j7qYtdKyZ5fA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/pubsub/-/pubsub-0.8.0.tgz", + "integrity": "sha512-DyikECFdar10y0UoIQRHgfOzt3WfcoX8xpMH1uPCuXIo0AVuNpUMOtOJNynWHHAQ3TdjoJbDX8u/PwZVDfLAiw==", + "license": "MIT", + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/pwa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/pwa/-/pwa-0.8.0.tgz", + "integrity": "sha512-bs8mVtv4dXzbZIlkONpysINVwkL9ir1jdzuQVWSr3naCe+bknKRvCeIw0Y9DqoxvpEVzAsIMLLR3vLbjCNIIFA==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/queue": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/queue/-/queue-0.7.0.tgz", - "integrity": "sha512-6ti38dKNCCeIvzjUkdPt3nKv5MCQtNF6AhMkeIAlX2l26Wgf4+iPGovz+yf+k3doN35+UFnQ1fg/zjZdC9K5Wg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/queue/-/queue-0.8.0.tgz", + "integrity": "sha512-PLM8KY/5R+3lwoDc2TK9PdEs7aOjCkdkfvK1nlz0ylbT0ej+LsfLFDTlAYifS0qrSJT9r88JWwswvJYUu7OnGg==", "license": "MIT", + "dependencies": { + "@wrnexus/core": "^0.8.0" + }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/reactive": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/reactive/-/reactive-0.7.0.tgz", - "integrity": "sha512-TVQmoXE8kiAdmUvVKiEFqWpW1WiklZ7BxW2A3z7esoQRzgBCrnSSsbjETm4GDNJUQJZaCg6NGV29QvuHZiGzDA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/reactive/-/reactive-0.8.0.tgz", + "integrity": "sha512-jkW7W5YxTmKbdcUiahgDl8laAZR7O8l0DSW0x4+Oj0G1jWuNP7/eEIXtIHtX9MC2UEGhK0dv5S78zTp/bMD/9A==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, - "node_modules/@wrnexus/router": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/router/-/router-0.7.0.tgz", - "integrity": "sha512-82VowxOouJjHj4O7sy3NDWmwdQb4BqZwK9a9mj03ULBrXuAFkbDeY/stHIPKE1K6K+ICH2E2qAF4o1eXgWVxeQ==", + "node_modules/@wrnexus/realtime": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/realtime/-/realtime-0.8.0.tgz", + "integrity": "sha512-NPZmkf3eyHpkMyLQ80Bu1Fq1/6geiGtL4amVV+ZQaUW7zvdFlrgWsM3fbyMJ9k1iLs/UoeOUCaWe++UXnuZPzA==", "license": "MIT", "dependencies": { - "@wrnexus/compiler": "^0.7.0", - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/ui": "^0.8.0" + }, + "engines": { + "bun": ">=1.3.0" + } + }, + "node_modules/@wrnexus/router": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/router/-/router-0.8.0.tgz", + "integrity": "sha512-7asmgW1zPf4uYjiDo7fhM2BQnGKNIearyIEV154QGppaA2OmGHN02bxWC0sd2tPWHY2qJLRCV221dUnE0kMtzg==", + "license": "MIT", + "dependencies": { + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/core": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/security": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/security/-/security-0.7.0.tgz", - "integrity": "sha512-XfnjwhbrDcwdDQzTMNyCwM9ODWVtzgL7IjsTix3bWd3zmEigkiyNxpCNxMoX79m0ATzi7YzBOriJ5o5hg8RGJQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/security/-/security-0.8.0.tgz", + "integrity": "sha512-PDFTFYX9HE4lBiS1+/UTcIgMr93m1VZ3M9EyRy0cvufOzXsoT6M1jlwoUEz56rjeZw1bT7ZDD1RLRmtUZRfkVw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/ssr": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/ssr/-/ssr-0.7.0.tgz", - "integrity": "sha512-1hRaXCDG16aBP7PlVGCRqXw9JHjMlxZUwqI9QiMgeJ+Z0lHU1zNjqepo4xN8Rmug3oUQ0rSpGYj7CxN1QWFgdw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/ssr/-/ssr-0.8.0.tgz", + "integrity": "sha512-yBidB8GKrmUSviPNW48BJHikKkiu3I3zlymTIK/1bAuVTT89FUfS5jU5rNGHjvthJbahuqOJxLiG0vTcLKQpxw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0", - "@wrnexus/security": "^0.7.0", - "@wrnexus/store": "^0.7.0" + "@wrnexus/core": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/store": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/store": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/store/-/store-0.7.0.tgz", - "integrity": "sha512-yrlVX1q1NRDWvQ6tDj7BGxy/IGzjPjhESqnZtWN7KnR53TsFT+yxhVZdnyJxVSp/IipvJh0u2bgK4H/ZDYEozg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/store/-/store-0.8.0.tgz", + "integrity": "sha512-T4nv6iNRf9Kw2mambBUMy5wteZfpwns6fVEuMpdaQtKceZ6MzXiaqWdeKU02mDHSnBW9W+GuIKNolZNZSZDT+w==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/styles": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/styles/-/styles-0.7.0.tgz", - "integrity": "sha512-PiSlWNlg+kJ2P4kpHD1q/yDteSzCdpsvyeUmC4uRS724orubAkmQe2yk4e+CRr3MoQnxvHzefo+NamJcdrJwGg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/styles/-/styles-0.8.0.tgz", + "integrity": "sha512-BjXyzI7qGWScyR9/+2Py3MrEu1p7lJOYu0UnXjKX20HOFfFGbKKPTdjsI1JHiFp15XtFejfDvvWB7bclnWjvcA==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/uploader": "^0.7.0" + "@wrnexus/core": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/uploader": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/syntax": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/syntax/-/syntax-0.7.0.tgz", - "integrity": "sha512-pygjZXLoQtHiP5DcxRX++GbZInmNzuoNtXmGgYWVH0oVMzPPYXUtyCX5O7tzY7hEqLhs+TG7CCyWIoum1rbkJg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/syntax/-/syntax-0.8.0.tgz", + "integrity": "sha512-RjkfeKBQ/Pj9UgAJ3DMcmEkZFZb80o56vVXy0CgvzPE/NrrOZJPpOgeRza07vHQ3ewdATSUXG85BS/pt2FNBNQ==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/test": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/test/-/test-0.7.0.tgz", - "integrity": "sha512-3sYKNC6WUuwFoFAoDnZxVPCIwBU3CTkXbme9yd6c51eaksiNkPJJsQxANx83c/AM2k6z9BeH04ESUPgedm4GFg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/test/-/test-0.8.0.tgz", + "integrity": "sha512-4Q4oAUsZNLSiJOxUYnTp9umrR8r+DBijSxI0ZakwF7iK9cps70r6TaAeDNfoDbv2XTgyeL/z6Ixj5EXLuOKaQw==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/tracking": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/tracking/-/tracking-0.7.0.tgz", - "integrity": "sha512-Q6cbKFD+0lW1PV8gPtXXZb1bS2w8wcKyCloOS2kRJR808LoIE6Y3XLWcL090w9HXmT2lBLVytriVl0LL19fe8g==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/tracking/-/tracking-0.8.0.tgz", + "integrity": "sha512-SZopBuL8vtw/gYFe/CUCGyJFAc4Q/bhOXVEHE81OPx9Af5lfsrx7Rzb+ktHUcpGwSxJ2uEJuPhkV4YWJYHHFyg==", "license": "MIT", "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/typecheck": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/typecheck/-/typecheck-0.7.0.tgz", - "integrity": "sha512-49BcKK+5vNJ3JO3kHuGvFYRhjQli1n9GCSg6ppTUq7pg95AB4Amtn8VrYOIhMKxbu/bmRJAvUAjfW/aLnZwJ6A==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/typecheck/-/typecheck-0.8.0.tgz", + "integrity": "sha512-ie8t9iYC1KjxyXipvyKXfkM5tDDSv9K7trFyRGD6m1cUzvZsqAzq9QcdxmbR8ypcxdGfNff5i+mz+NFujeZAPQ==", "license": "MIT", "dependencies": { - "@wrnexus/syntax": "^0.7.0", + "@wrnexus/syntax": "^0.8.0", "typescript": "^5.5.0" }, "engines": { @@ -1732,34 +2047,41 @@ } }, "node_modules/@wrnexus/ui": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/ui/-/ui-0.7.0.tgz", - "integrity": "sha512-31/8YOOl9iGckZ37C6s7gIwm1Xkq+YTkClNNC3VgM6/kn2BvGKKURiS9qngy2QznMmZ7jmRnwHOQmbTjldcJfA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/ui/-/ui-0.8.0.tgz", + "integrity": "sha512-KtYHZV50lDeOixZaS688UrulSRU39DTnl6gF+NhMBSdoIDqlX+FcAay7ccgzLN6B/6PlLBuQMsONGavzCZ8J8g==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/uploader": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/uploader/-/uploader-0.7.0.tgz", - "integrity": "sha512-YrT6KUWjR3ElO4DCTTSdXnZBEL+r3GDSpeXEZOpIZByd+6/vgsMPWbVSfqNZi9ZS2oYeUJtF9tKPAtQlOA8WGg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/uploader/-/uploader-0.8.0.tgz", + "integrity": "sha512-BcCzcIwnRsr7NnRYZVhrBXaqNkgI4dB8woWNgsujrYU0G43+oQ9tkLlSciY+vl8y0One/D9uTq+tjm3q1jlFMw==", "license": "MIT", "dependencies": { - "@wrnexus/core": "^0.7.0" + "@wrnexus/core": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/ui": "^0.8.0" }, "engines": { "bun": ">=1.3.0" } }, "node_modules/@wrnexus/validation": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@wrnexus/validation/-/validation-0.7.0.tgz", - "integrity": "sha512-nlIStY1coiCJDunGW1ilBuZqTAkiz7vlICAHe+h7sOhHJ2zd0FXVnwuN4yKR+RAn7pT9r3e/QG5NG8+/J5RsfQ==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@wrnexus/validation/-/validation-0.8.0.tgz", + "integrity": "sha512-07RE6Jm7ZK1U+i3OvDYt7mOJC+Q7u7lUnCffT02yFDW06oQ+hxiadVVR+fgNHOJEevCgZwyOaKJzVPTC5Qoumw==", "license": "MIT", + "dependencies": { + "@wrnexus/core": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/ui": "^0.8.0" + }, "engines": { "bun": ">=1.3.0" } @@ -1817,6 +2139,21 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "dev": true, @@ -1856,6 +2193,16 @@ "@types/node": "*" } }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/callsites": { "version": "3.1.0", "dev": true, @@ -3009,6 +3356,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -3041,6 +3406,33 @@ "node": ">=6" } }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/resolve-from": { "version": "4.0.0", "dev": true, @@ -3058,6 +3450,20 @@ "node": ">=11.0.0" } }, + "node_modules/selfsigned": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", + "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/x509": "^1.14.2", + "pkijs": "^3.3.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/semver": { "version": "7.8.5", "dev": true, @@ -3204,6 +3610,33 @@ "typescript": ">=4.8.4" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsyringe": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", + "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "dev": true, diff --git a/package.json b/package.json index 6f6d3a67..cbd8df99 100644 --- a/package.json +++ b/package.json @@ -27,50 +27,58 @@ "dependencies": { "@iconify-json/lucide": "^1.2.118", "@iconify/tailwind4": "^1.2.3", - "@wrnexus/ai": "^0.7.0", - "@wrnexus/authz": "^0.7.0", - "@wrnexus/compiler": "^0.7.0", - "@wrnexus/core": "^0.7.0", - "@wrnexus/csr": "^0.7.0", - "@wrnexus/db": "^0.7.0", - "@wrnexus/dev-server": "^0.7.0", - "@wrnexus/encryption": "^0.7.0", - "@wrnexus/helpers": "^0.7.0", - "@wrnexus/i18n": "^0.7.0", - "@wrnexus/jwt": "^0.7.0", - "@wrnexus/mobile": "^0.7.0", - "@wrnexus/native": "^0.7.0", - "@wrnexus/oauth": "^0.7.0", - "@wrnexus/pubsub": "^0.7.0", - "@wrnexus/queue": "^0.7.0", - "@wrnexus/reactive": "^0.7.0", - "@wrnexus/router": "^0.7.0", - "@wrnexus/ssr": "^0.7.0", - "@wrnexus/styles": "^0.7.0", - "@wrnexus/test": "^0.7.0", - "@wrnexus/tracking": "^0.7.0", - "@wrnexus/ui": "^0.7.0", - "@wrnexus/uploader": "^0.7.0", - "@wrnexus/validation": "^0.7.0", - "@wrnexus/dev-toolbar": "^0.7.0", - "@wrnexus/syntax": "^0.7.0", - "@wrnexus/plugin": "^0.7.0", - "@wrnexus/captcha": "^0.7.0", - "@wrnexus/auth": "^0.7.0", - "@wrnexus/store": "^0.7.0", - "@wrnexus/typecheck": "^0.7.0", - "@wrnexus/security": "^0.7.0", - "@wrnexus/cache": "^0.7.0", - "@wrnexus/image": "^0.7.0", - "@wrnexus/observability": "^0.7.0", - "@wrnexus/benchmark": "^0.7.0" + "@wrnexus/ai": "^0.8.0", + "@wrnexus/authz": "^0.8.0", + "@wrnexus/compiler": "^0.8.0", + "@wrnexus/core": "^0.8.0", + "@wrnexus/csr": "^0.8.0", + "@wrnexus/db": "^0.8.0", + "@wrnexus/dev-server": "^0.8.0", + "@wrnexus/encryption": "^0.8.0", + "@wrnexus/helpers": "^0.8.0", + "@wrnexus/i18n": "^0.8.0", + "@wrnexus/jwt": "^0.8.0", + "@wrnexus/mobile": "^0.8.0", + "@wrnexus/native": "^0.8.0", + "@wrnexus/oauth": "^0.8.0", + "@wrnexus/pubsub": "^0.8.0", + "@wrnexus/queue": "^0.8.0", + "@wrnexus/reactive": "^0.8.0", + "@wrnexus/router": "^0.8.0", + "@wrnexus/ssr": "^0.8.0", + "@wrnexus/styles": "^0.8.0", + "@wrnexus/test": "^0.8.0", + "@wrnexus/tracking": "^0.8.0", + "@wrnexus/ui": "^0.8.0", + "@wrnexus/uploader": "^0.8.0", + "@wrnexus/validation": "^0.8.0", + "@wrnexus/dev-toolbar": "^0.8.0", + "@wrnexus/syntax": "^0.8.0", + "@wrnexus/plugin": "^0.8.0", + "@wrnexus/captcha": "^0.8.0", + "@wrnexus/auth": "^0.8.0", + "@wrnexus/store": "^0.8.0", + "@wrnexus/typecheck": "^0.8.0", + "@wrnexus/security": "^0.8.0", + "@wrnexus/cache": "^0.8.0", + "@wrnexus/image": "^0.8.0", + "@wrnexus/observability": "^0.8.0", + "@wrnexus/benchmark": "^0.8.0", + "@wrnexus/realtime": "^0.8.0", + "@wrnexus/content": "^0.8.0", + "@wrnexus/graphql": "^0.8.0", + "@wrnexus/identity": "^0.8.0", + "@wrnexus/language-server": "^0.8.0", + "@wrnexus/mcp": "^0.8.0", + "@wrnexus/playground": "^0.8.0", + "@wrnexus/pwa": "^0.8.0" }, "devDependencies": { "@eslint/js": "^9.0.0", "@tailwindcss/cli": "^4.0.0", "@types/bun": "latest", "@types/node": "^26.1.1", - "@wrnexus/cli": "^0.7.0", + "@wrnexus/cli": "^0.8.0", "eslint": "^9.0.0", "prettier": "latest", "tailwindcss": "^4.0.0", @@ -78,6 +86,6 @@ "typescript-eslint": "latest" }, "wrnexus": { - "version": "0.7.0" + "version": "0.8.0" } } diff --git a/public/docs-index.json b/public/docs-index.json index 0588c563..80cfeaea 100644 --- a/public/docs-index.json +++ b/public/docs-index.json @@ -1,5 +1,5 @@ { - "version": "0.7.0", + "version": "0.8.0", "status": "private-developer-preview", "generatedAt": "2026-07-13", "documents": [ @@ -7,560 +7,616 @@ "url": "/", "title": "WRNexusJS", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/access", "title": "access", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/getting-started", "title": "getting started", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/tutorial", "title": "tutorial", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/architecture", "title": "architecture", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/language", "title": "language", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages", "title": "packages", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/project-structure", "title": "project structure", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/routing", "title": "routing", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/pages-and-components", "title": "pages and components", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/server-data", "title": "server data", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/api-routes", "title": "api routes", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/middleware", "title": "middleware", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/forms-and-validation", "title": "forms and validation", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/authentication", "title": "authentication", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/authorization", "title": "authorization", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/security", "title": "security", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/database", "title": "database", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/uploads", "title": "uploads", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/realtime", "title": "realtime", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/pubsub", "title": "pubsub", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/queues", "title": "queues", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "experimental" }, { "url": "/guides/testing", "title": "testing", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/workspaces-and-gateway", "title": "workspaces and gateway", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/deployment", "title": "deployment", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/configuration-and-profiles", "title": "configuration and profiles", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/i18n-and-themes", "title": "i18n and themes", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/mobile", "title": "mobile", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "experimental" }, { "url": "/guides/observability", "title": "observability", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/upgrading", "title": "upgrading", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/guides/troubleshooting", "title": "troubleshooting", "section": "guide", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/examples", "title": "examples", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/showcase", "title": "showcase", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/benchmarks", "title": "benchmarks", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/roadmap", "title": "roadmap", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/changelog", "title": "changelog", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { - "url": "/releases/0.7.0", - "title": "0.7.0", + "url": "/releases/0.8.0", + "title": "0.8.0", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/security", "title": "security", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/support", "title": "support", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/license", "title": "license", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/search", "title": "search", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/404", "title": "404", "section": "portal", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/ai", "title": "ai", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/auth", "title": "auth", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/authz", "title": "authz", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/benchmark", "title": "benchmark", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/cache", "title": "cache", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/captcha", "title": "captcha", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/cli", "title": "cli", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/compiler", "title": "compiler", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/content", + "title": "content", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/core", "title": "core", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/csr", "title": "csr", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/db", "title": "db", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/dev-server", "title": "dev server", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/dev-toolbar", "title": "dev toolbar", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/encryption", "title": "encryption", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/graphql", + "title": "graphql", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/helpers", "title": "helpers", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/i18n", "title": "i18n", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/identity", + "title": "identity", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/image", "title": "image", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/jwt", "title": "jwt", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/language-server", + "title": "language server", + "section": "package", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/mcp", + "title": "mcp", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/mobile", "title": "mobile", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "experimental" }, { "url": "/packages/native", "title": "native", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/oauth", "title": "oauth", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/observability", "title": "observability", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/playground", + "title": "playground", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/plugin", "title": "plugin", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/pubsub", "title": "pubsub", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/pwa", + "title": "pwa", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/queue", "title": "queue", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/reactive", "title": "reactive", "section": "package", - "version": "0.7.0", + "version": "0.8.0", + "stability": "preview" + }, + { + "url": "/packages/realtime", + "title": "realtime", + "section": "package", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/router", "title": "router", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/security", "title": "security", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/ssr", "title": "ssr", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/store", "title": "store", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/styles", "title": "styles", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/syntax", "title": "syntax", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/test", "title": "test", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/tracking", "title": "tracking", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/typecheck", "title": "typecheck", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/ui", "title": "ui", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/uploader", "title": "uploader", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" }, { "url": "/packages/validation", "title": "validation", "section": "package", - "version": "0.7.0", + "version": "0.8.0", "stability": "preview" } ] diff --git a/public/llms-full.txt b/public/llms-full.txt index b4c460de..29cdaf96 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -1,6 +1,6 @@ -# WRNexusJS documentation 0.7.0 +# WRNexusJS documentation 0.8.0 -Status: Private Developer Preview. This site documents 38 release-aligned packages. +Status: Private Developer Preview. This site documents 46 release-aligned packages. # WrNexus @@ -279,7 +279,7 @@ wrnexus eject # copy a Wire UI component's .wrn into app/compone 4. Style with Tailwind utility classes in the view, or theme tokens (`var(--wire-*)`), or `style { }`. 5. Never emit React/JSX, a manual router, or client-side island JS — the framework handles hydration. -Release: WRNexusJS 0.7.0 +Release: WRNexusJS 0.8.0 # Canonical documentation locations @@ -288,7 +288,7 @@ Release: WRNexusJS 0.7.0 # Installed package documentation -The following README files and declarations come from the installed private 0.7.0 release. +The following README files and declarations come from the installed private 0.8.0 release. ## @wrnexus/ai @@ -296,6 +296,10 @@ Documentation URL: https://wrnexusjs.dev/packages/ai # @wrnexus/ai +Provider-neutral AI orchestration for OpenAI, Anthropic, Google and local OpenAI-compatible models, +with streaming, structured output, tools, embeddings, vector search/RAG, conversation persistence, +templates, guardrails, usage events, fallback, rate limits and evaluation reports. + > A tiny, zero-dependency Claude (Anthropic) client for WrNexus apps — generate and stream text with Claude from any server-side code. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. @@ -416,6 +420,34 @@ try { } ``` +### Multi-provider client + +`createAIClient` adds named-provider selection and fallback, capability discovery, +validated JSON output, validated tool execution, abort-aware exponential retries, +and per-provider circuit breakers. Attempt events intentionally contain metadata +only: prompts, credentials, and raw model responses are never passed to telemetry. + +```ts +import { anthropicProvider, createAIClient } from "@wrnexus/ai"; + +const ai = createAIClient({ + providers: [anthropicProvider()], + retry: { attempts: 3, baseDelayMs: 100, maxDelayMs: 2_000 }, + circuitBreaker: { failureThreshold: 5, resetAfterMs: 30_000 }, +}); + +const result = await ai.generateObject<{ title: string }>("Return a JSON title", { + validate: (value): value is { title: string } => + typeof value === "object" && value !== null && "title" in value, +}); +``` + +Providers can return normalized `usage` (`inputTokens`, `outputTokens`, +`totalTokens`, and `costUsd`) and `toolCalls`. Use `executeTools` with a named, +validated tool registry; unknown tools and invalid arguments are rejected before +application code runs. `deterministicAIProvider` supplies ordered or computed +offline responses for tests and examples without API keys or network calls. + ## Usage ### Return generated JSON from an API route @@ -463,112 +495,7 @@ export const POST = async (ctx) => { ### Exported TypeScript declarations ```ts -interface AIUsage { - inputTokens?: number; - outputTokens?: number; - totalTokens?: number; -} -interface AIResult { - value: T; - provider: string; - model?: string; - usage?: AIUsage; - finishReason?: string; - raw?: unknown; -} -interface AIProvider { - name: string; - generate(prompt: string | Message[], options?: GenerateOptions): Promise>; - stream?(prompt: string | Message[], options?: GenerateOptions): AsyncGenerator; -} -interface AIClientOptions { - providers: AIProvider[]; - fallback?: boolean; - onAttempt?: (provider: string, error?: unknown) => void | Promise; -} -interface AIClient { - generate(prompt: string | Message[], options?: GenerateOptions & { - provider?: string; - }): Promise>; - generateObject(prompt: string | Message[], options?: GenerateOptions & { - provider?: string; - validate?: (value: unknown) => value is T; - }): Promise>; - stream(prompt: string | Message[], options?: GenerateOptions & { - provider?: string; - }): AsyncGenerator; -} -declare function anthropicProvider(config?: AIConfig): AIProvider; -declare function aiProvider(name: string, client: AI): AIProvider; -declare function createAIClient(options: AIClientOptions): AIClient; - -/** - * @wrnexus/ai — a tiny, zero-dependency Claude (Anthropic) client for WrNexus apps. - * - * Use it in API routes, jobs, or anywhere server-side to generate text with Claude. - * It talks to the Anthropic Messages API over `fetch` (no SDK dependency, Bun-native), - * and defaults to the most capable model, `claude-opus-4-8`. - * - * import { createAI } from "@wrnexus/ai"; - * const ai = createAI(); // reads ANTHROPIC_API_KEY - * const text = await ai.generate("Write a haiku about Bun."); - * - * Streaming (great for API routes): - * export const POST = async (ctx) => ai.streamResponse(await ctx.req.text()); - */ -type Role = "user" | "assistant"; -interface Message { - role: Role; - content: string; -} -/** Reasoning effort — higher means deeper thinking + more tokens. */ -type Effort = "low" | "medium" | "high" | "xhigh" | "max"; -interface AIConfig { - /** Anthropic API key. Default: `ANTHROPIC_API_KEY` from the environment. */ - apiKey?: string; - /** Model id. Default: `claude-opus-4-8` (the most capable Claude model). */ - model?: string; - /** Default max output tokens. Default: 4096. */ - maxTokens?: number; - /** API base URL. Default: `https://api.anthropic.com`. */ - baseURL?: string; - /** `anthropic-version` header. Default: `2023-06-01`. */ - version?: string; -} -interface GenerateOptions { - /** System prompt — sets the assistant's role/behavior. */ - system?: string; - /** Override the model for this call. */ - model?: string; - /** Override max output tokens for this call. */ - maxTokens?: number; - /** Enable adaptive extended thinking (slower, deeper reasoning). */ - thinking?: boolean; - /** Reasoning effort / token spend (`output_config.effort`). */ - effort?: Effort; - /** Full message history — supersedes the `prompt` argument when provided. */ - messages?: Message[]; - /** Abort the request. */ - signal?: AbortSignal; -} -/** Thrown when the API returns a non-2xx response or refuses the request. */ -declare class AIError extends Error { - readonly status: number; - readonly type: string; - constructor(message: string, status?: number, type?: string); -} -interface AI { - /** Generate a full text response (non-streaming). */ - generate(prompt: string | Message[], opts?: GenerateOptions): Promise; - /** Stream the response as text deltas, as they arrive. */ - stream(prompt: string | Message[], opts?: GenerateOptions): AsyncGenerator; - /** Stream straight to a `Response` (text/plain) — drop-in for an API route return. */ - streamResponse(prompt: string | Message[], opts?: GenerateOptions): Response; -} -/** Create a Claude client. Reads `ANTHROPIC_API_KEY` from the environment by default. */ -declare function createAI(config?: AIConfig): AI; - -export { type AI, type AIClient, type AIClientOptions, type AIConfig, AIError, type AIProvider, type AIResult, type AIUsage, type Effort, type GenerateOptions, type Message, type Role, aiProvider, anthropicProvider, createAI, createAIClient }; +export { A as AI, a as AIAttemptEvent, b as AICircuitBreakerOptions, c as AIClient, d as AIClientOptions, e as AIConfig, f as AIError, AIGuardrail, g as AIProvider, h as AIProviderCapabilities, i as AIResult, j as AIRetryOptions, k as AITool, l as AIToolCall, m as AIUsage, ConversationStore, D as DeterministicAIProviderOptions, E as Effort, EmbeddingProvider, G as GenerateOptions, HttpAIProviderOptions, M as Message, R as Role, VectorMatch, VectorRecord, VectorStore, n as aiProvider, aiRateLimiter, o as anthropicProvider, p as createAI, q as createAIClient, createRagPipeline, r as deterministicAIProvider, evaluateAI, googleAIProvider, guardedProvider, localAIProvider, maxPromptLength, memoryConversationStore, memoryVectorStore, openAIEmbeddings, openAIProvider, promptTemplate } from './platform.js'; ``` --- @@ -948,22 +875,34 @@ bun run validate:auth Read [SECURITY.md](./SECURITY.md) before production deployment. +## Package-owned UI blocks and route helpers + +Authentication forms continue to compose `@wrnexus/ui` inputs, buttons, cards, alerts, badges, avatars, and PIN controls. The package also provides: + +- `` +- `` +- `` +- complete sign-in, sign-up, MFA, passkey, recovery, account-status, session, and impersonation blocks + +Server helpers include `authRoute`, `authSuccess`, `authFailure`, `requireAuthUser`, `optionalAuthUser`, `currentAuthSession`, and `authComponentProps`. + ### Exported TypeScript declarations ```ts -export { A as AuthEngine, c as createAuthEngine, i as inferIdentityType, n as normalizeEmail, a as normalizeIdentity, b as normalizePhone, d as normalizeUsername, p as publicUser, s as safeAuthReturnTo } from './engine-ZXtjHSyW.js'; -import { n as AuthRiskSignals, l as AuthRiskDecision } from './types-CbJKeaWh.js'; -export { A as AuthAccountStatus, a as AuthClock, b as AuthDeliveryMessage, c as AuthDeliveryProvider, d as AuthEngineOptions, e as AuthIdentity, f as AuthIdentityType, g as AuthImpersonationDecision, h as AuthMfaMethod, i as AuthPublicUser, j as AuthRandom, k as AuthResult, m as AuthRiskLevel, o as AuthSecretProtector, p as AuthSecurityEvent, q as AuthSession, r as AuthSessionVerificationHandler, s as AuthSignedInHandler, t as AuthSignedOutHandler, N as AuthStore, u as AuthSuccessfulSignUpAction, v as AuthSuccessfulSignUpHandler, w as AuthTokenPurpose, x as AuthTokenUrlInput, y as AuthUser, z as AuthenticatedContext, L as LoginAttempt, B as LoginInput, Q as MemoryPasskeyChallengeStore, O as OAuthAccount, C as OneTimeToken, D as OtpChallenge, P as PasskeyAuthenticationOptions, S as PasskeyChallengeKind, U as PasskeyChallengeRecord, V as PasskeyChallengeStore, E as PasskeyCredential, F as PasskeyProvider, G as PasskeyRegistrationOptions, H as PasskeyVerificationResult, I as PasswordBreachProvider, J as PasswordCredential, R as RecoveryCodeRecord, K as RegisterInput, T as TotpCredential, M as TrustedDevice, W as assertPasskeyProvider } from './types-CbJKeaWh.js'; +import { A as AuthEngine } from './engine-BDu0-aZp.js'; +export { c as createAuthEngine, i as inferIdentityType, n as normalizeEmail, a as normalizeIdentity, b as normalizePhone, d as normalizeUsername, p as publicUser, s as safeAuthReturnTo } from './engine-BDu0-aZp.js'; +import { o as AuthRiskSignals, m as AuthRiskDecision, s as AuthSession, B as AuthUser } from './types-BhwPi3qr.js'; +export { A as AUTH_SECURITY_EVENT_TYPES, a as AuthAccountStatus, b as AuthClock, c as AuthDeliveryMessage, d as AuthDeliveryProvider, e as AuthEngineOptions, f as AuthIdentity, g as AuthIdentityType, h as AuthImpersonationDecision, i as AuthMfaMethod, j as AuthPublicUser, k as AuthRandom, l as AuthResult, n as AuthRiskLevel, p as AuthSecretProtector, q as AuthSecurityEvent, r as AuthSecurityEventType, t as AuthSessionVerificationHandler, u as AuthSignedInHandler, v as AuthSignedOutHandler, U as AuthStore, w as AuthSuccessfulSignUpAction, x as AuthSuccessfulSignUpHandler, y as AuthTokenPurpose, z as AuthTokenUrlInput, C as AuthenticatedContext, K as KnownAuthSecurityEventType, L as LoginAttempt, D as LoginInput, V as MemoryPasskeyChallengeStore, O as OAuthAccount, E as OneTimeToken, F as OtpChallenge, P as PasskeyAuthenticationOptions, W as PasskeyChallengeKind, X as PasskeyChallengeRecord, Y as PasskeyChallengeStore, G as PasskeyCredential, H as PasskeyProvider, I as PasskeyRegistrationOptions, J as PasskeyVerificationResult, M as PasswordBreachProvider, N as PasswordCredential, R as RecoveryCodeRecord, Q as RegisterInput, T as TotpCredential, S as TrustedDevice, Z as assertPasskeyProvider } from './types-BhwPi3qr.js'; export { MemoryAuthStore } from './stores/memory.js'; export { SqlAuthStore } from './stores/sql.js'; export { AUTH_SESSION_KEY, authSession, clearAuthSession, establishAuthSession, getAuthSession, getAuthUser, isAuthenticatedContext, requireAuth } from './middleware.js'; -export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-DS1geh2P.js'; +export { A as AuthHttpOptions, a as AuthPasskeyHttpOptions, b as AuthSchemaOverrides, c as AuthSchemaSet, d as authBrowserSchemaDescriptors, e as authBrowserSchemaMap, f as authSchemas, g as authenticatorConfirmSchema, h as authenticatorDisableSchema, i as authenticatorSetupSchema, j as changePasswordSchema, k as createAuthHttpHandlers, l as emptyActionSchema, m as impersonationStartSchema, n as invitationAcceptSchema, o as loginSchema, p as magicLinkConsumeSchema, q as magicLinkRequestSchema, r as mfaOtpRequestSchema, s as mfaSchema, t as otpIssueSchema, u as otpLoginCompleteSchema, v as otpLoginRequestSchema, w as otpSchema, x as passkeyAuthenticationOptionsSchema, y as passkeyAuthenticationVerifySchema, z as passkeyRegistrationOptionsSchema, B as passkeyRegistrationVerifySchema, C as passwordResetRequestSchema, D as passwordResetSchema, E as recoveryCodesSchema, F as registerSchema, G as resolveAuthSchemas, H as sessionRevokeSchema, I as signUpSchema, J as verificationRequestSchema, K as verificationTokenSchema } from './index-B4uaD0Z3.js'; export { AuthAuditIssue, AuthConfig, AuthPluginOptions, AuthRoutesConfig, authComponentsDir, authPlugin } from './plugin.js'; export { DefaultAuthRouteOptions, clearDefaultAuthEngine, getDefaultAuthEngine, getDefaultAuthRouteOptions, getDefaultAuthSchemas, hasDefaultAuthEngine, setDefaultAuthEngine, setDefaultAuthRouteOptions, setDefaultAuthSchemas, tryGetDefaultAuthEngine } from './runtime.js'; export { createAuthSecretProtector } from './protector.js'; export { decodeBase32, encodeBase32, generateTotp, generateTotpSecret, totpUri, verifyTotp } from './totp/index.js'; +import { Context } from '@wrnexus/core'; import '@wrnexus/oauth'; -import '@wrnexus/core'; import '@wrnexus/db'; import '@wrnexus/validation'; import '@wrnexus/plugin'; @@ -976,7 +915,23 @@ interface RiskPolicy { } declare function evaluateAuthRisk(signals?: AuthRiskSignals, policy?: RiskPolicy): AuthRiskDecision; -export { AuthRiskDecision, AuthRiskSignals, type RiskPolicy, evaluateAuthRisk }; +type AuthRouteName = "signIn" | "signUp" | "signOut" | "forgotPassword" | "resetPassword" | "verifyEmail" | "verifyPhone" | "twoFactor" | "sessions" | "passkeys"; +declare function authRoute(name: AuthRouteName, options?: { + basePath?: string; + overrides?: Partial>; +}): string; +declare function authSuccess>(data: T, init?: ResponseInit): Response; +declare function authFailure(code: string, message: string, status?: number, details?: Record): Response; +declare function requireAuthUser(ctx: Context): AuthUser; +declare function optionalAuthUser(ctx: Context): AuthUser | null; +declare function currentAuthSession(engine: AuthEngine, sessionId: string | undefined): Promise; +declare function authComponentProps(input: Record, defaults?: { + color?: string; + size?: string; + class?: string; +}): Record; + +export { AuthEngine, AuthRiskDecision, AuthRiskSignals, type AuthRouteName, AuthSession, AuthUser, type RiskPolicy, authComponentProps, authFailure, authRoute, authSuccess, currentAuthSession, evaluateAuthRisk, optionalAuthUser, requireAuthUser }; ``` --- @@ -1275,11 +1230,75 @@ Documentation URL: https://wrnexusjs.dev/packages/cache Bounded in-memory/tag caching and HTTP response caching for WRNexusJS. Supports request deduplication, tag invalidation, ETags, fresh/stale states, and optional detached stale revalidation. ```ts -import { TagCache, responseCache } from "@wrnexus/cache"; +import { connectCacheInvalidation, TagCache, responseCache } from "@wrnexus/cache"; const cache = new TagCache({ ttlMs: 60_000, staleWhileRevalidateMs: 300_000 }); export default responseCache({ cache, tags: ["products"] }); ``` +`TagCache` bounds entries with LRU-style eviction, deduplicates concurrent +loaders, and prevents an invalidated in-flight loader from repopulating stale +data. Use `lookup()` when fresh/stale state matters, or `getOrLoad()` for +stampede-safe loading. + +For multi-instance applications, connect the cache to any compatible pub/sub +bus (including `@wrnexus/pubsub`). Namespaces isolate applications sharing the +same broker. Local invalidation happens first and the returned promise confirms +cross-instance publication; failures remain visible to the caller. + +```ts +import { connectCacheInvalidation, TagCache } from "@wrnexus/cache"; +import { createPubSub } from "@wrnexus/pubsub"; +import { redisDriver } from "@wrnexus/pubsub/redis"; + +const cache = new TagCache({ maxEntries: 10_000 }); +const bus = createPubSub(redisDriver(process.env.REDIS_URL)); +const invalidation = connectCacheInvalidation(cache, bus, { + namespace: "storefront-production", + onError: (error) => logger.error("cache invalidation failed", { error }), +}); + +await invalidation.invalidateTag("products"); +await invalidation.delete("product:42"); + +// Unsubscribes this cache only; the shared bus remains owned by the app. +invalidation.close(); +await bus.close(); +``` + +## Framework cache layers + +`CacheCoordinator` keeps the four cache lifetimes explicit: + +- `coordinator.request()` creates request-only deduplication. +- `coordinator.data` caches loader/query results. +- `coordinator.component` caches reusable rendered fragments. +- `coordinator.page` caches complete safe documents. + +All cross-request layers are bounded, tag-aware, stale-while-revalidate capable, +stampede-safe, and expose `withLock()` for exclusive per-key work. `inspect()` +returns metadata without cached values. Development applications expose that +inspection through the Cache panel and `GET /__wrnexus/cache`. + +Pages and components can opt in declaratively: + +```wrn +cache { + scope = "page" + strategy = "stale-while-revalidate" + ttl = "5m" + stale = "10m" + tags = ["catalog", "marketing"] + vary = ["tenant", "language"] +} +``` + +Omit `scope` to cache named loader data. Use `scope = "page"` for full-page +caching. Component policies cache their rendered fragment. Authenticated user +and tenant identities are always included automatically; page caches also vary +by language, theme, and accent. Add header names or `cookie:name` entries for +other application-specific variation. Pages containing CSRF forms are never +stored in the full-page cache. + ### Exported TypeScript declarations ```ts @@ -1308,25 +1327,86 @@ interface TagCacheOptions { staleWhileRevalidateMs?: number; maxEntries?: number; clock?: () => number; + onEvent?: (event: CacheEvent) => void; +} +interface CacheEvent { + operation: "hit" | "stale" | "miss" | "set" | "delete" | "invalidate" | "clear" | "load"; + key?: string; + tags?: string[]; + at: number; +} +interface CacheSnapshotEntry { + key: string; + state: "fresh" | "stale"; + createdAt: number; + expiresAt: number; + staleUntil: number; + tags: string[]; } declare class TagCache { private entries; private tagIndex; private pending; + private locks; + private revisions; private readonly ttlMs; private readonly staleMs; private readonly maxEntries; private readonly clock; + private readonly onEvent?; constructor(options?: TagCacheOptions); + private emit; lookup(key: string): CacheLookup; get(key: string): V | undefined; set(key: string, value: V, options?: CacheSetOptions): void; + private store; getOrLoad(key: string, loader: () => V | Promise, options?: CacheSetOptions): Promise; + /** Serialize arbitrary cache-adjacent work for a key without storing its result. */ + withLock(key: string, task: () => T | Promise): Promise; delete(key: string): boolean; + private removeEntry; invalidateTag(tag: string): number; invalidateTags(tags: Iterable): number; clear(): void; get size(): number; + snapshot(): CacheSnapshotEntry[]; + private revision; + private bump; +} + +type CacheLayerName = "data" | "component" | "page"; +interface CacheInspection { + layers: Record["snapshot"]>>; + recentEvents: Array; +} +interface CacheCoordinatorOptions extends Omit { + eventLimit?: number; + onEvent?: (event: CacheEvent & { + layer: CacheLayerName; + }) => void; +} +/** A request-lifetime cache: deduplicates work without leaking values between requests. */ +declare class RequestCache { + private pending; + getOrLoad(key: string, loader: () => V | Promise): Promise; + clear(): void; +} +/** Owns the three cross-request cache layers and creates isolated request caches. */ +declare class CacheCoordinator { + readonly data: TagCache; + readonly component: TagCache; + readonly page: TagCache; + private readonly events; + private readonly eventLimit; + constructor(options?: CacheCoordinatorOptions); + request(): RequestCache; + layer(name: CacheLayerName): TagCache; + getOrLoad(layer: CacheLayerName, key: string, loader: () => V | Promise, options?: CacheSetOptions): Promise; + invalidateTags(tags: Iterable): number; + inspect(): CacheInspection; + clear(): void; } interface CachedResponse { @@ -1351,7 +1431,29 @@ interface ResponseCacheOptions extends CacheSetOptions { } declare function responseCache(options?: ResponseCacheOptions): Middleware; -export { type CacheEntry, type CacheLookup, type CacheSetOptions, type CachedResponse, type ResponseCacheOptions, TagCache, type TagCacheOptions, responseCache }; +interface CacheInvalidationBus { + publish(topic: string, message: unknown): void | Promise; + subscribe(pattern: string, handler: (message: unknown) => void | Promise): () => void; +} +interface DistributedInvalidationOptions { + namespace?: string; + instanceId?: string; + onError?: (error: unknown) => void; +} +interface DistributedInvalidation { + invalidateTag(tag: string): Promise; + invalidateTags(tags: Iterable): Promise; + delete(key: string): Promise; + clear(): Promise; + close(): void; +} +/** + * Propagate cache invalidations over any structurally compatible pub/sub bus. + * The bus is intentionally not closed because applications commonly share it. + */ +declare function connectCacheInvalidation(cache: TagCache, bus: CacheInvalidationBus, options?: DistributedInvalidationOptions): DistributedInvalidation; + +export { CacheCoordinator, type CacheCoordinatorOptions, type CacheEntry, type CacheEvent, type CacheInspection, type CacheInvalidationBus, type CacheLayerName, type CacheLookup, type CacheSetOptions, type CacheSnapshotEntry, type CachedResponse, type DistributedInvalidation, type DistributedInvalidationOptions, RequestCache, type ResponseCacheOptions, TagCache, type TagCacheOptions, connectCacheInvalidation, responseCache }; ``` --- @@ -1723,10 +1825,22 @@ const engine = createCaptchaEngine({ secret, generators: [wordChallenge] }); Applications may also implement `CaptchaStore`, `CaptchaAudioRenderer`, or use `defineCaptchaProvider()` for a completely custom service. +## Helper and block kit + +The package exports `captchaTokenFrom`, `captchaHeaders`, `captchaFields`, `verifyCaptcha`, `verifyCaptchaOrThrow`, `captchaResultResponse`, and `captchaContext` for consistent server and client integration. + +Enable the CAPTCHA plugin to use the low-level `` challenge plus complete UI-composed blocks: + +- `` +- `` + +`CaptchaField` composes `Card` from `@wrnexus/ui` and keeps the CAPTCHA-specific size separate from the surrounding UI size. + ### Exported TypeScript declarations ```ts -export { CaptchaAudioRenderer, CaptchaBinding, CaptchaChallenge, CaptchaChallengeGenerator, CaptchaChallengeRecord, CaptchaChallengeType, CaptchaConcreteImageStyle, CaptchaDifficulty, CaptchaEngine, CaptchaEngineOptions, CaptchaFailureCode, CaptchaGeneratorContext, CaptchaGuardOptions, CaptchaHttpHandlers, CaptchaImageItem, CaptchaImageStyle, CaptchaMiddleware, CaptchaPageGateOptions, CaptchaPolicyMode, CaptchaPolicyOptions, CaptchaPresentation, CaptchaProvider, CaptchaProviderClientConfig, CaptchaProviderName, CaptchaResponseTokenRecord, CaptchaRiskResult, CaptchaRiskSignals, CaptchaStore, CaptchaVerificationResult, CreateCaptchaOptions, GeneratedCaptchaChallenge, VerifyCaptchaInput } from './types.js'; +import { CaptchaVerificationResult, CaptchaProvider, CaptchaEngine, VerifyCaptchaInput } from './types.js'; +export { CaptchaAudioRenderer, CaptchaBinding, CaptchaChallenge, CaptchaChallengeGenerator, CaptchaChallengeRecord, CaptchaChallengeType, CaptchaConcreteImageStyle, CaptchaDifficulty, CaptchaEngineOptions, CaptchaFailureCode, CaptchaGeneratorContext, CaptchaGuardOptions, CaptchaHttpHandlers, CaptchaImageItem, CaptchaImageStyle, CaptchaMiddleware, CaptchaPageGateOptions, CaptchaPolicyMode, CaptchaPolicyOptions, CaptchaPresentation, CaptchaProviderClientConfig, CaptchaProviderName, CaptchaResponseTokenRecord, CaptchaRiskResult, CaptchaRiskSignals, CaptchaStore, CreateCaptchaOptions, GeneratedCaptchaChallenge } from './types.js'; export { CaptchaHttpOptions, CaptchaParseResult, CaptchaSessionGrant, DefaultCaptchaEngine, ParseWithCaptchaOptions, bindingHash, bytesToBase64Url, captchaGuard, captchaPageGate, clearCaptchaGrants, constantTimeEqual, createCaptchaEngine, createCaptchaHttpHandlers, defaultRandomBytes, evaluateCaptchaRisk, hmacSha256, parseWithCaptcha, randomId, sha256, shouldRequireCaptcha, validCaptchaGrant } from './server/index.js'; export { CaptchaAuditIssue, CaptchaPluginOptions, captchaComponentsDir, captchaPlugin } from './plugin.js'; export { MemoryCaptchaStore, MemoryCaptchaStoreOptions, createMemoryCaptchaStore } from './stores/memory.js'; @@ -1741,9 +1855,19 @@ export { ManagedCaptchaProvider, ManagedCaptchaProviderOptions, managedCaptchaPr export { defineCaptchaProvider } from './providers/custom.js'; export { CAPTCHA_CONCRETE_IMAGE_STYLES, CAPTCHA_IMAGE_STYLES, CalculationCaptchaGenerator, ImageCaptchaGenerator, InvisibleCaptchaGenerator, ResolveCaptchaImageStyleOptions, ResolvedCaptchaImageStyle, Rgba, RgbaImage, TextCaptchaGenerator, alphaCaptchaGenerator, alphanumericCaptchaGenerator, bytesToBase64, calculationCaptchaGenerator, createImage, defaultCaptchaGenerators, defineCaptchaGenerator, drawGlyph, drawLine, drawText, encodePng, fillCircle, fillPolygon, fillRect, honeypotCaptchaGenerator, imageCaptchaGenerator, isCaptchaImageStyle, normalizeCaptchaImageStyle, normalizeCaptchaImageStyleList, notRobotCaptchaGenerator, numberCaptchaGenerator, pngDataUri, resolveCaptchaImageStyle, setPixel, timingCaptchaGenerator } from './challenges/index.js'; export { AssetAudioRenderer, AssetAudioRendererOptions, createAssetAudioRenderer, resolveCaptchaAudioAssetsDir } from './audio/index.js'; -import '@wrnexus/core'; +import { Context } from '@wrnexus/core'; import '@wrnexus/validation'; import '@wrnexus/plugin'; + +declare function captchaTokenFrom(value: Request | Headers | FormData | URLSearchParams | Record, field?: string): Promise | string | undefined; +declare function captchaHeaders(token: string): HeadersInit; +declare function captchaFields(token: string, field?: string): Record; +declare function verifyCaptcha(providerOrEngine: CaptchaProvider | CaptchaEngine, input: VerifyCaptchaInput): Promise; +declare function verifyCaptchaOrThrow(providerOrEngine: CaptchaProvider | CaptchaEngine, input: VerifyCaptchaInput): Promise; +declare function captchaResultResponse(result: CaptchaVerificationResult): Response; +declare function captchaContext(ctx: Context): CaptchaVerificationResult | null; + +export { CaptchaEngine, CaptchaProvider, CaptchaVerificationResult, VerifyCaptchaInput, captchaContext, captchaFields, captchaHeaders, captchaResultResponse, captchaTokenFrom, verifyCaptcha, verifyCaptchaOrThrow }; ``` --- @@ -1754,6 +1878,19 @@ Documentation URL: https://wrnexusjs.dev/packages/cli # @wrnexus/cli +Production parity commands: + +```bash +wrnexus build . +wrnexus preview . --port=3000 +wrnexus dev . --production-runtime +``` + +`preview` refuses to start without `dist/server.js` and executes that exact +artifact with the production profile. Production-runtime development rebuilds +the same minified artifact after app, public, or configuration changes and +keeps the last good server running when a rebuild fails. + > The `wrnexus` command-line tool that scaffolds, runs, builds, tests, and manages WrNexus apps. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. @@ -1780,6 +1917,30 @@ bunx wrnexus dev ## Commands +### Local production services + +`wrnexus dev . --services` starts the application and the bounded local database, +cache, mail, SMS, webhook, storage, queue, cron, authentication and metrics simulator. +It generates a localhost/`*.localhost` development certificate under +`.wrnexus/certificates/` and serves both the application and service console over HTTPS. +Trust that certificate locally to remove the browser warning. Use `--services-http` only +when an external development proxy already terminates TLS. + +### Exact production runtime with live updates + +`wrnexus dev . --production-runtime` rebuilds and executes `dist/server.js` with +production resolution, serialization, caching, headers and assets. The supervisor keeps +the last good process when a build fails. On a successful rebuild the opt-in production +HMR socket reconnects, requests the new document and morphs it into the browser; ordinary +`wrnexus preview` and deployed production servers never include that client. + +### API platform + +`wrnexus api generate [app-dir]` (or `api docs`) derives operations from file routes and +emits `generated/api/openapi.json`, safe static documentation, Postman collection, curl examples, +and TypeScript, JavaScript, Java, Go and Python SDKs. Generate one client with +`wrnexus sdk generate [app-dir]`. + Every command accepts an optional `[app-dir]` (defaults to `.`). Commands that read config or `.env` also accept `--profile=` (see [Profiles](#profiles)). | Command | Purpose | @@ -1800,10 +1961,17 @@ Every command accepts an optional `[app-dir]` (defaults to `.`). Commands that r | `wrnexus db ` | Database migrations and tooling (see [db](#wrnexus-db)). | | `wrnexus test [app-dir] [--watch]` | Run the app's tests via `bun test` (defaults to the `test` profile). | | `wrnexus profiles [app-dir]` | List config profiles and their `.env` files, marking the active one. | +| `wrnexus compatibility check` | Check whether behavior defaults are explicitly pinned and current. | +| `wrnexus compatibility explain` | Explain configured, effective, and current compatibility behavior. | +| `wrnexus compatibility upgrade` | Back up config and explicitly opt into reviewed current behavior. | | `wrnexus help` | Print usage. | `wrnexus g` is an alias for `wrnexus generate`. +Compatibility upgrades never happen implicitly. New applications pin +`compatibilityDate` and `frameworkBehaviour`; existing applications use +`wrnexus compatibility explain` before the backed-up, idempotent upgrade command. + ### `wrnexus dev` Supervises a child dev-server process (from `@wrnexus/dev-server`). The child owns file watching and HMR: CSS and client-island edits update the live page over a WebSocket with no restart; when a server module changes, the child exits with a restart code and the supervisor respawns it (the browser reconnects and morphs in the new HTML). On startup it regenerates typed DB queries and typed routes (best effort). Use `--port=` to change the port (default `3000`). @@ -1830,7 +1998,9 @@ bun dist/server.js # PORT env var optional ### `wrnexus create` -Scaffolds a new app from an inline (dependency-free) template — `package.json`, `.gitignore`, config, and starter `app/` files. Use `npm run dev` during development, `npm run build && npm start` for production, or `npm run production` to build and start in one command. The generated production server currently requires Bun even when npm is used to manage packages and scripts. +Scaffolds a complete v0.8 app from an inline template. The generated project includes strict TypeScript, ESLint and Prettier, editor recommendations, environment templates, database migrations, locales, schemas, tests, API/middleware/realtime examples, Tailwind and Iconify, PWA/mobile defaults, and the framework package kits. Its `wrnexus.config.ts` documents the current imports, types, stores, performance, observability, tenancy, build, navigation, theme, i18n, database, storage, realtime, security, and profile configuration. + +Use `bun run dev` during development, `bun run check` for the complete typecheck/lint/test/format gate, `bun run build && bun run start` for production, or `bun run production` to build and start in one command. ### `wrnexus update` @@ -1916,7 +2086,7 @@ wrnexus db status --db=analytics ### `wrnexus workspace` and `wrnexus gateway` -`workspace ` scaffolds a monorepo: several WrNexus apps under `apps/*` and shared libraries under `packages/*`, plus a `wrnexus.workspace.ts` that maps each app to the domains it serves. `gateway` runs every app behind one port and routes by `Host` header, with optional per-app auth and gateway-wide security (trusted hosts, rate limit, security headers, access log). +`workspace ` scaffolds a monorepo: complete v0.8 apps under `apps/*`, shared libraries under `packages/*`, root TypeScript/lint/format/editor/environment tooling, and a `wrnexus.workspace.ts` that maps each app to the domains it serves. `gateway` runs every app behind one port and routes by `Host` header, with optional per-app auth and gateway-wide security (trusted hosts, rate limit, security headers, access log). Newly added workspace apps use the same current scaffold. ```bash wrnexus workspace acme @@ -1995,6 +2165,12 @@ wrnexus update --latest wrnexus doctor ``` +Use `wrnexus doctor --fix [app-dir]` to apply conservative repairs before the +health check: create missing `app/pages` and a default config, align skewed +`@wrnexus/*` dependency ranges, record the current migration marker, and format +only syntax-valid `.wrn` files. Invalid JSON or WRN sources are reported/skipped +instead of overwritten; repeat runs are idempotent. + ## Profiles Pass `--profile=` to `dev`, `build`, `db` (or set `WRNEXUS_PROFILE`) to select a config profile. The CLI publishes `WRNEXUS_PROFILE` so config loaders and the dev child pick it up, and loads that profile's `.env` cascade (`.env`, `.env.local`, `.env.`, `.env..local`) into `process.env`. @@ -2041,10 +2217,45 @@ Documentation URL: https://wrnexusjs.dev/packages/compiler # @wrnexus/compiler +## Partial-static rendering + +Pages can select `render = "partial-static"` and divide their view with `` and +`` boundaries. The compiler emits a build-only shell renderer that never evaluates +dynamic-boundary children. `wrnexus build` expands static component mounts into +`dist/partial-shells.json`, records byte/region evidence in `build-report.json`, and embeds +the shell in the production route manifest. At request time the production runtime retains +request-aware layouts, locale/theme metadata and security nonces while streaming dynamic +regions into stable placeholders. + > Compiler for the `.wrn` language — tokenizes, parses, and lowers `.wrn` page and component files to TypeScript. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. +Production adapters use `analyzeRuntimeImports` before bundling. Edge, worker, +service-worker, and browser targets reject Node filesystem, TCP, and process +modules with `WRN-RUNTIME-CAPABILITY`. Package manifests can declare supported +`wrnexus.runtimes` and required `wrnexus.requires` capabilities; discovery fails +when the selected deployment cannot satisfy them. + +## Server actions + +```wrn +action createUser using CreateUserSchema { + const user = await users.create(input) + invalidate("users") + return user +} + +view { +

    ...
    +} +``` + +The compiler produces a schema-aware server registry, a fully inferred action +client, and progressively enhanced form metadata. The shared runtime performs +validation, authentication/permission checks, CSRF verification, serialization, +invalidation reporting, and browser lifecycle events. + ## Overview `@wrnexus/compiler` turns `.wrn` source into TypeScript that targets the framework's runtime primitives. A `.wrn` file declares either a `page` (a route) or a `component` (a reusable, prop-driven fragment) with blocks for `state`, `view` (plain HTML), `seo`, `style`, `functions`, `api`, `ssr`/`client` data bindings, and `realtime` websocket handlers. The pipeline is `source → Lexer → parse() → PageAst → generate() → TypeScript`. It is a build/server-side library — the WrNexus dev loader calls it to compile `.wrn` files on the fly, surfacing `ParseError` as a readable error page. @@ -2225,7 +2436,7 @@ A file opens with `page ` or `component ` followed by a `{ ... }` bo ```ts import { PageAst as PageAst$1, StructuredImportDecl, WrnDiagnostic } from '@wrnexus/syntax'; -export { ActionBlock, ApiBlock, Attr, ComputedDecl, DataApiBlock, DataMode, EffectBlock, EventDecl, LexError, Lexer, LoadBlock, ModeFunctionsBlock, OutputDecl, PageAst, ParseError, PropDecl, RealtimeBlock, RuntimeFunctionDecl, SeoBlock, StateDecl, StateRuntime, StoreKind, StructuredImportDecl, ViewNode, WrnDiagnostic, assertValidAst, diagnose, diagnosticFromError, eraseFunctionTypes, formatDiagnostic, inferredRuntimeType, parse, runtimeTypeOf } from '@wrnexus/syntax'; +export { ActionBlock, ApiBlock, Attr, ComputedDecl, DataApiBlock, DataMode, EffectBlock, EventDecl, FormatWrnOptions, LexError, Lexer, LoadBlock, ModeFunctionsBlock, OutputDecl, PageAst, ParseError, PropDecl, RealtimeBlock, RuntimeFunctionDecl, SeoBlock, StateDecl, StateRuntime, StoreKind, StructuredImportDecl, ViewNode, WrnDiagnostic, assertValidAst, diagnose, diagnosticFromError, eraseFunctionTypes, formatDiagnostic, formatWrn, inferredRuntimeType, parse, runtimeTypeOf } from '@wrnexus/syntax'; import { PageAst } from '@wrnexus/syntax/parser'; /** @@ -2364,9 +2575,43 @@ interface RuntimeRequirements { needsServerRuntime: boolean; hydrationStrategy: string | null; reasons: string[]; + optimization: OptimizationReport; + cachePolicy: Record; + requiredPermission: string | null; } +interface OptimizationReport { + staticNodes: number; + reactiveRegions: number; + eliminatedBranches: number; + unusedState: string[]; + unusedHandlers: string[]; + constantProps: string[]; + unusedLocalCssClasses: string[]; + batchableStateUpdates: number; + memoizableComponents: string[]; + preloadDependencies: string[]; + serverOnlyModules: string[]; +} +/** Safe compile-time folding for literal conditional branches. */ +declare function optimizeAst(ast: PageAst$1): { + ast: PageAst$1; + eliminatedBranches: number; +}; +declare function analyzeOptimizations(ast: PageAst$1): OptimizationReport; declare function analyzeRuntimeRequirements(ast: PageAst$1): RuntimeRequirements; +type DeploymentRuntime = "bun" | "node" | "edge" | "worker" | "service-worker" | "browser"; +type RuntimeCapability = "filesystem" | "tcp" | "process" | "websocket" | "crypto" | "streams" | "background-tasks"; +interface RuntimeCapabilityDiagnostic { + code: "WRN-RUNTIME-CAPABILITY"; + runtime: DeploymentRuntime; + module: string; + capability: RuntimeCapability; + message: string; +} +declare function runtimeCapabilities(runtime: DeploymentRuntime): ReadonlySet; +declare function analyzeRuntimeImports(source: string, runtime: DeploymentRuntime): RuntimeCapabilityDiagnostic[]; + declare class NativeCompileError extends Error { constructor(message: string); } @@ -2431,7 +2676,174 @@ declare function compileWireFile(source: string, filePath?: string): string; /** Richer entry point returning the AST and structured diagnostics. */ declare function compile(source: string, filePath?: string): CompileResult; -export { type CompilationCache, type CompilationCacheEntry, type CompilationCacheOptions, type CompileResult, DependencyGraph, NativeCompileError, type RouteExecutionKind, type RuntimeRequirements, analyzeRuntimeRequirements, compilationKey, compile, compileNativeWireFile, compileWireFile, createCompilationCache, createComponentContract, createWrnSourceMap, generate, generateBrowserModule, generateDeclarations, generateNative, generateServerFunctionsModule, generateStoreBrowserModule, generateStoreModule, generateTargets, resolveWrnImport, resolveWrnImports, rpcManifest }; +export { type CompilationCache, type CompilationCacheEntry, type CompilationCacheOptions, type CompileResult, DependencyGraph, type DeploymentRuntime, NativeCompileError, type OptimizationReport, type RouteExecutionKind, type RuntimeCapability, type RuntimeCapabilityDiagnostic, type RuntimeRequirements, analyzeOptimizations, analyzeRuntimeImports, analyzeRuntimeRequirements, compilationKey, compile, compileNativeWireFile, compileWireFile, createCompilationCache, createComponentContract, createWrnSourceMap, generate, generateBrowserModule, generateDeclarations, generateNative, generateServerFunctionsModule, generateStoreBrowserModule, generateStoreModule, generateTargets, optimizeAst, resolveWrnImport, resolveWrnImports, rpcManifest, runtimeCapabilities }; +``` + +--- + +## @wrnexus/content + +Documentation URL: https://wrnexusjs.dev/packages/content + +# @wrnexus/content + +Typed content collections for Markdown/MDX-like documents and remote CMS records. Collections +validate frontmatter through any `{ parse(input) }` schema, render escaped HTML, and expose draft +preview, versions, references, headings, search indexes, pagination, RSS and sitemaps. + +```ts +const posts = defineCollection({ + name: "posts", + schema: PostSchema, + loader: localContentLoader("content/posts"), + previewToken: process.env.CONTENT_PREVIEW_TOKEN, +}); + +const published = await posts.load(); +const preview = await posts.load({ previewToken: request.headers.get("x-preview-token") ?? "" }); +``` + +Remote systems implement `CmsAdapter`, use `cmsContentLoader`, or return JSON records through +`remoteContentLoader`. Markdown HTML is escaped by default; raw executable HTML is never trusted. + +### Exported TypeScript declarations + +```ts +type MdxComponent = (props: Record, children: string) => string; +/** Execute explicitly registered MDX components without evaluating arbitrary JavaScript. */ +declare function renderMdxComponents(source: string, components: Record): string; +interface SyntaxLanguageBundle { + highlight(source: string): string; +} +declare function createIncrementalHighlighter(loaders: Record SyntaxLanguageBundle | Promise>): { + languages: () => string[]; + highlight(language: string, source: string): Promise; + render(html: string): Promise; +}; +interface VendorAdapterOptions { + fetch?: (input: string | URL | Request, init?: RequestInit) => Promise; + token?: string; + map?: (entry: any) => { + id: string; + content: string; + source?: string; + }; +} +declare function contentfulAdapter(space: string, environment?: string, options?: VendorAdapterOptions): { + list(collection: string): Promise; +}; +declare function sanityAdapter(project: string, dataset: string, options?: VendorAdapterOptions & { + apiVersion?: string; +}): { + list(collection: string): Promise; +}; +declare function strapiAdapter(baseUrl: string, options?: VendorAdapterOptions): { + list(collection: string): Promise; +}; + +interface ContentSchema { + parse(input: unknown): T; +} +interface ContentEntry> { + id: string; + slug: string; + collection: string; + data: T; + body: string; + html: string; + excerpt: string; + headings: ContentHeading[]; + draft: boolean; + version?: string; + source: string; +} +interface ContentHeading { + depth: number; + text: string; + slug: string; +} +interface ContentLoaderResult { + id: string; + source: string; + content: string; +} +interface ContentLoader { + load(): ContentLoaderResult[] | Promise; +} +interface ContentCollectionOptions { + name: string; + schema: ContentSchema; + loader: ContentLoader; + includeDrafts?: boolean; + previewToken?: string; + references?: Record>; +} +interface ContentCollection { + name: string; + load(options?: { + drafts?: boolean; + previewToken?: string; + version?: string; + }): Promise[]>; + get(id: string, options?: { + drafts?: boolean; + previewToken?: string; + version?: string; + }): Promise | null>; +} +declare function parseFrontmatter(source: string): { + data: Record; + body: string; +}; +declare function renderMarkdown(source: string): { + html: string; + headings: ContentHeading[]; + excerpt: string; +}; +declare function localContentLoader(directory: string): ContentLoader; +declare function remoteContentLoader(url: string, options?: { + fetch?: (input: string | URL | Request, init?: RequestInit) => Promise; + headers?: HeadersInit; +}): ContentLoader; +declare function defineCollection(options: ContentCollectionOptions): ContentCollection; +declare function resolveContentReference(collections: Record>, reference: string): Promise | null>; +declare function paginateContent(entries: T[], page?: number, pageSize?: number): { + items: T[]; + page: number; + pageSize: number; + total: number; + totalPages: number; + hasNext: boolean; + hasPrevious: boolean; +}; +declare function createSearchIndex(entries: ContentEntry[]): { + id: string; + slug: string; + title: string; + text: string; +}[]; +declare function searchContent(index: ReturnType, query: string): { + id: string; + slug: string; + title: string; + text: string; +}[]; +declare function contentSitemap(entries: ContentEntry[], baseUrl: string): string; +declare function contentRss(entries: ContentEntry[], options: { + title: string; + baseUrl: string; + description?: string; +}): string; +interface CmsAdapter { + list(collection: string): Promise>; +} +declare function cmsContentLoader(adapter: CmsAdapter, collection: string): ContentLoader; + +export { type CmsAdapter, type ContentCollection, type ContentCollectionOptions, type ContentEntry, type ContentHeading, type ContentLoader, type ContentLoaderResult, type ContentSchema, type MdxComponent, type SyntaxLanguageBundle, type VendorAdapterOptions, cmsContentLoader, contentRss, contentSitemap, contentfulAdapter, createIncrementalHighlighter, createSearchIndex, defineCollection, localContentLoader, paginateContent, parseFrontmatter, remoteContentLoader, renderMarkdown, renderMdxComponents, resolveContentReference, sanityAdapter, searchContent, strapiAdapter }; ``` --- @@ -2552,6 +2964,37 @@ instances. The default store is process-local memory. (default `console.log`), `requestIdKey` (default `"requestId"`), `now`. `RequestRecord` = `{ time, id, method, path, status, durationMs }`. +### Resilience — `@wrnexus/core` + +`resilientCall` standardizes cancellation-aware timeouts, controlled retries, +fixed or exponential backoff, fallback responses, circuit breaking, and bounded +concurrency. Reuse a declarative circuit/bulkhead options object, or an explicit +`CircuitBreaker`/`Bulkhead` instance, wherever calls must share health and +capacity state. + +```ts +import { resilientCall } from "@wrnexus/core"; + +const paymentCircuit = { failures: 5, resetAfter: "30s" } as const; + +const status = await resilientCall({ + timeout: "5s", + retries: 3, + retryDelay: "100ms", + backoff: "exponential", + circuitBreaker: paymentCircuit, + bulkhead: { concurrency: 20, queue: 100 }, + run: (signal) => paymentProvider.checkStatus({ signal }), + fallback: () => ({ state: "unavailable" }), +}); +``` + +`CircuitBreaker.snapshot()` reports `closed`, `open`, or `half-open`, failure +and success counts, and the remaining retry delay for health endpoints and +development tooling. Fail-fast conditions use stable `WRN-RESILIENCE-*` codes. +Core's existing `HealthRegistry`, `withIdempotency`, and pluggable stores/locks +cover health reporting, idempotent requests, and distributed coordination. + ### Caching — `@wrnexus/core` | Export | Kind | Notes | @@ -2833,6 +3276,36 @@ interface Tenant { name?: string; metadata?: Record; } +interface TenantResource { + tenantId: string; +} +interface TenantMembership { + tenantId: string; + userId: string; + roles?: string[]; + workspaceIds?: string[]; +} +interface TenantAuditEvent { + tenantId: string; + action: string; + actorId?: string; + resource?: string; + metadata?: Record; + createdAt: number; +} +interface TenantQuota { + tenantId: string; + resource: string; + limit: number; + usage: number; +} +interface TenantDirectoryStore { + putMembership(value: TenantMembership): Promise; + getMembership(tenantId: string, userId: string): Promise; + listMemberships(tenantId: string): Promise; + putQuota(value: TenantQuota): Promise; + getQuota(tenantId: string, resource: string): Promise; +} type TenantResolver = (ctx: Context) => Tenant | null | Promise; interface TenantMiddlewareOptions { required?: boolean; @@ -2840,11 +3313,68 @@ interface TenantMiddlewareOptions { } declare function tenantMiddleware(resolveTenant: TenantResolver, options?: TenantMiddlewareOptions): Middleware; declare function tenantFromSubdomain(lookup: (slug: string, ctx: Context) => Tenant | null | Promise, rootDomains?: string[]): TenantResolver; +declare function tenantFromDomain(lookup: (domain: string, ctx: Context) => Tenant | null | Promise): TenantResolver; +declare function tenantFromPath(lookup: (slug: string, ctx: Context) => Tenant | null | Promise, prefix?: string): TenantResolver; +/** Header resolution is intentionally opt-in and must only be used behind a trusted proxy. */ +declare function tenantFromHeader(lookup: (id: string, ctx: Context) => Tenant | null | Promise, header?: string): TenantResolver; +declare function tenantFromSession(resolveId: (ctx: Context) => string | null | Promise, lookup: (id: string, ctx: Context) => Tenant | null | Promise): TenantResolver; +declare function composeTenantResolvers(...resolvers: TenantResolver[]): TenantResolver; declare function requireTenant(ctx: Context): Tenant; /** Wrap a repository so every operation receives the current tenant id. */ declare function tenantScope(tenant: Tenant, repository: T): T & { tenantId: string; }; +declare function assertTenantAccess(tenant: Tenant, resource: TenantResource): void; +declare function tenantKey(tenant: Tenant | string, ...parts: Array): string; +declare function createTenantDirectory(options?: { + audit?: (event: TenantAuditEvent) => void | Promise; + now?: () => number; +}): { + addMembership(membership: TenantMembership, actorId?: string): Promise; + membership(tenantId: string, userId: string): TenantMembership | null; + switchWorkspace(tenantId: string, userId: string, workspaceId: string): Promise<{ + tenantId: string; + workspaceId: string; + }>; + setQuota(tenantId: string, resource: string, limit: number): void; + enforceQuota(tenantId: string, resource: string, usage: number, requested?: number): { + usage: number; + requested: number; + limit: number | undefined; + }; +}; +declare function memoryTenantDirectoryStore(): TenantDirectoryStore; +declare function createPersistentTenantDirectory(store: TenantDirectoryStore, options?: { + audit?: (event: TenantAuditEvent) => void | Promise; + now?: () => number; +}): { + addMembership(membership: TenantMembership, actorId?: string): Promise; + membership: (tenantId: string, userId: string) => Promise; + memberships: (tenantId: string) => Promise; + switchWorkspace(tenantId: string, userId: string, workspaceId: string): Promise<{ + tenantId: string; + workspaceId: string; + }>; + setQuota(tenantId: string, resource: string, limit: number, usage?: number): Promise; + consumeQuota(tenantId: string, resource: string, requested: number): Promise; +}; +interface TenantSqlClient { + query>(sql: string, parameters?: unknown[]): Promise<{ + rows: T[]; + }>; +} +declare function postgresTenantDirectoryStore(db: TenantSqlClient): TenantDirectoryStore; +declare const POSTGRES_TENANT_DIRECTORY_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_tenant_memberships (tenant_id text NOT NULL,user_id text NOT NULL,roles jsonb NOT NULL DEFAULT '[]',workspace_ids jsonb NOT NULL DEFAULT '[]',PRIMARY KEY (tenant_id,user_id)); CREATE TABLE IF NOT EXISTS wrnexus_tenant_quotas (tenant_id text NOT NULL,resource text NOT NULL,quota_limit bigint NOT NULL,usage bigint NOT NULL DEFAULT 0,PRIMARY KEY (tenant_id,resource));"; +declare function migrateTenants(tenants: T[], migrate: (tenant: T) => void | Promise, options?: { + concurrency?: number; + continueOnError?: boolean; +}): Promise<{ + migrated: string[]; + failed: { + tenantId: string; + error: string; + }[]; +}>; interface SpanRecord { name: string; @@ -3048,6 +3578,47 @@ declare function createContext(req: Request, url: URL): Context; /** Apply headers accumulated on the context, such as Set-Cookie. */ declare function withContextHeaders(ctx: Context, res: Response): Response; +type ExecutionKind = "http" | "api" | "action" | "loader" | "middleware" | "realtime" | "queue" | "cron" | "webhook"; +interface ResponseContext { + status: number; + headers: Headers; + setStatus(status: number): void; +} +interface ExecutionContext { + kind: ExecutionKind; + id: string; + request: Request; + response: ResponseContext; + user: unknown | null; + session: unknown | null; + tenant: Tenant | null; + locale: string; + timezone: string; + db?: unknown; + cache?: unknown; + logger?: unknown; + trace?: Tracer; + signal: AbortSignal; + deadline: Date | null; + metadata: Record; + authorize(permission: string): void | Promise; +} +interface ExecutionContextInput extends Partial> { + kind: ExecutionKind; + id?: string; + request?: Request; + response?: Partial> & { + headers?: HeadersInit; + }; + signal?: AbortSignal; + deadline?: Date | number | null; + timeoutMs?: number; + metadata?: Record; + authorize?: (permission: string) => void | Promise; +} +declare function createExecutionContext(input: ExecutionContextInput): ExecutionContext; +declare function executionContextFromHttp(context: Context, kind?: Extract, input?: Omit): ExecutionContext; + /** * Small, dependency-free security helpers shared across packages. */ @@ -3477,7 +4048,7 @@ interface RealtimeSecurityOptions { /** Called when a connection is rejected or closed for a policy violation. */ onViolation?(reason: string, client?: RoomClient): void; } -interface RoomHandlers> { +interface RoomHandlers, TMessage = any> { /** Per-room abuse and payload controls. */ security?: RealtimeSecurityOptions; /** @@ -3488,16 +4059,16 @@ interface RoomHandlers> { /** A client connected (a new tab joined the room). */ onConnect?(client: RoomClient): void | Promise; /** A message arrived (JSON is parsed; non-JSON arrives as a string). */ - onMessage?(client: RoomClient, message: any): void | Promise; + onMessage?(client: RoomClient, message: TMessage): void | Promise; /** A client disconnected. */ onLeave?(client: RoomClient): void | Promise; } -interface RoomDefinition> { +interface RoomDefinition, TMessage = any> { readonly __wrnexusRoom: true; - readonly handlers: RoomHandlers; + readonly handlers: RoomHandlers; } /** Define a realtime room. Export the result as the `default` of a realtime file. */ -declare function defineRoom>(handlers: RoomHandlers): RoomDefinition; +declare function defineRoom, TMessage = any>(handlers: RoomHandlers): RoomDefinition; declare function isRoomDefinition(value: unknown): value is RoomDefinition; interface RealtimeConnectMeta { room: string; @@ -3701,6 +4272,11 @@ declare function withSecurityHeaders(req: Request, res: Response, mode: Mode, se interface SchemaLike { parse(input: unknown): T; } +interface OutputSchemaLike { + readonly __output: T; + parse(input: unknown): unknown; +} +type InferEndpointSchema = TSchema extends OutputSchemaLike ? TValue : never; interface EndpointErrorBody { code: string; message: string; @@ -3713,8 +4289,8 @@ declare class EndpointError extends Error { constructor(status: number, code: string, message: string, details?: unknown | undefined); } interface EndpointDefinition { - input?: SchemaLike; - output?: SchemaLike; + input?: SchemaLike | OutputSchemaLike; + output?: SchemaLike | OutputSchemaLike; auth?: "optional" | "required"; description?: string; tags?: string[]; @@ -3725,6 +4301,10 @@ interface DefinedEndpoint { (ctx: Context, input?: unknown): Promise; } /** Define a validated, typed endpoint that can also drive SDK/OpenAPI generation. */ +declare function defineEndpoint, OutputSchema extends OutputSchemaLike>(definition: Omit, InferEndpointSchema>, "input" | "output"> & { + input: InputSchema; + output: OutputSchema; +}): DefinedEndpoint, InferEndpointSchema>; declare function defineEndpoint(definition: EndpointDefinition): DefinedEndpoint; interface RpcClientOptions { baseUrl?: string; @@ -3815,6 +4395,65 @@ interface BudgetViolation { declare const recommendedWebBudgets: Readonly; declare function checkPerformanceBudgets(budgets: PerformanceBudgets, measurement: PerformanceMeasurement): BudgetViolation[]; +type Duration = number | `${number}${"ms" | "s" | "m" | "h"}`; +type BackoffStrategy = "fixed" | "exponential" | ((attempt: number) => Duration); +interface CircuitBreakerOptions { + failures: number; + resetAfter: Duration; + successesToClose?: number; +} +interface CircuitBreakerSnapshot { + state: "closed" | "open" | "half-open"; + failures: number; + successes: number; + retryAfterMs: number; +} +declare class ResilienceError extends Error { + readonly code: "WRN-RESILIENCE-TIMEOUT" | "WRN-RESILIENCE-ABORTED" | "WRN-RESILIENCE-CIRCUIT-OPEN" | "WRN-RESILIENCE-BULKHEAD-FULL"; + constructor(code: "WRN-RESILIENCE-TIMEOUT" | "WRN-RESILIENCE-ABORTED" | "WRN-RESILIENCE-CIRCUIT-OPEN" | "WRN-RESILIENCE-BULKHEAD-FULL", message: string, options?: ErrorOptions); +} +declare function durationMs(value: Duration): number; +declare class CircuitBreaker { + private readonly options; + private failures; + private successes; + private openedAt; + private probing; + constructor(options: CircuitBreakerOptions); + snapshot(now?: number): CircuitBreakerSnapshot; + execute(operation: () => Promise): Promise; +} +interface BulkheadOptions { + concurrency: number; + queue?: number; +} +declare class Bulkhead { + private readonly options; + private active; + private readonly waiting; + constructor(options: BulkheadOptions); + get snapshot(): Readonly<{ + active: number; + queued: number; + capacity: number; + }>; + execute(operation: () => Promise): Promise; +} +interface ResilientCallOptions { + run: (signal: AbortSignal, attempt: number) => Promise; + timeout?: Duration; + retries?: number; + retryDelay?: Duration; + backoff?: BackoffStrategy; + circuitBreaker?: CircuitBreaker | CircuitBreakerOptions; + bulkhead?: Bulkhead | BulkheadOptions; + signal?: AbortSignal; + retryWhen?: (error: unknown, attempt: number) => boolean | Promise; + fallback?: (error: unknown, signal: AbortSignal) => T | Promise; + onRetry?: (error: unknown, attempt: number, delayMs: number) => void; +} +declare function resilientCall(options: ResilientCallOptions): Promise; + interface ProblemDetails { type: string; title: string; @@ -3889,7 +4528,7 @@ declare function withIdempotency(store: IdempotencyStore, key: string, exe replayed: boolean; }>; -export { type ActionDefinition, ApplicationLifecycle, type AsyncSessionBackend, type Bucket, type BudgetViolation, CSRF_COOKIE, CSRF_HEADER, type CacheControlOptions, type CachePolicy, type ContentSecurityPolicyConfig, type Context, type CookieOptions, type CookieStore, type CorsConfig, type CorsOrigin, type CspDirectiveValue, type CsrfProtectionOptions, type DefinedAction, type DefinedEndpoint, type DefinedLoader, type EndpointDefinition, EndpointError, type EndpointErrorBody, type FeatureFlags, type FeatureRule, type FeatureValue, type HealthCheck, type HealthCheckResult, HealthRegistry, type HstsConfig, type IdempotencyRecord, type IdempotencyStore, type LifecycleHandler, type LifecyclePhase, type LoaderDefinition, type LocalStorageSnapshot, type Middleware, type Mode, type Next, type PageComponent, type PageMeta, type PerformanceBudgets, type PerformanceMeasurement, type PermissionsPolicyConfig, type ProblemDetails, type ProblemDetailsInput, type RateLimitOptions, type RateLimitStore, type RawSocket, type RealtimeBridge, type RealtimeBus, type RealtimeConnectMeta, type RealtimeEnvelope, type RealtimeHandler, type RealtimeRegistry, type RealtimeRegistryOptions, type RealtimeSecurityOptions, type RealtimeSocket, type RequestLimitsConfig, type RequestLoggerOptions, type RequestRecord, type RequireAuthOptions, type Room, type RoomAuthInfo, type RoomClient, type RoomDefinition, type RoomHandlers, type RpcClientOptions, SESSION_USER_KEY, type SaveUploadOptions, type SavedUpload, type SchemaLike, type SecureUploadOptions, type SecurityConfig, type SeoConfig, type ServerSentEvent, ServiceContainer, type ServiceToken, type SessionBackend, type SessionEntry, type SessionPolicy, type SessionStore, type Span, type SpanRecord, type StreamResponseInit, type TFunction, TTLCache, type Target, type Tenant, type TenantMiddlewareOptions, type TenantResolver, type Tracer, type TrustedTypesConfig, UploadError, type UploadInspectionResult, type UploadInspector, type UploadScanner, bridgeRealtime, cacheControl, checkPerformanceBudgets, collectUploads, createContext, createCorsPreflightResponse, createRealtimeRegistry, createRpcClient, createTracer, csrfProtection, csrfToken, dedupe, defaultKey, defineAction, defineEndpoint, defineFeatureFlags, defineLoader, defineRoom, escapeHtml, etag, getUser, hashPassword, isRoomDefinition, isSafeIslandName, isSafeRequestPath, isWebSocketOriginAllowed, loadSession, logIn, logOut, memoryIdempotencyStore, notModified, peerKey, problem, proxyKey, randomUploadFilename, rateLimit, recommendedWebBudgets, renderDevError, renderError, renderNotFound, renderProdError, renderStatusPage, requestId, requestLogger, requireAuth, requireTenant, resolveRequestUrl, sanitizeFilename, saveUpload, saveUploadSecure, secureDownloadHeaders, serviceToken, sessionAuth, setSessionBackend, setSessionPolicy, sse, streamResponse, tenantFromSubdomain, tenantMiddleware, tenantScope, tracingMiddleware, verifyCsrf, verifyPassword, withCacheControl, withContextHeaders, withIdempotency, withSecurityHeaders, withSpan }; +export { type ActionDefinition, ApplicationLifecycle, type AsyncSessionBackend, type BackoffStrategy, type Bucket, type BudgetViolation, Bulkhead, type BulkheadOptions, CSRF_COOKIE, CSRF_HEADER, type CacheControlOptions, type CachePolicy, CircuitBreaker, type CircuitBreakerOptions, type CircuitBreakerSnapshot, type ContentSecurityPolicyConfig, type Context, type CookieOptions, type CookieStore, type CorsConfig, type CorsOrigin, type CspDirectiveValue, type CsrfProtectionOptions, type DefinedAction, type DefinedEndpoint, type DefinedLoader, type Duration, type EndpointDefinition, EndpointError, type EndpointErrorBody, type ExecutionContext, type ExecutionContextInput, type ExecutionKind, type FeatureFlags, type FeatureRule, type FeatureValue, type HealthCheck, type HealthCheckResult, HealthRegistry, type HstsConfig, type IdempotencyRecord, type IdempotencyStore, type InferEndpointSchema, type LifecycleHandler, type LifecyclePhase, type LoaderDefinition, type LocalStorageSnapshot, type Middleware, type Mode, type Next, type OutputSchemaLike, POSTGRES_TENANT_DIRECTORY_SCHEMA, type PageComponent, type PageMeta, type PerformanceBudgets, type PerformanceMeasurement, type PermissionsPolicyConfig, type ProblemDetails, type ProblemDetailsInput, type RateLimitOptions, type RateLimitStore, type RawSocket, type RealtimeBridge, type RealtimeBus, type RealtimeConnectMeta, type RealtimeEnvelope, type RealtimeHandler, type RealtimeRegistry, type RealtimeRegistryOptions, type RealtimeSecurityOptions, type RealtimeSocket, type RequestLimitsConfig, type RequestLoggerOptions, type RequestRecord, type RequireAuthOptions, ResilienceError, type ResilientCallOptions, type ResponseContext, type Room, type RoomAuthInfo, type RoomClient, type RoomDefinition, type RoomHandlers, type RpcClientOptions, SESSION_USER_KEY, type SaveUploadOptions, type SavedUpload, type SchemaLike, type SecureUploadOptions, type SecurityConfig, type SeoConfig, type ServerSentEvent, ServiceContainer, type ServiceToken, type SessionBackend, type SessionEntry, type SessionPolicy, type SessionStore, type Span, type SpanRecord, type StreamResponseInit, type TFunction, TTLCache, type Target, type Tenant, type TenantAuditEvent, type TenantDirectoryStore, type TenantMembership, type TenantMiddlewareOptions, type TenantQuota, type TenantResolver, type TenantResource, type TenantSqlClient, type Tracer, type TrustedTypesConfig, UploadError, type UploadInspectionResult, type UploadInspector, type UploadScanner, assertTenantAccess, bridgeRealtime, cacheControl, checkPerformanceBudgets, collectUploads, composeTenantResolvers, createContext, createCorsPreflightResponse, createExecutionContext, createPersistentTenantDirectory, createRealtimeRegistry, createRpcClient, createTenantDirectory, createTracer, csrfProtection, csrfToken, dedupe, defaultKey, defineAction, defineEndpoint, defineFeatureFlags, defineLoader, defineRoom, durationMs, escapeHtml, etag, executionContextFromHttp, getUser, hashPassword, isRoomDefinition, isSafeIslandName, isSafeRequestPath, isWebSocketOriginAllowed, loadSession, logIn, logOut, memoryIdempotencyStore, memoryTenantDirectoryStore, migrateTenants, notModified, peerKey, postgresTenantDirectoryStore, problem, proxyKey, randomUploadFilename, rateLimit, recommendedWebBudgets, renderDevError, renderError, renderNotFound, renderProdError, renderStatusPage, requestId, requestLogger, requireAuth, requireTenant, resilientCall, resolveRequestUrl, sanitizeFilename, saveUpload, saveUploadSecure, secureDownloadHeaders, serviceToken, sessionAuth, setSessionBackend, setSessionPolicy, sse, streamResponse, tenantFromDomain, tenantFromHeader, tenantFromPath, tenantFromSession, tenantFromSubdomain, tenantKey, tenantMiddleware, tenantScope, tracingMiddleware, verifyCsrf, verifyPassword, withCacheControl, withContextHeaders, withIdempotency, withSecurityHeaders, withSpan }; ``` --- @@ -3900,6 +4539,35 @@ Documentation URL: https://wrnexusjs.dev/packages/csr # @wrnexus/csr +## Navigation state preservation + +Pages can opt into restoration across client navigation: + +```wrn +page Users { + navigation { + preserve = ["filters", "pagination", "scroll", "tabs", "expanded"] + } +} +``` + +Form-like categories restore named inputs, selects, and textareas. Password, +file, hidden, CSRF/token/secret/credential fields, and elements marked +`data-no-preserve` are never saved. For tab, expanded, or component UI state, +mark stable elements with `data-wrn-preserve="key"`; their value and ARIA +selected/expanded state are restored. State is scoped to pathname plus query. + +## Typed server actions + +`createActionClient(route, name)` supports programmatic calls. +Schema-backed WRN actions also export `__wrnexusActionClients`, whose input and +output are inferred automatically. Enhanced forms expose +`data-wrn-action-state="pending|success|error"` and dispatch bubbling +`wrnexus:action:optimistic`, `:pending`, `:success`, and `:error` events. +Success details contain returned data and invalidated cache tags; error details +contain field errors. Without JavaScript, the same form posts to its page and +receives a 303 redirect or accessible validation response. + > The browser-side client runtime for WrNexus — generic, self-contained JS that hydrates server-rendered pages with reactivity, client-side navigation, and realtime rooms. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. @@ -3949,16 +4617,21 @@ getRealtimeRuntime(): string // → REALTIME_RUNTIME Applied to any subtree containing `data-scope`. Expressions are parsed by a tiny eval-free evaluator, so a strict CSP with no `unsafe-eval` works. -| Directive | Purpose | -| -------------------------------------------------------- | ----------------------------------------------------------------------- | -| `data-scope="count: 0, name: 'x'"` | Declare reactive state on a subtree | -| `data-on-="count++"` | Run a statement in scope on a DOM event | -| `data-text="expr"` | Bind an element's `textContent` to an expression | -| `data-show="expr"` | Toggle visibility (`display`) on truthiness | -| `data-for="item in list"` (opt. index and `key item.id`) | Per-item rendering; stable keys preserve DOM identity during reorder | -| `data-key="item.id"` | Alternative key declaration for `data-for` templates | -| `{{expr}}` or `{expr}` | Interpolation inside text nodes and attribute values | -| `data-wrnexus-csr="id"` | Target for a generated CSR fetch binding (fetches `/__wrnexus/csr?...`) | +| Directive | Purpose | +| ---------------------------------- | ---------------------------------------------------- | +| `data-scope="count: 0, name: 'x'"` | Declare reactive state on a subtree | +| `data-on-="count++"` | Run a statement in scope on a DOM event | +| `data-text="expr"` | Bind an element's `textContent` to an expression | +| `data-show="expr"` | Toggle visibility while preserving interactive state | + +Compiled conditional rendering and dynamic component cases omit inactive elements from the live +DOM. `data-show` is a visibility directive for stateful controls and keeps its element mounted. +Neither mechanism is authorization: never place secrets in client-rendered branches. Authorize on +the server and return only data the current request may access. +| `data-for="item in list"` (opt. index and `key item.id`) | Per-item rendering; stable keys preserve DOM identity during reorder | +| `data-key="item.id"` | Alternative key declaration for `data-for` templates | +| `{{expr}}` or `{expr}` | Interpolation inside text nodes and attribute values | +| `data-wrnexus-csr="id"` | Target for a generated CSR fetch binding (fetches `/__wrnexus/csr?...`) | Supported expression features: literals, identifiers, member access (`a.b`, `a[b]`), function/method calls, arrays, objects, arithmetic, comparison, equality, logical (`&& ||`), unary (`! - +`), and ternary. Statements support `++`/`--`, assignment operators (`= += -= *= /= %=`), and bare expression/method calls. Rendering is dependency-tracked: a signal change only re-runs the renderers that actually read it. @@ -4151,6 +4824,8 @@ declare const NAV_RUNTIME: string; */ declare const REALTIME_RUNTIME: string; +declare const ACTION_RUNTIME: string; + type OutputHandler = (payload: T) => void | Promise; interface OutputHost extends HTMLElement { __wrnexusOutputHandlers?: Map>; @@ -4185,6 +4860,23 @@ interface ClientModuleScope { declare function loadClientFunctions(url: string, scope: ClientModuleScope): Promise unknown>>; declare function invalidateClientModule(url: string): void; +interface ActionClientOptions { + signal?: AbortSignal; + csrfToken?: string; + headers?: HeadersInit; + serialize?: (input: I) => BodyInit; +} +interface ActionResult { + data: O; + invalidated: string[]; +} +declare class ActionClientError extends Error { + readonly status: number; + readonly errors?: Record | undefined; + constructor(status: number, errors?: Record | undefined); +} +declare function createActionClient(route: string, name: string): (input: I, options?: ActionClientOptions) => Promise>; + interface HydrationScopeApi { get(name: string): unknown; set(name: string, value: unknown): void; @@ -4212,8 +4904,9 @@ declare function getReactiveRuntime(): string; declare function getNavRuntime(): string; /** The realtime client runtime served at `/__wrnexus/realtime.js`. */ declare function getRealtimeRuntime(): string; +declare function getActionRuntime(): string; -export { type ClientModuleScope, type HydrationScopeApi, NAV_RUNTIME, type OutputHandler, type OutputHost, REACTIVE_RUNTIME, REALTIME_RUNTIME, type ServerCallOptions, WrnServerCallError, type WrnexusBrowserGlobals, callServerFunction, collectRefs, createOutputProxy, createServerProxy, getNavRuntime, getReactiveRuntime, getRealtimeRuntime, invalidateClientModule, invokeOutput, loadClientFunctions, registerOutputHandler }; +export { ACTION_RUNTIME, ActionClientError, type ActionClientOptions, type ActionResult, type ClientModuleScope, type HydrationScopeApi, NAV_RUNTIME, type OutputHandler, type OutputHost, REACTIVE_RUNTIME, REALTIME_RUNTIME, type ServerCallOptions, WrnServerCallError, type WrnexusBrowserGlobals, callServerFunction, collectRefs, createActionClient, createOutputProxy, createServerProxy, getActionRuntime, getNavRuntime, getReactiveRuntime, getRealtimeRuntime, invalidateClientModule, invokeOutput, loadClientFunctions, registerOutputHandler }; ``` --- @@ -4224,6 +4917,15 @@ Documentation URL: https://wrnexusjs.dev/packages/db # @wrnexus/db +## Rollout-safe migrations + +Run `wrnexus db check` in CI before deployment. The analyzer reports stable +diagnostics for drops, renames, type changes, new/enforced required columns, +and potentially blocking index creation, with an expand/backfill/switch/contract +recommendation. `wrnexus db migrate` blocks critical issues in pending +migrations. `--allow-breaking` is an explicit operator override; already-applied +migrations do not block later releases. + > The database layer for WrNexus: TS models as the single source of truth for DDL, validation, and result typing, plus a driver-based `Db` client, migrations, and a sqlc-style query generator. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. @@ -4309,7 +5011,8 @@ A `Driver` (implemented by adapters) exposes `dialect`, `query(sql, params?)`, - `exec(sql, params?)` — `Promise` (`{ changes, lastInsertId? }`). - `tx(fn)` — run `fn(db)` in a transaction; rolls back on throw. Nested `tx` reuses the current transaction. - `createTable(model)` — runs the model's `CREATE TABLE IF NOT EXISTS` DDL. -- `close()`. +- `close()` — idempotently rejects new top-level work, drains active queries and + transactions, then closes the underlying pool. Every query is parameterized (positional params). `createTableSql(model, dialect, ifNotExists?)` renders `CREATE TABLE` directly; `Dialect` is `"sqlite" | "postgres" | "mysql"`. @@ -4322,7 +5025,9 @@ A process-wide registry the runtime configures at startup from `wrnexus.config.t - `setDb(db)` / `setDb(name, db)` — set the default or a named connection. - `registerDb(name, db)` — alias of `setDb(name, db)`. - `getDb(name = "default")` — the default or a named `Db` (throws if unconfigured). -- `hasDb(name?)`, `databaseNames()`, `closeDatabases()`. +- `hasDb(name?)`, `databaseNames()`, `closeDatabases()`. Registry shutdown clears + registrations first, attempts every open database, and reports close failures + together with `AggregateError` instead of leaking later pools. ```ts const users = await getDb().all("SELECT * FROM users"); @@ -4345,8 +5050,8 @@ Migrations are `.sql` files (in e.g. `app/db/migrations`), each split into - `parseMigration(name, content)` → `Migration` (`{ name, up, down }`). - `loadMigrations(dir)` — parse all `.sql` files, sorted by filename. - `appliedMigrations(db)` — applied names, oldest first. -- `migrate(db, dir)` — apply all pending (each in a transaction); returns applied names. -- `rollback(db, dir)` — roll back the most recent; returns its name or `null`. +- `migrate(db, dir, options?)` — apply all pending (each in a transaction); returns applied names. +- `rollback(db, dir, options?)` — roll back the most recent; returns its name or `null`. - `status(db, dir)` — `{ name, applied }[]` for every migration file. - `scaffoldMigration(dir, name, dialect, models?)` — write a new numbered migration; with `models` it generates `CREATE`/`DROP` for every table (referenced tables first via topological sort). Returns the file path. @@ -4423,6 +5128,21 @@ const pageTwo = await paginate( ); ``` +For deployments, `{ dryRun: true }` reports pending names without applying +their SQL, `signal` cancels safely between migrations, and the default +database-backed lock prevents concurrent deploy runners. A live lock produces +`WRN-DB-MIGRATION-LOCKED`; crash-stale locks expire after `lockTimeoutMs` (five +minutes by default). Disable it with `lock: false` only when an external deploy +coordinator already guarantees exclusivity. + +```ts +const pending = await migrate(db, "app/db/migrations", { dryRun: true }); +await migrate(db, "app/db/migrations", { + signal: shutdownController.signal, + lockTimeoutMs: 10 * 60_000, +}); +``` + MongoDB (document API): ```ts @@ -4451,13 +5171,57 @@ SQL driver — use `@wrnexus/db/mongo` directly. - The `mongodb` npm package is an optional, lazily-imported peer — install it only if you use `@wrnexus/db/mongo`. The core package stays dependency-free. +## Repository and transaction helpers + +Repositories accept an immutable equality `scope`, normally `{ column: "tenant_id", value: +ctx.tenant.id }`. The scope is injected into every read, count, update and delete, while create +overwrites any caller-supplied tenant value. This makes accidental cross-tenant CRUD through the +repository API fail closed. + +```ts +import { createRepository, retryTransaction, databaseHealth, batch } from "@wrnexus/db"; + +const users = createRepository(db, { + table: "users", + allowedColumns: ["email", "name", "active"], +}); + +const user = await users.require(42); +await users.update(42, { active: true }); +``` + +Repository identifiers are validated, writes may be restricted to an allowlist, and values always use query parameters. Infrastructure packages remain helper-only and do not add UI dependencies to server code. + +## 0.8 repository and transaction helpers + +```ts +import { createRepository, databaseHealth, firstOrThrow, retryTransaction } from "@wrnexus/db"; + +const usersRepo = createRepository(db, { + table: "users", + allowedColumns: ["email", "name", "active"], + maxListLimit: 250, +}); + +const users = await usersRepo.all({ + orderBy: "name", + direction: "asc", + limit: 50, + offset: 0, +}); +``` + +Repository SQL identifiers are validated and values remain parameterized. Placeholder generation is dialect-aware: PostgreSQL uses `$1`, `$2`, and SQLite/MySQL use `?`. List limits are bounded. + +`retryTransaction()` retries recognized serialization, deadlock, and database-lock errors by default. Supply `shouldRetry` for application-specific retryable errors; ordinary validation or business errors are not retried automatically. + ### Exported TypeScript declarations ```ts import { M as Model } from './schema-tVurYsbL.js'; export { B as BaseType, C as Column, a as ColumnDef, b as Columns, t as table, v } from './schema-tVurYsbL.js'; -import { a as Db, b as Dialect, R as Row } from './driver-DA53QHkO.js'; -export { D as Driver, E as ExecResult, T as TxHandle, c as createDb, d as createTableSql } from './driver-DA53QHkO.js'; +import { a as Db, b as Dialect, R as Row, E as ExecResult } from './driver-DA53QHkO.js'; +export { D as Driver, T as TxHandle, c as createDb, d as createTableSql } from './driver-DA53QHkO.js'; /** * A process-wide database registry. The framework configures it at server @@ -4505,6 +5269,16 @@ interface Migration { up: string; down: string; } +interface MigrationRunOptions { + /** Return pending migration names without executing their SQL. */ + dryRun?: boolean; + /** Stop safely between migrations. Active database statements cannot be interrupted portably. */ + signal?: AbortSignal; + /** Coordinate migration runners through the database. Default true. */ + lock?: boolean; + /** Allow recovery of a lock left by a crashed process. Default 5 minutes. */ + lockTimeoutMs?: number; +} /** Split a migration file into its `up` and `down` SQL sections. */ declare function parseMigration(name: string, content: string): Migration; /** Load and parse all migration files in a directory, sorted by filename. */ @@ -4512,11 +5286,13 @@ declare function loadMigrations(dir: string): Migration[]; /** Names of already-applied migrations, oldest first. */ declare function appliedMigrations(db: Db): Promise; /** Apply an ordered migration list (each in a transaction). Returns applied names. */ -declare function applyMigrations(db: Db, migrations: readonly Migration[]): Promise; +declare function applyMigrations(db: Db, migrations: readonly Migration[], options?: MigrationRunOptions): Promise; /** Apply all pending migrations from a directory. */ -declare function migrate(db: Db, dir: string): Promise; +declare function migrate(db: Db, dir: string, options?: MigrationRunOptions): Promise; /** Roll back the most recently applied migration. Returns its name, or null. */ -declare function rollback(db: Db, dir: string): Promise; +declare function rollback(db: Db, dir: string, options?: Omit & { + dryRun?: boolean; +}): Promise; /** Full status: every migration file with whether it has been applied. */ declare function status(db: Db, dir: string): Promise<{ name: string; @@ -4529,6 +5305,16 @@ declare function status(db: Db, dir: string): Promise<{ */ declare function scaffoldMigration(dir: string, name: string, dialect: Dialect, models?: Model[]): string; +interface MigrationSafetyIssue { + code: "WRN-DB-DROP-TABLE" | "WRN-DB-DROP-COLUMN" | "WRN-DB-RENAME" | "WRN-DB-TYPE-CHANGE" | "WRN-DB-SET-NOT-NULL" | "WRN-DB-ADD-REQUIRED" | "WRN-DB-BLOCKING-INDEX"; + severity: "error" | "warning"; + migration: string; + statement: string; + recommendation: string; +} +declare function analyzeMigrationSafety(migration: Migration): MigrationSafetyIssue[]; +declare function analyzeMigrations(migrations: readonly Migration[]): MigrationSafetyIssue[]; + /** * sqlc-style query generator. Annotated SQL in `app/db/queries/*.sql` becomes * typed TS functions whose params + results are inferred from the TS models and @@ -4671,10 +5457,64 @@ interface QueryPolicy { onQuery?: (record: QueryRecord) => void | Promise; onIssue?: (issue: QueryIssue) => void | Promise; } +declare function getDbPerformanceSnapshot(): { + queries: QueryRecord[]; + issues: QueryIssue[]; +}; +declare function resetDbPerformanceSnapshot(): void; declare function instrumentDb(db: Db, policy?: QueryPolicy): Db; declare function queryOperation(sql: string): string; -export { type CursorPage, type CursorPageOptions, Db, Dialect, type Migration, Model, type ModelRef, type PageOptions, type Paginated, type QueryDef, type QueryIssue, type QueryKind, type QueryPolicy, type QueryRecord, type RelationOptions, Row, appliedMigrations, applyMigrations, closeDatabases, cursorPaginate, databaseNames, generateQueriesFile, getDb, hasDb, instrumentDb, loadMigrations, loadRelated, migrate, optimisticUpdate, paginate, parseMigration, parseQueries, queryOperation, registerDb, registerLazyDb, rollback, scaffoldMigration, setDb, softDeleteClause, status, tenantScope }; +declare class RecordNotFoundError extends Error { + constructor(message?: string); +} +declare function firstOrThrow(db: Db, sql: string, params?: unknown[], model?: Model, message?: string): Promise; +declare function exists(db: Db, sql: string, params?: unknown[]): Promise; +declare function countRows(db: Db, table: string, where?: string, params?: unknown[]): Promise; +declare function withTransaction(db: Db, callback: (tx: Db) => Promise): Promise; +declare function retryTransaction(db: Db, callback: (tx: Db, attempt: number) => Promise, options?: { + attempts?: number; + baseDelayMs?: number; + maxDelayMs?: number; + jitter?: boolean; + shouldRetry?: (error: unknown) => boolean; +}): Promise; +declare function batch(values: readonly T[], size?: number): T[][]; +declare function databaseHealth(db: Db): Promise<{ + ok: boolean; + latencyMs: number; + error?: string; +}>; +interface RepositoryListOptions { + limit?: number; + offset?: number; + orderBy?: keyof T & string; + direction?: "asc" | "desc"; +} +interface Repository { + all(options?: RepositoryListOptions): Promise; + find(id: string | number): Promise; + require(id: string | number): Promise; + create(values: Partial): Promise; + update(id: string | number, values: Partial): Promise; + remove(id: string | number): Promise; + exists(id: string | number): Promise; + count(): Promise; +} +declare function createRepository(db: Db, input: { + table: string; + idColumn?: string; + model?: Model; + allowedColumns?: readonly (keyof T & string)[]; + maxListLimit?: number; + /** Immutable equality scope (normally tenant_id) applied to every operation. */ + scope?: { + column: keyof T & string; + value: unknown; + }; +}): Repository; + +export { type CursorPage, type CursorPageOptions, Db, Dialect, ExecResult, type Migration, type MigrationRunOptions, type MigrationSafetyIssue, Model, type ModelRef, type PageOptions, type Paginated, type QueryDef, type QueryIssue, type QueryKind, type QueryPolicy, type QueryRecord, RecordNotFoundError, type RelationOptions, type Repository, Row, analyzeMigrationSafety, analyzeMigrations, appliedMigrations, applyMigrations, batch, closeDatabases, countRows, createRepository, cursorPaginate, databaseHealth, databaseNames, exists, firstOrThrow, generateQueriesFile, getDb, getDbPerformanceSnapshot, hasDb, instrumentDb, loadMigrations, loadRelated, migrate, optimisticUpdate, paginate, parseMigration, parseQueries, queryOperation, registerDb, registerLazyDb, resetDbPerformanceSnapshot, retryTransaction, rollback, scaffoldMigration, setDb, softDeleteClause, status, tenantScope, withTransaction }; ``` --- @@ -4751,6 +5591,12 @@ interface RunningServer { In development, `startServer` also connects `app/db/migrations` (and `app/db//migrations`) and auto-applies migrations, then starts an in-process file watcher. CSS edits hot-swap live. Page, component, layout, API, middleware, realtime, schema, locale, and public-asset edits invalidate only their cached modules, rescan routes where necessary, and morph fresh HTML through the existing HMR WebSocket. The server process and active gateway stay running. +`getWrnCompileMetrics()` exposes cumulative content-addressed compiler cache +`hits`, `misses`, successful `compilations`, `errors`, `totalDurationMs`, and +`lastDurationMs` for the DevToolbar or custom diagnostics. Tests and embedded +servers can call `resetWrnCompileMetrics()` to establish a fresh measurement +window. + ### `createHandlers(deps)` The core runtime shared by dev and prod. It handles CORS preflight, `/healthz` and `/__wrnexus/health`, request-body size limits (413), HMR socket upgrades (`/__wrnexus/hmr`), realtime WebSocket upgrades (`defineRoom` default export or a raw `websocket` export), the middleware pipeline, API routes (`/api/*`), framework assets (`/__wrnexus/*`), public assets, and full SSR page rendering (component mounts, layouts, slots, i18n markers, per-page script selection, ETag/304, gzip). @@ -4981,7 +5827,9 @@ Pages get only the scripts they use: `nav.js` always, `reactive.js` when a page - **Bun-only.** Uses `Bun.serve` (HTTP + WebSocket), `Bun.file`, and `Bun.gzipSync`. The full app also relies on `bun:sqlite` / `Bun.SQL` via `@wrnexus/db`. - Orchestrates the whole framework: `@wrnexus/core` (context, security, realtime registry), `@wrnexus/router`, `@wrnexus/ssr` (`renderDocument`), `@wrnexus/csr` (client runtimes), `@wrnexus/compiler` (`.wrn` → TS), `@wrnexus/styles`, `@wrnexus/ui`, `@wrnexus/validation`, `@wrnexus/i18n`, `@wrnexus/db`, and `@wrnexus/pubsub` (Redis-backed cross-process realtime). -- `.wrn` files are compiled to TypeScript into a hidden sibling `.wrnexus/` cache dir and dynamically imported; the module cache means each edited server module needs a fresh process (dev) — hence the restart-on-change model. +- `.wrn` files compile into a content-addressed hidden `.wrnexus/` cache. Targeted + invalidation gives changed modules a fresh import identity without restarting + the development server. - Responses are gzipped when the client accepts it and the body is a buffered, compressible payload ≥ 1 KB; streaming/SSE responses opt out via `Cache-Control: no-transform`. @@ -4990,19 +5838,58 @@ Pages get only the scripts they use: `nav.js` always, `reactive.js` when a page ### Exported TypeScript declarations ```ts -import { Mode, Middleware, SeoConfig, SecurityConfig, RealtimeBus, RealtimeConnectMeta } from '@wrnexus/core'; +import { Mode, Middleware, SeoConfig, SecurityConfig, HealthRegistry, RealtimeBus, RealtimeConnectMeta } from '@wrnexus/core'; import { Router } from '@wrnexus/router'; import { ResolvedTheme, MobileConfig, PwaConfig, ObservabilityConfig, TenancyConfig, NavigationConfig, StylesConfig, ThemeConfig } from '@wrnexus/styles'; import { ResolvedI18n, I18nConfig } from '@wrnexus/i18n'; import { StorageConfig } from '@wrnexus/uploader'; import { DevToolbarConfig, DevToolbarPlatformSnapshot, DevToolbarPanel } from '@wrnexus/dev-toolbar/types'; import { ClientRuntimeDefinition, PluginInput } from '@wrnexus/plugin'; +import { CacheCoordinator } from '@wrnexus/cache'; import { DevToolbarCollector } from '@wrnexus/dev-toolbar/server'; import { IncomingMessage, ServerResponse, Server } from 'node:http'; /** Exit code a dev-server child uses to request a clean supervisor restart. */ declare const RESTART_EXIT_CODE = 97; +interface PartialBuildModule { + default?: unknown; + render?: (props?: Record) => string | Promise; + layout?: string | { + name?: string; + render?: (props?: Record) => string; + }; + __wrnexusBuildStaticShell?: (ctx?: Record) => string | Promise; +} +interface PartialBuildEntry { + name: string; + mod: PartialBuildModule; +} +/** Expand compiler component mounts at build time using only their pure render exports. */ +declare function expandStaticComponents(html: string, components: readonly PartialBuildEntry[], depth?: number): Promise; +/** Produce the body shell stored in dist; dynamic region bodies are never evaluated here. */ +declare function precomputePartialStaticShell(page: PartialBuildModule, components: readonly PartialBuildEntry[]): Promise<{ + shell: string; + regions: number; +}>; + +/** + * Request pipeline helpers: middleware execution and safe module loading. + * These are deliberately runtime-agnostic (no Bun APIs) so they could run on + * Node too. + */ + +interface WrnCompileMetrics { + hits: number; + misses: number; + compilations: number; + errors: number; + totalDurationMs: number; + lastDurationMs: number; +} +declare function getWrnCompileMetrics(): Readonly; +declare function resetWrnCompileMetrics(): void; + /** * HMR hub — tracks connected browser HMR sockets and broadcasts update events. * @@ -5113,6 +6000,8 @@ interface RuntimeDeps { security?: SecurityConfig; /** Built-in request tracing and Server-Timing policy. */ observability?: ObservabilityConfig; + /** Dependency health checks used by `/readyz` and `/__wrnexus/ready`. */ + health?: HealthRegistry; /** Built-in tenant identity resolution. */ tenancy?: TenancyConfig; /** Max request body size in bytes (413 above this). Default 10 MB. */ @@ -5125,12 +6014,16 @@ interface RuntimeDeps { * bus (use the Redis pub/sub driver). Enables realtime across multiple apps. */ realtimeBus?: RealtimeBus; + /** Shared first-class data/component/page caches. */ + cache?: CacheCoordinator; + /** Final document transform supplied by the plugin render lifecycle. */ + renderHtml?: (html: string) => string | Promise; devToolbar?: { config: DevToolbarConfig; collector: DevToolbarCollector; root: string; platform?: DevToolbarPlatformSnapshot; - panels?: DevToolbarPanel[]; + panels?: DevToolbarPanel[] | (() => DevToolbarPanel[] | Promise); }; } interface UpgradeServer { @@ -5264,7 +6157,8 @@ declare function startGateway(opts: GatewayOptions): Promise; * `wrnexus build` generates an entry that statically imports every route and * component module and hands them here as a manifest. We rebuild the (cheap) * route-matching tables from the raw patterns and run the exact same request - * runtime as dev — just with production error pages and no live-reload client. + * runtime as dev. Normal preview/deploy output has no live-reload client; the + * supervised `dev --production-runtime` mode can explicitly enable it. */ type RouteModule = Record; @@ -5273,6 +6167,8 @@ interface ManifestRoute { raw: string; /** The statically-imported route module. */ mod: RouteModule; + /** Body shell precomputed by `wrnexus build` for a partial-static page. */ + staticShell?: string; } interface ProdManifest { pages: ManifestRoute[]; @@ -5373,6 +6269,8 @@ interface ProdOptions { port?: number; hostname?: string; maxBodyBytes?: number; + /** Enable only for the CLI's supervised exact-production development mode. */ + developmentRuntime?: boolean; } /** * Build the portable request handler from a precompiled manifest — a @@ -5427,6 +6325,11 @@ interface ServeOptions { appDir: string; port?: number; hostname?: string; + /** Development TLS material. Production TLS is normally terminated by the deployment proxy. */ + tls?: { + cert: string; + key: string; + }; mode?: Mode; /** Inject the live-reload client (defaults to true in development). */ hmr?: boolean; @@ -5479,7 +6382,7 @@ interface RunningServer { } declare function startServer(opts: ServeOptions): Promise; -export { type AssetServer, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WsData, createHandlers, createProductionHandlers, createProductionServer, nodeListener, serveNode, startGateway, startServer, toRequest, writeResponse }; +export { type AssetServer, type FetchHandler, type GatewayApp, type GatewayAuth, type GatewayOptions, type GatewaySecurity, RESTART_EXIT_CODE, type RunningGateway, type RunningServer, type RuntimeDeps, type ServeOptions, type WrnCompileMetrics, type WsData, createHandlers, createProductionHandlers, createProductionServer, expandStaticComponents, getWrnCompileMetrics, nodeListener, precomputePartialStaticShell, resetWrnCompileMetrics, serveNode, startGateway, startServer, toRequest, writeResponse }; ``` --- @@ -5497,6 +6400,9 @@ Development-only page quality toolbar for WRNexusJS. - Runtime, resource and unhandled promise error capture - Accessibility, SEO, image, media, color, HTML, form, link, responsive and security checks - Performance and network observations +- First-class application tabs for runtime, stores, cache, accessibility, SEO, performance, + security, images, links, and JavaScript +- Plugin-contributed applications with badges, descriptions, issue feeds, and structured data - Element highlighting and issue filtering - Server-side issue collector - Development-only asset strings for direct serving by `@wrnexus/dev-server` @@ -5512,12 +6418,16 @@ Serve `DEV_TOOLBAR_RUNTIME` at `/__wrnexus/dev-toolbar.js` and `DEV_TOOLBAR_CSS` The browser runtime exposes `window.__wrnexusDevToolbar`. +Plugin panels returned through `devToolbarPanels()` are automatically added to the application +strip. Their issue category is filterable, and structured `data` is rendered as escaped diagnostic +content so a plugin never needs to inject toolbar HTML. + ### Exported TypeScript declarations ```ts export { DevToolbarCategory, DevToolbarClientApi, DevToolbarConfig, DevToolbarElementTarget, DevToolbarFix, DevToolbarIssue, DevToolbarMetrics, DevToolbarPageReport, DevToolbarPanel, DevToolbarPlatformSnapshot, DevToolbarServerMessage, DevToolbarSeverity, DevToolbarSourceLocation } from './types.js'; export { DEV_TOOLBAR_RULES, DevToolbarRule, DevToolbarRuleContext, accessibilityRules, accessibleName, colorRules, contrastRatio, createFingerprint, createIssue, effectiveBackground, formRules, getStableSelector, htmlRules, imageRules, isVisible, linkRules, luminance, mediaRules, parseRgb, parseSource, performanceRules, responsiveRules, runDevToolbarRules, securityRules, seoRules } from './rules/index.js'; -export { DevToolbarApp, DevToolbarCollector, DevToolbarIssueListener, DevToolbarRegistry, DevToolbarRouteOptions, OpenEditorOptions, OpenEditorRequest, buildEditorCommand, createDevToolbarCollector, createDevToolbarRegistry, createServerIssue, handleDevToolbarRoute, issueFromError, openInEditor, resolveEditorFile, serializeDevToolbarJson } from './server/index.js'; +export { BuiltinPanelOptions, DevToolbarApp, DevToolbarCollector, DevToolbarIssueListener, DevToolbarRegistry, DevToolbarRouteOptions, OpenEditorOptions, OpenEditorRequest, buildEditorCommand, builtinDevToolbarPanels, createDevToolbarCollector, createDevToolbarRegistry, createServerIssue, handleDevToolbarRoute, issueFromError, openInEditor, resolveEditorFile, serializeDevToolbarJson } from './server/index.js'; export { DEV_TOOLBAR_CSS, DEV_TOOLBAR_RUNTIME } from './client/index.js'; ``` @@ -5529,88 +6439,77 @@ Documentation URL: https://wrnexusjs.dev/packages/encryption # @wrnexus/encryption -> Dependency-free crypto helpers for WrNexus: authenticated symmetric encryption (AES-256-GCM), hashing, and HMAC signing. +Authenticated encryption, hashing, HMAC, key rotation, and optional encrypted HTTP exchanges for WRNexusJS. -Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. +## Core helpers -## Overview +- `generateKey()` — random 256-bit AES key encoded as base64. +- `deriveKey(password, salt)` — PBKDF2-derived AES key. +- `encrypt(plaintext, key)` / `decrypt(payload, key)` — AES-256-GCM. +- `sha256(data)` — SHA-256 digest. +- `hmacSign(data, secret)` / `hmacVerify(...)` — HMAC-SHA256. +- `createKeyring(keys)` — active/previous key management. +- `seal()` / `open()` — versioned ciphertext with key ID. -This package provides small, focused cryptographic primitives for server-side use: encrypting secrets/tokens/database fields at rest with AES-256-GCM, deriving keys from passwords via PBKDF2, computing SHA-256 digests, and signing/verifying payloads with HMAC-SHA256. It is built entirely on the standard **Web Crypto API** (`crypto.subtle`) plus `btoa`/`atob` and `TextEncoder`/`TextDecoder` — no third-party dependencies. Reach for it whenever you need to protect sensitive values or verify webhook signatures. All functions are `async` (Web Crypto is promise-based). - -## Installation - -```bash -bun add @wrnexus/encryption -``` - -> Private package — the machine must be authenticated to the `wrnexus` npm org -> (a read token in `~/.npmrc`). Requires **Bun** (Node is not supported). - -## API - -All keys are exchanged as **base64 strings** and all digests/signatures as **hex strings**. - -| Export | Signature | Description | -| ------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -| `generateKey` | `() => Promise` | Generate a random 256-bit AES key, base64-encoded. Store it as a secret. | -| `deriveKey` | `(password: string, salt: string) => Promise` | Derive a base64 AES-256 key from a password + salt using PBKDF2 (100,000 iterations, SHA-256). | -| `encrypt` | `(plaintext: string, key: string) => Promise` | AES-256-GCM encrypt a string. Returns base64 of `iv(12 bytes) ‖ ciphertext+tag`. A fresh random IV is used each call. | -| `decrypt` | `(payload: string, key: string) => Promise` | Decrypt a value produced by `encrypt`. Throws if the key is wrong or the data was tampered with. | -| `sha256` | `(data: string) => Promise` | SHA-256 hex digest of a string (e.g. content hashing, dedup keys). | -| `hmacSign` | `(data: string, secret: string) => Promise` | HMAC-SHA256 hex signature of `data` with `secret` (e.g. signing webhooks). | -| `hmacVerify` | `(data: string, secret: string, signature: string) => Promise` | Constant-time verify of an HMAC-SHA256 hex signature. | - -Notes: - -- `generateKey` produces a 32-byte (256-bit) key via `crypto.getRandomValues`. -- `encrypt`/`decrypt` require a base64-encoded 256-bit key; anything else throws `"Encryption key must be a base64 256-bit key"`. -- `decrypt` throws `"Invalid ciphertext"` if the payload is shorter than the 12-byte IV, and the underlying Web Crypto call throws on any authentication (tag) mismatch. -- `hmacVerify` compares in constant time (length check plus XOR accumulation) to avoid timing leaks. - -## Usage - -Symmetric encryption of a secret at rest: +## Encrypted HTTP envelope ```ts -import { generateKey, encrypt, decrypt } from "@wrnexus/encryption"; +import { + createEncryptedRequest, + createKeyring, + createMemoryReplayStore, + decryptEncryptedResponse, + encryptedExchange, +} from "@wrnexus/encryption"; -const key = await generateKey(); // store this safely (env/secret manager) +const keyring = createKeyring([{ id: "2026-08", secret: process.env.API_BODY_KEY!, active: true }]); -const box = await encrypt("card #1234", key); // opaque base64 string, safe to persist -const plain = await decrypt(box, key); // "card #1234" +const replayStore = createMemoryReplayStore(); + +// Server middleware. +app.use( + encryptedExchange({ + keyring, + replayStore, + maxAgeMs: 60_000, + maxBodyBytes: 1_048_576, + }), +); + +// Controlled service/native client. +const request = await createEncryptedRequest( + "https://api.example.com/private/report", + { reportId: "report-1" }, + { method: "POST", keyring }, +); +const response = await fetch(request); +const result = await decryptEncryptedResponse(response, request, { keyring }); ``` -Deriving a key from a user password instead of a random key: +The envelope binds authenticated ciphertext to: -```ts -import { deriveKey, encrypt } from "@wrnexus/encryption"; +- HTTP method +- URL path and query +- request ID +- timestamp and expiry window +- encryption key ID +- optional replay-store consumption -const key = await deriveKey("correct horse battery staple", "per-user-salt"); -const box = await encrypt("secret note", key); -``` +`encryptedBody()` decrypts request bodies only. `encryptedExchange()` also encrypts successful downstream responses while allowing application exceptions to propagate normally. `encryptedFetch()` provides a convenient controlled-client call. -Hashing and webhook signature verification: +## Security boundary -```ts -import { sha256, hmacSign, hmacVerify } from "@wrnexus/encryption"; +Encrypted HTTP bodies **do not replace TLS/HTTPS**. Always use HTTPS. -const digest = await sha256("some content"); // 64-char hex string +This layer is appropriate for service-to-service traffic, native/mobile applications, controlled agents, and selected fields protected with server-managed keys. It cannot conceal data from an end user when browser JavaScript receives the decryption key. Never ship a long-lived server encryption key to a browser. -const signature = await hmacSign(rawBody, webhookSecret); -const ok = await hmacVerify(rawBody, webhookSecret, incomingSignatureHeader); -if (!ok) throw new Error("Invalid webhook signature"); -``` - -## Requirements / Notes - -- **Bun-only.** Relies on the Web Crypto API (`crypto.subtle`, `crypto.getRandomValues`) and the global `btoa`/`atob`, `TextEncoder`/`TextDecoder` — all available in Bun's runtime. -- **No dependencies.** The package has an empty dependency set; nothing is bundled beyond standard runtime APIs. -- Algorithms: AES-256-GCM (encryption), PBKDF2 with 100k SHA-256 iterations (key derivation), SHA-256 (digest), HMAC-SHA256 (signing). -- Keep generated/derived keys and HMAC secrets out of source control; treat them as first-class secrets. +Use a shared replay store such as Redis in multi-instance deployments. The memory replay store is process-local. ### Exported TypeScript declarations ```ts +import { Middleware } from '@wrnexus/core'; + interface EncryptionKey { id: string; secret: string; @@ -5631,6 +6530,66 @@ declare function open(sealed: string, keyring: EncryptionKeyring): Promise; +} +interface EncryptedHttpOptions { + keyring: EncryptionKeyring; + maxAgeMs?: number; + maxBodyBytes?: number; + replayStore?: ReplayStore; + now?: () => number; + /** Require the clear request-id header used to bind encrypted responses. Default true. */ + requireRequestIdHeader?: boolean; +} +interface DecryptedHttpBody { + body: T; + requestId: string; + timestamp: number; + keyId: string; +} +declare function createMemoryReplayStore(now?: () => number): ReplayStore; +declare function encryptHttpBody(body: T, input: { + keyring: EncryptionKeyring; + method?: string; + url: string | URL; + requestId?: string; + timestamp?: number; +}): Promise; +declare function decryptHttpBody(value: unknown, input: { + keyring: EncryptionKeyring; + method?: string; + url: string | URL; + maxAgeMs?: number; + replayStore?: ReplayStore; + now?: () => number; + expectedRequestId?: string; +}): Promise>; +declare function createEncryptedRequest(url: string | URL, body: T, input: Omit & { + keyring: EncryptionKeyring; + requestId?: string; +}): Promise; +declare function decryptRequest(request: Request, options: EncryptedHttpOptions): Promise>; +declare function encryptResponse(body: T, request: Request, options: EncryptedHttpOptions & { + status?: number; + headers?: HeadersInit; +}): Promise; +declare function decryptEncryptedResponse(response: Response, request: Request, options: EncryptedHttpOptions): Promise>; +declare function encryptedFetch(url: string | URL, body: TRequest, input: Omit & EncryptedHttpOptions): Promise; +declare function encryptedBody(options: EncryptedHttpOptions): Middleware; +declare function encryptedExchange(options: EncryptedHttpOptions & { + encryptResponses?: boolean; +}): Middleware; + /** * @wrnexus/encryption — authenticated symmetric encryption (AES-256-GCM) via * WebCrypto, dependency-free. Use it to encrypt secrets, tokens, or database @@ -5660,7 +6619,26 @@ declare function decrypt(payload: string, key: string): Promise; /** Derive a base64 AES key from a password + salt (PBKDF2, 100k iterations). */ declare function deriveKey(password: string, salt: string): Promise; -export { type EncryptionKey, type EncryptionKeyring, createKeyring, decrypt, deriveKey, encrypt, generateKey, hmacSign, hmacVerify, needsRotation, open, seal, sealedKeyId, sha256 }; +export { type DecryptedHttpBody, ENCRYPTED_HTTP_CONTENT_TYPE, ENCRYPTED_HTTP_VERSION, type EncryptedHttpEnvelope, type EncryptedHttpOptions, type EncryptionKey, type EncryptionKeyring, type ReplayStore, createEncryptedRequest, createKeyring, createMemoryReplayStore, decrypt, decryptEncryptedResponse, decryptHttpBody, decryptRequest, deriveKey, encrypt, encryptHttpBody, encryptResponse, encryptedBody, encryptedExchange, encryptedFetch, generateKey, hmacSign, hmacVerify, needsRotation, open, seal, sealedKeyId, sha256 }; +``` + +--- + +## @wrnexus/graphql + +Documentation URL: https://wrnexusjs.dev/packages/graphql + +# @wrnexus/graphql + +Optional GraphQL endpoint plugin. Supply the executor from GraphQL.js, GraphQL Yoga, Mercurius, +or another maintained engine; WRNexus owns bounded HTTP input, depth/alias limits, introspection +policy, generic production errors and plugin route integration. + +### Exported TypeScript declarations + +```ts +export { G as GraphqlExecutionResult, a as GraphqlOptions, b as GraphqlRequest, c as createGraphqlHandler, default as graphqlPlugin } from './plugin.js'; +import '@wrnexus/plugin'; ``` --- @@ -5835,176 +6813,104 @@ Documentation URL: https://wrnexusjs.dev/packages/i18n # @wrnexus/i18n -> Per-request translations plus locale-aware number, date, and currency formatting for WrNexus apps. +Recursive locale loading, fallback resolution, SSR/browser translations, locale formatting, and language UI blocks for WRNexusJS. -Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. +## Locale files -## Overview +Both layouts can be used together: -`@wrnexus/i18n` loads locale files from `app/locales/.json`, resolves the -active language for each request (cookie → `Accept-Language` → default), and -builds a `t(key, params)` translator used both in server code and in `.wrn` -views. It also ships Intl-based formatting helpers and a tiny client runtime that -wires up a language switcher. Translation lookup, language resolution, and HTML -marker rewriting run server-side; only the small `I18N_RUNTIME` snippet runs in -the browser. - -## Installation - -```bash -bun add @wrnexus/i18n +```text +app/locales/en.json +app/locales/en/common.json +app/locales/en/auth.json +app/locales/mr/common.json ``` -> Private package — the machine must be authenticated to the `wrnexus` npm org -> (a read token in `~/.npmrc`). Requires **Bun** (Node is not supported). - -## API - -### Loading & resolving - -| Export | Signature | Description | -| ------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| `loadLocales` | `(dir: string) => Record` | Reads every `.json` in `dir` into a `{ lang: messages }` map. Missing dir → `{}`; a bad file is warned and skipped. | -| `resolveI18n` | `(messages: Record, config?: I18nConfig) => ResolvedI18n` | Merges loaded messages + config into a resolved bundle (default lang, supported langs, messages). | -| `resolveLang` | `(i18n: ResolvedI18n, cookieValue: string \| undefined, acceptLanguage: string \| null) => string` | Picks the active language: matching cookie → best `Accept-Language` tag (falls back to base tag, e.g. `en-US` → `en`) → `i18n.default`. | -| `makeT` | `(i18n: ResolvedI18n, lang: string) => TFunction` | Builds a translator resolving current language → default → the key itself, with `{param}` interpolation. | - -### Types & constants - -| Export | Kind | Notes | -| -------------- | ----------- | ------------------------------------------------------------------------------ | -| `Messages` | `type` | `Record` — a locale's messages (supports nested/dotted keys). | -| `I18nConfig` | `interface` | `{ default?: string; locales?: string[] }`. | -| `ResolvedI18n` | `interface` | `{ default: string; langs: string[]; messages: Record }`. | -| `LANG_COOKIE` | `const` | `"wire-lang"` — the cookie the language is read from / written to. | -| `I18N_JS_HREF` | `const` | `"/__wrnexus/i18n.js"` — URL the client runtime is served at. | - -### HTML & client runtime - -| Export | Signature | Description | -| ---------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `translateHtml` | `(html: string, t: TFunction) => string` | Rewrites markers in rendered HTML: `t:="key"` → `=""` (attribute-escaped) and `` → element text becomes the translation (HTML-escaped). No-op unless a marker is present. | -| `renderI18nData` | `(i18n: ResolvedI18n, lang: string) => string` | JS snippet setting `window.__wireI18n = { lang, langs, default }` for the client switcher. | -| `I18N_RUNTIME` | `const string` | Browser IIFE that binds `[data-wire-lang-set="es"]` clicks and `select[data-wire-lang]` changes to set the `wire-lang` cookie and reload. Exposes `window.__wireLang.set(lang)`. | - -### Formatting helpers (re-exported from `./format.ts`) - -| Export | Signature | Example | -| -------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| `formatNumber` | `(value: number, lang: string, options?: Intl.NumberFormatOptions) => string` | `1234.5 → "1,234.5"` | -| `formatCurrency` | `(value: number, currency: string, lang: string) => string` | `9.99, "USD" → "$9.99"` | -| `formatDate` | `(value: Date \| number \| string, lang: string, options?: Intl.DateTimeFormatOptions) => string` | defaults to `{ dateStyle: "medium" }` | -| `formatRelativeTime` | `(value: number, unit: Intl.RelativeTimeFormatUnit, lang: string) => string` | `-3, "day" → "3 days ago"` (`numeric: "auto"`) | -| `plural` | `(count: number, forms: Partial>, lang: string) => string` | picks CLDR form; `#` is replaced by `count` | - -## Usage - -### Server: load, resolve, translate +Namespaced files become keys such as `common.save` and `auth.signIn`. ```ts -import { - loadLocales, - resolveI18n, - resolveLang, - makeT, - translateHtml, - LANG_COOKIE, -} from "@wrnexus/i18n"; +import { loadLocales, makeT, resolveI18n, resolveLang } from "@wrnexus/i18n"; -// app/locales/en.json, app/locales/es.json -const messages = loadLocales("app/locales"); -const i18n = resolveI18n(messages, { default: "en", locales: ["en", "es"] }); +const i18n = resolveI18n(loadLocales("app/locales", { strict: true }), { + default: "en", + locales: ["en", "mr", "hi"], + fallbacks: { "mr-IN": ["mr", "en"] }, + cookie: { name: "wire-lang", sameSite: "Lax", secure: true }, +}); -// Per request: -const lang = resolveLang(i18n, req.cookies?.[LANG_COOKIE], req.headers.get("accept-language")); +const lang = resolveLang(i18n, cookieValue, request.headers.get("accept-language")); const t = makeT(i18n, lang); - -t("nav.home"); // dotted key → "Home" -t("greeting", { name: "Ada" }); // "Hello, {name}" → "Hello, Ada" - -// After rendering a .wrn view, resolve translation markers in the HTML: -const finalHtml = translateHtml(renderedHtml, t); +t("common.hello", { name: "Ajay" }); ``` -`app/locales/en.json`: +## Resolution behavior -```json -{ - "nav": { "home": "Home" }, - "greeting": "Hello, {name}" -} -``` +- normalized BCP-47-style locale names +- cookie preference +- weighted `Accept-Language` +- wildcard language ranges +- regional base fallback +- explicit fallback chains +- configured default language +- automatic RTL for Arabic, Hebrew, Persian, Urdu, and related languages -### Views: translation markers +Locale JSON is size-limited and rejects prototype-pollution keys. Recursive namespace collisions are resolved safely. + +## Views and runtime ```html -

    Home

    +

    Dashboard

    ``` -`translateHtml` replaces the element text for `data-t` and the attribute value for -any `t:` (e.g. `t:placeholder`, `t:aria-label`). +Text and translated attributes are resolved during SSR. Active/fallback messages are serialized safely for the language runtime, which rebinds `data-t` markers after client navigation. -### Client: language switcher +Enable `i18nPlugin()` to use: -```ts -import { renderI18nData, I18N_RUNTIME, I18N_JS_HREF } from "@wrnexus/i18n"; +- `` +- `` -// In the document : -const head = ` - - -`; +`LanguageSwitcher` renders a native `select[data-wire-lang]`. The packaged runtime validates the +selection against the configured locales, writes the configured language cookie, updates the +document `lang`/`dir` attributes, emits `wrnexus:language-change`, and reloads so the next SSR +request uses the same cookie. No application-owned browser script is required. -// Serve I18N_RUNTIME at I18N_JS_HREF; then in markup: -// -// -``` +## Formatting -### Formatting +- `formatNumber` +- `formatCurrency` +- `formatDate` +- `formatRelativeTime` +- `plural` +- `createLocaleFormatter` +- `translationCoverage` + Localization tooling can extract statically discoverable `t("key")`, + `i18n.t("key")`, and `data-i18n="key"` usage, compare every locale with a + reference, and create layout-stressing pseudo-locales: ```ts import { - formatNumber, - formatCurrency, - formatDate, - formatRelativeTime, - plural, + auditLocaleKeys, + createPseudoLocale, + extractTranslationKeysFromFiles, } from "@wrnexus/i18n"; -formatNumber(1234.5, lang); // "1,234.5" -formatCurrency(9.99, "USD", lang); // "$9.99" -formatDate(Date.now(), lang); // "Jul 4, 2026" -formatRelativeTime(-3, "day", lang); // "3 days ago" -plural(2, { one: "# item", other: "# items" }, lang); // "2 items" +const used = extractTranslationKeysFromFiles(sourceFiles); +const coverage = auditLocaleKeys(messages, "en"); +const enXA = createPseudoLocale(messages.en); +const arXB = createPseudoLocale(messages.en, { rtl: true }); ``` -## Configuration - -`resolveI18n` accepts an `I18nConfig`: - -- `default` — fallback language; used when nothing else matches. Ignored if it has - no loaded messages, in which case the first supported language is used. -- `locales` — explicit supported-language list; defaults to the loaded locale names. - -Language resolution order at request time (`resolveLang`): a supported `wire-lang` -cookie value → the first matching `Accept-Language` tag (or its base subtag) → the -resolved default. - -## Requirements / Notes - -- **Bun-only.** Locale loading uses `node:fs` (`existsSync`, `readdirSync`, - `readFileSync`) and `node:path`; formatting relies on the platform `Intl` APIs. -- Works with [`@wrnexus/core`](../core) — `TFunction` (the `t(key, params)` type) - comes from core, and the resolved translator is exposed as `ctx.t` / `ctx.lang` - in request handling. -- Nested message objects are supported: keys are looked up whole first, then split - on `.` to walk the object tree. +Pseudo-localization preserves interpolation placeholders and markup tags. RTL +pseudo output uses Unicode direction controls, while runtime direction detection +continues to derive `rtl` from Arabic and other RTL language subtags. ### Exported TypeScript declarations ```ts import { TFunction } from '@wrnexus/core'; +export { I18nPluginOptions, i18nComponentsDir, default as i18nPlugin } from './plugin.js'; +import '@wrnexus/plugin'; /** * Locale-aware formatting helpers (Intl-based) + pluralization. Pair with the @@ -6025,6 +6931,25 @@ declare function formatRelativeTime(value: number, unit: Intl.RelativeTimeFormat */ declare function plural(count: number, forms: Partial>, lang: string): string; +interface ExtractedTranslationKey { + key: string; + file?: string; + offset: number; +} +declare function extractTranslationKeys(source: string, file?: string): ExtractedTranslationKey[]; +declare function extractTranslationKeysFromFiles(files: Iterable): ExtractedTranslationKey[]; +declare function flattenMessageKeys(messages: Messages, prefix?: string): string[]; +declare function auditLocaleKeys(messages: Record, referenceLocale: string): Record; +declare function pseudoLocalize(value: string, options?: { + rtl?: boolean; +}): string; +declare function createPseudoLocale(messages: Messages, options?: { + rtl?: boolean; +}): Messages; + declare function flattenMessages(messages: Messages, prefix?: string, output?: Record): Record; declare function localeFallbacks(locale: string, fallback?: string): string[]; declare function translationCoverage(i18n: ResolvedI18n): Record, locale: string): string; /** - * @wrnexus/i18n — translations for pages and API responses. - * - * Locales live in `app/locales/.json`. Per request the active language is - * resolved from the `wire-lang` cookie, then Accept-Language, then the default. - * `ctx.t(key, params)` translates on the server; in `.wrn` views `{t:key}` and - * `t:attr="key"` markers are resolved by `translateHtml` before the HTML is sent. + * @wrnexus/i18n — deterministic locale loading, fallback resolution, SSR + * translation markers, browser translation helpers, and UI language controls. */ type Messages = Record; -/** Load `/.json` files into a `{ lang: messages }` map. */ -declare function loadLocales(dir: string): Record; +interface LocaleLoadOptions { + /** Throw on invalid JSON instead of warning and continuing. */ + strict?: boolean; + /** Maximum JSON file size. Default 1 MiB. */ + maxFileBytes?: number; +} +interface I18nCookieConfig { + name?: string; + maxAge?: number; + path?: string; + sameSite?: "Strict" | "Lax" | "None"; + secure?: boolean; +} interface I18nConfig { - /** Default language, used as the fallback and when nothing else matches. */ default?: string; - /** Explicit set of supported languages (defaults to the loaded locale names). */ locales?: string[]; + /** Human-readable locale names used by package language controls. */ + labels?: Record; + /** Per-locale fallback override. Example: `{ "fr-CA": ["fr", "en"] }`. */ + fallbacks?: Record; + /** Locale direction overrides. Arabic/Hebrew/Persian/Urdu are RTL automatically. */ + direction?: Record; + cookie?: I18nCookieConfig; + strict?: boolean; } interface ResolvedI18n { default: string; langs: string[]; messages: Record; + fallbacks: Record; + direction: Record; + labels: Record; + cookie: Required; } declare const LANG_COOKIE = "wire-lang"; declare const I18N_JS_HREF = "/__wrnexus/i18n.js"; -/** Merge loaded locale messages + config into a resolved i18n bundle. */ +declare function normalizeLocale(locale: string): string; +/** + * Load both supported layouts: + * - `locales/en.json` + * - `locales/en/common.json`, `locales/en/auth.json` + * + * Namespaced files become `messages.en.common` and `messages.en.auth`. + */ +declare function loadLocales(dir: string, options?: LocaleLoadOptions): Record; +declare function localeDirection(locale: string, overrides?: Record): "ltr" | "rtl"; declare function resolveI18n(messages: Record, config?: I18nConfig): ResolvedI18n; -/** Build a `t()` for a language: current → default → the key itself. */ +declare function lookupMessage(messages: Messages | undefined, key: string): string | undefined; +declare function interpolate(message: string, params?: Record): string; +declare function translationChain(i18n: ResolvedI18n, locale: string): string[]; declare function makeT(i18n: ResolvedI18n, lang: string): TFunction; -/** Resolve the active language from a cookie, Accept-Language, then default. */ +/** Deeply apply tenant-specific translations without mutating the shared locale bundle. */ +declare function withTenantMessages(i18n: ResolvedI18n, overrides: Record): ResolvedI18n; +/** Load only common and route-specific messages for one locale. */ +declare function loadRouteMessages(directory: string, locale: string, route: string): Messages; +declare function parseAcceptLanguage(value: string | null): string[]; declare function resolveLang(i18n: ResolvedI18n, cookieValue: string | undefined, acceptLanguage: string | null): string; -/** - * Resolve translation markers in rendered HTML: - * t:="key" → ="" (e.g. t:placeholder, t:aria-label) - * → element text becomes the translation - * Only runs when the HTML actually contains a marker. - */ declare function translateHtml(html: string, t: TFunction): string; -/** `window.__wireI18n = { lang, langs }` for the client language switcher. */ declare function renderI18nData(i18n: ResolvedI18n, lang: string): string; -/** - * Client runtime: binds `[data-wire-lang-set="es"]` elements to set the - * `wire-lang` cookie and reload, so the server re-renders in the new language. - */ declare const I18N_RUNTIME: string; -export { I18N_JS_HREF, I18N_RUNTIME, type I18nConfig, LANG_COOKIE, type LocaleFormatter, type Messages, type ResolvedI18n, createLocaleFormatter, flattenMessages, formatCurrency, formatDate, formatMessage, formatNumber, formatRelativeTime, loadLocales, localeFallbacks, makeT, plural, renderI18nData, resolveI18n, resolveLang, translateHtml, translationCoverage }; +export { type ExtractedTranslationKey, I18N_JS_HREF, I18N_RUNTIME, type I18nConfig, type I18nCookieConfig, LANG_COOKIE, type LocaleFormatter, type LocaleLoadOptions, type Messages, type ResolvedI18n, auditLocaleKeys, createLocaleFormatter, createPseudoLocale, extractTranslationKeys, extractTranslationKeysFromFiles, flattenMessageKeys, flattenMessages, formatCurrency, formatDate, formatMessage, formatNumber, formatRelativeTime, interpolate, loadLocales, loadRouteMessages, localeDirection, localeFallbacks, lookupMessage, makeT, normalizeLocale, parseAcceptLanguage, plural, pseudoLocalize, renderI18nData, resolveI18n, resolveLang, translateHtml, translationChain, translationCoverage, withTenantMessages }; +``` + +--- + +## @wrnexus/identity + +Documentation URL: https://wrnexusjs.dev/packages/identity + +# @wrnexus/identity + +Enterprise identity and governance for WRNexusJS: OIDC discovery, signed SAML adapter flows, +LDAP/Active Directory synchronization adapters, SCIM provisioning, scoped API keys, service +accounts, approval workflows, consent history, retention, subject export/deletion and audit. + +The package complements `@wrnexus/auth` (passkeys, MFA, devices, sessions, OAuth and audited +impersonation) and `@wrnexus/authz` (RBAC, ABAC and policy decisions). Protocol-specific SAML and +directory parsing is supplied through adapters so applications can select a maintained vendor SDK +without weakening framework validation, replay protection or governance auditing. + +### Exported TypeScript declarations + +```ts +interface OidcMetadata { + issuer: string; + authorization_endpoint: string; + token_endpoint: string; + userinfo_endpoint?: string; + jwks_uri: string; + scopes_supported?: string[]; +} +declare function discoverOidc(issuer: string, options?: { + fetch?: typeof fetch; +}): Promise; +declare function oidcAuthorizationUrl(metadata: OidcMetadata, input: { + clientId: string; + redirectUri: string; + state: string; + nonce: string; + codeChallenge: string; + scopes?: string[]; +}): string; +interface EnterpriseIdentity { + externalId: string; + username: string; + displayName?: string; + email?: string; + groups: string[]; + active: boolean; + attributes?: Record; +} +interface SamlAssertion { + id: string; + issuer: string; + audience: string; + recipient: string; + expiresAt: number; + identity: EnterpriseIdentity; +} +interface SamlAdapter { + createLoginRequest(input: { + requestId: string; + callbackUrl: string; + relayState: string; + }): Promise | string; + verifySignedResponse(response: string): Promise; +} +interface ReplayStore { + consume(id: string, expiresAt: number): Promise; +} +declare function memoryReplayStore(now?: () => number): ReplayStore; +declare function createSamlFederation(options: { + adapter: SamlAdapter; + issuer: string; + audience: string; + recipient: string; + replayStore?: ReplayStore; + now?: () => number; +}): { + login: (input: { + requestId: string; + callbackUrl: string; + relayState: string; + }) => Promise | string; + callback(encodedResponse: string): Promise; +}; +interface DirectoryAdapter { + kind: "ldap" | "active-directory"; + search(input: { + baseDn: string; + filter: string; + attributes: string[]; + signal?: AbortSignal; + }): Promise; + authenticate?(username: string, password: string, signal?: AbortSignal): Promise; +} +declare function syncDirectory(adapter: DirectoryAdapter, options: { + baseDn: string; + filter?: string; + attributes?: string[]; + signal?: AbortSignal; + upsert: (identity: EnterpriseIdentity) => void | Promise; + disableMissing?: (externalIds: string[]) => void | Promise; +}): Promise<{ + provider: "ldap" | "active-directory"; + synchronized: number; +}>; +interface ScimUser extends EnterpriseIdentity { + id: string; + /** RFC 7643 field accepted at the HTTP boundary. */ + userName?: string; + schemas?: string[]; +} +interface ScimStore { + list(): Promise; + get(id: string): Promise; + create(user: Omit): Promise; + update(id: string, user: Partial): Promise; + delete(id: string): Promise; +} +declare function memoryScimStore(): ScimStore; +declare function createScimHandler(options: { + store: ScimStore; + bearerToken: string; + basePath?: string; + maxBodyBytes?: number; +}): (request: Request) => Promise; +interface MachineCredential { + id: string; + ownerId: string; + kind: "api-key" | "service-account"; + name: string; + scopes: string[]; + secretHash: string; + createdAt: number; + expiresAt?: number; + revokedAt?: number; +} +declare function createMachineIdentityManager(now?: () => number): { + issue(input: { + ownerId: string; + name: string; + scopes: string[]; + kind?: MachineCredential["kind"]; + expiresAt?: number; + }): Promise<{ + secret: string; + credential: { + secretHash: string; + id: string; + ownerId: string; + kind: "api-key" | "service-account"; + name: string; + scopes: string[]; + createdAt: number; + expiresAt?: number; + revokedAt?: number; + }; + }>; + authenticate(secret: string, requiredScope?: string): Promise<{ + secretHash: string; + id: string; + ownerId: string; + kind: "api-key" | "service-account"; + name: string; + scopes: string[]; + createdAt: number; + expiresAt?: number; + revokedAt?: number; + } | null>; + revoke(id: string): boolean; + list(ownerId: string): { + secretHash: string; + id: string; + ownerId: string; + kind: "api-key" | "service-account"; + name: string; + scopes: string[]; + createdAt: number; + expiresAt?: number; + revokedAt?: number; + }[]; +}; +interface GovernanceEvent { + id: string; + type: string; + subjectId: string; + actorId?: string; + createdAt: number; + data?: Record; +} +declare function createGovernance(options?: { + now?: () => number; + audit?: (event: GovernanceEvent) => void | Promise; + exportSubject?: (subjectId: string) => unknown | Promise; + deleteSubject?: (subjectId: string) => void | Promise; +}): { + consent(subjectId: string, purpose: string, granted: boolean, version: string): Promise<{ + granted: boolean; + version: string; + at: number; + }>; + consents(subjectId: string): { + [k: string]: { + granted: boolean; + version: string; + at: number; + }; + }; + request(subjectId: string, action: "export" | "delete"): Promise<{ + id: `${string}-${string}-${string}-${string}-${string}`; + subjectId: string; + action: "export" | "delete"; + status: "pending"; + requestedAt: number; + }>; + decide(id: string, actorId: string, approved: boolean): Promise<{ + decision: { + status: "approved" | "rejected"; + decidedAt: number; + decidedBy: string; + id: string; + subjectId: string; + action: "export" | "delete"; + requestedAt: number; + }; + result: unknown; + }>; + enforceRetention(records: Array<{ + subjectId: string; + createdAt: number; + }>, maxAgeMs: number, remove: (record: { + subjectId: string; + createdAt: number; + }) => void | Promise): Promise; +}; + +export { type DirectoryAdapter, type EnterpriseIdentity, type GovernanceEvent, type MachineCredential, type OidcMetadata, type ReplayStore, type SamlAdapter, type SamlAssertion, type ScimStore, type ScimUser, createGovernance, createMachineIdentityManager, createSamlFederation, createScimHandler, discoverOidc, memoryReplayStore, memoryScimStore, oidcAuthorizationUrl, syncDirectory }; ``` --- @@ -6102,24 +7285,105 @@ Documentation URL: https://wrnexusjs.dev/packages/image # @wrnexus/image -Responsive image attribute generation with secure remote-host policies and audits for dimensions, LCP loading, source oversizing, transfer size, and modern formats. +Secure responsive-image planning, loader adapters, picture sources, preload hints, placeholders, and performance auditing for WRNexusJS. + +Build-time conversion is available through `optimizeImage`. It normalizes and +bounds width/format variants, prevents variant explosions, writes deterministic +filenames, and returns a manifest with dimensions and byte sizes: ```ts -import { createResponsiveImage } from "@wrnexus/image"; -const attrs = createResponsiveImage({ - src: "/hero.jpg", - alt: "Hero", - width: 1600, - height: 900, - widths: [480, 960, 1600], - sizes: "100vw", - format: "avif", +import { optimizeImage } from "@wrnexus/image"; + +const manifest = await optimizeImage("public/hero.jpg", { + outputDir: "public/generated/images", + widths: [480, 960, 1440], + formats: ["avif", "webp"], + quality: 80, }); ``` +Install the optional `sharp` peer (`bun add sharp`) for the default AVIF/WebP +processor. Build systems can instead supply an `ImageProcessor` adapter, which +also makes transformation pipelines deterministic in tests. + +## Helper API + +```ts +import { + createResponsiveImage, + createPicture, + createCdnImageLoader, + createPathImageLoader, + createBlurPlaceholder, + imagePreload, + auditImage, +} from "@wrnexus/image"; + +const loader = createCdnImageLoader("https://images.example.com/transform"); +const picture = createPicture({ + src: "/hero.jpg", + alt: "Product dashboard", + width: 1600, + height: 900, + widths: [480, 768, 1200, 1600], + formats: ["avif", "webp"], + sizes: "(max-width: 768px) 100vw, 1200px", + fetchPriority: "high", + loader, +}); +``` + +Remote loaders require HTTPS. Source URLs are validated, dimensions and quality are bounded, placeholder colors are restricted to safe CSS colors, and preload attributes are escaped. + +## Components + +Enable `imagePlugin()` and use: + +- `` +- `` +- `` + +The package-owned blocks compose `@wrnexus/ui` where a complete UI block is appropriate while keeping the low-level image element lightweight. + ### Exported TypeScript declarations ```ts +export { ImagePluginOptions, imageComponentsDir, default as imagePlugin } from './plugin.js'; +import '@wrnexus/plugin'; + +interface ImageProcessorResult { + data: Uint8Array; + width: number; + height: number; +} +interface ImageProcessor { + transform(input: string, options: { + width: number; + format: Exclude; + quality: number; + }): Promise; +} +interface OptimizeImageOptions { + outputDir: string; + widths: number[]; + formats?: Array>; + quality?: number; + maxVariants?: number; + processor?: ImageProcessor; +} +interface OptimizedImageVariant { + path: string; + width: number; + height: number; + format: Exclude; + bytes: number; +} +interface OptimizedImageManifest { + source: string; + variants: OptimizedImageVariant[]; +} +declare function optimizeImage(input: string, options: OptimizeImageOptions): Promise; + type ImageFormat = "avif" | "webp" | "jpeg" | "png" | "original"; interface ImageLoaderInput { src: string; @@ -6179,8 +7443,43 @@ interface ImageAuditIssue { declare const defaultImageLoader: ImageLoader; declare function createResponsiveImage(options: ResponsiveImageOptions): ResponsiveImageAttributes; declare function auditImage(input: ImageAuditInput): ImageAuditIssue[]; +interface PictureSource { + type: string; + srcset: string; + sizes?: string; +} +interface PicturePlan { + image: ResponsiveImageAttributes; + sources: PictureSource[]; +} +declare function normalizeImageWidths(widths: readonly number[], options?: { + min?: number; + max?: number; +}): number[]; +declare function createCdnImageLoader(baseUrl: string, options?: { + sourceParam?: string; + widthParam?: string; + qualityParam?: string; + formatParam?: string; +}): ImageLoader; +declare function createPathImageLoader(prefix?: string): ImageLoader; +declare function createPicture(options: ResponsiveImageOptions & { + formats?: ImageFormat[]; +}): PicturePlan; +declare function createBlurPlaceholder(options?: { + width?: number; + height?: number; + color?: string; + accent?: string; +}): string; +declare function imagePreload(image: ResponsiveImageAttributes, options?: { + as?: string; + type?: string; + crossOrigin?: "anonymous" | "use-credentials"; +}): string; +declare function imageCacheKey(input: ImageLoaderInput): string; -export { type ImageAuditInput, type ImageAuditIssue, type ImageFormat, type ImageLoader, type ImageLoaderInput, type ImagePolicy, type ResponsiveImageAttributes, type ResponsiveImageOptions, auditImage, createResponsiveImage, defaultImageLoader }; +export { type ImageAuditInput, type ImageAuditIssue, type ImageFormat, type ImageLoader, type ImageLoaderInput, type ImagePolicy, type ImageProcessor, type ImageProcessorResult, type OptimizeImageOptions, type OptimizedImageManifest, type OptimizedImageVariant, type PicturePlan, type PictureSource, type ResponsiveImageAttributes, type ResponsiveImageOptions, auditImage, createBlurPlaceholder, createCdnImageLoader, createPathImageLoader, createPicture, createResponsiveImage, defaultImageLoader, imageCacheKey, imagePreload, normalizeImageWidths, optimizeImage }; ``` --- @@ -6322,6 +7621,65 @@ app.use(jwtAuth({ secret: process.env.JWT_SECRET!, required: false })); `ctx.user`; it complements the framework's cookie/session auth with a stateless bearer-token flow for API and mobile clients. +## Access, refresh, scope, and cookie helpers + +```ts +import { + createAccessToken, + createRefreshToken, + verifyAccessToken, + verifyRefreshToken, + extractBearerToken, + requireScopes, + jwtCookie, +} from "@wrnexus/jwt"; +``` + +The helpers add explicit `type: "access" | "refresh"` claims, scope checks, refresh-token family metadata, no-store token responses, and secure cookie defaults. `__Host-` cookies are rejected unless they use `Path=/` and `Secure`; `SameSite=None` is rejected without `Secure`. + +## 0.8 helper kit + +```ts +import { + createTokenPair, + verifyAccessToken, + verifyRefreshToken, + extractBearerToken, + readJwtCookie, + jwtCookie, + clearJwtCookie, + requireScopes, +} from "@wrnexus/jwt"; + +const pair = await createTokenPair(user.id, { + accessSecret: process.env.JWT_ACCESS_SECRET!, + refreshSecret: process.env.JWT_REFRESH_SECRET!, + scopes: ["profile:read"], + family: sessionFamily, +}); +``` + +The helper kit validates `__Host-` cookie invariants, cookie names and paths, `SameSite=None` security, typed access/refresh token types, scope requirements, and no-store token responses. +In addition to local HS256 secrets/keyrings, the package verifies standards-based +RS256 tokens through bounded remote JWKS caches: + +```ts +import { createRemoteJwks, verifyJwtWithJwks } from "@wrnexus/jwt"; + +const jwks = createRemoteJwks("https://issuer.example/.well-known/jwks.json"); +const claims = await verifyJwtWithJwks(token, jwks, { + issuer: "https://issuer.example", + audience: "my-api", + maxAge: 300, +}); +``` + +JWKS URLs must use HTTPS. Responses have key-count/byte limits, accept only +RS256 signing RSA keys, deduplicate concurrent refreshes, cache imported public +keys, and force an immediate refresh for an unknown `kid` so issuer rotation +does not wait for cache expiry. Never use decoded-but-unverified claims for an +authorization decision. + ### Exported TypeScript declarations ```ts @@ -6345,6 +7703,91 @@ declare function createJwtKeyring(keys: JwtKey[]): JwtKeyring; declare function signWithKeyring(claims: JwtClaims, keyring: JwtKeyring, options?: SignOptions): Promise; declare function verifyWithKeyring(token: string, keyring: JwtKeyring, options?: VerifyOptions): Promise; +interface AccessTokenClaims extends JwtClaims { + sub: string; + type: "access"; + scopes?: string[]; +} +interface RefreshTokenClaims extends JwtClaims { + sub: string; + type: "refresh"; + family?: string; +} +declare function extractBearerToken(value: Headers | Request | Context | string | null | undefined): string | undefined; +declare function tryVerifyJwt(token: string | undefined, secret: string, options?: VerifyOptions): Promise; +declare function assertJwtClaims(claims: T, requirements?: { + subject?: boolean; + type?: string; + required?: string[]; +}): T; +declare function tokenScopes(claims: JwtClaims): string[]; +declare function hasScopes(claims: JwtClaims, required: readonly string[], mode?: "all" | "any"): boolean; +declare function requireScopes(required: readonly string[], mode?: "all" | "any"): Middleware; +declare function createAccessToken(subject: string, secret: string, options?: Omit & { + expiresIn?: number; + scopes?: string[]; + claims?: JwtClaims; +}): Promise; +declare function createRefreshToken(subject: string, secret: string, options?: Omit & { + expiresIn?: number; + family?: string; + claims?: JwtClaims; +}): Promise; +declare function verifyAccessToken(token: string, secret: string, options?: VerifyOptions): Promise; +declare function verifyRefreshToken(token: string, secret: string, options?: VerifyOptions): Promise; +declare function readJwtCookie(value: Headers | Request | string | null | undefined, name?: string): string | undefined; +declare function jwtCookie(token: string, options?: { + name?: string; + maxAge?: number; + secure?: boolean; + sameSite?: "Strict" | "Lax" | "None"; + path?: string; +}): string; +declare function clearJwtCookie(options?: Omit[1], "maxAge">): string; +interface JwtTokenPair { + accessToken: string; + refreshToken: string; + tokenType: "Bearer"; + expiresIn: number; +} +declare function createTokenPair(subject: string, input: { + accessSecret: string; + refreshSecret?: string; + accessExpiresIn?: number; + refreshExpiresIn?: number; + scopes?: string[]; + family?: string; + accessOptions?: Omit; + refreshOptions?: Omit; +}): Promise; +declare function jwtResponse(accessToken: string, input?: { + refreshToken?: string; + expiresIn?: number; + tokenType?: string; + scope?: string[]; +}): Response; + +interface RemoteJwksOptions { + fetch?: typeof fetch; + cacheTtlMs?: number; + maxKeys?: number; + maxBytes?: number; + now?: () => number; +} +interface RemoteJwks { + resolve(kid: string, alg: string): Promise; + refresh(): Promise; + clear(): void; + stats(): { + fetches: number; + hits: number; + keys: number; + expiresAt: number; + }; +} +declare function createRemoteJwks(url: string, options?: RemoteJwksOptions): RemoteJwks; +declare function verifyJwtWithJwks(token: string, jwks: RemoteJwks, options?: VerifyOptions): Promise; + /** * @wrnexus/jwt — dependency-free JSON Web Tokens (HS256) via WebCrypto, plus a * bearer-token auth middleware. Pairs with the session auth in @wrnexus/core for @@ -6403,7 +7846,220 @@ interface JwtAuthOptions { */ declare function jwtAuth(options: JwtAuthOptions): Middleware; -export { type JwtAuthOptions, type JwtClaims, JwtError, type JwtKey, type JwtKeyring, type SignOptions, type VerifyOptions, createJwtKeyring, decodeJwt, jwtAuth, signJwt, signWithKeyring, verifyJwt, verifyWithKeyring }; +export { type AccessTokenClaims, type JwtAuthOptions, type JwtClaims, JwtError, type JwtKey, type JwtKeyring, type JwtTokenPair, type RefreshTokenClaims, type RemoteJwks, type RemoteJwksOptions, type SignOptions, type VerifyOptions, assertJwtClaims, clearJwtCookie, createAccessToken, createJwtKeyring, createRefreshToken, createRemoteJwks, createTokenPair, decodeJwt, extractBearerToken, hasScopes, jwtAuth, jwtCookie, jwtResponse, readJwtCookie, requireScopes, signJwt, signWithKeyring, tokenScopes, tryVerifyJwt, verifyAccessToken, verifyJwt, verifyJwtWithJwks, verifyRefreshToken, verifyWithKeyring }; +``` + +--- + +## @wrnexus/language-server + +Documentation URL: https://wrnexusjs.dev/packages/language-server + +# @wrnexus/language-server + +Editor-neutral Language Server Protocol support for `.wrn` files. It uses the canonical +`@wrnexus/syntax` parser, diagnostics, accessibility rules, and formatter. + +```bash +bunx wrnexus-language-server --stdio +``` + +Capabilities include syntax, accessibility and TypeScript expression diagnostics, formatting, +completion, hover, document symbols, go-to-definition, references, rename, and quick fixes. +The custom `wrnexus/virtualDocument` request returns the mapped TypeScript representation of an +open `.wrn` document for editor TypeScript plugins and safe refactoring tools. Any LSP 3.x client can launch the +stdio command. Example Neovim configuration: + +```lua +vim.lsp.start({ + name = "wrnexus", + cmd = { "bunx", "wrnexus-language-server", "--stdio" }, + root_dir = vim.fs.root(0, { "wrnexus.config.ts", "package.json", ".git" }), +}) +``` + +JetBrains users can register the same command through an LSP client/plugin. The server +does not require VS Code and never reads environment secrets or sends source over a +network. + +### Exported TypeScript declarations + +```ts +interface WorkspaceCompletionItem { + label: string; + kind: number; + detail: string; + insertText?: string; + data?: Record; +} +declare function workspaceCompletionItems(root: string): WorkspaceCompletionItem[]; +declare function clearWorkspaceIndexCache(root?: string): void; +declare function extractComponentRefactor(document: TextDocument, range: Range, name: string): { + documentChanges: ({ + kind: string; + uri: string; + textDocument?: undefined; + edits?: undefined; + } | { + textDocument: { + uri: string; + version: number | null; + }; + edits: { + range: Range; + newText: string; + }[]; + kind?: undefined; + uri?: undefined; + })[]; +}; +declare function htmlToWrn(html: string, name?: string): string; + +interface Position { + line: number; + character: number; +} +interface Range { + start: Position; + end: Position; +} +interface TextDocument { + uri: string; + text: string; + version?: number; +} +declare const WRN_COMPLETIONS: readonly ["page", "component", "layout", "props", "outputs", "state", "computed", "effect", "watch", "lifecycle", "load", "action", "api", "realtime", "view", "style", "runtime", "hydrate"]; +declare function offsetAt(text: string, position: Position): number; +declare function positionAt(text: string, requestedOffset: number): Position; +declare function wordAt(text: string, position: Position): { + word: string; + range: Range; +} | null; +declare function documentDiagnostics(document: TextDocument): { + range: { + start: { + line: number; + character: number; + }; + end: { + line: number; + character: number; + }; + }; + severity: number; + code: string; + source: string; + message: string; +}[]; +/** TypeScript representation consumed by editor TypeScript plugins and safe refactoring tools. */ +declare function virtualTypeScriptDocument(document: TextDocument): { + uri: string; + languageId: "typescript"; + text: string; + mappings: Array<{ + virtualStartLine: number; + virtualEndLine: number; + sourceStartLine: number; + sourceStartColumn: number; + }>; +}; +declare function formatDocument(document: TextDocument, tabSize?: number, insertSpaces?: boolean): { + range: { + start: { + line: number; + character: number; + }; + end: Position; + }; + newText: string; +}[]; +declare function documentSymbols(document: TextDocument): { + name: string; + kind: number; + range: { + start: Position; + end: Position; + }; + selectionRange: { + start: Position; + end: Position; + }; +}[]; +declare function symbolLocations(document: TextDocument, position: Position): { + uri: string; + range: { + start: Position; + end: Position; + }; +}[]; +declare function definitionLocation(document: TextDocument, position: Position): { + uri: string; + range: { + start: Position; + end: Position; + }; +} | null; +declare function hover(document: TextDocument, position: Position): { + contents: { + kind: string; + value: string; + }; + range: Range; +} | null; +declare function completionItems(): { + label: "page" | "component" | "layout" | "props" | "outputs" | "state" | "computed" | "effect" | "watch" | "lifecycle" | "load" | "action" | "api" | "realtime" | "view" | "style" | "runtime" | "hydrate"; + kind: number; + detail: string; +}[]; + +export { type Position, type Range, type TextDocument, WRN_COMPLETIONS, type WorkspaceCompletionItem, clearWorkspaceIndexCache, completionItems, definitionLocation, documentDiagnostics, documentSymbols, extractComponentRefactor, formatDocument, hover, htmlToWrn, offsetAt, positionAt, symbolLocations, virtualTypeScriptDocument, wordAt, workspaceCompletionItems }; +``` + +--- + +## @wrnexus/mcp + +Documentation URL: https://wrnexusjs.dev/packages/mcp + +# @wrnexus/mcp + +Editor-neutral Model Context Protocol server for AI development tools. + +```bash +bunx wrnexus-mcp --root=. +``` + +It exposes current routes, components with props/events, database schema files, compiler diagnostics, +runtime errors, dev-server health, framework documentation and installed packages. Files are resolved +inside the configured application root and returned as bounded structured JSON. + +### Exported TypeScript declarations + +```ts +interface McpTool { + name: string; + description: string; + inputSchema: { + type: "object"; + properties?: Record; + additionalProperties?: boolean; + }; +} +interface McpServerOptions { + maxFiles?: number; + maxFileBytes?: number; + fetch?: typeof fetch; + devServerUrl?: string; + runtimeErrors?: () => unknown[] | Promise; +} +interface McpServer { + tools(): McpTool[]; + call(name: string, args?: Record): Promise; + handle(message: unknown): Promise | null>; +} +declare function createFrameworkMcpServer(appRoot: string, options?: McpServerOptions): McpServer; + +export { type McpServer, type McpServerOptions, type McpTool, createFrameworkMcpServer }; ``` --- @@ -6490,6 +8146,14 @@ const status = network ? await network.getStatus() : { connected: true, connecti Unavailable required plugins throw `MobileUnavailableError` with an actionable message. +The package also provides portable application-facing primitives: + +- `listenDeepLinks` normalizes initial and live links with an allowed-scheme list. +- `PushNotifications` performs permission gating and validates registrations. +- `SecureStorage` namespaces and validates keys over an application-supplied encrypted + Keychain/Keystore adapter; it does not mislabel browser `localStorage` as secure. +- `OfflineQueue` persists bounded sync batches through a pluggable durable store. + ## Requirements / Notes - Capacitor plugin imports must remain in browser-owned modules. @@ -6507,6 +8171,42 @@ interface DeepLink { query: URLSearchParams; } declare function parseDeepLink(value: string, schemes?: string[]): DeepLink | null; +interface DeepLinkSource { + current?(): Promise; + subscribe(listener: (url: string) => void): void | (() => void); +} +/** Normalize initial and live native links and ignore malformed/unapproved schemes. */ +declare function listenDeepLinks(source: DeepLinkSource, listener: (link: DeepLink) => void, schemes?: string[]): () => void; +interface PushRegistration { + token: string; + platform?: string; +} +interface PushAdapter { + permission(): Promise<"granted" | "denied" | "prompt" | "unavailable">; + requestPermission?(): Promise<"granted" | "denied">; + register(): Promise; + subscribe?(listener: (notification: unknown) => void): () => void; +} +declare class PushNotifications { + private readonly adapter; + constructor(adapter: PushAdapter); + register(): Promise; + subscribe(listener: (notification: unknown) => void): () => void; +} +interface SecureStorageAdapter { + get(key: string): Promise; + set(key: string, value: string): Promise; + remove(key: string): Promise; +} +declare class SecureStorage { + #private; + private readonly adapter; + private readonly namespace; + constructor(adapter: SecureStorageAdapter, namespace?: string); + get(key: string): Promise; + set(key: string, value: string): Promise; + remove(key: string): Promise; +} interface OfflineTask { id: string; type: string; @@ -6574,7 +8274,7 @@ declare const mobile: { whenNative: typeof whenNative; }; -export { type CapacitorBridge, type DeepLink, type MobileEnvironment, type MobilePlatform, MobileUnavailableError, OfflineQueue, type OfflineTask, type OfflineTaskStore, invoke, isNative, memoryOfflineTaskStore, mobile, mobileEnvironment, parseDeepLink, platform, plugin, registerPlugin, requirePlugin, whenNative }; +export { type CapacitorBridge, type DeepLink, type DeepLinkSource, type MobileEnvironment, type MobilePlatform, MobileUnavailableError, OfflineQueue, type OfflineTask, type OfflineTaskStore, type PushAdapter, PushNotifications, type PushRegistration, SecureStorage, type SecureStorageAdapter, invoke, isNative, listenDeepLinks, memoryOfflineTaskStore, mobile, mobileEnvironment, parseDeepLink, platform, plugin, registerPlugin, requirePlugin, whenNative }; ``` --- @@ -6664,6 +8364,9 @@ const position = await native.run( Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`, `haptics`, storage, filesystem, notifications, and device information. +`defineNativeManifest` declares required capabilities and typed permissions, while +`PermissionManager` normalizes permission query/request flows across platform adapters. + ## Requirements / Notes Use `supports()` before showing optional controls. Mobile capabilities require their @@ -6688,10 +8391,11 @@ declare function supports(name: string, target?: NativeTarget): boolean; declare function run(name: string, options?: unknown, runOptions?: NativeRunOptions): Promise; declare function clearRegistry(): void; +type NativePermission = "camera" | "geolocation" | "microphone" | "notifications" | "photos" | "storage" | (string & {}); interface NativeCapabilityManifestEntry { name: string; description?: string; - permissions?: string[]; + permissions?: NativePermission[]; targets?: NativeTarget[]; optional?: boolean; } @@ -6707,14 +8411,14 @@ declare function inspectNativeCapabilities(target?: NativeTarget): Array<{ }>; declare function missingNativeCapabilities(manifest: NativeCapabilityManifest, target?: NativeTarget): NativeCapabilityManifestEntry[]; interface PermissionAdapter { - query(name: string): Promise<"granted" | "denied" | "prompt" | "unavailable">; - request?(name: string): Promise<"granted" | "denied">; + query(name: NativePermission): Promise<"granted" | "denied" | "prompt" | "unavailable">; + request?(name: NativePermission): Promise<"granted" | "denied">; } declare class PermissionManager { private readonly adapter; constructor(adapter: PermissionAdapter); - query(name: string): Promise<"denied" | "granted" | "prompt" | "unavailable">; - ensure(name: string): Promise; + query(name: NativePermission): Promise<"denied" | "granted" | "prompt" | "unavailable">; + ensure(name: NativePermission): Promise; } declare const native: { @@ -6726,7 +8430,7 @@ declare const native: { supports: typeof supports; }; -export { NativeCapability, type NativeCapabilityManifest, type NativeCapabilityManifestEntry, NativePlatform, NativeRunOptions, NativeTarget, NativeUnavailableError, type PermissionAdapter, PermissionManager, clearRegistry, defineNativeManifest, inspectNativeCapabilities, isMobile, missingNativeCapabilities, native, platform, register, registered, run, supports }; +export { NativeCapability, type NativeCapabilityManifest, type NativeCapabilityManifestEntry, type NativePermission, NativePlatform, NativeRunOptions, NativeTarget, NativeUnavailableError, type PermissionAdapter, PermissionManager, clearRegistry, defineNativeManifest, inspectNativeCapabilities, isMobile, missingNativeCapabilities, native, platform, register, registered, run, supports }; ``` --- @@ -6931,10 +8635,33 @@ const gitlab = defineProvider({ `verifier` between `startAuth` and `completeAuth` (session or signed cookie). - Pairs with [`@wrnexus/core`](../core) — feed the normalized `OAuthProfile` into `logIn` to establish a session. + OIDC integrations can combine strict discovery with the rotating JWKS verifier: + +```ts +import { createRemoteJwks } from "@wrnexus/jwt"; +import { discoverOidc, verifyOidcIdToken } from "@wrnexus/oauth"; + +const metadata = await discoverOidc("https://issuer.example"); +const jwks = createRemoteJwks(metadata.jwks_uri); +const claims = await verifyOidcIdToken(idToken, { + issuer: metadata.issuer, + clientId: "client-id", + jwks, + nonce: expectedNonce, + accessToken, +}); +``` + +Discovery requires an exact normalized issuer and HTTPS endpoints without URL +credentials/fragments. ID-token verification checks the RS256 signature, +expiry/not-before, issuer, audience, required OIDC claims, nonce, multi-audience +`azp`, optional token age, and optional `at_hash` binding. ### Exported TypeScript declarations ```ts +import { JwtClaims, RemoteJwks } from '@wrnexus/jwt'; + interface OAuthStateRecord { state: string; verifier: string; @@ -6960,6 +8687,28 @@ interface OidcDiscovery { revocation_endpoint?: string; } declare function discoverOidc(issuer: string, fetchImpl?: typeof fetch): Promise; +interface OidcIdTokenClaims extends JwtClaims { + sub: string; + iss: string; + aud: string | string[]; + exp: number; + iat: number; + nonce?: string; + azp?: string; + at_hash?: string; +} +interface VerifyOidcIdTokenOptions { + issuer: string; + clientId: string; + jwks: RemoteJwks; + nonce?: string; + accessToken?: string; + now?: number; + clockTolerance?: number; + maxAge?: number; +} +declare function validateOidcClaims(claims: JwtClaims, options: Pick): asserts claims is OidcIdTokenClaims; +declare function verifyOidcIdToken(token: string, options: VerifyOidcIdTokenOptions): Promise; declare function validateOAuthReturnTo(value: string | undefined, origin: string, fallback?: string): string; /** @@ -7051,7 +8800,7 @@ declare function exchangeCode(provider: OAuthProvider, options: CompleteAuthOpti /** Fetch + normalize the user's profile from the provider. */ declare function fetchProfile(provider: OAuthProvider, tokens: OAuthTokens, fetchImpl?: FetchLike): Promise; -export { type CompleteAuthOptions, type OAuthProfile, type OAuthProvider, type OAuthStateRecord, type OAuthStateStore, type OAuthTokens, type OidcDiscovery, type ProviderCredentials, type StartAuthOptions, type StartAuthResult, completeAuth, createOAuthState, defineProvider, discord, discoverOidc, exchangeCode, fetchProfile, github, google, memoryOAuthStateStore, randomToken, refreshOAuthTokens, startAuth, validateOAuthReturnTo }; +export { type CompleteAuthOptions, type OAuthProfile, type OAuthProvider, type OAuthStateRecord, type OAuthStateStore, type OAuthTokens, type OidcDiscovery, type OidcIdTokenClaims, type ProviderCredentials, type StartAuthOptions, type StartAuthResult, type VerifyOidcIdTokenOptions, completeAuth, createOAuthState, defineProvider, discord, discoverOidc, exchangeCode, fetchProfile, github, google, memoryOAuthStateStore, randomToken, refreshOAuthTokens, startAuth, validateOAuthReturnTo, validateOidcClaims, verifyOidcIdToken }; ``` --- @@ -7062,6 +8811,10 @@ Documentation URL: https://wrnexusjs.dev/packages/observability # @wrnexus/observability +Open-standard traces, metrics, logs, health checks, Web Vitals, error reporting and profiling. + +Use `createOperationTracer()` for `database`, `cache`, `queue`, `realtime`, `server-action` or custom `application` spans. Export through OTLP, Prometheus, Zipkin/Jaeger, or the Sentry-compatible error reporter; Grafana can consume the Prometheus or OTLP signals. + Privacy-conscious counters, gauges, histograms, HTTP middleware, Web Vitals ingestion, browser collection, and exporter adapters. Request bodies and user identifiers are not collected by default. ```ts @@ -7070,64 +8823,141 @@ export default { }; ``` +## Traces, correlated logs, and OTLP + +```ts +import { + createOtlpMetricExporter, + createOtlpTraceExporter, + createStructuredLogger, + metricsMiddleware, + traceMiddleware, +} from "@wrnexus/observability"; + +const traces = createOtlpTraceExporter("https://collector.example/v1/traces", { + serviceName: "checkout", + headers: { authorization: `Bearer ${process.env.OTLP_TOKEN}` }, +}); + +export const tracing = traceMiddleware({ + serviceName: "checkout", + sampleRate: 0.1, + exporter: traces, + onExportError(error) { + console.error("trace export failed", error); + }, +}); + +export const metrics = metricsMiddleware(); +export const metricExporter = createOtlpMetricExporter("https://collector.example/v1/metrics", { + serviceName: "checkout", +}); + +export const logger = createStructuredLogger({ service: "checkout" }); +// Request middleware can create a correlated child from ctx.locals. +logger + .child({ + traceId: ctx.locals.traceId, + spanId: ctx.locals.spanId, + requestId: ctx.locals.requestId, + }) + .info("order accepted", { orderId }); +``` + +The tracing middleware accepts and validates W3C `traceparent`, creates a child server span, +stores correlation identifiers in `ctx.locals`, installs the framework tracer on `ctx.tracer`, +and returns `traceparent` plus `x-request-id`. Export failures are isolated from application +responses when `onExportError` is configured. + +## Liveness and readiness + +```ts +import { HealthRegistry } from "@wrnexus/core"; +import { createLivenessHandler, createReadinessHandler } from "@wrnexus/observability"; + +const health = new HealthRegistry(); +health.register("database", async () => + (await db.ping()) ? { status: "up" } : { status: "down" }, +); + +export const live = createLivenessHandler(); +export const ready = createReadinessHandler(health); +``` + +Liveness reports whether the process can answer requests. Readiness returns HTTP 503 when a +registered dependency is down. Dependency messages and details are hidden unless +`exposeDetails: true` is explicitly selected for a trusted endpoint. + ### Exported TypeScript declarations ```ts -import { Context, Middleware } from '@wrnexus/core'; +export { MetricLabels, MetricPoint, MetricsRegistry } from './metrics.js'; +export { MetricExporter, MetricsMiddlewareOptions, WebVitalRecord, WebVitalsHandlerOptions, createHttpMetricExporter, createOtlpMetricExporter, createWebVitalsHandler, defaultMetrics, metricsMiddleware } from './server.js'; export { WebVitalsClientOptions, webVitalsClient } from './client.js'; +export { SpanExporter, SpanRecord, TraceContext, TraceMiddlewareOptions, createOtlpTraceExporter, formatTraceparent, parseTraceparent, traceMiddleware } from './trace.js'; +export { HealthHandlerOptions, createLivenessHandler, createReadinessHandler } from './health.js'; +export { LogLevel, LogRecord, StructuredLogger, StructuredLoggerOptions, createStructuredLogger } from './logging.js'; +export { ErrorReporter, FrameworkSpanKind, LogExporter, OperationTracer, createJaegerExporter, createOperationTracer, createOtlpLogExporter, createPerformanceProfiler, createPrometheusPushExporter, createSentryCompatibleReporter, createZipkinExporter, renderPrometheus } from './integrations.js'; +import '@wrnexus/core'; +``` -type MetricLabels = Record; -interface MetricPoint { - name: string; - type: "counter" | "gauge" | "histogram"; - value: number; - count?: number; - sum?: number; - min?: number; - max?: number; - labels: MetricLabels; - timestamp: number; -} -declare class MetricsRegistry { - private readonly clock; - private points; - constructor(clock?: () => number); - increment(name: string, value?: number, labels?: MetricLabels): void; - gauge(name: string, value: number, labels?: MetricLabels): void; - observe(name: string, value: number, labels?: MetricLabels): void; - snapshot(): MetricPoint[]; - reset(): void; -} +--- -interface MetricsMiddlewareOptions { - registry?: MetricsRegistry; - routeLabel?: (ctx: Context) => string; - includePath?: boolean; -} -declare function metricsMiddleware(options?: MetricsMiddlewareOptions): Middleware; -interface WebVitalRecord { - name: "LCP" | "INP" | "CLS" | "FCP" | "TTFB"; - value: number; - rating?: "good" | "needs-improvement" | "poor"; - route?: string; - navigationType?: string; -} -interface WebVitalsHandlerOptions { - registry?: MetricsRegistry; - onRecord?: (record: WebVitalRecord, request: Request) => void | Promise; - maxBodyBytes?: number; -} -declare function createWebVitalsHandler(options?: WebVitalsHandlerOptions): (request: Request) => Promise; -interface MetricExporter { - export(points: readonly MetricPoint[]): Promise | void; -} -declare function createHttpMetricExporter(endpoint: string, options?: { - headers?: HeadersInit; - fetch?: typeof fetch; -}): MetricExporter; -declare const defaultMetrics: MetricsRegistry; +## @wrnexus/playground -export { type MetricExporter, type MetricLabels, type MetricPoint, type MetricsMiddlewareOptions, MetricsRegistry, type WebVitalRecord, type WebVitalsHandlerOptions, createHttpMetricExporter, createWebVitalsHandler, defaultMetrics, metricsMiddleware }; +Documentation URL: https://wrnexusjs.dev/packages/playground + +# @wrnexus/playground + +A deployable, shareable `.wrn` playground with diagnostics, generated JavaScript, +safe SSR-shaped HTML, sandboxed preview, reactive/UI examples, and version adapters. + +Run `wrnexus playground`, or deploy `createPlaygroundHandler()`. + +### Exported TypeScript declarations + +```ts +interface PlaygroundCompilation { + source: string; + generated: string; + client: string; + html: string; + interactiveHtml: string; + diagnostics: Array<{ + code: string; + message: string; + severity: string; + }>; + version: string; +} +interface PlaygroundVersionAdapter { + version: string; + compile(source: string): Promise>; +} +declare function compilePlayground(source: string, version?: string): PlaygroundCompilation; +declare function encodePlaygroundShare(source: string): string; +declare function decodePlaygroundShare(value: string): string; +declare function comparePlaygroundVersions(source: string, adapters: PlaygroundVersionAdapter[]): Promise<{ + current: PlaygroundCompilation; + comparisons: { + generated: string; + client: string; + html: string; + interactiveHtml: string; + diagnostics: Array<{ + code: string; + message: string; + severity: string; + }>; + version: string; + }[]; +}>; +declare function createPlaygroundHandler(options?: { + versions?: PlaygroundVersionAdapter[]; + examples?: Record; +}): (request: Request) => Promise; + +export { type PlaygroundCompilation, type PlaygroundVersionAdapter, comparePlaygroundVersions, compilePlayground, createPlaygroundHandler, decodePlaygroundShare, encodePlaygroundShare }; ``` --- @@ -7138,21 +8968,90 @@ Documentation URL: https://wrnexusjs.dev/packages/plugin # @wrnexus/plugin +## Least-privilege package permissions + +Package manifests declare every framework capability they register: + +```json +{ + "wrnexus": { + "permissions": ["routes", "migrations"], + "routes": [{ "kind": "api", "path": "/api/example", "entry": "./route.ts" }] + } +} +``` + +Applications can enable fail-closed grants: + +```ts +export default { + pluginPermissions: { + enforce: true, + grants: { "example-plugin": ["routes"] }, + }, +}; +``` + +Discovery rejects used-but-undeclared capabilities with +`WRN-PLUGIN-PERMISSION-UNDECLARED` and ungranted capabilities with +`WRN-PLUGIN-PERMISSION-DENIED`. Permissions cover components, browser runtime, +assets, styles, routes, middleware, migrations, config, transforms, +diagnostics/tooling, and server/build hooks. + +## Compatibility matrices + +Manifests can add `compatibility: { bunMin: "1.3.0", os: ["linux", +"darwin"] }` alongside `runtimes` and `requires`. Use +`testPluginCompatibility(manifest, targets)` in a package test to exercise the +complete support matrix. Runtime discovery enforces the same Bun minimum, OS, +runtime, and capability declarations used by the test kit. + Deterministic WRNexusJS plugin contracts for configuration, AST/code transforms, diagnostics, development servers, production builds, and DevToolbar extensions. Use `definePlugin()` and declare `enforce`, `before`, or `after` when ordering matters. Duplicate names and dependency cycles are rejected. +## Complete lifecycle and contributions + +Plugins may implement `setup`, `configure`, `configResolved`, `transformAst`, +`transformCode`, `diagnostics`, `routes`, `configureServer`, `buildStart`, +`buildEnd`, `render`, `deploy`, `shutdown`, and `hmrUpdate`. The runner preserves +resolved plugin order for every hook and executes `setup` exactly once. + +In addition to components, routes, middleware, assets, styles, runtimes, and +migrations, plugins can contribute `directives`, `cliCommands`, +`virtualModules`, `deploymentAdapters`, `configSchemas`, `documentation`, and +`typeDefinitions`. Names are collision checked. Configuration schemas run after +configuration resolution, CLI commands are callable as normal `wrnexus` +commands, directives participate in AST transformation, and production builds +materialize virtual modules and invoke matching contributed adapters. + ### Exported TypeScript declarations ```ts export { PageAst, WrnDiagnostic } from '@wrnexus/syntax'; -import { WrnexusPlugin, PluginInput, PluginContext, PluginRunner } from './types.js'; -export { ClientRuntimeDefinition, ClientRuntimeInject, ClientRuntimeLoad, ClientRuntimeType, PackageAssetDefinition, PackageMigrationDefinition, PackagePluginManifest, PackageRouteDefinition, PackageStyleDefinition, PluginCommand, PluginContributions, PluginDevToolbarPanel, PluginOrder, TransformContext, WrnexusPackageManifest } from './types.js'; +import { WrnexusPackageManifest, WrnexusPlugin, PluginInput, PluginContext, PluginRunner } from './types.js'; +export { ClientRuntimeDefinition, ClientRuntimeInject, ClientRuntimeLoad, ClientRuntimeType, PackageAssetDefinition, PackageMigrationDefinition, PackagePluginManifest, PackageRouteDefinition, PackageStyleDefinition, PluginCliCommand, PluginCommand, PluginConfigSchema, PluginContributions, PluginDeploymentAdapter, PluginDevToolbarPanel, PluginDirective, PluginOrder, PluginPermission, PluginVirtualModule, TransformContext } from './types.js'; export { assertContributionId, contentTypeForPath, defaultClientRuntimePath, defaultPackageAssetPath, definePackageManifest, normalizeClientRuntime, normalizePackageAsset, validateStyleIds } from './manifest.js'; export { DiscoverPluginOptions, discoverPlugins } from './discovery.js'; +interface PluginCompatibilityTarget { + runtime: "bun" | "node" | "edge" | "worker" | "service-worker" | "browser"; + version?: string; + os?: "win32" | "linux" | "darwin" | string; + capabilities?: readonly string[]; +} +interface PluginCompatibilityResult { + target: PluginCompatibilityTarget; + ok: boolean; + issues: Array<{ + code: "WRN-PLUGIN-MATRIX-RUNTIME" | "WRN-PLUGIN-MATRIX-VERSION" | "WRN-PLUGIN-MATRIX-OS" | "WRN-PLUGIN-MATRIX-CAPABILITY"; + message: string; + }>; +} +declare function testPluginCompatibility(manifest: WrnexusPackageManifest, targets: readonly PluginCompatibilityTarget[]): PluginCompatibilityResult[]; + declare function definePlugin(plugin: WrnexusPlugin): WrnexusPlugin; declare function flattenPlugins(input: PluginInput, output?: WrnexusPlugin[]): WrnexusPlugin[]; @@ -7160,7 +9059,7 @@ declare function flattenPlugins(input: PluginInput, output?: WrnexusPlugin[]): W declare function resolvePlugins(input: PluginInput): WrnexusPlugin[]; declare function createPluginRunner(input: PluginInput, context: PluginContext): PluginRunner; -export { PluginContext, PluginInput, PluginRunner, WrnexusPlugin, createPluginRunner, definePlugin, flattenPlugins, resolvePlugins }; +export { type PluginCompatibilityResult, type PluginCompatibilityTarget, PluginContext, PluginInput, PluginRunner, WrnexusPackageManifest, WrnexusPlugin, createPluginRunner, definePlugin, flattenPlugins, resolvePlugins, testPluginCompatibility }; ``` --- @@ -7202,13 +9101,15 @@ Creates a bus over a driver. Defaults to `memoryDriver()` (in-process). interface PubSub { publish(topic: string, message: T): Promise; subscribe(pattern: string, handler: Handler): () => void; + close(): Promise; } type Handler = (message: T, topic: string) => void | Promise; ``` -- `publish(topic, message)` — resolves once the driver has dispatched the message. +- `publish(topic, message)` — resolves once the driver and in-memory async handlers finish. - `subscribe(pattern, handler)` — returns an unsubscribe function. +- `close()` — idempotently rejects new work, clears local subscriptions, and closes the driver. ### Pattern matching @@ -7238,7 +9139,7 @@ then `redis://localhost:6379`. The URL may carry a password and a database index (e.g. `redis://:secret@host:6379/2`). ```ts -function redisDriver(url?: string): PubSubDriver & { close(): void }; +function redisDriver(url?: string, options?: RedisDriverOptions): PubSubDriver & { close(): void }; ``` - Exact topics use Redis `SUBSCRIBE`; wildcard patterns (`ns:*`, `*`) use @@ -7246,6 +9147,9 @@ function redisDriver(url?: string): PubSubDriver & { close(): void }; - Messages are JSON-stringified on publish and `JSON.parse`d on receipt; a payload that isn't valid JSON is delivered as the raw string. - `close()` tears down both the subscriber and publisher connections. +- Lost sockets reconnect with bounded exponential backoff and active subscriptions + are replayed. `maxPending` bounds unavailable-connection writes (default 1000); + `reconnectDelayMs` and `reconnectMaxDelayMs` tune recovery (100ms/5000ms). ### RESP codec (internal) @@ -7286,8 +9190,8 @@ bus.subscribe("order:*", (msg, topic) => { await bus.publish("order:created", { id: 7 }); -// on shutdown -driver.close(); +// on shutdown (also closes the driver) +await bus.close(); ``` ## Requirements / Notes @@ -7347,17 +9251,211 @@ type Handler = (message: T, topic: string) => void | Promise; interface PubSubDriver { publish(topic: string, message: unknown): void | Promise; subscribe(pattern: string, handler: Handler): () => void; + close?(): void | Promise; } interface PubSub { publish(topic: string, message: T): Promise; subscribe(pattern: string, handler: Handler): () => void; + /** Stop new work, remove subscriptions, and close the backing driver. */ + close(): Promise; } /** In-process pub/sub driver (default). */ declare function memoryDriver(): PubSubDriver; /** Create a pub/sub bus over a driver (in-memory by default). */ declare function createPubSub(driver?: PubSubDriver): PubSub; -export { type Handler, type MessageEnvelope, PresenceChannel, type PresenceMember, type PubSub, type PubSubDriver, type ResilientPubSubOptions, createPubSub, createResilientPubSub, memoryDriver }; +interface NatsClient { + publish(subject: string, data: Uint8Array): void | Promise; + subscribe(subject: string, handler: (data: Uint8Array, subject: string) => void): () => void; + close?(): void | Promise; +} +declare function natsDriver(client: NatsClient): PubSubDriver; +interface KafkaClient { + publish(topic: string, value: string): void | Promise; + subscribe(pattern: string, handler: (value: string, topic: string) => void): () => void; + close?(): void | Promise; +} +/** Kafka adapter contract; consumer-group/rebalance policy remains owned by the selected client. */ +declare function kafkaDriver(client: KafkaClient): PubSubDriver; + +export { type Handler, type KafkaClient, type MessageEnvelope, type NatsClient, PresenceChannel, type PresenceMember, type PubSub, type PubSubDriver, type ResilientPubSubOptions, createPubSub, createResilientPubSub, kafkaDriver, memoryDriver, natsDriver }; +``` + +--- + +## @wrnexus/pwa + +Documentation URL: https://wrnexusjs.dev/packages/pwa + +# @wrnexus/pwa + +Official PWA primitives for manifests, service workers, offline pages and precaching, runtime +caching, background synchronization, push notifications, install/update events, offline mutation +stores, and conflict resolution. `createOfflineQueue()` accepts a durable IndexedDB-style store and +retries requests with stable idempotency headers. + +### Exported TypeScript declarations + +```ts +interface IndexedDbMigration { + version: number; + migrate(db: IDBDatabase, transaction: IDBTransaction): void; +} +declare function openPwaDatabase(name: string, migrations: IndexedDbMigration[], factory?: IDBFactory): Promise; +declare function indexedDbOfflineQueueStore(db: IDBDatabase, storeName?: string): OfflineQueueStore; +declare const offlineQueueMigration: IndexedDbMigration; +interface StoredPushSubscription { + id: string; + userId: string; + endpoint: string; + expirationTime?: number | null; + keys: { + p256dh: string; + auth: string; + }; + createdAt: number; +} +interface PushSubscriptionStore { + put(value: StoredPushSubscription): Promise; + remove(id: string): Promise; + list(userId: string): Promise; +} +declare function memoryPushSubscriptionStore(): PushSubscriptionStore; +interface PushSqlClient { + query>(sql: string, parameters?: unknown[]): Promise<{ + rows: T[]; + }>; +} +declare function postgresPushSubscriptionStore(db: PushSqlClient): PushSubscriptionStore; +declare const POSTGRES_PUSH_SUBSCRIPTION_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_push_subscriptions (id text PRIMARY KEY,user_id text NOT NULL,endpoint text NOT NULL,expiration_time bigint,p256dh text NOT NULL,auth text NOT NULL,created_at bigint NOT NULL); CREATE INDEX IF NOT EXISTS wrnexus_push_user ON wrnexus_push_subscriptions (user_id);"; +declare function createPushSubscriptionService(store: PushSubscriptionStore, options?: { + now?: () => number; + maxPerUser?: number; +}): { + subscribe(userId: string, value: { + endpoint: string; + expirationTime?: number | null; + keys: { + p256dh: string; + auth: string; + }; + }): Promise<{ + keys: { + p256dh: string; + auth: string; + }; + createdAt: number; + endpoint: string; + expirationTime?: number | null; + id: string; + userId: string; + }>; + unsubscribe: (id: string) => Promise; + list: (userId: string) => Promise; +}; +declare function renderOfflineQueueReview(items: OfflineMutation[], conflicts?: Array<{ + id: string; + message: string; +}>): string; +declare const PWA_REVIEW_RUNTIME = "document.addEventListener(\"click\",event=>{const button=event.target.closest(\"[data-pwa-retry],[data-pwa-remove],[data-pwa-client],[data-pwa-server]\");if(!button)return;const action=button.hasAttribute(\"data-pwa-retry\")?\"retry\":button.hasAttribute(\"data-pwa-remove\")?\"remove\":button.hasAttribute(\"data-pwa-client\")?\"client\":\"server\";const id=button.getAttribute(\"data-pwa-\"+action);dispatchEvent(new CustomEvent(\"wrnexus:pwa-review\",{detail:{action,id}}))});"; + +type RuntimeCacheStrategy = "network-first" | "cache-first" | "stale-while-revalidate"; +interface RuntimeCacheRule { + pattern: string; + strategy: RuntimeCacheStrategy; + cacheName?: string; + methods?: string[]; +} +interface ServiceWorkerOptions { + cacheName?: string; + offlineUrl?: string; + startUrl?: string; + cacheUrls?: string[]; + runtimeCaching?: RuntimeCacheRule[]; + backgroundSyncTag?: string; +} +interface WebManifestOptions { + name: string; + shortName?: string; + description?: string; + id?: string; + startUrl?: string; + scope?: string; + display?: "standalone" | "fullscreen" | "minimal-ui" | "browser"; + themeColor?: string; + backgroundColor?: string; + icons?: Array<{ + src: string; + sizes: string; + type?: string; + purpose?: string; + }>; + shortcuts?: unknown[]; + screenshots?: unknown[]; + categories?: string[]; + lang?: string; +} +declare function createWebManifest(options: WebManifestOptions): { + id: string; + name: string; + short_name: string; + description: string | undefined; + start_url: string; + scope: string; + display: "standalone" | "fullscreen" | "minimal-ui" | "browser"; + theme_color: string; + background_color: string; + icons: { + src: string; + sizes: string; + type?: string; + purpose?: string; + }[]; + shortcuts: unknown[]; + screenshots: unknown[]; + categories: string[]; + lang: string; +}; +declare function generateServiceWorker(options?: ServiceWorkerOptions): string; +interface OfflineMutation { + id: string; + createdAt: number; + updatedAt: number; + endpoint: string; + method: string; + payload: T; + attempts: number; +} +interface OfflineQueueStore { + list(): Promise; + put(item: OfflineMutation): Promise; + remove(id: string): Promise; +} +declare function memoryOfflineQueueStore(): OfflineQueueStore; +type ConflictResolution = { + action: "client" | "server" | "merge"; + value: T; +}; +declare function resolveOfflineConflict(client: T, server: T, strategy?: "client-wins" | "server-wins" | "last-write-wins" | ((client: T, server: T) => T)): ConflictResolution; +declare function createOfflineQueue(options?: { + store?: OfflineQueueStore; + fetch?: (input: string | URL | Request, init?: RequestInit) => Promise; + maxItems?: number; + now?: () => number; +}): { + enqueue(input: Omit, "id" | "createdAt" | "updatedAt" | "attempts">): Promise>; + list: () => Promise[]>; + sync(): Promise<{ + id: string; + ok: boolean; + status?: number; + }[]>; + remove: (id: string) => Promise; +}; +declare function pwaClientRuntime(serviceWorkerUrl?: string): string; +declare function subscribeToPush(registration: ServiceWorkerRegistration, publicKey: Uint8Array): Promise; + +export { type ConflictResolution, type IndexedDbMigration, type OfflineMutation, type OfflineQueueStore, POSTGRES_PUSH_SUBSCRIPTION_SCHEMA, PWA_REVIEW_RUNTIME, type PushSqlClient, type PushSubscriptionStore, type RuntimeCacheRule, type RuntimeCacheStrategy, type ServiceWorkerOptions, type StoredPushSubscription, type WebManifestOptions, createOfflineQueue, createPushSubscriptionService, createWebManifest, generateServiceWorker, indexedDbOfflineQueueStore, memoryOfflineQueueStore, memoryPushSubscriptionStore, offlineQueueMigration, openPwaDatabase, postgresPushSubscriptionStore, pwaClientRuntime, renderOfflineQueueReview, resolveOfflineConflict, subscribeToPush }; ``` --- @@ -7411,33 +9509,45 @@ function createQueue(options?: QueueOptions): Queue; | `backoffMs` | `number` | `1000` | Base retry backoff in ms; doubles per attempt. | | `pollMs` | `number` | `250` | Poll interval used once `start()` is called (ms). | | `onFailed` | `(job: Job, error: unknown) => void` | — | Called when a job exhausts its attempts. | +| `concurrency` | `number` | unlimited | Maximum jobs claimed by one `drain()` call. | +| `capacity` | `number` | unlimited | Maximum queued plus active jobs before adds reject. | | `now` | `() => number` | `Date.now` | Clock injection for deterministic tests. | ### `Queue` The object returned by `createQueue`. -| Method | Signature | Description | -| --------- | -------------------------------------------------------------- | -------------------------------------------------------------- | -| `add` | `add(name, data: T, options?: AddOptions): Promise>` | Enqueue a job under a worker name. Returns the created job. | -| `process` | `process(name, handler: JobHandler): void` | Register the worker that runs jobs of the given name. | -| `drain` | `drain(now?: number): Promise` | Run every job whose `runAt ≤ now`, once. Returns how many ran. | -| `start` | `start(): void` | Begin polling every `pollMs`. No-op if already started. | -| `stop` | `stop(): void` | Stop the poll timer. | -| `size` | `size(): number` | Number of jobs currently queued. | +| Method | Signature | Description | +| ---------- | -------------------------------------------------------------- | -------------------------------------------------------------- | +| `add` | `add(name, data: T, options?: AddOptions): Promise>` | Enqueue a job under a worker name. Returns the created job. | +| `process` | `process(name, handler: JobHandler): void` | Register the worker that runs jobs of the given name. | +| `drain` | `drain(now?: number): Promise` | Run every job whose `runAt ≤ now`, once. Returns how many ran. | +| `start` | `start(): void` | Begin polling every `pollMs`. No-op if already started. | +| `stop` | `stop(): void` | Stop the poll timer. | +| `shutdown` | `shutdown({ force? }): Promise` | Stop accepting jobs and await active work; force aborts it. | +| `size` | `size(): number` | Number of jobs currently queued. | +| `get/list` | `get(id)` / `list(name?)` | Inspect defensive copies of pending jobs. | +| `cancel` | `cancel(id): boolean` | Remove queued work or abort an active handler. | +| `failed` | `failed(): Job[]` | Inspect exhausted jobs in the dead-letter collection. | +| `retry` | `retry(id): Promise` | Reset and requeue a dead-lettered job. | #### `AddOptions` -| Option | Type | Description | -| ------------- | -------- | -------------------------------------------------------------------------- | -| `delayMs` | `number` | Delay before the job becomes runnable (ms). | -| `maxAttempts` | `number` | Max attempts before dead-lettering. Defaults to the queue's `maxAttempts`. | -| `repeat` | `number` | Re-enqueue this job this many ms after each successful run (recurring). | +| Option | Type | Description | +| ---------------- | -------- | -------------------------------------------------------------------------- | +| `delayMs` | `number` | Delay before the job becomes runnable (ms). | +| `maxAttempts` | `number` | Max attempts before dead-lettering. Defaults to the queue's `maxAttempts`. | +| `repeat` | `number` | Re-enqueue this job this many ms after each successful run (recurring). | +| `priority` | `number` | Higher values are selected first among due jobs. | +| `idempotencyKey` | `string` | Return the matching pending job instead of enqueueing a duplicate. | #### `JobHandler` ```ts -type JobHandler = (job: Job) => void | Promise; +type JobHandler = ( + job: Job, + context: { signal: AbortSignal }, +) => void | Promise; ``` #### `Job` @@ -7474,6 +9584,18 @@ await queue.add("email", { to: "a@b.com" }, { delayMs: 5000, maxAttempts: 3 }); queue.start(); // begin polling; queue.stop() to halt ``` +Use `context.signal` in network/database calls so forced shutdown and active +cancellation finish promptly. For process termination, prefer +`await queue.shutdown()`; use `{ force: true }` only after your grace period. + +### Durable queue + +`createDurableQueue({ store })` retains jobs until their handler succeeds and +supports atomic leases when a driver implements `QueueStore.claim`. It exposes +the same cancellation/shutdown behavior plus `list`, `failed`, and `retry`. +The included `memoryQueueStore()` is useful for tests; production Redis/SQL +drivers should make `claim()` atomic to prevent two workers executing one job. + ### Recurring jobs Pass `repeat` to re-enqueue a job a fixed interval after each successful run: @@ -7513,6 +9635,29 @@ clock = 5000; const ran = await queue.drain(); // => 1 ``` +### Durable workflows and approvals + +`createWorkflowEngine(store)` executes dependency-ordered steps and persists every transition, +result, progress update, failure, cancellation, and approval record. Approval steps pause safely +and can resume after a process restart because the snapshot lives in the supplied `WorkflowStore`. + +```ts +const workflow = defineDurableWorkflow({ + name: "publish-report", + steps: [ + { name: "build", run: buildReport }, + { name: "approve", dependsOn: ["build"], approval: true, run: (report) => report }, + { name: "publish", dependsOn: ["approve"], run: publishReport }, + ], +}); + +const run = await engine.start(workflow, input); +await engine.approve(workflow, run.id, "approve", currentUser.id); +``` + +Use `memoryWorkflowStore()` for tests. Production stores implement the small `get`, `put`, and +`list` contract using the same transactional database or durable service as the application. + ## Retry & backoff behavior - On a thrown handler error, the job is retried while `attempts < maxAttempts`. @@ -7534,6 +9679,8 @@ const ran = await queue.drain(); // => 1 ### Exported TypeScript declarations ```ts +import { ExecutionContext } from '@wrnexus/core'; + /** * Persistence contract for the durable queue. * @@ -7555,20 +9702,142 @@ interface DurableQueueOptions { workerId?: string; maxAttempts?: number; concurrency?: number; + capacity?: number; leaseMs?: number; backoff?: (attempt: number) => number; now?: () => number; onDeadLetter?: (job: Job, error: unknown) => void | Promise; + context?: (job: Job, signal: AbortSignal) => ExecutionContext; } interface DurableQueue { add(name: string, data: T, options?: AddOptions): Promise>; process(name: string, handler: JobHandler): void; drain(): Promise; + cancel(id: string): Promise; + shutdown(options?: { + force?: boolean; + }): Promise; + list(name?: string): Promise; failed(): Job[]; retry(id: string): Promise; } declare function createDurableQueue(options?: DurableQueueOptions): DurableQueue; +interface RedisQueueClient { + get(key: string): Promise; + set(key: string, value: string, options?: { + NX?: boolean; + PX?: number; + }): Promise; + del(...keys: string[]): Promise; + zadd(key: string, score: number, member: string): Promise; + zrem(key: string, member: string): Promise; + zrangebyscore(key: string, min: number, max: number, options?: { + limit: [number, number]; + }): Promise; + smembers(key: string): Promise; + sadd(key: string, member: string): Promise; + srem(key: string, member: string): Promise; +} +/** Redis-backed queue store using only the common client command surface. */ +declare function redisQueueStore(client: RedisQueueClient, prefix?: string): QueueStore; +interface SqlQueueClient { + query>(sql: string, parameters?: unknown[]): Promise<{ + rows: T[]; + }>; +} +/** PostgreSQL store with atomic SKIP LOCKED leasing and JSON payloads. */ +declare function postgresQueueStore(db: SqlQueueClient, table?: string): QueueStore; +declare const POSTGRES_QUEUE_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_jobs (\n id text PRIMARY KEY, name text NOT NULL, payload jsonb NOT NULL, run_at bigint NOT NULL,\n priority integer NOT NULL DEFAULT 0, lease_owner text, lease_until bigint\n); CREATE INDEX IF NOT EXISTS wrnexus_jobs_due ON wrnexus_jobs (run_at, priority DESC);"; + +interface ScheduledJob { + name: string; + data: T; + everyMs: number; + options?: AddOptions; +} +interface QueueScheduler { + start(): void; + stop(): void; + tick(now?: number): Promise; + snapshot(): { + running: boolean; + schedules: number; + nextRuns: Record; + }; +} +/** Restart-safe scheduler when used with a durable queue and stable idempotency buckets. */ +declare function createQueueScheduler(queue: DurableQueue, schedules: ScheduledJob[], options?: { + pollMs?: number; + now?: () => number; +}): QueueScheduler; +declare function addBatch(queue: DurableQueue, name: string, values: T[], options?: AddOptions): Promise[]>; +interface QueueDashboardSnapshot { + generatedAt: number; + pending: number; + failed: number; + byName: Record; + oldestRunAt?: number; +} +declare function queueDashboardSnapshot(queue: DurableQueue): Promise; +declare function renderQueueDashboard(snapshot: QueueDashboardSnapshot): string; +/** Long-running scheduler/worker loop suitable for a dedicated process or container. */ +declare function runQueueDaemon(queue: DurableQueue, scheduler: QueueScheduler, options?: { + signal?: AbortSignal; + pollMs?: number; + onError?: (error: unknown) => void; +}): Promise; + +type WorkflowStatus = "pending" | "running" | "waiting-approval" | "completed" | "failed" | "cancelled"; +interface WorkflowStep$1 { + name: string; + dependsOn?: string[]; + approval?: boolean; + run(input: I, context: WorkflowRunContext): O | Promise; +} +interface WorkflowRunContext { + workflowId: string; + step: string; + results: Readonly>; + signal: AbortSignal; + progress(value: number, message?: string): void; +} +interface WorkflowSnapshot { + id: string; + name: string; + status: WorkflowStatus; + input: unknown; + results: Record; + completed: string[]; + waitingFor?: string; + progress: number; + message?: string; + error?: string; + updatedAt: number; +} +interface WorkflowStore { + get(id: string): Promise; + put(snapshot: WorkflowSnapshot): Promise; + list(): Promise; +} +declare function memoryWorkflowStore(): WorkflowStore; +interface WorkflowDefinition { + name: string; + steps: WorkflowStep$1[]; + /** Compile-time input marker; definitions do not store runtime input values. */ + readonly __input?: I; +} +interface WorkflowEngine { + start(definition: WorkflowDefinition, input: I, id?: string): Promise; + resume(definition: WorkflowDefinition, id: string): Promise; + approve(definition: WorkflowDefinition, id: string, step: string, actor: string): Promise; + cancel(id: string): Promise; + get(id: string): Promise; + list(): Promise; +} +declare function createWorkflowEngine(store?: WorkflowStore): WorkflowEngine; +declare function defineDurableWorkflow(definition: WorkflowDefinition): WorkflowDefinition; + /** * @wrnexus/queue — a background job queue with delays, retries + backoff, and * concurrent workers. The default store is in-process; a pluggable driver lets @@ -7594,7 +9863,13 @@ interface Job { idempotencyKey?: string; createdAt: number; } -type JobHandler = (job: Job) => void | Promise; +interface JobContext { + /** Aborted when an active job is cancelled or the queue is force-stopped. */ + signal: AbortSignal; + /** The same trusted context shape used by HTTP, actions, realtime and webhooks. */ + execution: ExecutionContext; +} +type JobHandler = (job: Job, context: JobContext) => void | Promise; interface AddOptions { /** Delay before the job becomes runnable (ms). */ delayMs?: number; @@ -7618,8 +9893,11 @@ interface QueueOptions { onFailed?: (job: Job, error: unknown) => void; /** Maximum jobs executed in one drain. Default: unlimited. */ concurrency?: number; + /** Maximum queued + active jobs. Adds reject once this limit is reached. */ + capacity?: number; /** Clock injection (tests). Default Date.now. */ now?: () => number; + context?: (job: Job, signal: AbortSignal) => ExecutionContext; } interface Queue { add(name: string, data: T, options?: AddOptions): Promise>; @@ -7628,10 +9906,16 @@ interface Queue { drain(now?: number): Promise; start(): void; stop(): void; + /** Stop accepting work and wait for active handlers (or abort them). */ + shutdown(options?: { + force?: boolean; + }): Promise; size(): number; get(id: string): Job | undefined; list(name?: string): Job[]; cancel(id: string): boolean; + failed(): Job[]; + retry(id: string): Promise; } interface JobDefinition { name: string; @@ -7651,7 +9935,7 @@ declare function defineWorkflow(name: string, steps: Array extends Signal { + undo(): boolean; + redo(): boolean; + canUndo(): boolean; + canRedo(): boolean; + clearHistory(): void; +} +declare function historySignal(initial: T, options?: { + limit?: number; + equals?: (left: T, right: T) => boolean; +}): HistorySignal; +interface UrlStateOptions { + url?: URL; + parameter: string; + parse?: (value: string | null) => T; + serialize?: (value: T) => string | null; + replace?: (url: URL) => void; +} +declare function urlSignal(initial: T, options: UrlStateOptions): Signal; +interface ReactiveContext { + provide(value: T, run: () => R): R; + use(): T; +} +declare function createContextProvider(defaultValue?: T): ReactiveContext; +declare function mountPortal(content: Node | string, target: Element): () => void; +declare function transition(update: () => void, options?: { + className?: string; + target?: Element; + durationMs?: number; + signal?: AbortSignal; +}): Promise; +interface TimelineStep { + durationMs: number; + delayMs?: number; + easing?: (progress: number) => number; + update(progress: number): void; +} +interface AnimationTimeline { + play(options?: { + reverse?: boolean; + signal?: AbortSignal; + }): Promise; + cancel(reason?: unknown): void; + readonly running: boolean; +} +declare function createTimeline(steps: TimelineStep[], options?: { + now?: () => number; + frame?: (callback: () => void) => unknown; +}): AnimationTimeline; + +export { type AnimationTimeline, type Cleanup, type HistorySignal, type ReactiveContext, type ReactiveScope, type ReadonlySignal, type Resource, type ResourceOptions, type ResourceStatus, type Signal, type Subscriber, type TimelineStep, type Unsubscribe, type UrlStateOptions, type WatchOptions, batch, computed, createContextProvider, createScope, createTimeline, effect, historySignal, mountPortal, resource, signal, transition, untrack, urlSignal, watch }; +``` + +--- + +## @wrnexus/realtime + +Documentation URL: https://wrnexusjs.dev/packages/realtime + +# @wrnexus/realtime + +Typed rooms, secure message envelopes, browser room helpers, presence utilities, and complete realtime UI blocks for WRNexusJS. + +## Server rooms + +```ts +import { defineRoom } from "@wrnexus/realtime"; + +export default defineRoom("support", { + async authorize(context) { + return Boolean(context.user); + }, + message(client, message) { + client.broadcast(message); + }, +}); +``` + +The package re-exports the hardened realtime registry from `@wrnexus/core`, including authentication, origin checks, quotas, message-size limits, schema validation hooks, and room authorization. + +## Messages and browser helpers + +```ts +import { + createRealtimeMessage, + createPresenceEvent, + createTypingEvent, + connectRoom, + sendRoomMessage, +} from "@wrnexus/realtime"; + +const room = connectRoom("support", { query: { ticket: "T-100" } }); +sendRoomMessage( + room, + createRealtimeMessage({ + type: "message", + room: "support", + data: { text: "Hello" }, + }), +); +``` + +Message IDs use Web Crypto. A runtime without secure randomness must provide an explicit message ID. + +## Components + +Enable `realtimePlugin()` and use: + +- `` +- `` +- `` +- `` +- `` +- `` +- `` + +These package-owned blocks compose existing `@wrnexus/ui` components such as `Card`, `Alert`, `Avatar`, `Badge`, `Button`, `Input`, and `ChatBubble`. + +Incoming messages can be bounded and constrained: + +```ts +const message = parseRealtimeMessage(rawMessage, { + maxBytes: 64 * 1024, + maxDepth: 12, + allowedTypes: ["message", "typing", "presence"], + room: "support", +}); +``` + +The parser rejects oversized payloads, circular/unsupported values, unsafe object keys, invalid message types, invalid room names, and room mismatches. + +## Replay, acknowledgements, SSE, and monitoring + +`createRealtimeHistory()` keeps a bounded sequenced log per room. Clients acknowledge a +sequence and `resume(room, clientId)` returns only missed events. A snapshot exposes room, +message, acknowledgement, and sequence counts for monitoring without exposing payloads. + +```ts +const history = createRealtimeHistory({ limitPerRoom: 100 }); +const entry = history.publish("support", message); +history.acknowledge("support", clientId, entry.sequence); +const missed = history.resume("support", clientId); +``` + +`realtimeSseResponse(stream, signal)` converts the same sequenced envelope into standards-based +Server-Sent Events with event IDs, event types, JSON data, cancellation, and no-cache headers. + +### Exported TypeScript declarations + +```ts +export { RawSocket, RealtimeBridge, RealtimeBus, RealtimeConnectMeta, RealtimeEnvelope, RealtimeHandler, RealtimeRegistry, RealtimeRegistryOptions, RealtimeSecurityOptions, RealtimeSocket, Room, RoomAuthInfo, RoomClient, RoomDefinition, RoomHandlers, Target, bridgeRealtime, createRealtimeRegistry, defineRoom, isRoomDefinition } from '@wrnexus/core'; +export { RealtimePluginOptions, realtimeComponentsDir, default as realtimePlugin } from './plugin.js'; +import '@wrnexus/plugin'; + +type RealtimeMessageType = string; +interface RealtimeMessage { + id: string; + type: RealtimeMessageType; + room?: string; + senderId?: string; + senderName?: string; + sentAt: string; + data: T; + meta?: Record; +} +interface CreateRealtimeMessageOptions { + id?: string; + type: string; + room?: string; + senderId?: string; + senderName?: string; + sentAt?: string | Date; + data: T; + meta?: Record; +} +interface ParseRealtimeMessageOptions { + maxBytes?: number; + maxDepth?: number; + allowedTypes?: readonly string[]; + room?: string; +} +interface RealtimePresence { + userId: string; + name?: string; + avatar?: string; + status?: "online" | "away" | "busy" | "offline"; + joinedAt?: string; + lastSeenAt?: string; + meta?: Record; +} +interface RealtimeRoomMeta { + id: string; + name: string; + description?: string; + memberCount?: number; + onlineCount?: number; + createdAt?: string; + updatedAt?: string; + private?: boolean; + tags?: string[]; +} +declare function assertRealtimeRoomName(name: string): string; +declare function createRealtimeMessage(options: CreateRealtimeMessageOptions): RealtimeMessage; +declare function isRealtimeMessage(value: unknown): value is RealtimeMessage; +declare function parseRealtimeMessage(value: string | unknown, options?: ParseRealtimeMessageOptions): RealtimeMessage; +declare function createPresenceEvent(action: "join" | "leave" | "update", presence: RealtimePresence, room?: string): RealtimeMessage<{ + action: "join" | "leave" | "update"; + presence: RealtimePresence; +}>; +declare function createTypingEvent(userId: string, typing: boolean, options?: { + room?: string; + name?: string; +}): RealtimeMessage<{ + userId: string; + name?: string; + typing: boolean; +}>; +declare function roomMemberSummary(members: readonly RealtimePresence[]): { + total: number; + online: number; + away: number; + busy: number; +}; + +interface BrowserRoomConnection { + readonly name: string; + send(message: unknown): BrowserRoomConnection; + on(type: string | ((message: unknown) => void), callback?: (message: unknown) => void): BrowserRoomConnection; + close(): void; +} +interface WrnexusRealtimeWindow extends Window { + wire?: { + room?: (name: string, query?: string) => BrowserRoomConnection; + }; +} +declare function roomQuery(params: Record): string; +declare function connectRoom(name: string, options?: { + query?: Record; + window?: WrnexusRealtimeWindow; +}): BrowserRoomConnection; +declare function sendRoomMessage(room: BrowserRoomConnection, message: RealtimeMessage | T): BrowserRoomConnection; + +interface SequencedRealtimeMessage { + sequence: number; + message: RealtimeMessage; +} +interface RealtimeHistorySnapshot { + rooms: number; + messages: number; + acknowledgements: number; + oldestSequence?: number; + latestSequence?: number; +} +interface RealtimeHistoryOptions { + limitPerRoom?: number; + maxClients?: number; +} +interface RealtimeHistory { + publish(room: string, message: RealtimeMessage): SequencedRealtimeMessage; + replay(room: string, afterSequence?: number, limit?: number): SequencedRealtimeMessage[]; + acknowledge(room: string, clientId: string, sequence: number): void; + acknowledged(room: string, clientId: string): number; + resume(room: string, clientId: string, limit?: number): SequencedRealtimeMessage[]; + snapshot(): RealtimeHistorySnapshot; + clear(room?: string): void; +} +declare function createRealtimeHistory(options?: RealtimeHistoryOptions): RealtimeHistory; +declare function createAcknowledgement(room: string, sequence: number, clientId: string): RealtimeMessage<{ + sequence: number; + clientId: string; +}>; +declare function realtimeSseResponse(stream: ReadableStream, signal?: AbortSignal): Response; + +interface DatabaseChange { + table: string; + operation: "insert" | "update" | "delete"; + key?: string | number; + record?: T; + occurredAt: number; +} +interface DatabaseChangeSource { + subscribe(handler: (change: DatabaseChange) => void | Promise): () => void; +} +declare function databaseChangeFeed(source: DatabaseChangeSource, publish: (topic: string, change: DatabaseChange) => void | Promise, options?: { + prefix?: string; + allowTables?: string[]; +}): () => void; +interface FileStreamFrame { + streamId: string; + index: number; + total: number; + bytes: Uint8Array; +} +declare function frameFileStream(streamId: string, bytes: Uint8Array, options?: { + chunkBytes?: number; + maxBytes?: number; +}): FileStreamFrame[]; +declare function createFileStreamReceiver(options?: { + maxBytes?: number; + maxStreams?: number; +}): { + accept(frame: FileStreamFrame): Uint8Array | null; + snapshot: () => { + activeStreams: number; + bufferedBytes: number; + }; +}; + +export { type BrowserRoomConnection, type CreateRealtimeMessageOptions, type DatabaseChange, type DatabaseChangeSource, type FileStreamFrame, type ParseRealtimeMessageOptions, type RealtimeHistory, type RealtimeHistoryOptions, type RealtimeHistorySnapshot, type RealtimeMessage, type RealtimeMessageType, type RealtimePresence, type RealtimeRoomMeta, type SequencedRealtimeMessage, type WrnexusRealtimeWindow, assertRealtimeRoomName, connectRoom, createAcknowledgement, createFileStreamReceiver, createPresenceEvent, createRealtimeHistory, createRealtimeMessage, createTypingEvent, databaseChangeFeed, frameFileStream, isRealtimeMessage, parseRealtimeMessage, realtimeSseResponse, roomMemberSummary, roomQuery, sendRoomMessage }; ``` --- @@ -8368,6 +10960,17 @@ interface ScriptAsset { attributes?: Record; } type RenderScript = string | ScriptAsset; +interface PartialPrerenderResult { + shell: string; + regions: Array<{ + id: string; + html: string; + }>; +} +/** Extract compiler-emitted dynamic regions into a cacheable static shell. */ +declare function partialPrerender(html: string, startIndex?: number): PartialPrerenderResult; +/** Stream the static shell first, followed by inert region templates for client insertion. */ +declare function streamPartialDocument(result: PartialPrerenderResult, nonce?: string): ReadableStream; interface RenderOptions { /** Page metadata for the document head. */ meta: PageMeta; @@ -8427,7 +11030,7 @@ interface StreamRenderOptions extends Omit { declare function renderDocumentStream(opts: StreamRenderOptions): ReadableStream; declare function streamDocumentResponse(opts: StreamRenderOptions, init?: ResponseInit): Response; -export { type RenderOptions, type RenderScript, type ScriptAsset, type StreamRenderOptions, extractWrnexusStyles, renderDocument, renderDocumentStream, streamDocumentResponse }; +export { type PartialPrerenderResult, type RenderOptions, type RenderScript, type ScriptAsset, type StreamRenderOptions, extractWrnexusStyles, partialPrerender, renderDocument, renderDocumentStream, streamDocumentResponse, streamPartialDocument }; ``` --- @@ -8438,9 +11041,9 @@ Documentation URL: https://wrnexusjs.dev/packages/store # @wrnexus/store -@wrnexus/store — part of the WrNexus framework. +Typed global and page-scoped WRNexusJS stores with runtime-specific state, computed values, actions, lifecycle hooks, persistence, SSR isolation, and HMR support. -Part of the WrNexus framework. +Use `defineStore()` to declare a store and `createStoreContainer()` to create an isolated request or browser container. Store definitions are framework helpers and do not require UI components. ### Exported TypeScript declarations @@ -8499,6 +11102,27 @@ Documentation URL: https://wrnexusjs.dev/packages/styles # @wrnexus/styles +## Reusable layers and presets + +Compose local or package foundations in order; later layers override earlier +ones and the application has final base-config precedence: + +```ts +export default defineConfig({ + extends: ["@workroot/wrnexus-enterprise", "./layers/company"], + profiles: { production: { port: 8080 } }, +}); +``` + +A directory layer exports `wrnexus.layer.ts` (JavaScript/MJS are supported). +A package can provide that conventional file or declare +`wrnexus.layer` in its `package.json`. Layers may extend other layers and carry +the complete app configuration, including plugins that contribute layouts, +components, routes, middleware, and migrations. `plugins` and `head` compose; +other arrays intentionally replace earlier values. Cycles and missing/invalid +entries fail with stable `WRN-CONFIG-LAYER-*` diagnostics. `wrnexus config +--explain` lists every resolved layer source. + > Global CSS bundling, the `--wire-*` design-token theme system, and the `wrnexus.config.ts` app-config loader for WrNexus apps. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. @@ -8754,7 +11378,7 @@ In templates, consume tokens via the custom properties: ```ts import { PerformanceBudgets, SeoConfig, SecurityConfig } from '@wrnexus/core'; -import { PluginInput } from '@wrnexus/plugin'; +import { PluginInput, PluginPermission } from '@wrnexus/plugin'; import { StorageConfig } from '@wrnexus/uploader'; /** @@ -8769,7 +11393,12 @@ import { StorageConfig } from '@wrnexus/uploader'; * present before the first paint. The reserved token key `color-scheme` is * emitted as the native CSS property instead of a custom property. */ -type ThemeTokens = Record; +type ThemeSemanticColor = "primary" | "secondary" | "info" | "success" | "warning" | "danger" | "error"; +type ThemeToken = "color-scheme" | "color-bg" | "color-background" | "color-foreground" | "color-surface" | "color-surface-2" | "color-surface-raised" | "color-surface-muted" | "color-text" | "color-text-muted" | "color-text-subtle" | "color-muted" | "color-border" | "color-border-strong" | "color-code-background" | "color-code-surface" | "color-code-text" | "color-code-muted" | "color-code-border" | `color-${ThemeSemanticColor}` | `color-${ThemeSemanticColor}-${"hover" | "active" | "contrast" | "soft" | "muted" | "text"}` | `color-on-${"primary" | "secondary"}` | "radius" | "radius-sm" | "shadow-1" | "shadow-sm" | "shadow-md" | "shadow-lg" | "space-section" | "space-section-sm" | "container-max" | "font-sans"; +/** Known tokens get autocomplete while applications may add namespaced custom tokens. */ +type ThemeTokens = Partial> & Record; +declare function defineThemeTokens(tokens: T): T; +declare function themeVar(token: ThemeToken, fallback?: string): string; declare const THEME_PALETTE_NAMES: readonly ["blue", "indigo", "violet", "emerald", "cyan", "rose", "amber", "slate"]; type ThemePaletteName = (typeof THEME_PALETTE_NAMES)[number]; /** Required semantic colors for a custom application palette. */ @@ -8923,6 +11552,26 @@ declare function fontCspSources(fonts?: FontConfig): { font: string[]; }; +declare const CURRENT_COMPATIBILITY_DATE = "2026-08-02"; +declare const CURRENT_FRAMEWORK_BEHAVIOUR = 1; +interface CompatibilityPolicy { + compatibilityDate?: string; + frameworkBehaviour?: number; +} +interface CompatibilityReport { + configuredDate?: string; + effectiveDate: string; + currentDate: string; + configuredBehaviour?: number; + effectiveBehaviour: number; + currentBehaviour: number; + needsUpgrade: boolean; + future: boolean; + messages: string[]; +} +declare function isCompatibilityDate(value: string): boolean; +declare function resolveCompatibility(policy: CompatibilityPolicy): CompatibilityReport; + /** * App configuration loader (`wrnexus.config.ts`). * @@ -9031,6 +11680,15 @@ interface PwaConfig { cacheUrls?: string[]; /** Service-worker cache key. Change it to invalidate existing PWA caches. */ cacheName?: string; + /** Ordered URL rules for runtime caching. Patterns are regular-expression source strings. */ + runtimeCaching?: Array<{ + pattern: string; + strategy: "network-first" | "cache-first" | "stale-while-revalidate"; + cacheName?: string; + methods?: string[]; + }>; + /** Background Sync tag used by the offline mutation queue. */ + backgroundSyncTag?: string; } type DevToolbarPosition = "bottom-center" | "bottom-left" | "bottom-right"; interface DevToolbarConfig { @@ -9126,9 +11784,16 @@ interface CompatibilityConfig { legacyComponentDiscovery?: boolean; stringLayouts?: boolean; } -interface AppConfig { +interface AppConfig extends CompatibilityPolicy { + /** Ordered reusable configuration layers; the application always has final precedence. */ + extends?: string | string[]; /** Compiler/dev/build plugins, resolved in deterministic pre/normal/post order. */ plugins?: PluginInput; + /** Optional least-privilege enforcement for automatically discovered packages. */ + pluginPermissions?: { + enforce?: boolean; + grants?: Record; + }; /** WRN v0.6 explicit import and compatibility resolution. */ imports?: ImportsConfig; /** TypeScript-backed .wrn type checking and declaration generation. */ @@ -9176,6 +11841,17 @@ interface AppConfig { i18n?: { default?: string; locales?: string[]; + labels?: Record; + fallbacks?: Record; + direction?: Record; + cookie?: { + name?: string; + maxAge?: number; + path?: string; + sameSite?: "Strict" | "Lax" | "None"; + secure?: boolean; + }; + strict?: boolean; }; /** Default database connection (driver + url); reached with `getDb()`. */ db?: { @@ -9225,6 +11901,11 @@ declare function resolveProfile(options?: { explicit?: string; mode?: Mode; }): string; +interface ResolvedConfigLayers { + config: AppConfig; + sources: string[]; +} +declare function resolveConfigLayers(appRoot: string, application: AppConfig): Promise; /** Load the raw `wrnexus.config.*` (with the `profiles` map intact), or `{}`. */ declare function loadRawConfig(appRoot: string): Promise; /** Load `wrnexus.config.*`, applying the active profile's overrides. */ @@ -9324,7 +12005,7 @@ declare function auditCssPerformance(source: string): CssPerformanceAuditIssue[] */ declare function renderStyles(ctx: StyleProcessContext, styles?: StylesConfig): Promise; -export { ACCENT_COOKIE, type AppConfig, type BuildConfig, type ConfigIssue, type ContrastResult, type CssPerformanceAuditIssue, type CssTokenAudit, type CustomThemePalette, DEFAULT_THEMES, type DevToolbarConfig, type ExperimentalConfig, type ExplainedConfig, type FontConfig, type FontDisplay, type GoogleFont, type LocalFontFace, type MobileConfig, type Mode, type NavigationConfig, type ObservabilityConfig, type PerformanceConfig, type PwaConfig, type ResolvedTheme, type StyleProcessContext, type StyleSource, type StylesConfig, type Mode as StylesMode, THEME_COOKIE, THEME_CSS_HREF, THEME_JS_HREF, THEME_PALETTES, THEME_PALETTE_NAMES, type TenancyConfig, type ThemeAccentConfig, type ThemeConfig, type ThemePaletteName, type ThemeTokens, auditCssPerformance, auditWireTokens, bundleCss, contrast, defineConfig, explainAppConfig, findStyleEntry, fontCspSources, headToString, loadAppConfig, loadEnv, loadRawConfig, normalizeStyleSources, renderFontHead, renderProductionFontHead, renderStyles, renderThemeCss, renderThemeRuntime, resolveAccentName, resolveProfile, resolveThemeConfig, resolveThemeName, tailwindSourceDirectives, validateAppConfig }; +export { ACCENT_COOKIE, type AppConfig, type BuildConfig, CURRENT_COMPATIBILITY_DATE, CURRENT_FRAMEWORK_BEHAVIOUR, type CompatibilityPolicy, type CompatibilityReport, type ConfigIssue, type ContrastResult, type CssPerformanceAuditIssue, type CssTokenAudit, type CustomThemePalette, DEFAULT_THEMES, type DevToolbarConfig, type ExperimentalConfig, type ExplainedConfig, type FontConfig, type FontDisplay, type GoogleFont, type LocalFontFace, type MobileConfig, type Mode, type NavigationConfig, type ObservabilityConfig, type PerformanceConfig, type PwaConfig, type ResolvedConfigLayers, type ResolvedTheme, type StyleProcessContext, type StyleSource, type StylesConfig, type Mode as StylesMode, THEME_COOKIE, THEME_CSS_HREF, THEME_JS_HREF, THEME_PALETTES, THEME_PALETTE_NAMES, type TenancyConfig, type ThemeAccentConfig, type ThemeConfig, type ThemePaletteName, type ThemeSemanticColor, type ThemeToken, type ThemeTokens, auditCssPerformance, auditWireTokens, bundleCss, contrast, defineConfig, defineThemeTokens, explainAppConfig, findStyleEntry, fontCspSources, headToString, isCompatibilityDate, loadAppConfig, loadEnv, loadRawConfig, normalizeStyleSources, renderFontHead, renderProductionFontHead, renderStyles, renderThemeCss, renderThemeRuntime, resolveAccentName, resolveCompatibility, resolveConfigLayers, resolveProfile, resolveThemeConfig, resolveThemeName, tailwindSourceDirectives, themeVar, validateAppConfig }; ``` --- @@ -9345,7 +12026,8 @@ See `docs/WRN-LANGUAGE-SPEC-1.0.md` in the WRNexusJS repository. ```ts export { LexError, Lexer } from './tokenizer.js'; -export { A as ActionBlock, a as ApiBlock, b as Attr, C as ComputedDecl, D as DataApiBlock, c as DataMode, E as EffectBlock, d as EventDecl, F as FunctionParameterDecl, e as FunctionRuntime, L as LifecycleBlock, f as LoadBlock, M as ModeFunctionsBlock, O as OutputDecl, P as PageAst, g as ParseError, h as PersistDecl, i as PropDecl, R as RealtimeBlock, j as RealtimeHandler, k as RuntimeFunctionDecl, S as SeoBlock, l as StateDecl, m as StateRuntime, n as StoreKind, o as StoreLifecycleDecl, p as StructuredImportDecl, V as VOID_ELEMENTS, q as ViewNode, W as WatchBlock, r as parse, s as parseComputedDeclarations, t as parseHtmlView, u as parseOutputs, v as parsePersist, w as parseRuntimeFunctions, x as parseStateDeclarations, y as parseStoreLifecycle, z as parseStructuredImports, B as stripRuntimeFunctionModifiers } from './parser-BGaF5Zdu.js'; +export { FormatWrnOptions, formatWrn } from './formatter.js'; +export { A as ActionBlock, a as ApiBlock, b as Attr, C as ComputedDecl, D as DataApiBlock, c as DataMode, E as EffectBlock, d as EventDecl, F as FunctionParameterDecl, e as FunctionRuntime, L as LifecycleBlock, f as LoadBlock, M as ModeFunctionsBlock, O as OutputDecl, P as PageAst, g as ParseError, h as PersistDecl, i as PropDecl, R as RealtimeBlock, j as RealtimeHandler, k as RuntimeFunctionDecl, S as SeoBlock, l as StateDecl, m as StateRuntime, n as StoreKind, o as StoreLifecycleDecl, p as StructuredImportDecl, V as VOID_ELEMENTS, q as ViewNode, W as WatchBlock, r as parse, s as parseComputedDeclarations, t as parseHtmlView, u as parseOutputs, v as parsePersist, w as parseRuntimeFunctions, x as parseStateDeclarations, y as parseStoreLifecycle, z as parseStructuredImports, B as stripRuntimeFunctionModifiers } from './parser-CTLO4mcT.js'; export { RuntimeType, eraseFunctionTypes, inferredRuntimeType, runtimeTypeOf, validateTypedInitializer } from './types.js'; import { WrnDiagnostic } from './diagnostics.js'; export { DiagnoseOptions, WrnDiagnosticSeverity, WrnSourcePosition, assertValidAst, classifyParseError, containsReadonlyPropMutation, diagnose, diagnosticFromError, formatDiagnostic, isHydrationStrategy, isRuntimeTarget, positionAt } from './diagnostics.js'; @@ -9483,6 +12165,22 @@ Remember to `await app.close()` when done. ## Usage +The CLI supports focused suites by file or directory convention: + +```bash +wrnexus test unit # *.unit.test.ts or test/unit/** +wrnexus test component # *.component.test.ts or test/component/** +wrnexus test api # *.api.test.ts or test/api/** +wrnexus test accessibility # *.a11y.test.ts / *.accessibility.test.ts +wrnexus test performance # *.performance.test.ts / *.benchmark.test.ts +wrnexus test browser # Playwright project when configured +wrnexus test visual # Playwright tests tagged @visual +``` + +Pass the application directory after the level, for example +`wrnexus test component examples/basic-app`. A focused command fails clearly when no matching +suite exists instead of silently running unrelated tests. + ```ts import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test"; @@ -9571,6 +12269,38 @@ declare class MemoryCookieJar { clear(): void; } +interface TransactionalDatabase { + tx(callback: (transaction: TransactionalDatabase) => Promise): Promise; +} +/** Run test work in a real transaction and always force rollback. */ +declare function withDatabaseRollback(db: TransactionalDatabase, run: (transaction: TransactionalDatabase) => T | Promise): Promise; +declare function createFactory>(build: (sequence: number) => T): { + build(overrides?: Partial): T; + buildMany(count: number, overrides?: Partial): T[]; + reset(): void; +}; +interface BrowserArtifactPage { + screenshot(options: { + path: string; + fullPage?: boolean; + }): Promise; + context(): { + tracing?: { + stop(options: { + path: string; + }): Promise; + }; + }; +} +declare function captureBrowserArtifacts(page: BrowserArtifactPage, testName: string, options?: { + root?: string; + screenshot?: boolean; + trace?: boolean; +}): Promise<{ + screenshot?: string; + trace?: string; +}>; + /** * @wrnexus/test — testing utilities for WrNexus apps. Runs on `bun test` (via * `wrnexus test`). Import everything from one place: @@ -9626,7 +12356,7 @@ interface HarnessOptions { */ declare function createHarness(projectRoot: string, options?: HarnessOptions): Promise; -export { type Deferred, type Harness, type HarnessOptions, type JsonResponse, MemoryCookieJar, type TestRequestOptions, type WaitForOptions, callRoute, createHarness, deferred, expectProblem, mountHtml, readJsonResponse, renderComponent, testContext, testRequest, waitFor }; +export { type BrowserArtifactPage, type Deferred, type Harness, type HarnessOptions, type JsonResponse, MemoryCookieJar, type TestRequestOptions, type TransactionalDatabase, type WaitForOptions, callRoute, captureBrowserArtifacts, createFactory, createHarness, deferred, expectProblem, mountHtml, readJsonResponse, renderComponent, testContext, testRequest, waitFor, withDatabaseRollback }; ``` --- @@ -9853,9 +12583,9 @@ Documentation URL: https://wrnexusjs.dev/packages/typecheck # @wrnexus/typecheck -@wrnexus/typecheck — part of the WrNexus framework. +Static type checking for `.wrn` declarations, props, state, outputs, functions, stores, and generated virtual TypeScript files. -Part of the WrNexus framework. +The package is compiler tooling rather than a browser UI package, so its public kit consists of programmatic typecheck helpers and diagnostics. ### Exported TypeScript declarations @@ -10310,6 +13040,11 @@ export const GET = serveFromStore("docs"); // your middleware decides who gets i ## API +Uploads can participate in security and media pipelines without changing storage drivers. Pass a +`scan` hook to reject malware/DLP findings before storage, and `afterStore` to enqueue image/video +processing or indexing. If post-processing throws, WRNexus deletes the newly written object so a +partially accepted upload is never left behind. + | Export | What | | --------------------------------------- | --------------------------------------------------------------- | | `handleUpload(opts)` | POST route handler → JSON `{ ok, files }` | @@ -10326,10 +13061,45 @@ export const GET = serveFromStore("docs"); // your middleware decides who gets i Live AWS/R2 connectivity depends on your credentials + bucket policy. - v1 buffers each file in memory up to its size cap (fine for images/docs up to tens of MB). +## Helper and component kit + +Use `formatFileSize`, `uploadAccept`, `uploadedFileMap`, `uploaderAttributes`, and `assertUploadedFiles` to keep upload forms and server validation consistent. + +Enable `uploaderPlugin()` for: + +- `` +- `` + +The complete blocks compose `Card`, `Alert`, and `Badge` from `@wrnexus/ui`; the specialized upload runtime remains responsible for the native file input and secure transport behavior. +Large files can use `createResumableUploadManager`. Sessions are bounded and +expiring; chunks may arrive out of order, carry SHA-256 checksums, and are +idempotent when retried. Conflicting retries reject, and the object is assembled +only after every exact-sized chunk is present. + +```ts +const uploads = createResumableUploadManager({ + driver: getStore("documents").driver, + sessions: redisUploadSessionStore, + chunkSize: 5 * 1024 * 1024, + maxBytes: 500 * 1024 * 1024, + accept: ["application/pdf"], +}); + +const session = await uploads.create({ name: "report.pdf", size, type }); +await uploads.uploadChunk(session.id, index, bytes, sha256); +``` + +The included memory session store is intended for one-process apps and tests. +Multi-instance production deployments should implement `ResumableSessionStore` +with shared durable storage and atomic session updates, and periodically call +`prune()` for abandoned uploads. + ### Exported TypeScript declarations ```ts import { Context } from '@wrnexus/core'; +export { UploaderPluginOptions, uploaderComponentsDir, default as uploaderPlugin } from './plugin.js'; +import '@wrnexus/plugin'; /** * Storage driver contract + config types. @@ -10459,6 +13229,25 @@ interface UploadOptions { accept?: string[]; /** Key prefix, e.g. `"avatars"` → keys become `avatars///.`. */ prefix?: string; + /** Virus/DLP/content scanner invoked before bytes enter storage. Throw or return unsafe to reject. */ + scan?: (file: UploadScanInput) => UploadScanResult | Promise; + /** Image/video/indexing hook invoked after storage. Failure removes the just-written object. */ + afterStore?: (file: UploadedFile & { + bytes: Uint8Array; + store: Store; + }) => void | Promise; +} +interface UploadScanInput { + name: string; + type: string; + size: number; + bytes: Uint8Array; + store: Store; +} +interface UploadScanResult { + safe: boolean; + reason?: string; + scanner?: string; } /** A 4xx-carrying error so `handleUpload` can map it to a status. */ declare class UploadError extends Error { @@ -10633,7 +13422,145 @@ interface SignedFileToken { declare function createSignedFileToken(input: SignedFileToken, secret: string): Promise; declare function verifySignedFileToken(token: string, secret: string, now?: number): Promise; -export { type LocalStoreConfig, type PutMeta, type S3StoreConfig, type SignedFileToken, type StorageConfig, type StorageDriver, type Store, type StoreAccess, type StoreConfig, type StoredObject, UPLOADS_PREFIX, UPLOAD_JS_HREF, UPLOAD_RUNTIME, UploadError, type UploadInspection, type UploadOptions, type UploadPolicy, UploadPolicyError, type UploadedFile, accepts, configureStorage, contentTypeOf, createSignedFileToken, encodeKey, enforceUploadPolicy, extForType, extOf, getStore, handleUpload, hasStorage, inspectUpload, localDriver, s3Driver, safeObjectKey, serveFromStore, serveStoredFile, sha256Hex, signS3, sniffContentType, storeNames, storedUrl, upload, verifySignedFileToken }; +declare function formatFileSize(bytes: number, locale?: string): string; +declare function uploadAccept(value: string | readonly string[]): string; +declare function uploadedFileMap(files: readonly UploadedFile[]): Record; +declare function uploaderAttributes(options?: { + store?: string; + endpoint?: string; + accept?: string | readonly string[]; + maxBytes?: number; + multiple?: boolean; + field?: string; + label?: string; +}): Record; +declare function assertUploadedFiles(files: readonly UploadedFile[], options?: { + min?: number; + max?: number; +}): readonly UploadedFile[]; + +interface ResumableUploadSession { + id: string; + key: string; + name: string; + type: string; + size: number; + chunkSize: number; + totalChunks: number; + createdAt: number; + expiresAt: number; + chunks: Record; + digests: Record; +} +interface ResumableSessionStore { + get(id: string): Promise; + put(session: ResumableUploadSession): Promise; + delete(id: string): Promise; + list(): Promise; +} +declare function memoryResumableSessionStore(): ResumableSessionStore; +interface ResumableUploadManagerOptions { + driver: StorageDriver; + sessions?: ResumableSessionStore; + maxBytes?: number; + chunkSize?: number; + maxSessions?: number; + ttlMs?: number; + accept?: string[]; + prefix?: string; + publicUrl?: (key: string) => string | null; + now?: () => number; +} +interface CreateResumableUpload { + name: string; + type?: string; + size: number; + chunkSize?: number; +} +interface ResumableChunkResult { + receivedChunks: number; + totalChunks: number; + complete: boolean; + file?: UploadedFile; +} +interface ResumableUploadManager { + create(input: CreateResumableUpload): Promise; + uploadChunk(id: string, index: number, data: Uint8Array, sha256?: string): Promise; + status(id: string): Promise<{ + received: number[]; + totalChunks: number; + expiresAt: number; + } | null>; + cancel(id: string): Promise; + prune(): Promise; +} +declare function createResumableUploadManager(options: ResumableUploadManagerOptions): ResumableUploadManager; + +interface QuotaUsage { + owner: string; + bytes: number; + objects: number; + updatedAt: number; +} +interface QuotaStore { + get(owner: string): Promise; + reserve(owner: string, bytes: number, limits: { + bytes: number; + objects?: number; + }): Promise; + release(owner: string, bytes: number): Promise; +} +declare function memoryQuotaStore(): QuotaStore; +interface QuotaSqlClient { + query(sql: string, parameters?: unknown[]): Promise<{ + rows: T[]; + }>; +} +/** PostgreSQL quota accounting using a single atomic conditional upsert. */ +declare function postgresQuotaStore(db: QuotaSqlClient, table?: string): QuotaStore; +declare const POSTGRES_QUOTA_SCHEMA = "CREATE TABLE IF NOT EXISTS wrnexus_storage_quota (owner text PRIMARY KEY, bytes bigint NOT NULL DEFAULT 0, objects integer NOT NULL DEFAULT 0, updated_at bigint NOT NULL);"; +interface MultipartObjectClient { + create(key: string, meta: PutMeta): Promise; + uploadPart(uploadId: string, key: string, part: number, bytes: Uint8Array): Promise; + complete(uploadId: string, key: string, parts: Array<{ + part: number; + etag: string; + }>): Promise; + abort(uploadId: string, key: string): Promise; +} +declare function multipartUpload(client: MultipartObjectClient, key: string, bytes: Uint8Array, meta: PutMeta, options?: { + partBytes?: number; + concurrency?: number; +}): Promise; +interface TemporaryObject { + key: string; + expiresAt: number; +} +declare function createTemporaryObjectCleaner(driver: StorageDriver, options?: { + now?: () => number; + limit?: number; +}): { + track(key: string, ttlMs: number): void; + cleanup(at?: number): Promise; + snapshot: () => { + tracked: number; + nextExpiry: number | undefined; + }; +}; +interface VideoTranscodeOptions { + format: "mp4" | "webm"; + width?: number; + height?: number; + videoBitrateKbps?: number; +} +declare function ffmpegVideoTranscoder(options?: { + executable?: string; + spawn?: (args: string[]) => { + exited: Promise; + }; +}): (input: string, output: string, config: VideoTranscodeOptions) => Promise; + +export { type CreateResumableUpload, type LocalStoreConfig, type MultipartObjectClient, POSTGRES_QUOTA_SCHEMA, type PutMeta, type QuotaSqlClient, type QuotaStore, type QuotaUsage, type ResumableChunkResult, type ResumableSessionStore, type ResumableUploadManager, type ResumableUploadManagerOptions, type ResumableUploadSession, type S3StoreConfig, type SignedFileToken, type StorageConfig, type StorageDriver, type Store, type StoreAccess, type StoreConfig, type StoredObject, type TemporaryObject, UPLOADS_PREFIX, UPLOAD_JS_HREF, UPLOAD_RUNTIME, UploadError, type UploadInspection, type UploadOptions, type UploadPolicy, UploadPolicyError, type UploadScanInput, type UploadScanResult, type UploadedFile, type VideoTranscodeOptions, accepts, assertUploadedFiles, configureStorage, contentTypeOf, createResumableUploadManager, createSignedFileToken, createTemporaryObjectCleaner, encodeKey, enforceUploadPolicy, extForType, extOf, ffmpegVideoTranscoder, formatFileSize, getStore, handleUpload, hasStorage, inspectUpload, localDriver, memoryQuotaStore, memoryResumableSessionStore, multipartUpload, postgresQuotaStore, s3Driver, safeObjectKey, serveFromStore, serveStoredFile, sha256Hex, signS3, sniffContentType, storeNames, storedUrl, upload, uploadAccept, uploadedFileMap, uploaderAttributes, verifySignedFileToken }; ``` --- @@ -10648,6 +13575,31 @@ Documentation URL: https://wrnexusjs.dev/packages/validation Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. +## Boundary contracts + +Use `ContractRegistry` with `defineContract` or `defineEvent` to publish the +same schema descriptors for APIs, actions, webhooks, realtime, queues, cron, +pub/sub, plugins, configuration, and environment variables. + +```ts +import { ContractRegistry, defineEvent, v } from "@wrnexus/validation"; + +export const contracts = new ContractRegistry().register( + defineEvent({ + name: "user.created", + version: 1, + consumers: ["notification-worker", "audit-service"], + payload: v.object({ userId: v.string().uuid(), createdAt: v.string().date() }), + }), +); +``` + +Export the registry from `app/contracts.ts`, then accept a baseline with +`wrnexus contracts snapshot`. CI can run `wrnexus contracts check`; removed +contracts/fields, required-field additions, type changes, narrowed enums, and +tighter validation fail with stable `WRN-CONTRACT-*` diagnostics and list known +consumers. A generated `wrnexus.contracts.json` can be used instead of a module. + ## Overview Define a schema once with the fluent `v` builder, then reuse it in three places: `.parse()` runs server-side and returns coerced values plus per-field errors; `.describe()` emits a plain-JSON `SchemaDescriptor` that the browser runtime interprets (no `eval`, no bundled validator); and helpers like `parseBody` and `parseEnv` wire schemas straight into API routes and startup config. The server rule logic (`applyRule`/`checkField`) and the client runtime (`VALIDATE_RUNTIME`) mirror each other exactly, so a form validates identically in both places. Schemas are conventionally kept in `app/schemas/`. @@ -10823,9 +13775,64 @@ const head = `