docs: add complete framework feature report
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,302 @@
|
||||
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 app’s `/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).`);
|
||||
Reference in New Issue
Block a user