refactor: migrate legacy wire namespace to wrn
This commit is contained in:
@@ -63,7 +63,7 @@ page Home {
|
||||
}
|
||||
|
||||
style {
|
||||
h1 { color: var(--wire-color-text); }
|
||||
h1 { color: var(--wrn-color-text); }
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
@@ -95,7 +95,7 @@ Components render on the server with their props, then hydrate — no per-compon
|
||||
- **Server loop (DB/list/table):** \`{#each <list> as <item>[, <i>]} …rows… {:empty} …fallback… {/each}\` — iterates SSR data on the server and renders markup per item. \`{item.field}\` interpolates (HTML-escaped, XSS-safe). \`<list>\` is a JS expression, usually an \`ssr\` data binding (see "Data-driven tables" below). This is how you render a database table in \`.wrn\`.
|
||||
- **Server conditional:** \`{#if <expr>} … {:else if <expr>} … {:else} … {/if}\` — renders the first truthy branch on the server. \`<expr>\` can reference \`ssr\` data, or the \`item\`/\`index\` of an enclosing \`{#each}\`. Works at page level and inside loops (e.g. \`{#if r.active}<span>●</span>{:else}<span>○</span>{/if}\` per row). For client-side show/hide based on reactive \`state\`, use \`data-show="expr"\` instead.
|
||||
- i18n: \`{t:home.title}\` in text, \`t:placeholder="form.name"\` on attributes — resolved per request from \`app/locales/\`.
|
||||
- Theme: any element with \`data-wire-theme-toggle\` toggles light/dark; \`data-wire-theme-set="dark"\` sets it.
|
||||
- Theme: any element with \`data-wrn-theme-toggle\` toggles light/dark; \`data-wrn-theme-set="dark"\` sets it.
|
||||
- Void/self-closing tags are fine: \`<br />\`, \`<img src="..." />\`.
|
||||
- Only \`{\` and \`}\` are special (interpolation). Don't use a bare \`}\` in view text.
|
||||
|
||||
@@ -246,7 +246,7 @@ export default v.object({
|
||||
});
|
||||
\`\`\`
|
||||
In an API route: \`import s from "../schemas/login"; import { parseBody } from "@wrnexus/validation"; const r = await parseBody(s, ctx.req);\` → \`r.ok ? r.value : r.response\`.
|
||||
In a form: \`<form data-schema="login" action="/api/login" method="post">\` + \`<span data-error="email"></span>\` (client + server validation wired automatically).
|
||||
In a form: \`<form data-schema="login" action="/api/login" method="post">\` + \`<span data-error="email"></span>\` (client + server validation connected automatically).
|
||||
|
||||
## AI / LLM (\`@wrnexus/ai\`)
|
||||
|
||||
@@ -271,7 +271,7 @@ wrnexus update --latest # deps + syntax/config migrations + verification
|
||||
wrnexus generate page <Name> # scaffold a page (aliases: g p)
|
||||
wrnexus generate component <name> | api <path> | schema <name>
|
||||
wrnexus db migrate | rollback | status | new [--from-models] | generate | seed
|
||||
wrnexus eject <component> # copy a Wire UI component's .wrn into app/components to customize
|
||||
wrnexus eject <component> # copy a WrNexus UI component's .wrn into app/components to customize
|
||||
\`\`\`
|
||||
|
||||
## When asked to "create a page/component/feature"
|
||||
@@ -279,7 +279,7 @@ wrnexus eject <component> # copy a Wire UI component's .wrn into app/compone
|
||||
1. Create the \`.wrn\` file under \`app/pages/\` (or \`app/components/\`) with a \`page\`/\`component\` block — or run \`wrnexus generate page <Name>\`.
|
||||
2. Put markup in \`view { }\`, interactive bits in \`state\` + \`{expr}\` + \`@event\`, reusable UI as components mounted via \`data-component\`.
|
||||
3. For data, add an \`app/api/*.ts\` route and \`getDb()\`; for forms, add an \`app/schemas/*.ts\` and \`data-schema\`.
|
||||
4. Style with Tailwind utility classes in the view, or theme tokens (\`var(--wire-*)\`), or \`style { }\`.
|
||||
4. Style with Tailwind utility classes in the view, or theme tokens (\`var(--wrn-*)\`), or \`style { }\`.
|
||||
5. Never emit React/JSX, a manual router, or client-side island JS — the framework handles hydration.\n`;
|
||||
|
||||
/** Agent-oriented instructions (shipped as CLAUDE.md): a preamble + the full guide. */
|
||||
|
||||
@@ -515,7 +515,7 @@ export async function runBuild(appRoot: string): Promise<void> {
|
||||
assetHash.update(themeJs);
|
||||
console.log(`✓ Theme: ${theme.names.length} themes (default: ${theme.default})`);
|
||||
|
||||
// 1a2) Wire UI stylesheet (all component classes, themed via tokens).
|
||||
// 1a2) WrNexus UI stylesheet (all component classes, themed via tokens).
|
||||
const uiStyles = config.styles?.includeUi === false ? "" : uiCss();
|
||||
writeFileSync(join(distDir, "ui.css"), uiStyles, "utf8");
|
||||
const frameworkStyles = `${themeCss}\n${uiStyles}`;
|
||||
|
||||
@@ -447,11 +447,11 @@ export const contactSchema = v.object({
|
||||
|
||||
/* Make Tailwind's \`dark:\` variant follow the framework's data-theme attribute
|
||||
* (set on <html> by the theme system), not the OS setting. Any element with
|
||||
* data-wire-theme-toggle flips it. */
|
||||
* data-wrn-theme-toggle flips it. */
|
||||
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
|
||||
|
||||
body {
|
||||
font-family: var(--wire-font-sans, "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif);
|
||||
font-family: var(--wrn-font-sans, "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif);
|
||||
}
|
||||
`,
|
||||
"app/layouts/document.wrn": `// Global document layout. The framework renders this once around the selected
|
||||
@@ -497,7 +497,7 @@ page Home {
|
||||
<span class="grid h-7 w-7 place-items-center rounded-md bg-gradient-to-br from-indigo-500 to-violet-600 text-sm font-bold text-white">W</span>
|
||||
APP_NAME
|
||||
</span>
|
||||
<button data-wire-theme-toggle class="rounded-md border border-slate-200 px-3 py-1.5 text-sm text-slate-600 transition hover:border-slate-300 hover:text-slate-900 dark:border-white/10 dark:text-slate-400 dark:hover:border-white/20 dark:hover:text-white">
|
||||
<button data-wrn-theme-toggle class="rounded-md border border-slate-200 px-3 py-1.5 text-sm text-slate-600 transition hover:border-slate-300 hover:text-slate-900 dark:border-white/10 dark:text-slate-400 dark:hover:border-white/20 dark:hover:text-white">
|
||||
Toggle theme
|
||||
</button>
|
||||
</header>
|
||||
|
||||
@@ -52,7 +52,7 @@ async function listTables(db: import("@wrnexus/db").Db): Promise<string[]> {
|
||||
? "SELECT table_name AS name FROM information_schema.tables WHERE table_schema = DATABASE() ORDER BY table_name"
|
||||
: "SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name";
|
||||
const rows = await db.all<{ name: string }>(sql);
|
||||
return rows.map((r) => r.name).filter((n) => n !== "_wire_migrations");
|
||||
return rows.map((r) => r.name).filter((n) => n !== "_wrn_migrations");
|
||||
}
|
||||
|
||||
function isModel(value: unknown): value is Model {
|
||||
|
||||
@@ -49,7 +49,7 @@ const COMPOSE = `services:
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: "3000"
|
||||
DATABASE_URL: postgres://wire:wire@db:5432/app
|
||||
DATABASE_URL: postgres://wrn:wrn@db:5432/app
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
@@ -58,11 +58,11 @@ const COMPOSE = `services:
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: wire
|
||||
POSTGRES_PASSWORD: wire
|
||||
POSTGRES_USER: wrn
|
||||
POSTGRES_PASSWORD: wrn
|
||||
POSTGRES_DB: app
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U wire -d app"]
|
||||
test: ["CMD-SHELL", "pg_isready -U wrn -d app"]
|
||||
interval: 3s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* `wrnexus eject <name...>` — copy a Wire UI component's `.wrn` source into the
|
||||
* `wrnexus eject <name...>` — copy a WrNexus UI component's `.wrn` source into the
|
||||
* app's `app/components/`, so you fully own and can edit it. The auto-discovered
|
||||
* library version is shadowed by the app copy (same name → app wins).
|
||||
*/
|
||||
|
||||
@@ -75,7 +75,7 @@ export function scaffold(type: GenerateType, name: string): GeneratedFile {
|
||||
}
|
||||
|
||||
view {
|
||||
<div class="wire-${baseName(clean)}">{label}</div>
|
||||
<div class="wrn-${baseName(clean)}">{label}</div>
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* wrnexus dev [app-dir] [--port=3000] start the dev server (live reload)
|
||||
* wrnexus build [app-dir] build a production server + assets
|
||||
* wrnexus create <app-name> scaffold a new app
|
||||
* wrnexus eject <name...> copy a Wire UI component into your app
|
||||
* wrnexus eject <name...> copy a WrNexus UI component into your app
|
||||
* wrnexus db <migrate|rollback|status|new> database migrations
|
||||
* wrnexus authz <list|generate|init> authorization catalog tooling
|
||||
*/
|
||||
@@ -64,7 +64,7 @@ Usage:
|
||||
wrnexus mobile compile Compile .wrn pages into native Expo routes
|
||||
wrnexus native list List cross-platform native capabilities
|
||||
wrnexus native add <capability...> Install capability packages for the configured mobile mode
|
||||
wrnexus eject <name...> Copy a Wire UI component into app/components
|
||||
wrnexus eject <name...> Copy a WrNexus UI component into app/components
|
||||
wrnexus update [dir] [--latest] Upgrade deps, migrate project files, and verify the app
|
||||
wrnexus db <cmd> Migrations: migrate | rollback | status | seed | generate | new
|
||||
wrnexus authz <cmd> Authorization: list | generate | init [--dialect=sqlite|postgres|mysql]
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from "node:fs";
|
||||
import { join, resolve } from "node:path";
|
||||
import { loadAppConfig } from "@wrnexus/styles";
|
||||
import { compileNativeWireFile } from "@wrnexus/compiler";
|
||||
import { compileNativeWrnFile } from "@wrnexus/compiler";
|
||||
|
||||
function validPackageName(value: string): boolean {
|
||||
return /^(?:@[a-z0-9._~-]+\/)?[a-z0-9._~-]+(?:@[a-zA-Z0-9._~^<>=|*+-]+)?$/.test(value);
|
||||
@@ -144,7 +144,7 @@ export async function runMobileCommand(
|
||||
const output = join(mobileDir, "app", relative);
|
||||
mkdirSync(resolve(output, ".."), { recursive: true });
|
||||
try {
|
||||
writeFileSync(output, compileNativeWireFile(readFileSync(source, "utf8")), "utf8");
|
||||
writeFileSync(output, compileNativeWrnFile(readFileSync(source, "utf8")), "utf8");
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Native compilation failed for app/pages/${entry}: ${(error as Error).message}`,
|
||||
|
||||
@@ -2064,7 +2064,7 @@ const MIGRATIONS: Migration[] = [
|
||||
version: "0.8.6",
|
||||
id: "0.8.6-navigation-and-layout-groups",
|
||||
description:
|
||||
"Rebuilds the navigation and layout component groups, moves them off Tailwind utilities onto wire-* classes, defines theme tokens that components referenced but nothing declared, and makes component outputs actually reach parent bindings.",
|
||||
"Rebuilds the navigation and layout component groups, moves them off Tailwind utilities onto wrn-* classes, defines theme tokens that components referenced but nothing declared, and makes component outputs actually reach parent bindings.",
|
||||
apply() {
|
||||
// Source changes no codemod can make safely, so they are listed rather
|
||||
// than attempted.
|
||||
@@ -2100,11 +2100,11 @@ const MIGRATIONS: Migration[] = [
|
||||
// move to the @change and @select bindings.
|
||||
//
|
||||
// Sidebar renamed its classes to the BEM form used everywhere else:
|
||||
// wire-sidebar-shell, -items, -group, -toggle, -backdrop, -panel and
|
||||
// -layout became wire-sidebar__*. Nesting via children still works.
|
||||
// wrn-sidebar-shell, -items, -group, -toggle, -backdrop, -panel and
|
||||
// -layout became wrn-sidebar__*. Nesting via children still works.
|
||||
//
|
||||
// The layout, page and section components moved from Tailwind utility
|
||||
// classes to wire-* classes with their own styles. Application CSS
|
||||
// classes to wrn-* classes with their own styles. Application CSS
|
||||
// selecting on the utility classes they used to render -- max-w-7xl,
|
||||
// gap-5, sm:grid-cols-2 and the rest -- no longer matches. Variants are
|
||||
// data attributes now, so target [data-variant] and friends instead.
|
||||
@@ -2118,12 +2118,12 @@ const MIGRATIONS: Migration[] = [
|
||||
// radius.
|
||||
//
|
||||
// ui.css lost several application-pattern class families that nothing
|
||||
// referenced: wire-catalog-*, wire-page-shell, wire-product-card,
|
||||
// wire-legal-toc, wire-sdk-tabs, wire-cookie-* and wire-analytics-preview.
|
||||
// referenced: wrn-catalog-*, wrn-page-shell, wrn-product-card,
|
||||
// wrn-legal-toc, wrn-sdk-tabs, wrn-cookie-* and wrn-analytics-preview.
|
||||
// Anything hand-written against those needs its own styles.
|
||||
//
|
||||
// Themes gain tokens that were referenced but never defined, including
|
||||
// --wire-color-focus, --wire-color-surface-soft, --wire-color-on-danger
|
||||
// --wrn-color-focus, --wrn-color-surface-soft, --wrn-color-on-danger
|
||||
// and the input-* family. A custom theme that declared these itself
|
||||
// keeps winning; one that did not will see focus rings and soft surfaces
|
||||
// start painting where they previously rendered as nothing.
|
||||
@@ -2133,7 +2133,7 @@ const MIGRATIONS: Migration[] = [
|
||||
version: "0.8.7",
|
||||
id: "0.8.7-ui-component-depth",
|
||||
description:
|
||||
"Removes superseded UI scaffolds and moves the remaining utility-styled components to self-contained wire-* BEM styles.",
|
||||
"Removes superseded UI scaffolds and moves the remaining utility-styled components to self-contained wrn-* BEM styles.",
|
||||
apply() {
|
||||
// AdvancedDatePicker -> DatePicker; AdvancedRangeSlider -> RangeSlider;
|
||||
// FileUpload -> FileInput + FileUploadProgress (or @wrnexus/uploader);
|
||||
@@ -2141,7 +2141,7 @@ const MIGRATIONS: Migration[] = [
|
||||
//
|
||||
// List, InputNumber, Marquee, TextLink, Map, SearchBox and Timeline no
|
||||
// longer render Tailwind utility class names. Application CSS selecting
|
||||
// those internal utilities must move to the component's wire-* BEM
|
||||
// those internal utilities must move to the component's wrn-* BEM
|
||||
// classes or its data-size/data-variant attributes. List now emits
|
||||
// select for non-link items as well as navigation items.
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user