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

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
+50
View File
@@ -0,0 +1,50 @@
name: Quality
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
quality:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.14
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: editors/vscode/package-lock.json
- name: Install framework dependencies
run: bun install --frozen-lockfile
- name: Install editor dependencies
run: npm ci --prefix editors/vscode
- name: Typecheck
run: bun run typecheck
- name: Lint
run: bun run lint
- name: Formatting
run: bun run format:check
- name: Package and application tests
run: bun run test:all
- name: Package contracts
run: bun run check:public-api && bun run check:ui-visual && bun run audit:packages && bun run test:package-kits && bun run validate:staging
- name: Stage and test publishable packages
if: matrix.os == 'ubuntu-latest'
run: bun run stage:packages && bun run test:staged-consumers
- name: Framework validation
run: bun run validate:0.8
- name: Dependency audit
run: bun audit
- name: Editor dependency audit
run: npm audit --prefix editors/vscode --audit-level=high
+3
View File
@@ -0,0 +1,3 @@
@wrnexus:registry=https://registry.npmjs.org/
audit=true
fund=false
+5
View File
@@ -10,9 +10,14 @@ bun.lockb
# Generated code (queries.gen.ts, routes.gen.ts, etc.) # Generated code (queries.gen.ts, routes.gen.ts, etc.)
**/*.gen.ts **/*.gen.ts
**/*.generated.d.ts
# Bundled .wire compiler for the VS Code extension (generated) # Bundled .wire compiler for the VS Code extension (generated)
editors/vscode/src/compiler.cjs editors/vscode/src/compiler.cjs
editors/vscode/src/language-server.cjs
editors/vscode/src/extension.bundle.cjs
docs/public-api-0.8.json
docs/ui-visual-contract-0.8.json
*.svg *.svg
**/.vscodeignore **/.vscodeignore
+32
View File
@@ -1,5 +1,9 @@
# @wrnexus/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. > 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. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.
@@ -120,6 +124,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 ## Usage
### Return generated JSON from an API route ### Return generated JSON from an API route
+23 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/ai", "name": "@wrnexus/ai",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.", "description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/ai"
},
"homepage": "https://wrnexusjs.dev/packages/ai",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"ai"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -18,9 +34,14 @@
".": { ".": {
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"import": "./dist/index.js" "import": "./dist/index.js"
},
"./platform": {
"types": "./dist/platform.d.ts",
"import": "./dist/platform.js"
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/authz", "name": "@wrnexus/authz",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/authz — part of the WrNexus framework.", "description": "@wrnexus/authz — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/authz"
},
"homepage": "https://wrnexusjs.dev/packages/authz",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"authz"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,6 +37,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+54 -2
View File
@@ -1,5 +1,18 @@
# @wrnexus/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. > 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. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.
@@ -26,6 +39,30 @@ bunx wrnexus dev
## Commands ## 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)). Every command accepts an optional `[app-dir]` (defaults to `.`). Commands that read config or `.env` also accept `--profile=<name>` (see [Profiles](#profiles)).
| Command | Purpose | | Command | Purpose |
@@ -46,10 +83,17 @@ Every command accepts an optional `[app-dir]` (defaults to `.`). Commands that r
| `wrnexus db <cmd>` | Database migrations and tooling (see [db](#wrnexus-db)). | | `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 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 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 help` | Print usage. |
`wrnexus g` is an alias for `wrnexus generate`. `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` ### `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`). 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`).
@@ -76,7 +120,9 @@ bun dist/server.js # PORT env var optional
### `wrnexus create` ### `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`
@@ -162,7 +208,7 @@ wrnexus db status --db=analytics
### `wrnexus workspace` and `wrnexus gateway` ### `wrnexus workspace` and `wrnexus gateway`
`workspace <name>` 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 <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.
```bash ```bash
wrnexus workspace acme wrnexus workspace acme
@@ -241,6 +287,12 @@ wrnexus update --latest
wrnexus doctor 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 ## 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`. 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`.
+36 -14
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/cli", "name": "@wrnexus/cli",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/cli — part of the WrNexus framework.", "description": "@wrnexus/cli — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/cli"
},
"homepage": "https://wrnexusjs.dev/packages/cli",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"cli"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -28,20 +44,26 @@
"wrnexus": "./dist/index.js" "wrnexus": "./dist/index.js"
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0", "@wrnexus/core": "^0.8.0",
"@wrnexus/router": "^0.7.0", "@wrnexus/router": "^0.8.0",
"@wrnexus/csr": "^0.7.0", "@wrnexus/csr": "^0.8.0",
"@wrnexus/compiler": "^0.7.0", "@wrnexus/compiler": "^0.8.0",
"@wrnexus/styles": "^0.7.0", "@wrnexus/styles": "^0.8.0",
"@wrnexus/dev-server": "^0.7.0", "@wrnexus/dev-server": "^0.8.0",
"@wrnexus/ui": "^0.7.0", "@wrnexus/ui": "^0.8.0",
"@wrnexus/validation": "^0.7.0", "@wrnexus/validation": "^0.8.0",
"@wrnexus/i18n": "^0.7.0", "@wrnexus/i18n": "^0.8.0",
"@wrnexus/db": "^0.7.0", "@wrnexus/mcp": "^0.8.0",
"@wrnexus/plugin": "^0.7.0", "@wrnexus/playground": "^0.8.0",
"@wrnexus/syntax": "^0.7.0" "@wrnexus/db": "^0.8.0",
"@wrnexus/plugin": "^0.8.0",
"@wrnexus/syntax": "^0.8.0",
"@wrnexus/typecheck": "^0.8.0",
"@wrnexus/security": "^0.8.0",
"selfsigned": "^5.5.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+35
View File
@@ -1,9 +1,44 @@
# @wrnexus/compiler # @wrnexus/compiler
## 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. > 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. 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 {
<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 ## 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. `@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.
+23 -4
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/compiler", "name": "@wrnexus/compiler",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/compiler — part of the WrNexus framework.", "description": "@wrnexus/compiler — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/compiler"
},
"homepage": "https://wrnexusjs.dev/packages/compiler",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"compiler"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,10 +37,13 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/syntax": "^0.7.0", "@wrnexus/csr": "^0.8.0",
"@wrnexus/store": "^0.7.0" "@wrnexus/syntax": "^0.8.0",
"@wrnexus/store": "^0.8.0",
"@wrnexus/validation": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+31
View File
@@ -110,6 +110,37 @@ instances. The default store is process-local memory.
(default `console.log`), `requestIdKey` (default `"requestId"`), `now`. (default `console.log`), `requestIdKey` (default `"requestId"`), `now`.
`RequestRecord` = `{ time, id, method, path, status, durationMs }`. `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` ### Caching — `@wrnexus/core`
| Export | Kind | Notes | | Export | Kind | Notes |
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/core", "name": "@wrnexus/core",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/core — part of the WrNexus framework.", "description": "@wrnexus/core — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/core"
},
"homepage": "https://wrnexusjs.dev/packages/core",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"core"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -29,6 +45,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+36 -2
View File
@@ -1,5 +1,34 @@
# @wrnexus/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<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 WrNexus — generic, self-contained JS that hydrates server-rendered pages with reactivity, client-side navigation, and realtime rooms. > 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. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.
@@ -50,11 +79,16 @@ 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. 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 | | Directive | Purpose |
| -------------------------------------------------------- | ----------------------------------------------------------------------- | | ---------------------------------- | ---------------------------------------------------- |
| `data-scope="count: 0, name: 'x'"` | Declare reactive state on a subtree | | `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-on-<event>="count++"` | Run a statement in scope on a DOM event |
| `data-text="expr"` | Bind an element's `textContent` to an expression | | `data-text="expr"` | Bind an element's `textContent` to an expression |
| `data-show="expr"` | Toggle visibility (`display`) on truthiness | | `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-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 | | `data-key="item.id"` | Alternative key declaration for `data-for` templates |
| `{{expr}}` or `{expr}` | Interpolation inside text nodes and attribute values | | `{{expr}}` or `{expr}` | Interpolation inside text nodes and attribute values |
+20 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/csr", "name": "@wrnexus/csr",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/csr — part of the WrNexus framework.", "description": "@wrnexus/csr — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/csr"
},
"homepage": "https://wrnexusjs.dev/packages/csr",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"csr"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,9 +37,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0" "@wrnexus/core": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+75 -4
View File
@@ -1,5 +1,14 @@
# @wrnexus/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. > 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. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.
@@ -85,7 +94,8 @@ A `Driver` (implemented by adapters) exposes `dialect`, `query(sql, params?)`,
- `exec(sql, params?)``Promise<ExecResult>` (`{ changes, lastInsertId? }`). - `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. - `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. - `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?)` Every query is parameterized (positional params). `createTableSql(model, dialect, ifNotExists?)`
renders `CREATE TABLE` directly; `Dialect` is `"sqlite" | "postgres" | "mysql"`. renders `CREATE TABLE` directly; `Dialect` is `"sqlite" | "postgres" | "mysql"`.
@@ -98,7 +108,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. - `setDb(db)` / `setDb(name, db)` — set the default or a named connection.
- `registerDb(name, db)` — alias of `setDb(name, db)`. - `registerDb(name, db)` — alias of `setDb(name, db)`.
- `getDb(name = "default")` — the default or a named `Db` (throws if unconfigured). - `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 ```ts
const users = await getDb().all("SELECT * FROM users"); const users = await getDb().all("SELECT * FROM users");
@@ -121,8 +133,8 @@ Migrations are `.sql` files (in e.g. `app/db/migrations`), each split into
- `parseMigration(name, content)``Migration` (`{ name, up, down }`). - `parseMigration(name, content)``Migration` (`{ name, up, down }`).
- `loadMigrations(dir)` — parse all `.sql` files, sorted by filename. - `loadMigrations(dir)` — parse all `.sql` files, sorted by filename.
- `appliedMigrations(db)` — applied names, oldest first. - `appliedMigrations(db)` — applied names, oldest first.
- `migrate(db, dir)` — apply all pending (each in a transaction); returns applied names. - `migrate(db, dir, options?)` — apply all pending (each in a transaction); returns applied names.
- `rollback(db, dir)` — roll back the most recent; returns its name or `null`. - `rollback(db, dir, options?)` — roll back the most recent; returns its name or `null`.
- `status(db, dir)``{ name, applied }[]` for every migration file. - `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. - `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.
@@ -199,6 +211,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): MongoDB (document API):
```ts ```ts
@@ -226,3 +253,47 @@ SQL driver — use `@wrnexus/db/mongo` directly.
`wrnexus.config.ts`. `wrnexus.config.ts`.
- The `mongodb` npm package is an optional, lazily-imported peer — install it - 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. 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<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
```ts
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.
+20 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/db", "name": "@wrnexus/db",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/db — part of the WrNexus framework.", "description": "Typed database drivers, migrations, instrumentation, repositories, pagination, and transaction helpers.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/db"
},
"homepage": "https://wrnexusjs.dev/packages/db",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"db"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -45,6 +61,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+9 -1
View File
@@ -66,6 +66,12 @@ interface RunningServer {
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. 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)` ### `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). 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).
@@ -296,7 +302,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`. - **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). - 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`. - 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> </content>
+38 -19
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/dev-server", "name": "@wrnexus/dev-server",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/dev-server — part of the WrNexus framework.", "description": "@wrnexus/dev-server — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/dev-server"
},
"homepage": "https://wrnexusjs.dev/packages/dev-server",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"dev-server"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -25,25 +41,28 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0", "@wrnexus/core": "^0.8.0",
"@wrnexus/dev-toolbar": "^0.7.0", "@wrnexus/dev-toolbar": "^0.8.0",
"@wrnexus/router": "^0.7.0", "@wrnexus/router": "^0.8.0",
"@wrnexus/ssr": "^0.7.0", "@wrnexus/ssr": "^0.8.0",
"@wrnexus/csr": "^0.7.0", "@wrnexus/csr": "^0.8.0",
"@wrnexus/compiler": "^0.7.0", "@wrnexus/compiler": "^0.8.0",
"@wrnexus/styles": "^0.7.0", "@wrnexus/styles": "^0.8.0",
"@wrnexus/ui": "^0.7.0", "@wrnexus/ui": "^0.8.0",
"@wrnexus/validation": "^0.7.0", "@wrnexus/validation": "^0.8.0",
"@wrnexus/i18n": "^0.7.0", "@wrnexus/i18n": "^0.8.0",
"@wrnexus/db": "^0.7.0", "@wrnexus/db": "^0.8.0",
"@wrnexus/pubsub": "^0.7.0", "@wrnexus/pubsub": "^0.8.0",
"@wrnexus/uploader": "^0.7.0", "@wrnexus/uploader": "^0.8.0",
"@wrnexus/plugin": "^0.7.0", "@wrnexus/plugin": "^0.8.0",
"@wrnexus/store": "^0.7.0", "@wrnexus/store": "^0.8.0",
"@wrnexus/security": "^0.7.0", "@wrnexus/security": "^0.8.0",
"@wrnexus/observability": "^0.7.0" "@wrnexus/observability": "^0.8.0",
"@wrnexus/cache": "^0.8.0",
"@wrnexus/pwa": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+7
View File
@@ -7,6 +7,9 @@ Development-only page quality toolbar for WRNexusJS.
- Runtime, resource and unhandled promise error capture - Runtime, resource and unhandled promise error capture
- Accessibility, SEO, image, media, color, HTML, form, link, responsive and security checks - Accessibility, SEO, image, media, color, HTML, form, link, responsive and security checks
- Performance and network observations - 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 - Element highlighting and issue filtering
- Server-side issue collector - Server-side issue collector
- Development-only asset strings for direct serving by `@wrnexus/dev-server` - Development-only asset strings for direct serving by `@wrnexus/dev-server`
@@ -21,3 +24,7 @@ Serve `DEV_TOOLBAR_RUNTIME` at `/__wrnexus/dev-toolbar.js` and `DEV_TOOLBAR_CSS`
``` ```
The browser runtime exposes `window.__wrnexusDevToolbar`. 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.
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/dev-toolbar", "name": "@wrnexus/dev-toolbar",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/dev-toolbar — part of the WrNexus framework.", "description": "@wrnexus/dev-toolbar — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/dev-toolbar"
},
"homepage": "https://wrnexusjs.dev/packages/dev-toolbar",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"dev-toolbar"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -37,6 +53,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+50 -63
View File
@@ -1,80 +1,67 @@
# @wrnexus/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). ## Encrypted HTTP envelope
## 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<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:
- `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:
```ts ```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 replayStore = createMemoryReplayStore();
const plain = await decrypt(box, key); // "card #1234"
// 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 - HTTP method
import { deriveKey, encrypt } from "@wrnexus/encryption"; - 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"); `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.
const box = await encrypt("secret note", key);
```
Hashing and webhook signature verification: ## Security boundary
```ts Encrypted HTTP bodies **do not replace TLS/HTTPS**. Always use HTTPS.
import { sha256, hmacSign, hmacVerify } from "@wrnexus/encryption";
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); Use a shared replay store such as Redis in multi-instance deployments. The memory replay store is process-local.
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.
+23 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/encryption", "name": "@wrnexus/encryption",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/encryption — part of the WrNexus framework.", "description": "Authenticated encryption, key rotation, hashing, and optional application-layer encrypted HTTP envelopes.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/encryption"
},
"homepage": "https://wrnexusjs.dev/packages/encryption",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"encryption"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -20,7 +36,11 @@
"import": "./dist/index.js" "import": "./dist/index.js"
} }
}, },
"dependencies": {
"@wrnexus/core": "^0.8.0"
},
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+20 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/helpers", "name": "@wrnexus/helpers",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "Safe convenience helpers for WrNexus request contexts and common application flows.", "description": "Safe convenience helpers for WrNexus request contexts and common application flows.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/helpers"
},
"homepage": "https://wrnexusjs.dev/packages/helpers",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"helpers"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,9 +37,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0" "@wrnexus/core": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+60 -134
View File
@@ -1,167 +1,93 @@
# @wrnexus/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/<lang>.json`, resolves the ```text
active language for each request (cookie → `Accept-Language` → default), and app/locales/en.json
builds a `t(key, params)` translator used both in server code and in `.wrn` app/locales/en/common.json
views. It also ships Intl-based formatting helpers and a tiny client runtime that app/locales/en/auth.json
wires up a language switcher. Translation lookup, language resolution, and HTML app/locales/mr/common.json
marker rewriting run server-side; only the small `I18N_RUNTIME` snippet runs in
the browser.
## Installation
```bash
bun add @wrnexus/i18n
``` ```
> Private package — the machine must be authenticated to the `wrnexus` npm org Namespaced files become keys such as `common.save` and `auth.signIn`.
> (a read token in `~/.npmrc`). Requires **Bun** (Node is not supported).
## API
### Loading & resolving
| Export | Signature | Description |
| ------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `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) => 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<string, unknown>` — a locale's messages (supports nested/dotted keys). |
| `I18nConfig` | `interface` | `{ default?: string; locales?: string[] }`. |
| `ResolvedI18n` | `interface` | `{ default: string; langs: string[]; messages: Record<string, Messages> }`. |
| `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:<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) => 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<Record<Intl.LDMLPluralRule, string>>, lang: string) => string` | picks CLDR form; `#` is replaced by `count` |
## Usage
### Server: load, resolve, translate
```ts ```ts
import { import { loadLocales, makeT, resolveI18n, resolveLang } from "@wrnexus/i18n";
loadLocales,
resolveI18n,
resolveLang,
makeT,
translateHtml,
LANG_COOKIE,
} from "@wrnexus/i18n";
// app/locales/en.json, app/locales/es.json const i18n = resolveI18n(loadLocales("app/locales", { strict: true }), {
const messages = loadLocales("app/locales"); default: "en",
const i18n = resolveI18n(messages, { default: "en", locales: ["en", "es"] }); locales: ["en", "mr", "hi"],
fallbacks: { "mr-IN": ["mr", "en"] },
cookie: { name: "wire-lang", sameSite: "Lax", secure: true },
});
// Per request: const lang = resolveLang(i18n, cookieValue, request.headers.get("accept-language"));
const lang = resolveLang(i18n, req.cookies?.[LANG_COOKIE], req.headers.get("accept-language"));
const t = makeT(i18n, lang); const t = makeT(i18n, lang);
t("common.hello", { name: "Ajay" });
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`: ## Resolution behavior
```json - normalized BCP-47-style locale names
{ - cookie preference
"nav": { "home": "Home" }, - weighted `Accept-Language`
"greeting": "Hello, {name}" - 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 ```html
<h1 data-t="nav.home">Home</h1> <h1 data-t="dashboard.title">Dashboard</h1>
<input t:placeholder="search.placeholder" /> <input t:placeholder="search.placeholder" />
``` ```
`translateHtml` replaces the element text for `data-t` and the attribute value for 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.
any `t:<attr>` (e.g. `t:placeholder`, `t:aria-label`).
### Client: language switcher Enable `i18nPlugin()` to use:
```ts - `<LanguageSwitcher />`
import { renderI18nData, I18N_RUNTIME, I18N_JS_HREF } from "@wrnexus/i18n"; - `<LocaleStatus />`
// In the document <head>: `LanguageSwitcher` renders a native `select[data-wire-lang]`. The packaged runtime validates the
const head = ` selection against the configured locales, writes the configured language cookie, updates the
<script>${renderI18nData(i18n, lang)}</script> document `lang`/`dir` attributes, emits `wrnexus:language-change`, and reloads so the next SSR
<script src="${I18N_JS_HREF}"></script> request uses the same cookie. No application-owned browser script is required.
`;
// Serve I18N_RUNTIME at I18N_JS_HREF; then in markup: ## Formatting
// <button data-wire-lang-set="es">Español</button>
// <select data-wire-lang>…</select>
```
### 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 ```ts
import { import {
formatNumber, auditLocaleKeys,
formatCurrency, createPseudoLocale,
formatDate, extractTranslationKeysFromFiles,
formatRelativeTime,
plural,
} from "@wrnexus/i18n"; } from "@wrnexus/i18n";
formatNumber(1234.5, lang); // "1,234.5" const used = extractTranslationKeysFromFiles(sourceFiles);
formatCurrency(9.99, "USD", lang); // "$9.99" const coverage = auditLocaleKeys(messages, "en");
formatDate(Date.now(), lang); // "Jul 4, 2026" const enXA = createPseudoLocale(messages.en);
formatRelativeTime(-3, "day", lang); // "3 days ago" const arXB = createPseudoLocale(messages.en, { rtl: true });
plural(2, { one: "# item", other: "# items" }, lang); // "2 items"
``` ```
## Configuration Pseudo-localization preserves interpolation placeholders and markup tags. RTL
pseudo output uses Unicode direction controls, while runtime direction detection
`resolveI18n` accepts an `I18nConfig`: continues to derive `rtl` from Arabic and other RTL language subtags.
- `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.
+37 -5
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/i18n", "name": "@wrnexus/i18n",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/i18n — part of the WrNexus framework.", "description": "Locale loading, fallback resolution, SSR/browser translations, formatters, and WRNexusJS language components.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/i18n"
},
"homepage": "https://wrnexusjs.dev/packages/i18n",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"i18n"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -18,12 +34,28 @@
".": { ".": {
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"import": "./dist/index.js" "import": "./dist/index.js"
} },
"./plugin": {
"types": "./dist/plugin.d.ts",
"import": "./dist/plugin.js"
},
"./components/*": "./components/*"
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0" "@wrnexus/core": "^0.8.0",
"@wrnexus/plugin": "^0.8.0",
"@wrnexus/ui": "^0.8.0"
},
"wrnexus": {
"plugin": {
"plugin": "./dist/plugin.js",
"export": "default",
"factory": true
}
}, },
"files": [ "files": [
"dist" "dist",
"README.md",
"components"
] ]
} }
+59
View File
@@ -130,3 +130,62 @@ app.use(jwtAuth({ secret: process.env.JWT_SECRET!, required: false }));
- Integrates with [`@wrnexus/core`](../core) for `Context`, `Middleware`, and - Integrates with [`@wrnexus/core`](../core) for `Context`, `Middleware`, and
`ctx.user`; it complements the framework's cookie/session auth with a `ctx.user`; it complements the framework's cookie/session auth with a
stateless bearer-token flow for API and mobile clients. 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.
+23 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/jwt", "name": "@wrnexus/jwt",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/jwt — part of the WrNexus framework.", "description": "HS256 JSON Web Tokens, key rotation, access/refresh helpers, scopes, cookies, and auth middleware.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/jwt"
},
"homepage": "https://wrnexusjs.dev/packages/jwt",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"jwt"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -20,7 +36,11 @@
"import": "./dist/index.js" "import": "./dist/index.js"
} }
}, },
"dependencies": {
"@wrnexus/core": "^0.8.0"
},
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+8
View File
@@ -76,6 +76,14 @@ const status = network ? await network.getStatus() : { connected: true, connecti
Unavailable required plugins throw `MobileUnavailableError` with an actionable message. 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 ## Requirements / Notes
- Capacitor plugin imports must remain in browser-owned modules. - Capacitor plugin imports must remain in browser-owned modules.
+20 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/mobile", "name": "@wrnexus/mobile",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/mobile — part of the WrNexus framework.", "description": "@wrnexus/mobile — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/mobile"
},
"homepage": "https://wrnexusjs.dev/packages/mobile",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"mobile"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,9 +37,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/native": "^0.7.0" "@wrnexus/native": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+3
View File
@@ -79,6 +79,9 @@ const position = await native.run(
Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`, Built-ins include `camera`, `clipboard.write`, `share`, `geolocation`, `network`,
`haptics`, storage, filesystem, notifications, and device information. `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 ## Requirements / Notes
Use `supports()` before showing optional controls. Mobile capabilities require their Use `supports()` before showing optional controls. Mobile capabilities require their
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/native", "name": "@wrnexus/native",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/native — part of the WrNexus framework.", "description": "@wrnexus/native — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/native"
},
"homepage": "https://wrnexusjs.dev/packages/native",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"native"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -29,6 +45,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+21
View File
@@ -194,3 +194,24 @@ const gitlab = defineProvider({
`verifier` between `startAuth` and `completeAuth` (session or signed cookie). `verifier` between `startAuth` and `completeAuth` (session or signed cookie).
- Pairs with [`@wrnexus/core`](../core) — feed the normalized `OAuthProfile` into - Pairs with [`@wrnexus/core`](../core) — feed the normalized `OAuthProfile` into
`logIn` to establish a session. `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.
+22 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/oauth", "name": "@wrnexus/oauth",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/oauth — part of the WrNexus framework.", "description": "@wrnexus/oauth — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/oauth"
},
"homepage": "https://wrnexusjs.dev/packages/oauth",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"oauth"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -20,7 +36,11 @@
"import": "./dist/index.js" "import": "./dist/index.js"
} }
}, },
"dependencies": {
"@wrnexus/jwt": "^0.8.0"
},
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+53
View File
@@ -1,7 +1,60 @@
# @wrnexus/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, Deterministic WRNexusJS plugin contracts for configuration, AST/code transforms,
diagnostics, development servers, production builds, and DevToolbar extensions. diagnostics, development servers, production builds, and DevToolbar extensions.
Use `definePlugin()` and declare `enforce`, `before`, or `after` when ordering matters. Use `definePlugin()` and declare `enforce`, `before`, or `after` when ordering matters.
Duplicate names and dependency cycles are rejected. 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.
+20 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/plugin", "name": "@wrnexus/plugin",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/plugin — part of the WrNexus framework.", "description": "@wrnexus/plugin — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/plugin"
},
"homepage": "https://wrnexusjs.dev/packages/plugin",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"plugin"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -33,9 +49,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/syntax": "^0.7.0" "@wrnexus/syntax": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+9 -4
View File
@@ -31,13 +31,15 @@ Creates a bus over a driver. Defaults to `memoryDriver()` (in-process).
interface PubSub { interface PubSub {
publish<T = unknown>(topic: string, message: T): Promise<void>; publish<T = unknown>(topic: string, message: T): Promise<void>;
subscribe<T = unknown>(pattern: string, handler: Handler<T>): () => void; subscribe<T = unknown>(pattern: string, handler: Handler<T>): () => void;
close(): Promise<void>;
} }
type Handler<T = unknown> = (message: T, topic: string) => void | 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. - `subscribe(pattern, handler)` — returns an unsubscribe function.
- `close()` — idempotently rejects new work, clears local subscriptions, and closes the driver.
### Pattern matching ### Pattern matching
@@ -67,7 +69,7 @@ then `redis://localhost:6379`. The URL may carry a password and a database index
(e.g. `redis://:secret@host:6379/2`). (e.g. `redis://:secret@host:6379/2`).
```ts ```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 - Exact topics use Redis `SUBSCRIBE`; wildcard patterns (`ns:*`, `*`) use
@@ -75,6 +77,9 @@ function redisDriver(url?: string): PubSubDriver & { close(): void };
- Messages are JSON-stringified on publish and `JSON.parse`d on receipt; a payload - 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. that isn't valid JSON is delivered as the raw string.
- `close()` tears down both the subscriber and publisher connections. - `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) ### RESP codec (internal)
@@ -115,8 +120,8 @@ bus.subscribe("order:*", (msg, topic) => {
await bus.publish("order:created", { id: 7 }); await bus.publish("order:created", { id: 7 });
// on shutdown // on shutdown (also closes the driver)
driver.close(); await bus.close();
``` ```
## Requirements / Notes ## Requirements / Notes
+23 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/pubsub", "name": "@wrnexus/pubsub",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/pubsub — part of the WrNexus framework.", "description": "@wrnexus/pubsub — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/pubsub"
},
"homepage": "https://wrnexusjs.dev/packages/pubsub",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"pubsub"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -19,12 +35,17 @@
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"import": "./dist/index.js" "import": "./dist/index.js"
}, },
"./brokers": {
"types": "./dist/brokers.d.ts",
"import": "./dist/brokers.js"
},
"./redis": { "./redis": {
"types": "./dist/redis.d.ts", "types": "./dist/redis.d.ts",
"import": "./dist/redis.js" "import": "./dist/redis.js"
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+50 -3
View File
@@ -43,6 +43,8 @@ function createQueue(options?: QueueOptions): Queue;
| `backoffMs` | `number` | `1000` | Base retry backoff in ms; doubles per attempt. | | `backoffMs` | `number` | `1000` | Base retry backoff in ms; doubles per attempt. |
| `pollMs` | `number` | `250` | Poll interval used once `start()` is called (ms). | | `pollMs` | `number` | `250` | Poll interval used once `start()` is called (ms). |
| `onFailed` | `(job: Job, error: unknown) => void` | — | Called when a job exhausts its attempts. | | `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. | | `now` | `() => number` | `Date.now` | Clock injection for deterministic tests. |
### `Queue` ### `Queue`
@@ -50,26 +52,36 @@ function createQueue(options?: QueueOptions): Queue;
The object returned by `createQueue`. The object returned by `createQueue`.
| Method | Signature | Description | | Method | Signature | Description |
| --------- | -------------------------------------------------------------- | -------------------------------------------------------------- | | ---------- | -------------------------------------------------------------- | -------------------------------------------------------------- |
| `add` | `add<T>(name, data: T, options?: AddOptions): Promise<Job<T>>` | Enqueue a job under a worker name. Returns the created job. | | `add` | `add<T>(name, data: T, options?: AddOptions): Promise<Job<T>>` | Enqueue a job under a worker name. Returns the created job. |
| `process` | `process<T>(name, handler: JobHandler<T>): void` | Register the worker that runs jobs of the given name. | | `process` | `process<T>(name, handler: JobHandler<T>): void` | Register the worker that runs jobs of the given name. |
| `drain` | `drain(now?: number): Promise<number>` | Run every job whose `runAt ≤ now`, once. Returns how many ran. | | `drain` | `drain(now?: number): Promise<number>` | Run every job whose `runAt ≤ now`, once. Returns how many ran. |
| `start` | `start(): void` | Begin polling every `pollMs`. No-op if already started. | | `start` | `start(): void` | Begin polling every `pollMs`. No-op if already started. |
| `stop` | `stop(): void` | Stop the poll timer. | | `stop` | `stop(): void` | Stop the poll timer. |
| `shutdown` | `shutdown({ force? }): Promise<void>` | Stop accepting jobs and await active work; force aborts it. |
| `size` | `size(): number` | Number of jobs currently queued. | | `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<boolean>` | Reset and requeue a dead-lettered job. |
#### `AddOptions` #### `AddOptions`
| Option | Type | Description | | Option | Type | Description |
| ------------- | -------- | -------------------------------------------------------------------------- | | ---------------- | -------- | -------------------------------------------------------------------------- |
| `delayMs` | `number` | Delay before the job becomes runnable (ms). | | `delayMs` | `number` | Delay before the job becomes runnable (ms). |
| `maxAttempts` | `number` | Max attempts before dead-lettering. Defaults to the queue's `maxAttempts`. | | `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). | | `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<T>` #### `JobHandler<T>`
```ts ```ts
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>` #### `Job<T>`
@@ -106,6 +118,18 @@ await queue.add("email", { to: "a@b.com" }, { delayMs: 5000, maxAttempts: 3 });
queue.start(); // begin polling; queue.stop() to halt 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 ### Recurring jobs
Pass `repeat` to re-enqueue a job a fixed interval after each successful run: Pass `repeat` to re-enqueue a job a fixed interval after each successful run:
@@ -145,6 +169,29 @@ clock = 5000;
const ran = await queue.drain(); // => 1 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 ## Retry & backoff behavior
- On a thrown handler error, the job is retried while `attempts < maxAttempts`. - On a thrown handler error, the job is retried while `attempts < maxAttempts`.
+22 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/queue", "name": "@wrnexus/queue",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/queue — part of the WrNexus framework.", "description": "@wrnexus/queue — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/queue"
},
"homepage": "https://wrnexusjs.dev/packages/queue",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"queue"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -20,7 +36,11 @@
"import": "./dist/index.js" "import": "./dist/index.js"
} }
}, },
"dependencies": {
"@wrnexus/core": "^0.8.0"
},
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/reactive", "name": "@wrnexus/reactive",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/reactive — part of the WrNexus framework.", "description": "@wrnexus/reactive — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/reactive"
},
"homepage": "https://wrnexusjs.dev/packages/reactive",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"reactive"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,6 +37,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+21 -4
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/router", "name": "@wrnexus/router",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/router — part of the WrNexus framework.", "description": "@wrnexus/router — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/router"
},
"homepage": "https://wrnexusjs.dev/packages/router",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"router"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,10 +37,11 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/compiler": "^0.7.0", "@wrnexus/compiler": "^0.8.0",
"@wrnexus/core": "^0.7.0" "@wrnexus/core": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+22 -5
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/ssr", "name": "@wrnexus/ssr",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/ssr — part of the WrNexus framework.", "description": "@wrnexus/ssr — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/ssr"
},
"homepage": "https://wrnexusjs.dev/packages/ssr",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"ssr"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -29,11 +45,12 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0", "@wrnexus/core": "^0.8.0",
"@wrnexus/store": "^0.7.0", "@wrnexus/store": "^0.8.0",
"@wrnexus/security": "^0.7.0" "@wrnexus/security": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+21
View File
@@ -1,5 +1,26 @@
# @wrnexus/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. > 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. Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework.
+22 -5
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/styles", "name": "@wrnexus/styles",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/styles — part of the WrNexus framework.", "description": "@wrnexus/styles — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/styles"
},
"homepage": "https://wrnexusjs.dev/packages/styles",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"styles"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,11 +37,12 @@
} }
}, },
"dependencies": { "dependencies": {
"@wrnexus/uploader": "^0.7.0", "@wrnexus/uploader": "^0.8.0",
"@wrnexus/core": "^0.7.0", "@wrnexus/core": "^0.8.0",
"@wrnexus/plugin": "^0.7.0" "@wrnexus/plugin": "^0.8.0"
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+23 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/syntax", "name": "@wrnexus/syntax",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/syntax — part of the WrNexus framework.", "description": "@wrnexus/syntax — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/syntax"
},
"homepage": "https://wrnexusjs.dev/packages/syntax",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"syntax"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -38,9 +54,14 @@
"./spec": { "./spec": {
"types": "./dist/spec.d.ts", "types": "./dist/spec.d.ts",
"import": "./dist/spec.js" "import": "./dist/spec.js"
},
"./formatter": {
"types": "./dist/formatter.d.ts",
"import": "./dist/formatter.js"
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+16
View File
@@ -103,6 +103,22 @@ Remember to `await app.close()` when done.
## Usage ## 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 ```ts
import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test"; import { test, expect, renderComponent, mountHtml, createHarness } from "@wrnexus/test";
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/test", "name": "@wrnexus/test",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/test — part of the WrNexus framework.", "description": "@wrnexus/test — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/test"
},
"homepage": "https://wrnexusjs.dev/packages/test",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"test"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,6 +37,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/tracking", "name": "@wrnexus/tracking",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/tracking — part of the WrNexus framework.", "description": "@wrnexus/tracking — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/tracking"
},
"homepage": "https://wrnexusjs.dev/packages/tracking",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"tracking"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -21,6 +37,7 @@
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md"
] ]
} }
+19 -2
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/ui", "name": "@wrnexus/ui",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/ui — part of the WrNexus framework.", "description": "@wrnexus/ui — part of the WrNexus framework.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/ui"
},
"homepage": "https://wrnexusjs.dev/packages/ui",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"ui"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -26,10 +42,11 @@
"./ui.css": "./ui.css" "./ui.css": "./ui.css"
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0" "@wrnexus/core": "^0.8.0"
}, },
"files": [ "files": [
"dist", "dist",
"README.md",
"components", "components",
"ui.css", "ui.css",
"component-catalog.json", "component-catalog.json",
+38
View File
@@ -108,6 +108,11 @@ export const GET = serveFromStore("docs"); // your middleware decides who gets i
## API ## 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 | | Export | What |
| --------------------------------------- | --------------------------------------------------------------- | | --------------------------------------- | --------------------------------------------------------------- |
| `handleUpload(opts)` | POST route handler → JSON `{ ok, files }` | | `handleUpload(opts)` | POST route handler → JSON `{ ok, files }` |
@@ -123,3 +128,36 @@ export const GET = serveFromStore("docs"); // your middleware decides who gets i
- SigV4 signing is implemented from scratch (no `@aws-sdk`); tested against local S3 semantics. - SigV4 signing is implemented from scratch (no `@aws-sdk`); tested against local S3 semantics.
Live AWS/R2 connectivity depends on your credentials + bucket policy. 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). - 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:
- `<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.
```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.
+37 -5
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/uploader", "name": "@wrnexus/uploader",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/uploader — part of the WrNexus framework.", "description": "Secure upload drivers, policies, client runtime, helper functions, and reusable upload components.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/uploader"
},
"homepage": "https://wrnexusjs.dev/packages/uploader",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"uploader"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -18,12 +34,28 @@
".": { ".": {
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"import": "./dist/index.js" "import": "./dist/index.js"
} },
"./plugin": {
"types": "./dist/plugin.d.ts",
"import": "./dist/plugin.js"
},
"./components/*": "./components/*"
}, },
"dependencies": { "dependencies": {
"@wrnexus/core": "^0.7.0" "@wrnexus/core": "^0.8.0",
"@wrnexus/plugin": "^0.8.0",
"@wrnexus/ui": "^0.8.0"
},
"wrnexus": {
"plugin": {
"plugin": "./dist/plugin.js",
"export": "default",
"factory": true
}
}, },
"files": [ "files": [
"dist" "dist",
"README.md",
"components"
] ]
} }
+77
View File
@@ -4,6 +4,31 @@
Part of the **WrNexus** framework — an SSR-first, Bun-native full-stack web framework. 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 ## 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/`. 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/`.
@@ -178,3 +203,55 @@ const head = `<script>${renderSchemasScript({ signup: signupSchema.describe() })
- 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. - 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. - No runtime dependencies. Ships as TypeScript source (`src/index.ts`) executed directly by Bun.
- Pairs with the WrNexus server (`@wrnexus/core`) for route handlers and the SSR layer that injects `renderSchemasScript` / `VALIDATE_RUNTIME`. - Pairs with the WrNexus server (`@wrnexus/core`) for route handlers and the SSR layer that injects `renderSchemasScript` / `VALIDATE_RUNTIME`.
## 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:
```ts
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:
```ts
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.
+38 -3
View File
@@ -1,9 +1,25 @@
{ {
"name": "@wrnexus/validation", "name": "@wrnexus/validation",
"version": "0.7.0", "version": "0.8.0",
"type": "module", "type": "module",
"description": "@wrnexus/validation — part of the WrNexus framework.", "description": "Shared server/browser schemas, validation helpers, form runtime, and reusable error components.",
"license": "MIT", "license": "MIT",
"repository": {
"type": "git",
"url": "https://git.workroot.in/WorkRoot/WRNexusJS.git",
"directory": "packages/validation"
},
"homepage": "https://wrnexusjs.dev/packages/validation",
"bugs": {
"url": "https://git.workroot.in/WorkRoot/WRNexusJS/issues"
},
"keywords": [
"wrnexus",
"bun",
"typescript",
"validation"
],
"sideEffects": false,
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.js", "module": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -18,9 +34,28 @@
".": { ".": {
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"import": "./dist/index.js" "import": "./dist/index.js"
},
"./plugin": {
"types": "./dist/plugin.d.ts",
"import": "./dist/plugin.js"
},
"./components/*": "./components/*"
},
"dependencies": {
"@wrnexus/core": "^0.8.0",
"@wrnexus/plugin": "^0.8.0",
"@wrnexus/ui": "^0.8.0"
},
"wrnexus": {
"plugin": {
"plugin": "./dist/plugin.js",
"export": "default",
"factory": true
} }
}, },
"files": [ "files": [
"dist" "dist",
"README.md",
"components"
] ]
} }
-109
View File
@@ -1,109 +0,0 @@
param(
[string]$Root = "E:\WireJS",
[switch]$SkipValidation
)
$ErrorActionPreference = "Stop"
$PackageRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$Root = [System.IO.Path]::GetFullPath($Root)
if (-not (Test-Path (Join-Path $Root "packages\ui\components"))) {
throw "WRNexusJS repository was not found at: $Root"
}
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$backupRoot = Join-Path $Root ".wrnexus\component-showcase-backup-$timestamp"
New-Item -ItemType Directory -Path $backupRoot -Force | Out-Null
$files = @(
"scripts/generate-ui-component-reference.mjs",
"packages/ui/component-catalog.json",
"examples/component-showcase/scripts/generate-showcase.mjs",
"examples/component-showcase/scripts/showcase-profiles.mjs",
"examples/component-showcase/public/playground.js",
"examples/component-showcase/app/styles/global.css",
"examples/component-showcase/test/showcase.test.ts",
"examples/component-showcase/README.md"
)
$generatedFiles = @(
"packages/ui/component-reference.json",
"packages/ui/COMPONENTS.md",
"examples/component-showcase/showcase-manifest.json"
)
function Convert-RelativePath([string]$relative) {
return $relative.Replace("/", [System.IO.Path]::DirectorySeparatorChar)
}
function Backup-Path([string]$relative) {
$platformPath = Convert-RelativePath $relative
$source = Join-Path $Root $platformPath
if (-not (Test-Path $source)) { return }
$destination = Join-Path $backupRoot $platformPath
$destinationParent = Split-Path -Parent $destination
New-Item -ItemType Directory -Path $destinationParent -Force | Out-Null
Copy-Item $source $destination -Recurse -Force
}
foreach ($relative in $files) { Backup-Path $relative }
foreach ($relative in $generatedFiles) { Backup-Path $relative }
Backup-Path "examples/component-showcase/app/pages"
Backup-Path "examples/component-showcase/app/layouts"
foreach ($relative in $files) {
$platformPath = Convert-RelativePath $relative
$source = Join-Path $PackageRoot $platformPath
$destination = Join-Path $Root $platformPath
if (-not (Test-Path $source)) {
throw "Patch file is missing: $source"
}
New-Item -ItemType Directory -Path (Split-Path -Parent $destination) -Force | Out-Null
Copy-Item $source $destination -Force
Write-Host "Updated $relative" -ForegroundColor Green
}
function Invoke-BunStep {
param(
[string]$Label,
[string[]]$Arguments
)
Write-Host "`n$Label" -ForegroundColor Cyan
& bun @Arguments
if ($LASTEXITCODE -ne 0) {
throw "$Label failed with exit code $LASTEXITCODE."
}
}
Push-Location $Root
try {
Invoke-BunStep "Generating the current UI component reference" @(
"run",
"scripts/generate-ui-component-reference.mjs"
)
$showcaseRoot = Join-Path $Root "examples\component-showcase"
Remove-Item (Join-Path $showcaseRoot ".wrnexus") -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item (Join-Path $showcaseRoot "dist") -Recurse -Force -ErrorAction SilentlyContinue
Push-Location $showcaseRoot
try {
Invoke-BunStep "Generating component showcase pages and manifest" @("run", "generate")
if (-not $SkipValidation) {
Invoke-BunStep "Validating the complete component showcase" @("run", "check")
}
}
finally {
Pop-Location
}
}
finally {
Pop-Location
}
Write-Host "`nComponent showcase update applied successfully." -ForegroundColor Green
Write-Host "Backup: $backupRoot"
if ($SkipValidation) {
Write-Host "Validation was skipped. Run: bun run --cwd examples/component-showcase check" -ForegroundColor Yellow
}
-36
View File
@@ -1,36 +0,0 @@
param(
[Parameter(Mandatory = $false)]
[string]$Root = "E:\WireJS"
)
$ErrorActionPreference = "Stop"
$Root = (Resolve-Path $Root).Path
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Write-Host "Stopping Bun processes..." -ForegroundColor Cyan
Get-Process bun -ErrorAction SilentlyContinue | Stop-Process -Force
Write-Host "Applying overlay reactivity fix..." -ForegroundColor Cyan
node (Join-Path $ScriptDir "patch-overlay-showcase.mjs") $Root
Push-Location $Root
try {
Write-Host "Regenerating UI component reference..." -ForegroundColor Cyan
bun run scripts/generate-ui-component-reference.mjs
Write-Host "Running focused UI tests..." -ForegroundColor Cyan
bun test packages/ui/test/overlay-reactivity.test.ts
Push-Location (Join-Path $Root "examples\component-showcase")
try {
Write-Host "Regenerating showcase..." -ForegroundColor Cyan
bun run generate
bun test test/showcase.test.ts
} finally {
Pop-Location
}
} finally {
Pop-Location
}
Write-Host "Done. Start with: cd E:\WireJS\examples\component-showcase; bun run dev" -ForegroundColor Green
-16
View File
@@ -1,16 +0,0 @@
{
"name": "WRNexusJS",
"version": "0.6.0",
"status": "developer-test-build",
"sourceArchive": "WRNexusJS(4).zip",
"frameworkPackages": 33,
"uiComponents": 108,
"showcaseComponentPages": 108,
"showcaseLiveDemos": 417,
"showcaseComponentCategories": 11,
"showcaseV06Guides": 8,
"wrnFilesParsed": 250,
"wrnParseFailures": 0,
"bunFullSuiteExecuted": false,
"bunUnavailableInPackagingEnvironment": true
}
+12
View File
@@ -0,0 +1,12 @@
# Changelog
All notable framework changes are recorded here. Every release must also include an idempotent
entry in the CLI migration registry.
## 0.8.0 - 2026-08-02
- Added package-owned helper and component kits across all 39 framework packages.
- Added standalone realtime and package-aware auth, i18n, image, uploader, validation, JWT,
encryption, database, and CAPTCHA improvements.
- Added whole-application WRN syntax, import, and formatting modernization to the CLI update.
- Added Windows/Linux CI, read-only package audits, governance documents, and security gates.
-421
View File
@@ -1,421 +0,0 @@
## R9 — ToggleCount animation stability
- Schedules animation frames by absolute offsets to prevent cumulative timer drift.
- Cancels stale ToggleCount animation frames with per-animation tokens.
- Binds generated browser peer functions through a scoped function table.
# WRNexusJS v0.6.0 changed files
- Canonicalized v0.6 syntax helpers through `@wrnexus/syntax`; removed the public `@wrnexus/syntax/v060` subpath and editor-bundle alias.
## R3 correction
- Regenerated/aligned `editors/vscode/src/compiler.cjs`.
- Added `FIXES-0.6.0-VSCODE-COMPILER-BUNDLE.md`.
Comparison base: `WRNexusJS(4).zip`. Dependency directories, `.git`, and `.wrnexus` caches are excluded from this comparison.
- Added: **57** files
- Modified: **284** files
- Removed: **0** files
## Added files
- `MIGRATION-DRY-RUN-0.6.0.json`
- `MIGRATION-DRY-RUN-0.6.0.md`
- `OLD-PROJECT-TEST-CHECKLIST.md`
- `PUBLISHING-0.6.0.md`
- `RELEASE_MANIFEST.json`
- `RELEASE_NOTES-0.6.0.md`
- `ROLLBACK-0.6.0.md`
- `UPGRADE-0.6.0.md`
- `VALIDATION-0.6.0.md`
- `docs/v0.6/architecture.md`
- `docs/v0.6/language.md`
- `examples/component-showcase/app/pages/v06-functions.wrn`
- `examples/component-showcase/app/pages/v06-imports.wrn`
- `examples/component-showcase/app/pages/v06-migration.wrn`
- `examples/component-showcase/app/pages/v06-outputs.wrn`
- `examples/component-showcase/app/pages/v06-runtime.wrn`
- `examples/component-showcase/app/pages/v06-state.wrn`
- `examples/component-showcase/app/pages/v06-stores.wrn`
- `examples/component-showcase/app/pages/v06-types.wrn`
- `integration/fixtures/v0.5-legacy-app/app/components/LegacyModal.wrn`
- `integration/fixtures/v0.5-legacy-app/app/layouts/PublicLayout.wrn`
- `integration/fixtures/v0.5-legacy-app/app/pages/index.wrn`
- `integration/fixtures/v0.5-legacy-app/app/types/global.d.ts`
- `integration/fixtures/v0.5-legacy-app/package.json`
- `packages/cli/test/update-v060.test.ts`
- `packages/compiler/src/client-codegen.ts`
- `packages/compiler/src/component-contract.ts`
- `packages/compiler/src/import-resolver.ts`
- `packages/compiler/src/server-codegen.ts`
- `packages/compiler/src/source-map.ts`
- `packages/compiler/src/store-codegen.ts`
- `packages/compiler/src/targets.ts`
- `packages/compiler/src/type-codegen.ts`
- `packages/compiler/test/v060-targets.test.ts`
- `packages/csr/src/client-functions.ts`
- `packages/csr/src/outputs.ts`
- `packages/csr/src/refs.ts`
- `packages/csr/src/server-client.ts`
- `packages/csr/src/types.ts`
- `packages/ssr/src/rpc.ts`
- `packages/ssr/src/store-context.ts`
- `packages/ssr/test/rpc-v060.test.ts`
- `packages/store/package.json`
- `packages/store/src/client.ts`
- `packages/store/src/index.ts`
- `packages/store/src/server.ts`
- `packages/store/src/types.ts`
- `packages/store/test/store.test.ts`
- `packages/syntax/src/v060.ts`
- `packages/syntax/test/v060.test.ts`
- `packages/typecheck/package.json`
- `packages/typecheck/src/contracts.ts`
- `packages/typecheck/src/index.ts`
- `packages/typecheck/src/project.ts`
- `packages/typecheck/test/imports-and-components.test.ts`
- `packages/typecheck/test/typecheck.test.ts`
- `scripts/validate-0.6.mjs`
## Modified files
- `bun.lock`
- `editors/vscode/package.json`
- `editors/vscode/snippets/wrn.json`
- `editors/vscode/src/completion.js`
- `editors/vscode/src/diagnostics.js`
- `editors/vscode/syntaxes/wrn.tmLanguage.json`
- `examples/component-showcase/app/layouts/showcase.wrn`
- `examples/component-showcase/app/pages/components/accordion.wrn`
- `examples/component-showcase/app/pages/components/advanced-date-picker.wrn`
- `examples/component-showcase/app/pages/components/advanced-range-slider.wrn`
- `examples/component-showcase/app/pages/components/advanced-select.wrn`
- `examples/component-showcase/app/pages/components/alert.wrn`
- `examples/component-showcase/app/pages/components/announcement-bar.wrn`
- `examples/component-showcase/app/pages/components/auth-form.wrn`
- `examples/component-showcase/app/pages/components/auth-split-layout.wrn`
- `examples/component-showcase/app/pages/components/avatar-group.wrn`
- `examples/component-showcase/app/pages/components/avatar.wrn`
- `examples/component-showcase/app/pages/components/back-to-top.wrn`
- `examples/component-showcase/app/pages/components/badge.wrn`
- `examples/component-showcase/app/pages/components/blockquote.wrn`
- `examples/component-showcase/app/pages/components/breadcrumb.wrn`
- `examples/component-showcase/app/pages/components/button-group.wrn`
- `examples/component-showcase/app/pages/components/button.wrn`
- `examples/component-showcase/app/pages/components/card.wrn`
- `examples/component-showcase/app/pages/components/carousel.wrn`
- `examples/component-showcase/app/pages/components/chart.wrn`
- `examples/component-showcase/app/pages/components/chat-bubble.wrn`
- `examples/component-showcase/app/pages/components/checkbox.wrn`
- `examples/component-showcase/app/pages/components/clipboard.wrn`
- `examples/component-showcase/app/pages/components/collapse.wrn`
- `examples/component-showcase/app/pages/components/color-picker.wrn`
- `examples/component-showcase/app/pages/components/columns.wrn`
- `examples/component-showcase/app/pages/components/combo-box.wrn`
- `examples/component-showcase/app/pages/components/confetti.wrn`
- `examples/component-showcase/app/pages/components/container.wrn`
- `examples/component-showcase/app/pages/components/context-menu.wrn`
- `examples/component-showcase/app/pages/components/copy-markup.wrn`
- `examples/component-showcase/app/pages/components/ctasection.wrn`
- `examples/component-showcase/app/pages/components/custom-scrollbar.wrn`
- `examples/component-showcase/app/pages/components/data-map.wrn`
- `examples/component-showcase/app/pages/components/data-table.wrn`
- `examples/component-showcase/app/pages/components/date-picker.wrn`
- `examples/component-showcase/app/pages/components/device-frame.wrn`
- `examples/component-showcase/app/pages/components/divider.wrn`
- `examples/component-showcase/app/pages/components/drag-and-drop.wrn`
- `examples/component-showcase/app/pages/components/drawer.wrn`
- `examples/component-showcase/app/pages/components/dropdown.wrn`
- `examples/component-showcase/app/pages/components/feature-card.wrn`
- `examples/component-showcase/app/pages/components/feature-grid.wrn`
- `examples/component-showcase/app/pages/components/feature-icon-card.wrn`
- `examples/component-showcase/app/pages/components/file-input.wrn`
- `examples/component-showcase/app/pages/components/file-upload-progress.wrn`
- `examples/component-showcase/app/pages/components/file-upload.wrn`
- `examples/component-showcase/app/pages/components/footer.wrn`
- `examples/component-showcase/app/pages/components/grid.wrn`
- `examples/component-showcase/app/pages/components/hero-actions.wrn`
- `examples/component-showcase/app/pages/components/hero.wrn`
- `examples/component-showcase/app/pages/components/image.wrn`
- `examples/component-showcase/app/pages/components/input-group.wrn`
- `examples/component-showcase/app/pages/components/input-number.wrn`
- `examples/component-showcase/app/pages/components/input.wrn`
- `examples/component-showcase/app/pages/components/kbd.wrn`
- `examples/component-showcase/app/pages/components/layout-splitter.wrn`
- `examples/component-showcase/app/pages/components/legend-indicator.wrn`
- `examples/component-showcase/app/pages/components/link.wrn`
- `examples/component-showcase/app/pages/components/list-group.wrn`
- `examples/component-showcase/app/pages/components/list.wrn`
- `examples/component-showcase/app/pages/components/map.wrn`
- `examples/component-showcase/app/pages/components/marketing-section-header.wrn`
- `examples/component-showcase/app/pages/components/marquee.wrn`
- `examples/component-showcase/app/pages/components/mega-menu.wrn`
- `examples/component-showcase/app/pages/components/metric-card.wrn`
- `examples/component-showcase/app/pages/components/metric-grid.wrn`
- `examples/component-showcase/app/pages/components/modal.wrn`
- `examples/component-showcase/app/pages/components/nav.wrn`
- `examples/component-showcase/app/pages/components/navbar.wrn`
- `examples/component-showcase/app/pages/components/page-header.wrn`
- `examples/component-showcase/app/pages/components/pagination.wrn`
- `examples/component-showcase/app/pages/components/pin-input.wrn`
- `examples/component-showcase/app/pages/components/popover.wrn`
- `examples/component-showcase/app/pages/components/portal-dashboard.wrn`
- `examples/component-showcase/app/pages/components/preference-switcher.wrn`
- `examples/component-showcase/app/pages/components/progress.wrn`
- `examples/component-showcase/app/pages/components/public-page-shell.wrn`
- `examples/component-showcase/app/pages/components/radio.wrn`
- `examples/component-showcase/app/pages/components/range-slider.wrn`
- `examples/component-showcase/app/pages/components/rating.wrn`
- `examples/component-showcase/app/pages/components/scrollspy.wrn`
- `examples/component-showcase/app/pages/components/search-box.wrn`
- `examples/component-showcase/app/pages/components/section-header.wrn`
- `examples/component-showcase/app/pages/components/section.wrn`
- `examples/component-showcase/app/pages/components/select.wrn`
- `examples/component-showcase/app/pages/components/sidebar.wrn`
- `examples/component-showcase/app/pages/components/skeleton.wrn`
- `examples/component-showcase/app/pages/components/spinner.wrn`
- `examples/component-showcase/app/pages/components/split-hero.wrn`
- `examples/component-showcase/app/pages/components/stats-bar.wrn`
- `examples/component-showcase/app/pages/components/stepper.wrn`
- `examples/component-showcase/app/pages/components/strong-password.wrn`
- `examples/component-showcase/app/pages/components/styled-icon.wrn`
- `examples/component-showcase/app/pages/components/switch.wrn`
- `examples/component-showcase/app/pages/components/table.wrn`
- `examples/component-showcase/app/pages/components/tabs.wrn`
- `examples/component-showcase/app/pages/components/text-link.wrn`
- `examples/component-showcase/app/pages/components/textarea.wrn`
- `examples/component-showcase/app/pages/components/time-picker.wrn`
- `examples/component-showcase/app/pages/components/timeline.wrn`
- `examples/component-showcase/app/pages/components/toast-notifications.wrn`
- `examples/component-showcase/app/pages/components/toast.wrn`
- `examples/component-showcase/app/pages/components/toggle-count.wrn`
- `examples/component-showcase/app/pages/components/toggle-password.wrn`
- `examples/component-showcase/app/pages/components/tooltip.wrn`
- `examples/component-showcase/app/pages/components/tree-view.wrn`
- `examples/component-showcase/app/pages/components/typography.wrn`
- `examples/component-showcase/app/pages/components/wysiwyg-editor.wrn`
- `examples/component-showcase/public/playground.js`
- `examples/component-showcase/scripts/generate-showcase.mjs`
- `llms.txt`
- `package.json`
- `packages/ai/package.json`
- `packages/auth/package.json`
- `packages/authz/package.json`
- `packages/captcha/package.json`
- `packages/cli/package.json`
- `packages/cli/src/update.ts`
- `packages/compiler/package.json`
- `packages/compiler/src/codegen.ts`
- `packages/compiler/src/index.ts`
- `packages/core/package.json`
- `packages/csr/package.json`
- `packages/csr/src/index.ts`
- `packages/csr/src/nav-runtime.ts`
- `packages/csr/src/reactive-runtime.ts`
- `packages/db/package.json`
- `packages/dev-server/package.json`
- `packages/dev-server/src/assets.ts`
- `packages/dev-server/src/index.ts`
- `packages/dev-server/src/pipeline.ts`
- `packages/dev-server/src/runtime.ts`
- `packages/dev-toolbar/package.json`
- `packages/dev-toolbar/src/client/runtime.ts`
- `packages/dev-toolbar/src/client/styles.ts`
- `packages/dev-toolbar/src/types.ts`
- `packages/encryption/package.json`
- `packages/helpers/package.json`
- `packages/i18n/package.json`
- `packages/jwt/package.json`
- `packages/mobile/package.json`
- `packages/native/package.json`
- `packages/oauth/package.json`
- `packages/plugin/package.json`
- `packages/pubsub/package.json`
- `packages/queue/package.json`
- `packages/reactive/package.json`
- `packages/router/package.json`
- `packages/ssr/package.json`
- `packages/ssr/src/index.ts`
- `packages/styles/package.json`
- `packages/styles/src/config.ts`
- `packages/syntax/package.json`
- `packages/syntax/src/diagnostics.ts`
- `packages/syntax/src/index.ts`
- `packages/syntax/src/parser.ts`
- `packages/syntax/src/spec.ts`
- `packages/syntax/src/tokenizer.ts`
- `packages/test/package.json`
- `packages/tracking/package.json`
- `packages/ui/COMPONENTS.md`
- `packages/ui/component-reference.json`
- `packages/ui/components/Accordion.wrn`
- `packages/ui/components/AdvancedDatePicker.wrn`
- `packages/ui/components/AdvancedRangeSlider.wrn`
- `packages/ui/components/AdvancedSelect.wrn`
- `packages/ui/components/AnnouncementBar.wrn`
- `packages/ui/components/AuthForm.wrn`
- `packages/ui/components/AuthSplitLayout.wrn`
- `packages/ui/components/AvatarGroup.wrn`
- `packages/ui/components/BackToTop.wrn`
- `packages/ui/components/Badge.wrn`
- `packages/ui/components/Blockquote.wrn`
- `packages/ui/components/Breadcrumb.wrn`
- `packages/ui/components/ButtonGroup.wrn`
- `packages/ui/components/CTASection.wrn`
- `packages/ui/components/Card.wrn`
- `packages/ui/components/Chart.wrn`
- `packages/ui/components/ChatBubble.wrn`
- `packages/ui/components/Checkbox.wrn`
- `packages/ui/components/Clipboard.wrn`
- `packages/ui/components/Collapse.wrn`
- `packages/ui/components/ColorPicker.wrn`
- `packages/ui/components/Columns.wrn`
- `packages/ui/components/Combobox.wrn`
- `packages/ui/components/Confetti.wrn`
- `packages/ui/components/Container.wrn`
- `packages/ui/components/ContextMenu.wrn`
- `packages/ui/components/CopyMarkup.wrn`
- `packages/ui/components/CustomScrollbar.wrn`
- `packages/ui/components/DataMap.wrn`
- `packages/ui/components/DataTable.wrn`
- `packages/ui/components/DatePicker.wrn`
- `packages/ui/components/DeviceFrame.wrn`
- `packages/ui/components/Divider.wrn`
- `packages/ui/components/DragAndDrop.wrn`
- `packages/ui/components/Drawer.wrn`
- `packages/ui/components/Dropdown.wrn`
- `packages/ui/components/FeatureCard.wrn`
- `packages/ui/components/FeatureGrid.wrn`
- `packages/ui/components/FeatureIconCard.wrn`
- `packages/ui/components/FileInput.wrn`
- `packages/ui/components/FileUpload.wrn`
- `packages/ui/components/FileUploadProgress.wrn`
- `packages/ui/components/Footer.wrn`
- `packages/ui/components/Grid.wrn`
- `packages/ui/components/Hero.wrn`
- `packages/ui/components/HeroActions.wrn`
- `packages/ui/components/Image.wrn`
- `packages/ui/components/Input.wrn`
- `packages/ui/components/InputGroup.wrn`
- `packages/ui/components/InputNumber.wrn`
- `packages/ui/components/Kbd.wrn`
- `packages/ui/components/LayoutSplitter.wrn`
- `packages/ui/components/LegendIndicator.wrn`
- `packages/ui/components/Link.wrn`
- `packages/ui/components/List.wrn`
- `packages/ui/components/ListGroup.wrn`
- `packages/ui/components/Map.wrn`
- `packages/ui/components/MarketingSectionHeader.wrn`
- `packages/ui/components/Marquee.wrn`
- `packages/ui/components/MegaMenu.wrn`
- `packages/ui/components/MetricCard.wrn`
- `packages/ui/components/MetricGrid.wrn`
- `packages/ui/components/Modal.wrn`
- `packages/ui/components/Nav.wrn`
- `packages/ui/components/Navbar.wrn`
- `packages/ui/components/PageHeader.wrn`
- `packages/ui/components/Pagination.wrn`
- `packages/ui/components/PinInput.wrn`
- `packages/ui/components/Popover.wrn`
- `packages/ui/components/PortalDashboard.wrn`
- `packages/ui/components/PreferenceSwitcher.wrn`
- `packages/ui/components/PublicPageShell.wrn`
- `packages/ui/components/Radio.wrn`
- `packages/ui/components/RangeSlider.wrn`
- `packages/ui/components/Rating.wrn`
- `packages/ui/components/Scrollspy.wrn`
- `packages/ui/components/SearchBox.wrn`
- `packages/ui/components/Section.wrn`
- `packages/ui/components/SectionHeader.wrn`
- `packages/ui/components/Select.wrn`
- `packages/ui/components/Sidebar.wrn`
- `packages/ui/components/SplitHero.wrn`
- `packages/ui/components/StatsBar.wrn`
- `packages/ui/components/Stepper.wrn`
- `packages/ui/components/StrongPassword.wrn`
- `packages/ui/components/StyledIcon.wrn`
- `packages/ui/components/Switch.wrn`
- `packages/ui/components/Tabs.wrn`
- `packages/ui/components/TextLink.wrn`
- `packages/ui/components/Textarea.wrn`
- `packages/ui/components/TimePicker.wrn`
- `packages/ui/components/Timeline.wrn`
- `packages/ui/components/Toast.wrn`
- `packages/ui/components/ToastNotifications.wrn`
- `packages/ui/components/ToggleCount.wrn`
- `packages/ui/components/TogglePassword.wrn`
- `packages/ui/components/Tooltip.wrn`
- `packages/ui/components/TreeView.wrn`
- `packages/ui/components/Typography.wrn`
- `packages/ui/components/WysiwygEditor.wrn`
- `packages/ui/components/alert.wrn`
- `packages/ui/components/avatar.wrn`
- `packages/ui/components/button.wrn`
- `packages/ui/components/carousel.wrn`
- `packages/ui/components/progress.wrn`
- `packages/ui/components/skeleton.wrn`
- `packages/ui/components/spinner.wrn`
- `packages/ui/components/table.wrn`
- `packages/ui/package.json`
- `packages/uploader/package.json`
- `packages/validation/package.json`
- `scripts/generate-ui-component-reference.mjs`
- `services/managed-captcha/package.json`
- `tsconfig.json`
- `update-package-versions.mjs`
## Removed files
- None
## R7 test-cascade corrections
- Restored synchronous CSR hydration for inline behavior and unresolved direct-compile module placeholders.
- Restored strict component/store lifecycle hook validation.
- Prevented browser runtime API names from colliding with generated prop/state aliases.
- Preserved synchronous page exports when no imported store requires asynchronous initialization.
- Allowed store dispose lifecycle hooks to mutate store state through the internal mutation context.
- Updated UI tests and generated references for typed props and `outputs {}` contracts.
- Added universal size/color support to FeatureGrid and complete RangeSlider output metadata.
## R8 UI compiler regression fixes
- Fixed readonly-prop false positives for comparisons, string literals, object/member access, and shadowing function parameters.
- Restored compilation and runtime tests for AuthForm, Carousel, RangeSlider, InputNumber, Select, AdvancedSelect, ComboBox, ContextMenu, and Tooltip.
- Synchronized component catalog and generated component reference with all 108 bundled UI declarations.
- Added full UI compilation and native-attribute forwarding checks to `validate:0.6`.
## R10 peer-function scoped-state correction
- Peer client/shared functions are invoked through synchronized scoped wrappers.
- Nested peer calls no longer have their state changes overwritten by stale outer aliases.
- Synchronous, asynchronous, and throwing peer calls refresh shared state correctly.
- Added an executable `validate:0.6` regression probe for the exact compiler failure.
## R11 peer-function test correction
- Corrected the compiler regression test export-stripping regex from an over-escaped literal `\\s` match to the intended whitespace `\s` match.
- Confirmed the generated peer-function browser module executes and updates shared state from `0` to `1`.
- Added a release validator guard for the exact test source regression.
## R13 release reference stability
- Prevented the UI reference generator from rewriting current files solely because of CRLF/LF differences.
- Added an executable regression test proving line-ending-only differences are ignored and real stale content is repaired.
## 0.7.0 R2 typecheck correction
- Removed leaked focused-typecheck shim files that polluted the root TypeScript program.
- Added a validation gate preventing those temporary files from entering future archives.
## 0.7.0 R4 Happy DOM event typing
- Fixed strict event-type compatibility in `packages/validation/test/validation.test.ts`.
- Improved `check:workspace` dry-run wording.
- Added a validation guard preventing browser DOM `Event` from being reintroduced as the Happy DOM helper return type.
## 0.7.0 R6 lint cleanup
See `FIXES-0.7.0-R6-LINT-CLEANUP.md` for the final lint and secure hydration corrections.
+8
View File
@@ -0,0 +1,8 @@
# Code of conduct
Be respectful, constructive, and specific. Harassment, discrimination, threats, personal attacks,
and publication of private information are not acceptable. Discuss technical decisions with
evidence, assume good intent, and give contributors room to correct mistakes.
Report conduct concerns privately to the maintainers. Maintainers may remove content, limit
participation, or ban contributors when necessary to protect the community.
+17
View File
@@ -0,0 +1,17 @@
# Contributing
Install Bun 1.3.14 or newer and Node.js 24, then run:
```sh
bun install --frozen-lockfile
npm ci --prefix editors/vscode
bun run typecheck
bun run lint
bun run format:check
bun run test:all
bun run validate:0.8
```
Keep migrations conservative, backed up, idempotent, and covered by fixtures. Generated files
must be produced by their documented `generate:*` command and committed with their source change.
Security issues follow `SECURITY.md` and must not be disclosed publicly before a coordinated fix.
-65
View File
@@ -1,65 +0,0 @@
# WRNexusJS 0.6.0 focused fixes — issues 1 through 7
This developer-test archive fixes the seven blockers identified in `WRNexusJS-v0.6.0-validation-against-spec.md`.
## Fixed
1. **Generated browser-module syntax**
- JavaScript reserved words such as the `class` prop are never destructured into invalid bindings.
- Function parameters no longer collide with generated prop, state, output, server, props, or refs aliases.
- All 108 UI component browser modules were regenerated and passed JavaScript syntax parsing.
2. **Browser-store RPC**
- Generated store actions bind `server` from the store action context.
- Browser store RPC sends same-origin structured requests with CSRF and request identifiers.
- A live simulated store called a server function successfully and updated reactive state.
3. **Concrete UI output contracts**
- No `unknown` remains inside any UI `outputs {}` declaration.
- Component reference and showcase metadata were regenerated.
- Legacy `$emit`, `@event`, `$event`, and `event.detail` remain absent from framework UI components.
4. **Configured import modes**
- Dev compilation reads `imports.mode`, `imports.aliases`, and `imports.autoImport` from application configuration.
- `legacy` accepts implicit discovery.
- `compatible` accepts it with `WRN-IMPORT-IMPLICIT` diagnostics.
- `explicit` rejects missing imports and accepts correctly imported components/layouts/stores.
5. **Store persistence migration and validation**
- `persist { migrations { ... } validate { ... } }` is parsed and emitted.
- Browser restore executes version migration before validation.
- Invalid or incompatible persisted values are reset with diagnostics.
- Include-only state is written with the current persistence version.
6. **Store HMR integration**
- Store browser modules expose hot-update definitions.
- The dev server broadcasts versioned `store-update` messages.
- The browser HMR client imports changed store modules and applies updates without a mandatory document reload.
- Compatible fields are preserved; added, removed, and incompatible fields are reported.
7. **Restricted RPC exposure**
- RPC manifests include only server functions referenced through `server.name(...)` by browser-capable code.
- Unreferenced server functions remain available for local SSR/server execution but are not remotely exposed.
## Focused validation completed
- 108 UI browser artifacts generated: **0 generation failures**.
- 108 UI browser artifacts syntax checked: **0 syntax failures**.
- 250 UI/showcase `.wrn` files parsed: **0 parser failures**.
- Browser-store RPC/persistence/validation/HMR simulation: **passed**.
- Import mode simulation for legacy/compatible/explicit: **passed**.
- Restricted component and store RPC manifest probes: **passed**.
- Generated server-store TypeScript transpilation: **0 diagnostics**.
- VS Code extension Node tests: **28 passed**.
- `node scripts/validate-0.6.mjs`: **12 passed, 1 Bun warning, 0 failed**.
## Remaining local release gate
Bun is unavailable in the packaging environment. Run the full point-8 suite locally before publishing:
```powershell
bun install
bun run validate:0.6
bun run check
bun run --cwd examples/component-showcase check
```
-44
View File
@@ -1,44 +0,0 @@
# WRNexusJS v0.6.0 R6 lint corrections
This revision fixes the lint failures reported by `bun run check` after R5.
## Corrected files
- `editors/vscode/test/formatter.test.js`
- Replaced hard-to-count literal regex spaces with quantified spaces.
- `examples/component-showcase/scripts/generate-showcase.mjs`
- Removed unused `uiComponentsPath` and `jsonAttribute` declarations.
- `examples/component-showcase/scripts/showcase-profiles.mjs`
- Removed the unused `actionSlot` declaration.
- `packages/cli/src/update.ts`
- Removed an unnecessary regex escape.
- `packages/compiler/src/client-codegen.ts`
- Rewrote store-path regexes without unnecessary character-class escapes.
- `packages/compiler/src/codegen.ts`
- Rewrote the store-path regex without unnecessary character-class escapes.
- `packages/syntax/src/diagnostics.ts`
- Corrected dynamic `RegExp` string escaping for word boundaries, property separators, and whitespace.
- `packages/syntax/src/parser.ts`
- Removed an unused `FunctionRuntime` type import.
- `patch-overlay-showcase.mjs`
- Added explicit Node imports for `process` and `console`.
- `scripts/generate-ui-component-reference.mjs`
- Removed an unnecessary closing-parenthesis escape in a regex character class.
- `scripts/validate-0.6.mjs`
- Added explicit Node imports for `console`, `process`, and `fileURLToPath`.
- Replaced URL pathname manipulation with `fileURLToPath`, improving Windows path handling.
## Validation performed in the packaging environment
- `node scripts/validate-0.6.mjs`: 14 passes, zero failures; Bun unavailable warning only.
- VS Code extension Node tests: 28 passes, zero failures.
- VS Code extension validation: all checks passed.
- All JavaScript and MJS syntax checks passed.
- Exact regression guards for all 31 reported lint findings passed.
Run the complete release gate locally with Bun:
```powershell
bun install
bun run check
```
-25
View File
@@ -1,25 +0,0 @@
# WRNexusJS v0.6.0 R10 peer-function state fix
## Failure
The compiler test `browser codegen binds peer client functions through the scoped function table` failed because an outer client function captured local state before calling a peer function. The peer updated `context.state`, but the outer function's `finally` block copied its stale local value back over the peer update.
## Fix
`packages/compiler/src/client-codegen.ts` now generates peer-function wrappers that:
1. synchronize the caller's local state into `context.state` before the peer call;
2. invoke the peer through `context.functions`;
3. refresh local aliases from `context.state` after synchronous completion, asynchronous completion, or a synchronous throw;
4. copy local state back only when it actually changed from the function-entry snapshot.
This preserves shared scoped state for nested client/shared function calls without changing synchronous functions into promises.
## Regression validation
- Exact peer-call execution probe: passed (`run()` calls `increment()`, final state is `1`).
- Focused TypeScript compiler check: passed.
- UI browser targets generated and syntax-checked: 108/108.
- UI and showcase WRN files parsed: 250/250.
- VS Code tests: 28/28.
- Root v0.6 validator: 18 passed, 0 failed (Bun availability warning only in the packaging environment).
-17
View File
@@ -1,17 +0,0 @@
# WRNexusJS 0.6.0 R11 peer-function regression test fix
The final failing compiler test used an over-escaped regular expression:
```ts
targets.browser.replace(/^export\\s+/gm, "");
```
That pattern matches a literal `\\s` sequence rather than whitespace, so generated `export` keywords remained in the source passed to `new Function()`.
R11 corrects the test to:
```ts
targets.browser.replace(/^export\s+/gm, "");
```
The generated browser module itself was already correct. The corrected executable probe returns `state.value === 1` after calling the peer-bound `run()` function.
-33
View File
@@ -1,33 +0,0 @@
# R12 release reference gate fix
## Failure
`bun run scripts/release.ts publish` could stop with:
```text
UI component reference is stale.
M packages/ui/component-reference.json
```
even when the generated content was current.
## Root cause
The release gate used `git status --short` immediately after the generator ran. On Windows, generated files are written with LF while an `autocrlf` checkout may use CRLF. Git status can report the worktree file as modified even when its canonical Git content is unchanged.
The generator also writes `component-catalog.json`, but that file was not part of the release gate. Component ordering used `localeCompare`, which can vary by operating-system locale.
## Fix
- Compare generated files with `git diff --quiet`, which applies Git text normalization.
- Show real differences with `git diff --name-status`.
- Include all generated UI reference files:
- `packages/ui/component-catalog.json`
- `packages/ui/component-reference.json`
- `packages/ui/COMPONENTS.md`
- Replace locale-dependent sorting with a deterministic ASCII comparator.
- Add validation guards for the complete release gate.
## Expected result
A line-ending-only rewrite does not block publication. A real component-reference, catalog, or documentation difference still blocks publication and prints the exact changed files.
-19
View File
@@ -1,19 +0,0 @@
# WRNexusJS 0.6.0 R13 - UI reference release stability
## Problem
`release:private` regenerated the UI component catalog and reference before publishing. On Windows, the generator always wrote LF output. When the checked-out JSON files used CRLF, Git reported both generated JSON files as modified even though their normalized content was already current.
## Fix
- Added normalized newline comparison to `scripts/generate-ui-component-reference.mjs`.
- Generated files are no longer rewritten when their content differs only by line endings.
- Real generated-content differences are still written and remain visible to the release gate.
- Added `scripts/test-ui-reference-generation.mjs` to execute both the CRLF no-op case and the genuine stale-content repair case.
- Wired the executable regression into `scripts/validate-0.6.mjs`.
## Verified behavior
- Current CRLF catalog/reference files remain byte-for-byte unchanged.
- A stale reference count is regenerated to the correct value.
- Release verification still blocks real generated-content drift.
-21
View File
@@ -1,21 +0,0 @@
# WRNexusJS v0.6.0 R5 store type regression fix
R4 accidentally restored an older `@wrnexus/store` type surface while changing the syntax package import boundary.
## Corrected
- Shared, client, and server store state now use separate generic types.
- `StoreCombinedState<S, CS, SS>` is used by computed values, actions, persistence, and lifecycle hooks.
- Store action inference defaults to callable `StoreFunction` values instead of `never`.
- `createClientState` and `createServerState` no longer have to overlap with shared state.
- The internal initialization promise is named `whenReady`, allowing application state to use `ready` safely.
- Generated browser stores also expose `whenReady` rather than reserving `ready`.
- `validate:0.6` now guards all of these signatures to prevent regression.
## Focused validation
- `packages/store/test/store.test.ts` passes strict TypeScript checking with a local `bun:test` type shim.
- Runtime probe passes client/server action selection, computed values, client-only state, server-state serialization exclusion, and a boolean state field named `ready`.
- VS Code tests: 28 passed.
- VS Code validation: all checks passed.
- Repository v0.6 validator: 14 passed, 0 failed; only the expected local Bun availability warning remains in the packaging environment.
-53
View File
@@ -1,53 +0,0 @@
# WRNexusJS v0.6.0 R7 test-cascade fixes
This revision addresses the 71 failures reported after running `bun run check` on R6.
## Root fixes
1. **Synchronous CSR hydration restored**
- Scopes without a browser module hydrate immediately again.
- The unresolved `__WRNEXUS_CLIENT_MODULE__` placeholder used by direct compiler/test rendering also hydrates inline behavior immediately.
- Real resolved browser modules still load asynchronously before scope setup.
2. **Component event target selection corrected**
- A scope with its own `data-wrn-events` now uses itself before searching descendants.
3. **Lifecycle validation restored**
- Component lifecycle supports `mount`, `update`, and `unmount`.
- Compatibility aliases `clientInit` and `dispose` map to mount/unmount.
- Unknown component and store lifecycle hooks fail parsing.
4. **Browser binding collisions fixed**
- Runtime names such as `output`, `server`, `props`, and `refs` are not generated as implicit state/prop aliases.
- Function parameters may still intentionally use those names.
5. **Synchronous page exports preserved**
- Pages remain synchronous unless imported stores require `await`.
- This restores in-process WRN HMR module behavior.
6. **Store dispose lifecycle mutations fixed**
- `dispose` now runs through the same internal mutation guard as initialization and hydration hooks.
7. **Typed UI contract tests updated**
- Tests inspect parsed typed props and `outputs {}` declarations instead of matching legacy untyped declarations and `@event` lines.
- Dropdown danger styling is asserted through its canonical `data-danger="true"` state.
8. **Component reference generation corrected**
- Output payload parsing now supports nested parentheses and object/union types.
- RangeSlider now documents `input`, `change`, `focus`, and `blur`.
- FeatureGrid now includes the universal `size` and `color` props.
## Focused validation performed
- 250 WRN UI/showcase files parsed, generated, and browser-module syntax checked.
- 108 UI browser modules generated without syntax errors.
- Unknown lifecycle hook rejection passed.
- Reserved output/prop browser codegen probe passed.
- Synchronous non-store page generation probe passed.
- Store clientInit/dispose mutation probe passed.
- UI component reference exactly matches parsed public outputs.
- Component reference regeneration is idempotent.
- VS Code extension: 28 tests passed and all validation checks passed.
- `node scripts/validate-0.6.mjs`: 15 passed, 0 failed; Bun warning only.
The complete Bun workspace test suite must still be run on a machine with installed dependencies.
-28
View File
@@ -1,28 +0,0 @@
# WRNexusJS v0.6.0 R8 UI compile fixes
R8 fixes the remaining UI test cascade reported after R7.
## Root causes
1. Readonly-prop diagnostics treated comparison operators such as `===` as assignments.
2. Text inside JavaScript string literals, including selectors such as `input[name='...']`, was scanned as executable assignment syntax.
3. Function parameters that intentionally shadowed prop names were treated as mutations of those props.
4. `component-catalog.json` did not contain four bundled declarations even though the generated component reference did.
## Changes
- Added JavaScript trivia masking before readonly-prop mutation analysis.
- Assignment recognition now distinguishes `=`, compound assignments, `++`, and `--` from `==`, `===`, `=>`, and comparisons.
- `props.name = ...` is still rejected.
- Bare prop assignment is ignored when the name is a function parameter or local variable.
- Syntax and typecheck packages now share the same readonly-prop mutation detector.
- Component catalog generation now includes every bundled component while preserving existing metadata.
- Added R8 validation gates that compile all 108 UI components, verify native attribute forwarding, and compare catalog/reference declarations.
## Focused validation
- 108/108 UI components compile.
- 108/108 UI components include native attribute forwarding.
- Component catalog: 108 declarations.
- Component reference: 108 declarations.
- Generated showcase: 108 detail pages, 417 demos, 11 categories.
-25
View File
@@ -1,25 +0,0 @@
# WRNexusJS v0.6.0 R9 — ToggleCount animation stability
R9 fixes the final full-suite failure in `ToggleCount`.
## Root cause
The previous animation scheduled the next frame only after the preceding timeout fired. Under a heavily loaded full test suite, timer drift accumulated across every frame and the animation could finish later than `animationDuration`.
## Fix
- Every animation frame is scheduled immediately against its absolute offset within `animationDuration`.
- The displayed value remains at the previous value synchronously after a toggle.
- Every intermediate value is rounded to an integer.
- The final value is independently scheduled at exactly `animationDuration`.
- Animation tokens prevent stale timers from an earlier toggle overwriting a newer selection.
- Browser modules now bind peer client/shared functions through `context.functions`, so generated functions can safely call one another.
- `animateValueAt` is classified as a client function because it touches DOM nodes and schedules browser timers.
## Local validation
```powershell
bun install
bun run validate:0.6
bun run check
```
-18
View File
@@ -1,18 +0,0 @@
# WRNexusJS 0.6.0 syntax package root export fix
The v0.6 parser helpers are implementation details of `@wrnexus/syntax`, not a separate public versioned package surface.
## Canonical usage
```ts
import {
parseRuntimeFunctions,
parseStateDeclarations,
parseOutputs,
stripRuntimeFunctionModifiers,
} from "@wrnexus/syntax";
```
The compiler now imports `stripRuntimeFunctionModifiers` from `@wrnexus/syntax`. The `./v060` package export and the VS Code standalone-bundle alias were removed. `packages/syntax/src/v060.ts` remains an internal source module and its public APIs are re-exported by `packages/syntax/src/index.ts`.
This keeps application and framework imports stable across future releases and avoids exposing version numbers in package import paths.
-17
View File
@@ -1,17 +0,0 @@
# WRNexusJS v0.6.0 typecheck correction R2
This correction addresses the first local Bun validation failures reported after the focused issues 1-7 build.
## Corrected
- Added a valid root `.vscode/settings.json` so the v0.6 JSON validator succeeds.
- Store definitions now model shared, client-only, and server-only state as separate inferred object types.
- Store actions no longer infer as `never`; action methods remain callable from returned store instances.
- Renamed the internal initialization promise from `ready` to `whenReady` so application state may safely declare a field named `ready`.
- Updated generated browser-store modules to use the same collision-safe `whenReady` field.
## Focused validation
- `packages/store/test/store.test.ts` passes strict TypeScript checking with a local Bun test declaration shim.
- A live Node type-stripping probe passed server/client action dispatch, computed state, server-state exclusion, and the `ready` state collision case.
- `node scripts/validate-0.6.mjs` reports 12 passed, 0 failed in the packaging environment; only the expected warning remains because Bun is unavailable there.
-11
View File
@@ -1,11 +0,0 @@
# WRNexusJS 0.6.0 VS Code compiler bundle fix
The standalone VS Code compiler bundle must resolve the public syntax package through:
```text
@wrnexus/syntax -> packages/syntax/src/index.ts
```
The v0.6 syntax helpers are re-exported by `packages/syntax/src/index.ts`. No public or bundled import uses a version-specific `@wrnexus/syntax/v060` path.
This makes the editor compiler self-contained while keeping the package API stable.
-30
View File
@@ -1,30 +0,0 @@
# WRNexusJS 0.7.0 R1 — Local environment audit boundary
## Problem
The security audit recursively scanned every file in the working directory. Local, ignored environment files such as `examples/basic-app/.env` and `.env.uat` therefore failed the release audit even though they were not tracked by Git and would not be published.
## Fix
- Release security checks now scan `git ls-files -z` when Git metadata is available.
- Secret-like files tracked by Git still fail with `SEC-NO-TRACKED-SECRET-FILES`.
- Ignored or untracked local secret files produce `SEC-LOCAL-SECRET-FILES` warnings only.
- Source archives without `.git` metadata still scan every included file.
- The JSON report schema is updated to version 2 and includes warnings separately from errors.
## Existing repositories
If old `.env` files are still tracked, remove them from the Git index while retaining local copies:
```powershell
git rm --cached examples/basic-app/.env examples/basic-app/.env.uat
git add examples/basic-app/.env.example examples/basic-app/.env.uat.example .gitignore
git commit -m "security(examples): stop tracking local environment files"
```
The root `.gitignore` now also explicitly allows environment templates for named environments:
```gitignore
!.env.example
!.env.*.example
```
-19
View File
@@ -1,19 +0,0 @@
# WRNexusJS 0.7.0 R2 — Root Typecheck Fix
## Cause
The R1 source archive accidentally contained two temporary files used only for a dependency-free focused compile:
- `focus-shims.d.ts`
- `tsconfig.focus.json`
The root `tsc --noEmit` command automatically included `focus-shims.d.ts`. Its intentionally broad declarations replaced or merged with the installed Bun, Node.js, TypeScript, Happy DOM, filesystem, child-process, and build-tool declarations. That caused callback parameters to become implicit `any`, removed real Bun APIs and generics, and produced the reported 78 errors across otherwise valid source files.
## Fix
- Removed `focus-shims.d.ts` from the source tree.
- Removed `tsconfig.focus.json` from the source tree.
- Added a `validate:0.7` release guard that fails if either temporary file is present.
- Re-ran the root TypeScript program with typed Bun/Node/TypeScript module declarations.
No public framework API or runtime behavior changed in this correction.
-43
View File
@@ -1,43 +0,0 @@
# WRNexusJS 0.7.0 R3 — Workspace Repair and Typecheck Isolation
## Problem
Applying a source ZIP over an existing Git checkout cannot delete files or change the Git index. Two local focused-typecheck files and two previously tracked environment files therefore survived earlier archive updates:
- `focus-shims.d.ts`
- `tsconfig.focus.json`
- `examples/basic-app/.env`
- `examples/basic-app/.env.uat`
The ambient declarations in `focus-shims.d.ts` replaced or weakened the installed Bun, Node.js, TypeScript, filesystem, child-process, Happy DOM, and tsup typings. That produced dozens of false `implicit any`, missing namespace member, and untyped `Bun.serve` errors.
## Corrections
1. Root `tsconfig.json` now has explicit include/exclude rules and always excludes focused-typecheck helper files.
2. Added `bun run repair:workspace` to:
- remove the two temporary typecheck files;
- remove unsafe secret-like files and temporary shims from Git tracking;
- preserve local `.env` file contents;
- ensure the required `.gitignore` rules exist.
3. Added `bun run check:workspace` for non-mutating CI/release verification.
4. `validate:0.7` warns about local leftovers instead of allowing a TypeScript cascade, and verifies that the root typecheck excludes them.
5. The security audit blocks tracked typecheck shims and tracked environment files with the repair command in its error message.
6. Release prepare/publish now runs `check:workspace` before validation.
7. Package staging rejects `focus-shims.d.ts` and `tsconfig.focus.json`.
8. Added an executable Git regression test proving local environment values are retained while unsafe files are removed from tracking.
## Required one-time command for an existing checkout
```powershell
bun run repair:workspace
```
Then review and commit the index changes:
```powershell
git status
git add .gitignore package.json tsconfig.json scripts
git commit -m "fix(tooling): isolate temporary typecheck files and repair workspace state"
git push origin main
```
-29
View File
@@ -1,29 +0,0 @@
# WRNexusJS 0.7.0 R4 — Happy DOM Event Type Correction
## Problem
`packages/validation/test/validation.test.ts` returned the browser DOM `Event` type from its synthetic event helper. Happy DOM elements require Happy DOM's own event class, so strict TypeScript reported two incompatible `dispatchEvent()` calls.
## Fix
The helper now derives its event type directly from Happy DOM's own `document.dispatchEvent` parameter:
```ts
type HappyDOMEvent = Parameters<Window["document"]["dispatchEvent"]>[0];
type HappyDOMEventConstructor = new (type: string, init?: EventInit) => HappyDOMEvent;
function windowEvent(win: Window, type: string, init?: EventInit): HappyDOMEvent {
const EventConstructor = (win as unknown as { Event: HappyDOMEventConstructor }).Event;
return new EventConstructor(type, init);
}
```
This keeps browser DOM tests and Happy DOM tests type-safe without using an unsafe browser `Event` return type.
## Workspace repair
The two `.env` files and temporary focused-typecheck files shown by `check:workspace` are local leftovers. Run `bun run repair:workspace` once before the security audit. The command preserves local `.env` contents while removing unsafe files from Git tracking.
## Additional improvement
`check:workspace` now says `would remove` in check mode, instead of incorrectly implying files were already removed.
@@ -1,21 +0,0 @@
# WRNexusJS 0.7.0 R5 — Happy DOM element/event type alignment
## Problem
R4 returned Happy DOM `Event` objects from the test helper, but two inputs were still cast to the browser DOM `HTMLInputElement` type. TypeScript therefore rejected the Happy DOM event at `dispatchEvent()`.
## Correction
`packages/validation/test/validation.test.ts` now imports and consistently uses Happy DOM types for:
- `Event`
- `IEventInit`
- `HTMLElement`
- `HTMLInputElement`
- `HTMLFormElement`
The input, field, error and form nodes no longer use browser DOM global casts. Submit events also no longer cast back to the browser DOM `Event` type.
## Regression gate
`validate:0.7` now verifies that the validation tests use one Happy DOM type system and rejects the old `as unknown as HTMLInputElement`, `HTMLFormElement`, or `HTMLElement` casts.
-26
View File
@@ -1,26 +0,0 @@
# WRNexusJS 0.7.0 R6 - Lint cleanup
R6 fixes the remaining root ESLint findings reported after R5.
## Corrections
- Replaced control-character regular expressions in compiler, security URL validation, and syntax diagnostics with explicit ASCII character-code checks.
- `renderStoreHydration()` now actually uses `serializeForHtml()` for bounded, prototype-safe, HTML-safe hydration JSON.
- SBOM parse errors preserve the original caught error through `ErrorOptions.cause`.
- The workspace repair regression imports `node:process` explicitly.
- ESLint and Prettier ignore local `focus-shims.d.ts` and `tsconfig.focus.json` leftovers until `bun run repair:workspace` removes them.
- Added `validate:0.7` guards for every R6 regression.
## Security behavior retained
URLs containing ASCII whitespace, C0 control characters, or DEL are rejected by `@wrnexus/security`. Static compiler and syntax checks continue to normalize embedded C0 characters before detecting dangerous protocols such as `javascript:`.
## Local validation
Run on the target Bun workspace:
```powershell
bun run repair:workspace
bun install
bun run check
```
-40
View File
@@ -1,40 +0,0 @@
{
"release": "0.6.0",
"scope": "Specification issues 1 through 7",
"status": "passed-focused-validation",
"fullBunSuiteExecuted": false,
"results": {
"frameworkPackages": 33,
"uiComponents": 108,
"generatedUiBrowserModules": 108,
"browserModuleSyntaxFailures": 0,
"wrnFilesParsed": 250,
"wrnParseFailures": 0,
"unknownTypesInsideUiOutputContracts": 0,
"showcaseComponentPages": 108,
"showcaseLiveDemos": 417,
"showcaseCategories": 11,
"vscodeNodeTestsPassed": 28,
"repositoryValidatorPassed": 12,
"repositoryValidatorWarnings": 1,
"repositoryValidatorFailed": 0
},
"focusedProbes": {
"browserStoreRpc": "passed",
"persistenceMigration": "passed",
"persistenceValidation": "passed",
"storeHmr": "passed",
"legacyImportMode": "passed",
"compatibleImportMode": "passed",
"explicitImportMode": "passed",
"restrictedComponentRpcManifest": "passed",
"restrictedStoreRpcManifest": "passed",
"generatedServerStoreTypeScript": "passed"
},
"remainingReleaseGate": [
"bun install",
"bun run validate:0.6",
"bun run check",
"bun run --cwd examples/component-showcase check"
]
}
-20
View File
@@ -1,20 +0,0 @@
{
"release": "0.7.0-r1",
"fix": "Git-tracked secret-file audit boundary",
"results": {
"validate_0_7": {
"passed": 35,
"failed": 0
},
"clean_archive_security_audit": "passed",
"ignored_local_env_files": {
"result": "warning-only",
"exitCode": 0
},
"git_tracked_env_files": {
"result": "blocked",
"exitCode": 1
},
"javascript_syntax": "passed"
}
}
-30
View File
@@ -1,30 +0,0 @@
{
"release": "0.7.0-r2",
"reportedTypeScriptErrors": 78,
"reportedFiles": 28,
"rootCause": [
"focus-shims.d.ts was accidentally included in the release source and automatically loaded by the root TypeScript program",
"tsconfig.focus.json was a temporary packaging-only configuration and should not have been distributed"
],
"removedFiles": ["focus-shims.d.ts", "tsconfig.focus.json"],
"hardening": [
"validate:0.7 now rejects temporary focused-typecheck files",
"compressed response bodies are copied into a concrete ArrayBuffer for TypeScript 5.9 DOM compatibility",
"Happy DOM event constructors are accessed through explicit typed window shapes",
"Redis tests use the typed Bun global directly",
"package publishing imports node:process explicitly"
],
"validation": {
"rootTypeScriptProgram": "passed",
"validate07": { "passed": 36, "failed": 0 },
"securityFramework": { "passed": 10, "failed": 0 },
"validate06Compatibility": { "passed": 20, "warnings": 1, "failed": 0 },
"vscodeTests": { "passed": 28, "failed": 0 },
"vscodeValidation": "passed",
"temporaryFileGuard": {
"temporaryFilePresentExitCode": 1,
"temporaryFileAbsentExitCode": 0
}
},
"localAuthoritativeCommand": "bun run check"
}
-28
View File
@@ -1,28 +0,0 @@
{
"release": "0.7.0-r3",
"focus": "workspace repair, tracked secret cleanup, and root typecheck isolation",
"results": {
"validate_0_7": {
"passed": 37,
"warnings": 0,
"failed": 0
},
"security_framework": "passed",
"validate_0_6_compatibility": {
"passed": 20,
"warnings": 1,
"failed": 0
},
"workspace_repair_git_regression": "passed",
"package_staging_integrity": "passed",
"temporary_shim_excluded_from_root_typescript_program": "passed",
"vscode_tests": {
"passed": 28,
"failed": 0
},
"vscode_extension_validation": "passed",
"sbom_components": 339
},
"local_full_bun_check_required": true,
"required_command": "bun run repair:workspace && bun run check"
}
-26
View File
@@ -1,26 +0,0 @@
{
"release": "0.7.0-r4",
"fix": "Happy DOM synthetic event type compatibility",
"results": {
"validate_0_7": {
"passed": 38,
"warnings": 0,
"failed": 0
},
"security_framework_audit": "passed",
"workspace_repair_regression": "passed",
"validate_0_6_compatibility": {
"passed": 20,
"warnings": 1,
"failed": 0
},
"vscode_tests": {
"passed": 28,
"failed": 0
},
"vscode_extension_validation": "passed",
"happy_dom_event_type_structural_compile": "passed",
"zip_integrity": "passed"
},
"environment_limit": "Bun and the repository dependency tree are unavailable in the packaging environment, so the complete bun run check remains required on the target Windows workspace."
}
-31
View File
@@ -1,31 +0,0 @@
{
"release": "WRNexusJS 0.7.0 R5",
"fix": "Happy DOM event and element receiver type alignment",
"validation": {
"validate_0_7": {
"passed": 38,
"warnings": 0,
"failed": 0
},
"security_framework": "passed",
"validate_0_6": {
"passed": 20,
"warnings": 1,
"failed": 0
},
"vscode_tests": {
"passed": 28,
"failed": 0
},
"vscode_extension_validation": "passed",
"focused_happy_dom_type_compile": "passed",
"full_bun_typecheck": "requires target Windows environment"
},
"changed_files": [
"packages/validation/test/validation.test.ts",
"scripts/validate-0.7.mjs",
"FIXES-0.7.0-R5-HAPPY-DOM-ELEMENT-EVENT-TYPES.md",
"CHANGES-0.6.0.md",
"RELEASE_NOTES-0.7.0.md"
]
}
-19
View File
@@ -1,19 +0,0 @@
{
"release": "0.7.0-r6",
"reportedLintFindings": 8,
"reportedErrorsFixed": 5,
"reportedWarningsFixedOrIsolated": 3,
"validation": {
"validate07": { "passed": 41, "warnings": 0, "failed": 0 },
"securityFrameworkAudit": "passed",
"workspaceRepairRegression": "passed",
"packageStagingIntegrity": "passed",
"focusedTypeScript": "passed",
"urlControlCharacterProbe": "passed",
"compatibilityValidator06": { "passed": 20, "warnings": 1, "failed": 0 },
"vscodeTests": { "passed": 28, "failed": 0 },
"vscodeValidation": "passed",
"benchmarkFramework": "passed"
},
"environmentBoundary": "Bun and repository ESLint dependencies are unavailable in the packaging environment; run bun run check on the target Windows workspace."
}
-68
View File
@@ -1,68 +0,0 @@
{
"release": "0.7.0",
"implementation": {
"requestedAreas": 21,
"implementedAreas": 21,
"newPackages": 5,
"frameworkPackages": 38
},
"validators": {
"v070": {
"passed": 34,
"failed": 0
},
"v060Compatibility": {
"passed": 20,
"warnings": 1,
"failed": 0,
"warning": "Bun unavailable in packaging environment"
},
"securityPerformanceAudit": {
"passed": 10,
"failed": 0
}
},
"compiler": {
"wrnFilesCompiled": 281,
"uiComponentsCompiled": 108,
"browserModulesSyntaxChecked": 108,
"failures": 0
},
"vscode": {
"compilerModulesBundled": 24,
"testsPassed": 28,
"testsFailed": 0,
"extensionValidationPassed": true
},
"supplyChain": {
"sbomFormat": "CycloneDX 1.5",
"sbomComponents": 339,
"workspaceComponents": 38,
"deterministic": true,
"packageStageIntegrityProbePassed": true
},
"benchmarks": {
"syntaxParseComponent": {
"meanMs": 0.19686705000000188,
"p95Ms": 0.4446000000000083,
"operationsPerSecond": 5079.570197247282
},
"secureHydrationSerialization": {
"meanMs": 0.05032330799999943,
"p95Ms": 0.07434000000000651,
"operationsPerSecond": 19871.50765208065
},
"tagCacheRead100": {
"meanMs": 0.018023848000000498,
"p95Ms": 0.04413500000001136,
"operationsPerSecond": 55482.04800661725
}
},
"typeScript": {
"focusedStrictIntegrationPassed": true
},
"completeBunCheck": {
"runInPackagingEnvironment": false,
"requiredOnTargetMachine": true
}
}
-7
View File
@@ -1,7 +0,0 @@
{
"uiComponents": 108,
"browserTargetsChecked": 108,
"wrnFilesParsed": 250,
"peerFunctionStateProbe": "passed",
"failures": []
}
-13
View File
@@ -1,13 +0,0 @@
{
"release": "WRNexusJS v0.6.0 R11",
"fixedTest": "browser codegen binds peer client functions through the scoped function table",
"cause": "The test used /^export\\\\s+/gm, matching a literal backslash-s instead of whitespace, so export keywords remained in code passed to new Function().",
"correctPattern": "/^export\\s+/gm",
"peerFunctionStateResult": 1,
"validator": {
"passed": 19,
"warnings": 1,
"failed": 0,
"warning": "Bun is unavailable in the packaging environment; run the complete suite locally."
}
}
-19
View File
@@ -1,19 +0,0 @@
{
"releaseReferenceGate": {
"deterministicGeneration": true,
"lineEndingOnlyDiffIgnored": true,
"regeneratedReferenceClean": true,
"realContentDifferenceDetected": true,
"generatedFiles": [
"packages/ui/component-catalog.json",
"packages/ui/component-reference.json",
"packages/ui/COMPONENTS.md"
]
},
"validation": {
"passes": 20,
"warnings": 1,
"failures": 0,
"warning": "Bun is unavailable in the packaging environment; run the full Bun check locally."
}
}
-18
View File
@@ -1,18 +0,0 @@
{
"releaseReference": {
"crlfCurrentFilesUntouched": true,
"staleContentRegenerated": true,
"realDriftStillDetected": true
},
"rootValidator": {
"passed": 20,
"warnings": 1,
"failed": 0,
"warning": "Bun unavailable in packaging environment"
},
"vscode": {
"testsPassed": 28,
"testsFailed": 0,
"validationPassed": true
}
}
-13
View File
@@ -1,13 +0,0 @@
{
"revision": "R7",
"wrnFilesChecked": 250,
"uiComponentsChecked": 108,
"browserModuleSyntaxFailures": 0,
"componentReferenceMismatches": 0,
"vscodeTestsPassed": 28,
"vscodeTestsFailed": 0,
"validatorPassed": 15,
"validatorFailed": 0,
"fullBunSuiteExecuted": false,
"remainingGate": "bun run check"
}
-27
View File
@@ -1,27 +0,0 @@
{
"release": "WRNexusJS 0.6.0 R8",
"reportedFailuresAddressed": 20,
"rootCauses": [
"readonly prop diagnostics confused comparisons with assignments",
"readonly prop diagnostics scanned JavaScript strings and comments",
"readonly prop diagnostics ignored function parameter shadowing",
"component catalog omitted four bundled declarations"
],
"validation": {
"uiComponentsDeclared": 108,
"uiComponentsCompiled": 108,
"nativeAttributeForwarding": 108,
"componentReferenceDeclarations": 108,
"componentCatalogDeclarations": 108,
"showcaseDetailPages": 108,
"showcaseLiveDemos": 417,
"showcaseCategories": 11,
"vscodeTestsPassed": 28,
"vscodeTestsFailed": 0,
"rootValidatorPassed": 16,
"rootValidatorFailed": 0,
"readonlyComparisonProbe": "passed",
"readonlyMutationProbe": "passed"
},
"remainingReleaseGate": "Run bun install and bun run check on the target machine."
}
-8
View File
@@ -1,8 +0,0 @@
{
"uiComponents": 108,
"browserTargetsChecked": 108,
"wrnFilesParsed": 250,
"toggleFrameOffsets": [10, 20, 30, 40],
"toggleFinalValue": "10",
"failures": []
}
-67
View File
@@ -1,67 +0,0 @@
# WRNexusJS 0.7.0 — 21-Point Security and Performance Implementation
WRNexusJS 0.7.0 implements the framework-side foundations for all 21 requested security and performance areas. Secure defaults, compiler diagnostics, runtime enforcement, production reports, release gates, and adapter interfaces are included in this source release.
External infrastructure remains an application/deployment responsibility: TLS termination, Redis or another distributed cache, antivirus/CDR engines, image transcoding services, CDN configuration, an OTLP/metrics backend, database indexes, registry MFA, and project-specific authorization policy.
## Implementation matrix
| # | Area | Implemented in 0.7.0 |
| --: | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | Targets and budgets | Expanded route, CSS, HTML, image, hydration, SSR, Web Vitals, request-count, and long-task budgets with warning/error enforcement and build reporting. |
| 2 | Compiler/template security | Context-aware URL validation, unsafe protocol diagnostics, dangerous DOM/dynamic-code diagnostics, client/server boundary checks, persisted-secret checks, Trusted HTML policy, and bounded secure hydration serialization. |
| 3 | Browser headers | CSP with nonce/report-only support, Trusted Types, HSTS, COOP, CORP, Referrer-Policy, Permissions-Policy, nosniff, frame protection, Origin-Agent-Cluster, and presets. |
| 4 | Sessions/authentication | Idle and absolute expiry, sliding access, secure cookie defaults, server-side session backend support, and safer session lifecycle configuration. |
| 5 | CSRF/CORS/authorization | CSRF token plus Origin and Fetch Metadata validation, opt-in exact-origin CORS, and continued server-side authz/tenant policy enforcement. |
| 6 | Gateway/API hardening | URL/header/query/body limits, timeouts, concurrency limits, host/proxy trust, request IDs, IP rate limits, Fetch Metadata, access logs, and WebSocket queue/origin/message controls. |
| 7 | SSRF | Safe fetch validates protocols and hosts, resolves and checks addresses, blocks private/special networks, revalidates redirects, limits size/time/redirects, and avoids credential forwarding. |
| 8 | Uploads | Extension/MIME/size/aggregate/path controls, generated names, secure download disposition, inspector hooks, and antivirus/CDR adapter interfaces. |
| 9 | Database | Query timing, timeouts, row caps, slow-query reporting, duplicate/N+1 detection, SELECT-star/unbounded-query warnings, and per-request query records. |
| 10 | SSR/server | Runtime route classification, zero-JS/prerender analysis, request dedupe and cache foundations, streaming compatibility, and build-report visibility. |
| 11 | Hydration/CSR | Static pages default to zero framework JavaScript, auto/client/document navigation modes, partial/lazy hydration foundations, batched reactive work, keyed updates, cancellation/disposal, and hydration telemetry. |
| 12 | Build/bundles | Server/client separation, minification/hashing support, immutable runtime assets, runtime classification, production build reports, and enforceable budgets. |
| 13 | CSS | Existing minification/token tooling plus diagnostics for transition-all, expensive blur/shadow patterns, broad selectors, and duplicate keyframes. |
| 14 | Images/icons/fonts | Responsive image planning, srcset/sizes/dimensions/loading/decoding/fetch-priority policy, remote-host validation, LCP/oversizing audits, and continued per-icon/font optimization helpers. |
| 15 | HTTP delivery | Brotli-first negotiation, gzip fallback, compression exclusions, ETags/conditional responses, immutable assets, cache-control helpers, stale policies, and preload/modulepreload support. |
| 16 | Realtime/WebSocket | Authentication, origins, message byte/rate/depth limits, room/user quotas, schema and authorization predicates, prototype-pollution rejection, and gateway backpressure controls. |
| 17 | Observability | Counters, gauges, histograms, HTTP middleware, request/error/active-request metrics, same-origin Web Vitals, browser collector, exporters, and Server-Timing integration. |
| 18 | DevToolbar | Security checks for forms/CSRF/CSP/mixed content/storage/hydration leaks and performance checks for transfer, DOM, hydration, images, blocking assets, and long tasks. |
| 19 | Tests/release gates | 0.7 validator, production security audit, benchmark budgets, type/lint/test/format pipeline, deterministic UI references, stage integrity checks, and compatibility validation. |
| 20 | Supply chain | Private release policy, aligned versions, explicit migration, deterministic CycloneDX SBOM, secret/source-map/source leakage scanning, package SHA-256 manifests, and clean/pushed Git requirements. |
| 21 | New packages | `@wrnexus/security`, `@wrnexus/cache`, `@wrnexus/image`, `@wrnexus/observability`, and `@wrnexus/benchmark`. |
## Compatibility
- Existing 0.6 component, parser, store, RPC, and runtime contracts remain supported.
- The updater preserves existing security, performance, observability, and navigation configuration.
- New projects use `navigation.mode: "auto"`; fully static routes ship no WRNexusJS JavaScript.
- Set `navigation.mode: "client"` only when every route requires in-place client navigation.
## Mandatory project review before production
Framework controls do not replace application-specific review. Each production project must define and test:
- Roles, permissions, object ownership, tenant boundaries, and sensitive field access.
- CSP source allowlists and third-party scripts.
- Trusted proxies, public hosts, CORS origins, WebSocket origins, and outbound URL allowlists.
- Session duration, MFA/passkey requirements, recovery policy, and high-risk reauthentication.
- Upload type policy, storage isolation, antivirus/CDR adapters, quotas, and retention.
- Cache privacy and invalidation for authenticated or tenant-specific data.
- Database indexes, pool sizes, query limits, backups, and migration rollback.
- Observability retention, sampling, redaction, and incident alerts.
- CDN/TLS configuration, registry MFA, short-lived publish credentials, and disaster recovery.
## Production gates
```sh
bun install
bun run validate:0.7
bun run security:framework
bun run sbom
bun run benchmark:framework
bun run validate:staging
bun run check
bun run release:prepare
```
Run `release:private` only after generated files and release changes are committed, pushed, and the working tree is clean.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 WorkRoot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-28
View File
@@ -1,28 +0,0 @@
# WRNexusJS 0.7.0 local validation requirement
The packaging environment does not provide Bun or the repository's installed ESLint/Prettier dependencies. Source-only TypeScript, Node-compatible validators, compiler sweeps, security probes, benchmarks, SBOM generation, package-stage integrity probes, and VS Code tests were completed here.
The authoritative complete validation must run in the target Windows repository with Bun 1.3 or newer:
```powershell
bun install
bun run validate:0.7
bun run security:framework
bun run sbom
bun run benchmark:framework
bun run validate:staging
bun run check
```
`bun run check` is required because it executes the complete repository TypeScript, ESLint, Bun test, and Prettier checks with the actual dependency graph.
Before publication:
```powershell
bun run release:prepare
git status
git push origin main
bun run release:private
```
Do not publish if the working tree is dirty, the generated UI reference changes, a benchmark budget fails, the security audit reports an error, or staged package integrity verification fails.
-32
View File
@@ -1,32 +0,0 @@
# Local validation required for WRNexusJS 0.6.0
Issues 1 through 7 from the specification validation report have been corrected and focused-tested. The remaining release gate is the complete Bun suite on your development machine.
## Run the complete framework suite
```powershell
bun install
bun run validate:0.6
bun run check
```
## Regenerate and validate UI documentation/showcase
```powershell
bun run scripts/generate-ui-component-reference.mjs
bun run --cwd examples/component-showcase generate
bun run --cwd examples/component-showcase test
bun run --cwd examples/component-showcase build
```
## Test migration and compatibility using a real project copy
```powershell
wrnexus update --dry-run --report
wrnexus update
bun run check
```
Confirm that a second migration run makes no changes. Test one new project and at least one existing deployed application before publishing.
Do not publish the final npm or VS Code release until these commands pass and the upgraded application behaves correctly in SSR, CSR navigation, HMR, RPC, stores, outputs, imports, and component interactions.
-10
View File
@@ -1,10 +0,0 @@
{
"fixture": "integration/fixtures/v0.5-legacy-app",
"dryRun": true,
"changedAutomatically": ["app/components/LegacyModal.wrn", "app/pages/index.wrn"],
"needsReview": [],
"unresolvedImports": [],
"ambiguousFunctions": [],
"legacyOutputPayloads": ["app/components/LegacyModal.wrn: confirm(payload: unknown)"],
"parseFailures": []
}
-18
View File
@@ -1,18 +0,0 @@
# Migration dry-run report template
Run against each existing project:
```powershell
wrnexus update --version=0.6.0 --dry-run --report
```
The generated `.wrnexus/migrations/0.6.0-report.json` contains:
- `changedAutomatically`
- `needsReview`
- `unresolvedImports`
- `ambiguousFunctions`
- `legacyOutputPayloads`
- `parseFailures`
No application-specific dry run is claimed in this source archive; run it against copies of the real deployed applications before publishing.

Some files were not shown because too many files have changed in this diff Show More