Refresh UI components and showcase; release updated framework packages

This commit is contained in:
Clintchiz committed 2026-09-20 18:13:24 +05:30
1 parent d800228585
commit c77f5e1cec
293 files changed
+22544 -35778

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/cli",
"version": "0.8.70",
"version": "0.8.71",
"type": "module",
"main": "src/index.ts",
"exports": {
+14 -3
View File
@@ -60,6 +60,7 @@ import { loadLocales, resolveI18n } from "@wrnexus/i18n";
import { pathToFileURL } from "node:url";
import { checkPerformanceBudgets } from "@wrnexus/core";
import { currentCliVersion } from "./update-notifier.ts";
import { shouldInlineCss } from "./inline-css.ts";
import {
createPluginRunner,
discoverPlugins,
@@ -73,7 +74,6 @@ import {
// the generated entry resolves whether @wrnexus/dev-server is a workspace or an
// installed dependency. Bun.build bundles it into a self-contained server.js.
const PROD_MODULE = "@wrnexus/dev-server";
const INLINE_CSS_LIMIT_BYTES = 4096;
const fwd = (p: string) => p.replace(/\\/g, "/");
@@ -648,7 +648,7 @@ export async function runBuild(appRoot: string): Promise<void> {
// theme stylesheet is selected from the request cookie and loaded first.
writeFileSync(join(distDir, "styles.css"), combinedCss, "utf8");
hasStyles = true;
if (Buffer.byteLength(combinedCss, "utf8") <= INLINE_CSS_LIMIT_BYTES) {
if (shouldInlineCss(combinedCss, config.styles?.inlineMaxBytes)) {
inlineStyles = combinedCss;
}
console.log(`✓ Styles: ${join(distDir, "styles.css")}`);
@@ -709,7 +709,16 @@ applyAuthzManifestEarly([${authzSetupEntries}]);
const runtimeConfigPath = ["wrnexus.config.ts", "wrnexus.config.js", "wrnexus.config.mjs"]
.map((name) => resolve(appRoot, name))
.find(existsSync);
if (runtimeConfigPath) imports.push(`import ${JSON.stringify(fwd(runtimeConfigPath))};`);
if (runtimeConfigPath && config.auth) {
// Importing config creates the engine, but does not run plugin.configure.
// Initialize route options before route/middleware modules are evaluated.
// Credentials are read by the config at server startup, never serialized here.
writeFileSync(join(distDir, ".auth-runtime.ts"),
`import config from ${JSON.stringify(fwd(runtimeConfigPath))};\n` +
`import { configureAuthRuntime } from "@wrnexus/auth/plugin";\n` +
`configureAuthRuntime(config.auth);\n`, "utf8");
imports.push(`import "./.auth-runtime.ts";`);
} else if (runtimeConfigPath) imports.push(`import ${JSON.stringify(fwd(runtimeConfigPath))};`);
const manifestRoutes = (routes: Route[]): string => {
const parts = routes.map((r) => {
@@ -796,6 +805,7 @@ applyAuthzManifestEarly([${authzSetupEntries}]);
const entry = `// AUTO-GENERATED production server entry — do not edit.
import { join } from "node:path";
import { createProductionServer } from ${JSON.stringify(PROD_MODULE)};
import { productionConnections } from "@wrnexus/cli/runtime-connections";
${imports.join("\n")}
await createProductionServer(
@@ -855,6 +865,7 @@ await createProductionServer(
tenancy: ${JSON.stringify(config.tenancy ?? {})},
navigation: ${JSON.stringify(config.navigation ?? {})},
developmentRuntime: process.env.WRNEXUS_PRODUCTION_DEV === "1",
...productionConnections(),
},
);
`;
+14
View File
@@ -0,0 +1,14 @@
/** Keep the default conservative; sites can opt in for a measured first-load improvement. */
export function shouldInlineCss(css: string, configuredLimit: number | undefined): boolean {
const limit = configuredLimit ?? 4096;
if (!Number.isSafeInteger(limit) || limit < 0) {
throw new Error("styles.inlineMaxBytes must be a non-negative safe integer");
}
if (!limit || Buffer.byteLength(css, "utf8") > limit) return false;
// Moving CSS into HTML must not change the base of relative asset URLs.
for (const match of css.matchAll(/url\(\s*([^)]+)\s*\)/gi)) {
const url = match[1]!.trim().replace(/^["']|["']$/g, "");
if (!/^(?:\/|https?:|data:)/i.test(url)) return false;
}
return true;
}
+14
View File
@@ -0,0 +1,14 @@
/** Deployment-time connection overrides for immutable production images. */
export function productionConnections(value = process.env.WRNEXUS_RUNTIME_CONNECTIONS) {
if (!value) return {};
const parsed = JSON.parse(value);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
throw new Error("WRNEXUS_RUNTIME_CONNECTIONS must be a JSON object");
const allowed = new Set(["db", "databases", "realtime", "queue", "storage"]);
for (const key of Object.keys(parsed)) {
if (!allowed.has(key)) throw new Error(`Unsupported runtime connection: ${key}`);
if (!parsed[key] || typeof parsed[key] !== "object" || Array.isArray(parsed[key]))
throw new Error(`Runtime connection ${key} must be an object`);
}
return parsed;
}
+20
View File
@@ -0,0 +1,20 @@
import { expect, test } from "bun:test";
import { shouldInlineCss } from "../src/inline-css.ts";
test("production CSS inlining uses a configurable UTF-8 byte budget", () => {
expect(shouldInlineCss("x".repeat(4096), undefined)).toBe(true);
expect(shouldInlineCss("x".repeat(4097), undefined)).toBe(false);
expect(shouldInlineCss("x".repeat(5000), 6000)).toBe(true);
expect(shouldInlineCss("é".repeat(10), 10)).toBe(false);
expect(shouldInlineCss("", 0)).toBe(false);
for (const value of [-1, NaN, Infinity, 1.5]) expect(() => shouldInlineCss("", value)).toThrow();
});
test("relative asset URLs stay external so their base does not change", () => {
for (const url of ['./font.woff2', '../font.woff2', 'font.woff2', '#mask']) {
expect(shouldInlineCss(`a{background:url("${url}")}`, undefined)).toBe(false);
}
for (const url of ['/font.woff2', 'https://cdn.example/font.woff2', 'data:image/svg+xml;base64,AAAA']) {
expect(shouldInlineCss(`a{background:url('${url}')}`, undefined)).toBe(true);
}
});
@@ -0,0 +1,10 @@
import { expect, test } from "bun:test";
import { productionConnections } from "../src/runtime-connections.ts";
test("deployment connections override build placeholders without accepting server settings", () => {
const db = { driver: "postgres", url: "postgres://runtime:secret@db/app" };
expect(productionConnections(JSON.stringify({ db, realtime: { scale: true } }))).toEqual({ db, realtime: { scale: true } });
expect(productionConnections("")).toEqual({});
for (const value of ["null", "[]", "invalid", '{"port":80}', '{"db":null}', '{"db":[]}'])
expect(() => productionConnections(value)).toThrow();
});