Files
WRNexusJS/scripts/generate-complete-framework-report.mjs
T
Clintchiz b3ed9689fa
Quality / quality (ubuntu-latest) (push) Failing after 9m54s
Quality / quality (windows-latest) (push) Canceled after 0s
docs: add complete framework feature report
2026-08-19 17:52:08 +05:30

303 lines
22 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
import { join, relative } from "node:path";
import console from "node:console";
import process from "node:process";
import { format } from "prettier";
const root = process.cwd();
const json = (path) => JSON.parse(readFileSync(join(root, path), "utf8"));
const rootPackage = json("package.json");
const publicApi = json("docs/public-api-0.8.json");
const uiReference = json("packages/ui/component-reference.json");
function walk(dir, extension, out = []) {
for (const entry of readdirSync(dir)) {
const path = join(dir, entry);
const info = statSync(path);
if (info.isDirectory() && !["node_modules", "dist", ".wrnexus"].includes(entry))
walk(path, extension, out);
else if (path.endsWith(extension)) out.push(path);
}
return out;
}
const packageRows = readdirSync(join(root, "packages"), { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => {
const manifest = json(`packages/${entry.name}/package.json`);
return {
name: manifest.name,
version: manifest.version,
description: manifest.description ?? "—",
};
})
.sort((a, b) => a.name.localeCompare(b.name));
const wrnFiles = walk(join(root, "packages"), ".wrn").sort();
const packageBlocks = new Map();
for (const file of wrnFiles) {
const packageName = relative(join(root, "packages"), file).split(/[\\/]/)[0];
const list = packageBlocks.get(packageName) ?? [];
list.push(relative(root, file).replaceAll("\\", "/"));
packageBlocks.set(packageName, list);
}
const apiPackages = Object.entries(publicApi.packages);
const apiSymbolCount = apiPackages.reduce(
(total, [, entries]) =>
total + Object.values(entries).reduce((sum, symbols) => sum + symbols.length, 0),
0,
);
const lines = [];
const add = (...value) => lines.push(...value);
add(
"# WRNexusJS complete framework and `.wrn` report",
"",
`Generated for workspace version **${rootPackage.version}** from the checked-out source and generated references.`,
"",
"> Scope and source of truth: this report describes the checked-out implementation, not only the prose docs. The parser in `packages/syntax`, compiler/runtime code, package manifests, `docs/public-api-0.8.json`, and `packages/ui/component-reference.json` take precedence when older documents disagree.",
"",
"## 1. Executive summary",
"",
`- Workspace framework version: **${rootPackage.version}**. The 48 independently published packages have their own patch versions; see Appendix A.`,
"- Architecture: compiler-driven, SSR-first, Bun-native/full-stack, with Node-friendly selected tooling.",
"- Static routes retain the zero-framework-JavaScript goal; hydration is selective and islands are loaded only where declared.",
"- Current headline features include typed callable API blocks, reactive `if`/`each` control blocks, runtime-scoped state and functions, typed outputs, stores, React islands, HTML-aware editor tooling, package/plugin discovery, generated contracts, security gates, and multi-app RPC.",
`- Audited public API baseline: **${apiPackages.length} packages / ${apiSymbolCount} exported symbols** across root and subpath exports.`,
`- Audited packaged \`.wrn\` sources: **${wrnFiles.length}**; generated UI reference: **${uiReference.components.length} components**.`,
"",
"## 2. What a `.wrn` file is",
"",
"A `.wrn` file is a single compiler-owned source unit combining imports, a root declaration, typed data/state, runtime behavior, HTML view markup, styles, metadata, API handlers/bindings, and realtime handlers. It is parsed into the canonical AST owned by `@wrnexus/syntax`; `@wrnexus/compiler` turns that AST into SSR, browser, route, style, and metadata artifacts.",
"",
"Valid roots:",
"",
"| Root | Purpose |",
"| --- | --- |",
"| `page Name {}` | Routed page. |",
"| `component Name {}` | Reusable server-rendered component. |",
"| `layout Name {}` | Reusable page wrapper. |",
"| `global store Name {}` | Application-wide store. |",
"| `page store Name {}` | Page-lifetime store. |",
"",
"A file may start with static TypeScript imports. Component and layout symbols can be imported explicitly; compatibility discovery remains configurable for upgraded applications.",
"",
"## 3. Complete `.wrn` block and declaration catalog",
"",
"| Declaration/block | Shape | Meaning and current behavior |",
"| --- | --- | --- |",
"| `layout = LayoutSymbol` | root member | Preferred imported layout reference. String layout names remain a compatibility path. |",
'| `runtime = "…"` | root member | Targets: `server`, `client`, `universal`, `edge`, `worker`, `service-worker`. |',
'| `render = "…"` | root member | Modes: `static`, `server`, `hybrid`, `client`, `partial-static`. |',
'| `hydrate = "…"` | root member | `load`, `idle`, `visible`, `interaction`, `none`, or `media:<query>`; legacy `never` normalizes to `none`. |',
'| `client = "…"` | root member | Legacy alias for hydration configuration; `client {}` remains a different runtime-mode block. |',
"| `types {}` | raw TypeScript | Local type declarations emitted for checking. |",
"| `props {}` | typed declarations | Required without default; optional via `?`; defaults supported; legacy `@event name = function` is parsed for compatibility. |",
"| `outputs {}` | typed declarations | Canonical child-to-parent callable output contract, zero or one typed payload. |",
"| `state name = expr` / `state {}` | reactive data | Shared state; type annotation optional, initializer required. Arrays, objects, and multiline expressions are supported. |",
"| `server state {}` / `client state {}` | runtime-scoped data | State visible only in the declared runtime boundary. |",
"| `computed name = expr` / `computed {}` | derived data | Dependency-tracked cached values. |",
"| `effect {}` | reactive side effect | Runs after batched updates when referenced reactive values change. |",
"| `load server {}` / `load client {}` | loader | Runtime-specific loading; named/dependent/deferred forms are represented in the AST. |",
"| `action name(args) {}` | action | Named action, optionally schema-backed, exported for adapters. |",
"| `view {}` | HTML/template | HTML/component tree with expressions, events, directives, and reactive control blocks. |",
"| `style {}` | scoped CSS | Multiple blocks allowed; promoted into the document head with CSP/HMR/navigation support. |",
"| `seo {}` | metadata | Key/value SEO metadata. |",
"| `security {}` | policy metadata | Auth, CSRF, roles, rate-limit and organization-specific enforcement metadata. |",
"| `navigation {}` | navigation metadata | Page navigation policy/configuration consumed by runtime tooling. |",
"| `cache {}` | cache metadata | Declarative framework cache policy. |",
"| `functions {}` | shared helpers | Legacy/general shared helper body; runtime-specific function grammar is preferred where applicable. |",
"| `server { functions {} }` / `client { functions {} }` | mode helper block | Raw helpers scoped to SSR or browser execution. |",
"| `[async] server function name(args) {}` | callable function | Explicit server RPC boundary. |",
"| `[async] client function name(args) {}` | browser function | Explicit client callable function. |",
"| `[async] shared function name(args) {}` | universal helper | Explicit shared function. |",
"| `ssr { api … }` | render-time own-route data | Executes during render. Legacy bare response body is supported; sectioned `response`/`error` is supported; request parameters are intentionally forbidden. |",
"| `client { api … }` | callable own-route data | Sectioned form creates `api.name(input)` in browser scope; GET uses query parameters, other methods use JSON and CSRF. |",
"| `api METHOD /path {}` | route handler | Defines an application API endpoint/handler. Distinct from named data API bindings inside `ssr`/`client`. |",
"| `lifecycle { mount/update/unmount {} }` | component lifecycle | Hydrated lifecycle hooks. |",
"| `watch stateName {}` | watcher | Runs for changes to the named state. |",
"| `realtime name { on event(args) {} }` | websocket behavior | Declares named realtime handlers. |",
"| `persist {}` | store persistence | Storage (`memory`, `session`, `local`), included keys, version, migrations, and validation. |",
"| `lifecycle { serverInit/clientInit/hydrate/dispose {} }` | store lifecycle | Store-specific lifecycle form. |",
"",
"### View/template features",
"",
"- Standard HTML and custom/component tags; HTML void elements follow the platform list.",
"- Escaped `{expression}` interpolation. Raw HTML is an explicit security boundary.",
"- Browser event attributes: `@click`, `@window:scroll`, `@document:click`, and other event names.",
"- Conditional classes through `class:name='expression'`; visibility through `data-show`.",
'- Legacy loop attribute: `data-for="item, index in items key item.id"`, with optional `data-key`.',
"- Canonical control blocks: `{#if}`, `{:else if}`, `{:else}`, `{/if}` and `{#each list as item, index key expr}`, `{:empty}`, `{/each}`. Initial output is SSR and remains reactive after hydration.",
"- JSX-style expression props (`items={items}`, object/array expressions) are current; quoted expressions remain compatible. Literal HTML attributes remain quoted.",
"- React/TSX islands use imported `.tsx` components and `client:only`, `client:load`, `client:visible`, or `client:idle`. They are client-only in v1; island props must be JSON-serializable.",
"",
"### Typed callable API block (latest form)",
"",
"```wrn",
"client {",
" api searchUsers POST /api/users {",
" request { body { name?: string age?: number } }",
" response { return data.users }",
" error { return [] }",
" }",
"}",
"```",
"",
"Call it with `await api.searchUsers({ name })`. GET uses `request { parameters {} }`; non-GET uses `body {}`. Fields are type-only declarations checked against generated route contracts in `app/types/wrnexus.generated.api-checks.ts`. Success binds parsed JSON as `data`. `error {}` converts failure to its returned value; without it, non-2xx, network, and parse failures reject. Targets are restricted to the current apps `/api/*` routes. External APIs, custom headers, parameterized SSR calls, caching, and deduplication are deferred.",
"",
"Legacy API binding remains valid: `ssr { api users GET /api/users { return users } }`. Its bare body receives payload fields through the legacy dynamic scope. The sectioned form deliberately uses `data` so TypeScript can check it.",
"",
"## 4. Runtime, rendering, and data flow",
"",
"1. `@wrnexus/syntax` tokenizes/parses and emits stable diagnostics and AST nodes.",
"2. The compiler resolves imports/components/islands and generates SSR HTML functions, client modules, route/API exports, styles, metadata, and contracts.",
"3. Static pages ship no framework JS. Interactive pages receive only the required CSR runtime; island routes lazily receive React/island assets.",
"4. State changes batch, invalidate computed values, run effects/watchers, update expressions/classes/visibility, and rerender `if`/`each` regions.",
"5. Server functions use the RPC boundary; typed API blocks call same-app API routes; realtime blocks produce websocket handlers; stores bridge SSR and client state.",
"6. Generated types validate component props, outputs, functions, routes, and typed API-block request contracts during `tsc` and release checks.",
"",
"## 5. Framework feature inventory",
"",
"- Routing and rendering: filesystem pages/layouts, static/request/hybrid/client/partial-static rendering, route analysis, advanced routing, CSR navigation, layouts, streaming/SSR packages.",
"- Reactivity: state, computed values, effects, watchers, reactive attributes/events, SSR-to-client control blocks, loaders/actions, explicit hydration.",
"- Components/UI: application components, package-owned blocks, generated prop/output references, theming/tokens, 102 audited first-party UI components, app overrides/ejection.",
"- Data/backend: database drivers and migrations, repositories, cache, queue, pub/sub, realtime, GraphQL, route APIs, server functions, workspace RPC.",
"- Identity/security: auth, authorization, OAuth, JWT/JWKS, MFA/passkeys/recovery, CAPTCHA, encryption, SSRF defenses, CSP/CSRF, request limits, audit/security gates.",
"- Product capabilities: AI/RAG/provider adapters, content, i18n, image optimization, uploads, validation, PWA, native/mobile, analytics/tracking, observability.",
"- Developer experience: CLI create/dev/build/update/doctor/inspect/generate/eject/db/workspace operations, HMR, dev toolbar, language server, VS Code completion/HTML editing/formatting/diagnostics, playground, MCP, tests/benchmarks/release validation.",
"- Deployment: production builds, Docker and platform examples, migrations, package staging/integrity checks, SBOM and security/performance reports.",
"",
"## 6. Legacy-to-current migration map",
"",
"| Legacy/earlier approach | Current approach | Compatibility/status |",
"| --- | --- | --- |",
"| Compiler-owned/internal parsing imports | Canonical `@wrnexus/syntax` lexer/parser/AST/diagnostics | Compiler re-exports remain for compatibility; direct internals are deprecated. |",
"| Implicit component discovery everywhere | Explicit imports and generated contracts | Upgraded apps can retain `legacyComponentDiscovery`; unresolved symbols are reported rather than guessed. |",
'| `layout = "PublicLayout"` | Import layout and use `layout = PublicLayout` | String layouts remain behind compatibility configuration. |',
"| `@event changed = function` in props | `outputs { changed(payload: Type) }` | v0.6 migration converts declarations; ambiguous payloads become `unknown`. |",
'| `$emit("changed", value)` and `event.detail` | `output.changed(value)` and direct `payload` | Static cases auto-migrated; dynamic emit names require review. |',
"| Unclassified functions | `server function`, `client function`, or `shared function` | v0.6 classifies unambiguous cases; compatibility default can preserve ambiguous behavior. |",
"| Manually copied CAPTCHA JS/script tags | Package-discovered client runtime/assets | v0.4 removes tags and archives old assets under `.wrnexus/legacy-assets/0.4.0`. |",
"| Package components/routes/assets wired manually | Automatic package/plugin discovery and contribution registry | Current CLI/build/dev server inspect and consume contributions. |",
"| Only scalar/quoted dynamic props | Native arrays/objects and JSX-style unquoted expressions | Quoted expression attributes remain supported. |",
"| `data-for` and older each forms | `{#each …}{:empty}{/each}` | Legacy loop forms remain supported; canonical blocks offer keyed/empty/reactive behavior. |",
"| Static server-only `if`/`each` after hydration | Reactive client rerendering of control blocks | Current runtime updates branches/rows after state changes. |",
"| Bare `api` binding bodies and hand-written `fetch` for inputs | Sectioned typed callable client API blocks | Bare body stays supported; new form adds inputs, route-contract checking, CSRF, response/error transforms. |",
"| Generated API assertions in `.d.ts` | Assertions in real `wrnexus.generated.api-checks.ts` | Changed because `skipLibCheck` made `.d.ts` assertions inert. |",
"| Client functions accidentally retaining TypeScript | Compiler strips type syntax before browser-module emission | Fixed and regression-tested. |",
"| Markup merely highlighted as embedded HTML | Virtual HTML document plus HTML language service | Current editor adds tag/attribute completion, auto-close/rename, hover, Emmet, and folding; WRN formatter still owns formatting. |",
"| Framework-only component ecosystem | Optional React `.tsx` islands | React is isolated and lazy; zero-JS routes remain unchanged; island SSR/Fast Refresh are deferred. |",
"| Per-component/global style placement inconsistencies | `style {}` promoted to document head | Current pipeline supports CSP, HMR and CSR navigation. |",
"| Manually maintained API/component knowledge | Generated public API and component references plus validation gates | `check:public-api`, generated-type checks, UI visual contract and package audits detect drift. |",
"",
"Compatibility flags visible in generated/upgraded config include `legacyEmit`, `legacyEventProps`, `legacyComponentDiscovery`, `stringLayouts`, and `functions.legacyDefaultRuntime`. New projects default legacy flags off; migration-created configs may enable them to preserve behavior until source modernization is complete.",
"",
"## 7. Diagnostics, security, and correctness guarantees",
"",
"Stable diagnostics include parse/member/prop/state/hydration/runtime/accessibility codes and feature-specific diagnostics such as island prop or missing-React errors. Compiler, CLI doctor/build, type generation, and editor tooling share syntax ownership to reduce parser drift.",
"",
"Security properties include escaped output by default, CSP-aware styles/scripts, same-origin API restriction, CSRF on non-GET callable API requests, credential handling via same-origin cookies, safe serialization, SSRF policies, request limits, auth/authz metadata and middleware, secret/audit gates, and application-layer encryption where explicitly needed. Security metadata is declarative input; enforcement still belongs to installed middleware/plugins and route policy.",
"",
"## 8. Current limitations and deferred work",
"",
"- Typed API blocks do not target third-party URLs, accept custom author headers, parameterize SSR requests, or provide built-in request caching/deduplication.",
"- React islands are client-rendered in v1; island SSR/hydration and React Fast Refresh are deferred.",
"- Native compilation does not directly port data API blocks; native screens use generated backend helpers.",
"- HTML language features intentionally do not replace the WRN formatter.",
"- Generated type checks must stay fresh; `check:generated-types` is the enforcement gate.",
"",
"## 9. Documentation drift discovered by this audit",
"",
`- Root ` +
"`README.md`" +
` says 0.8.0, while the workspace manifest is ${rootPackage.version}.`,
`- ` +
"`packages/ui/README.md`" +
` says 85 components and ` +
"`docs/UI-COMPONENT-INVENTORY.md`" +
` says 891; the current generated component reference contains ${uiReference.components.length}.`,
"- `docs/WRN-LANGUAGE-SPEC-1.0.md` calls itself the 0.3.x contract and predates several implemented roots/members (stores, rendering modes, outputs, runtime-scoped state/functions, React islands, sectioned callable API blocks). Use it as historical baseline, not a complete 0.8.8 reference.",
"- Package patch versions are intentionally ahead of the workspace umbrella version in many packages. Consumers should use the actual package manifest/version selected by the release process.",
"",
"## 10. Recommended release verification",
"",
"Run `bun run check:production` for the complete production gate. Its chain covers workspace repair, generated types, public API, UI visual contract, 0.8 validation, framework/ASVS security, editor bundle freshness, typecheck, lint, component imports, package tests, formatting, and examples. Additional focused commands include `bun run test:all`, `bun run audit:packages`, `bun run test:package-kits`, `bun run validate:staging`, `bun run sbom`, and `bun run benchmark:framework`.",
"",
"## Appendix A — package/version inventory",
"",
"| Package | Version | Purpose |",
"| --- | --- | --- |",
);
for (const item of packageRows)
add(`| \`${item.name}\` | ${item.version} | ${item.description.replaceAll("|", "\\|")} |`);
add("", "## Appendix B — complete audited public export inventory", "");
for (const [packageName, entries] of apiPackages) {
const count = Object.values(entries).reduce((sum, symbols) => sum + symbols.length, 0);
add(`### \`${packageName}\` (${count} symbols)`, "");
for (const [subpath, symbols] of Object.entries(entries)) {
add(`- **${subpath}:** ${symbols.map((symbol) => `\`${symbol}\``).join(", ")}`);
}
add("");
}
add("## Appendix C — current UI component/block reference", "");
for (const component of uiReference.components) {
const props = component.props.length
? component.props
.map(
(prop) =>
`${prop.name}: ${prop.type}${prop.required ? " (required)" : ` = ${prop.default}`}`,
)
.join("; ")
: "none";
const outputs = component.outputs?.length
? component.outputs.map((output) => `${output.name}(${output.payloadType})`).join("; ")
: "none";
const slots = component.slots?.length ? component.slots.join(", ") : "none";
add(
`### \`${component.name}\``,
"",
`- Category: ${component.category}; mount: \`${component.mount}\`; source: \`${component.source}\`.`,
`- Purpose: ${component.purpose}`,
`- Props: ${props}`,
`- Outputs/events: ${outputs}`,
`- Slots: ${slots}`,
"",
);
}
add("## Appendix D — all other package-owned `.wrn` blocks", "");
for (const [packageName, files] of [...packageBlocks.entries()].sort(([a], [b]) =>
a.localeCompare(b),
)) {
if (packageName === "ui") continue;
add(
`### \`@wrnexus/${packageName}\` (${files.length})`,
"",
...files.map((file) => `- \`${file}\``),
"",
);
}
add(
"## Appendix E — authoritative files",
"",
"- Language parser/AST: `packages/syntax/src/parser.ts`, `v060.ts`, `api-sections.ts`, `spec.ts`.",
"- Compiler/runtime: `packages/compiler/src`, `packages/csr/src`, `packages/ssr/src`, `packages/dev-server/src`.",
"- Migration registry: `packages/cli/src/update.ts`.",
"- Public exports: `docs/public-api-0.8.json` (checked by `scripts/check-public-api.mjs`).",
"- UI blocks: `packages/ui/component-reference.json` and `packages/ui/COMPONENTS.md`.",
"- Latest feature designs: `docs/superpowers/specs/2026-08-19-typed-api-block-design.md`, `2026-08-18-react-islands-design.md`, and `2026-08-18-wrn-html-editing-design.md`.",
"",
"---",
"",
"This report is reproducible: run `node scripts/generate-complete-framework-report.mjs` after implementation or generated-reference changes.",
);
const report = await format(`${lines.join("\n")}\n`, { parser: "markdown" });
writeFileSync(join(root, "docs", "WRNEXUS-COMPLETE-FEATURE-REPORT.md"), report, "utf8");
console.log(`Wrote docs/WRNEXUS-COMPLETE-FEATURE-REPORT.md (${lines.length} lines).`);