diff --git a/.publish/ai/package.json b/.publish/ai/package.json index 15530150..b87eb234 100644 --- a/.publish/ai/package.json +++ b/.publish/ai/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ai", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.", "license": "MIT", diff --git a/.publish/authz/package.json b/.publish/authz/package.json index 27bd449a..35ba1931 100644 --- a/.publish/authz/package.json +++ b/.publish/authz/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/authz", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/authz — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/cli/package.json b/.publish/cli/package.json index 61badbc9..ad32b272 100644 --- a/.publish/cli/package.json +++ b/.publish/cli/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/cli", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/cli — part of the WrNexus framework.", "license": "MIT", @@ -28,16 +28,16 @@ "wrnexus": "./dist/index.js" }, "dependencies": { - "@wrnexus/core": "^0.2.14", - "@wrnexus/router": "^0.2.14", - "@wrnexus/csr": "^0.2.14", - "@wrnexus/compiler": "^0.2.14", - "@wrnexus/styles": "^0.2.14", - "@wrnexus/dev-server": "^0.2.14", - "@wrnexus/ui": "^0.2.14", - "@wrnexus/validation": "^0.2.14", - "@wrnexus/i18n": "^0.2.14", - "@wrnexus/db": "^0.2.14" + "@wrnexus/core": "^0.2.15", + "@wrnexus/router": "^0.2.15", + "@wrnexus/csr": "^0.2.15", + "@wrnexus/compiler": "^0.2.15", + "@wrnexus/styles": "^0.2.15", + "@wrnexus/dev-server": "^0.2.15", + "@wrnexus/ui": "^0.2.15", + "@wrnexus/validation": "^0.2.15", + "@wrnexus/i18n": "^0.2.15", + "@wrnexus/db": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/compiler/package.json b/.publish/compiler/package.json index c5354cfa..92f14e35 100644 --- a/.publish/compiler/package.json +++ b/.publish/compiler/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/compiler", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/compiler — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/core/package.json b/.publish/core/package.json index 7cd5f055..93d9be28 100644 --- a/.publish/core/package.json +++ b/.publish/core/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/core", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/core — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/csr/package.json b/.publish/csr/package.json index 450ecce4..cb8fa32a 100644 --- a/.publish/csr/package.json +++ b/.publish/csr/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/csr", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/csr — part of the WrNexus framework.", "license": "MIT", @@ -21,7 +21,7 @@ } }, "dependencies": { - "@wrnexus/core": "^0.2.14" + "@wrnexus/core": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/db/package.json b/.publish/db/package.json index e455940e..5027e4ee 100644 --- a/.publish/db/package.json +++ b/.publish/db/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/db", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/db — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/dev-server/package.json b/.publish/dev-server/package.json index 3772e2ef..cb910d4a 100644 --- a/.publish/dev-server/package.json +++ b/.publish/dev-server/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/dev-server", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/dev-server — part of the WrNexus framework.", "license": "MIT", @@ -25,18 +25,18 @@ } }, "dependencies": { - "@wrnexus/core": "^0.2.14", - "@wrnexus/router": "^0.2.14", - "@wrnexus/ssr": "^0.2.14", - "@wrnexus/csr": "^0.2.14", - "@wrnexus/compiler": "^0.2.14", - "@wrnexus/styles": "^0.2.14", - "@wrnexus/ui": "^0.2.14", - "@wrnexus/validation": "^0.2.14", - "@wrnexus/i18n": "^0.2.14", - "@wrnexus/db": "^0.2.14", - "@wrnexus/pubsub": "^0.2.14", - "@wrnexus/uploader": "^0.2.14" + "@wrnexus/core": "^0.2.15", + "@wrnexus/router": "^0.2.15", + "@wrnexus/ssr": "^0.2.15", + "@wrnexus/csr": "^0.2.15", + "@wrnexus/compiler": "^0.2.15", + "@wrnexus/styles": "^0.2.15", + "@wrnexus/ui": "^0.2.15", + "@wrnexus/validation": "^0.2.15", + "@wrnexus/i18n": "^0.2.15", + "@wrnexus/db": "^0.2.15", + "@wrnexus/pubsub": "^0.2.15", + "@wrnexus/uploader": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/encryption/package.json b/.publish/encryption/package.json index 86e6cf11..6e280b94 100644 --- a/.publish/encryption/package.json +++ b/.publish/encryption/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/encryption", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/encryption — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/i18n/package.json b/.publish/i18n/package.json index 67a9a7ef..0fe7498e 100644 --- a/.publish/i18n/package.json +++ b/.publish/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/i18n", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/i18n — part of the WrNexus framework.", "license": "MIT", @@ -21,7 +21,7 @@ } }, "dependencies": { - "@wrnexus/core": "^0.2.14" + "@wrnexus/core": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/jwt/package.json b/.publish/jwt/package.json index 86da75dc..b724c984 100644 --- a/.publish/jwt/package.json +++ b/.publish/jwt/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/jwt", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/jwt — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/mobile/package.json b/.publish/mobile/package.json index fff308d9..8adffe27 100644 --- a/.publish/mobile/package.json +++ b/.publish/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/mobile", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/mobile — part of the WrNexus framework.", "license": "MIT", @@ -21,7 +21,7 @@ } }, "dependencies": { - "@wrnexus/native": "^0.2.14" + "@wrnexus/native": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/native/package.json b/.publish/native/package.json index ba17d37b..74ad87ee 100644 --- a/.publish/native/package.json +++ b/.publish/native/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/native", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/native — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/oauth/package.json b/.publish/oauth/package.json index ce073bdc..d7a94e35 100644 --- a/.publish/oauth/package.json +++ b/.publish/oauth/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/oauth", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/oauth — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/pubsub/package.json b/.publish/pubsub/package.json index 0ddca09f..636ce286 100644 --- a/.publish/pubsub/package.json +++ b/.publish/pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/pubsub", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/pubsub — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/queue/package.json b/.publish/queue/package.json index e32ce67a..fe16f90f 100644 --- a/.publish/queue/package.json +++ b/.publish/queue/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/queue", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/queue — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/reactive/package.json b/.publish/reactive/package.json index 9a986470..a60c3a66 100644 --- a/.publish/reactive/package.json +++ b/.publish/reactive/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/reactive", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/reactive — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/router/package.json b/.publish/router/package.json index f7763ee9..7e311705 100644 --- a/.publish/router/package.json +++ b/.publish/router/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/router", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/router — part of the WrNexus framework.", "license": "MIT", @@ -21,8 +21,8 @@ } }, "dependencies": { - "@wrnexus/compiler": "^0.2.14", - "@wrnexus/core": "^0.2.14" + "@wrnexus/compiler": "^0.2.15", + "@wrnexus/core": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/ssr/package.json b/.publish/ssr/package.json index ea21a688..2a7e29d8 100644 --- a/.publish/ssr/package.json +++ b/.publish/ssr/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ssr", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/ssr — part of the WrNexus framework.", "license": "MIT", @@ -21,7 +21,7 @@ } }, "dependencies": { - "@wrnexus/core": "^0.2.14" + "@wrnexus/core": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/styles/package.json b/.publish/styles/package.json index 40341002..7effda12 100644 --- a/.publish/styles/package.json +++ b/.publish/styles/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/styles", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/styles — part of the WrNexus framework.", "license": "MIT", @@ -21,7 +21,7 @@ } }, "dependencies": { - "@wrnexus/uploader": "^0.2.14" + "@wrnexus/uploader": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/test/package.json b/.publish/test/package.json index 1c0db4a6..126d4f8e 100644 --- a/.publish/test/package.json +++ b/.publish/test/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/test", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/test — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/tracking/package.json b/.publish/tracking/package.json index c99ae5c9..877d77a1 100644 --- a/.publish/tracking/package.json +++ b/.publish/tracking/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/tracking", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/tracking — part of the WrNexus framework.", "license": "MIT", diff --git a/.publish/ui/package.json b/.publish/ui/package.json index c8da4044..538c19d6 100644 --- a/.publish/ui/package.json +++ b/.publish/ui/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ui", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/ui — part of the WrNexus framework.", "license": "MIT", @@ -22,7 +22,7 @@ "./ui.css": "./ui.css" }, "dependencies": { - "@wrnexus/core": "^0.2.14" + "@wrnexus/core": "^0.2.15" }, "files": [ "dist", diff --git a/.publish/uploader/package.json b/.publish/uploader/package.json index c92fd62f..fd5fdb6e 100644 --- a/.publish/uploader/package.json +++ b/.publish/uploader/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/uploader", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/uploader — part of the WrNexus framework.", "license": "MIT", @@ -21,7 +21,7 @@ } }, "dependencies": { - "@wrnexus/core": "^0.2.14" + "@wrnexus/core": "^0.2.15" }, "files": [ "dist" diff --git a/.publish/validation/package.json b/.publish/validation/package.json index e77a4a94..8542f77e 100644 --- a/.publish/validation/package.json +++ b/.publish/validation/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/validation", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "description": "@wrnexus/validation — part of the WrNexus framework.", "license": "MIT", diff --git a/packages/ai/package.json b/packages/ai/package.json index 5c1c60b2..0d03bf0e 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ai", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "description": "Zero-dependency Claude (Anthropic) client for WrNexus apps.", diff --git a/packages/authz/package.json b/packages/authz/package.json index 12572de1..07844fde 100644 --- a/packages/authz/package.json +++ b/packages/authz/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/authz", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3c67f013..aa5ec5db 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/cli", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/cli/src/build.ts b/packages/cli/src/build.ts index a4f31db8..cbcd11c9 100644 --- a/packages/cli/src/build.ts +++ b/packages/cli/src/build.ts @@ -158,10 +158,13 @@ export async function runBuild(appRoot: string): Promise { config.styles, ); assetHash.update(css); - writeFileSync(join(distDir, "styles.css"), css, "utf8"); + const combinedCss = `${frameworkStyles}\n${css}`; + // One blocking CSS request in production: tokens → UI → application CSS. + // The standalone framework.css remains available for apps without global CSS. + writeFileSync(join(distDir, "styles.css"), combinedCss, "utf8"); hasStyles = true; - if (Buffer.byteLength(css, "utf8") <= INLINE_CSS_LIMIT_BYTES) { - inlineStyles = css; + if (Buffer.byteLength(combinedCss, "utf8") <= INLINE_CSS_LIMIT_BYTES) { + inlineStyles = combinedCss; } console.log(`✓ Styles: ${join(distDir, "styles.css")}`); } @@ -254,6 +257,7 @@ await createProductionServer( realtime: ${config.realtime ? JSON.stringify(config.realtime) : "undefined"}, publicDir: join(import.meta.dir, "public"), ${hasStyles ? `stylesPath: join(import.meta.dir, "styles.css"),` : ""} + ${hasStyles ? `stylesIncludeFramework: true,` : ""} ${inlineStyles ? `inlineStyles: ${JSON.stringify(inlineStyles)},` : ""} assetVersion: ${JSON.stringify(assetVersion)}, head: ${JSON.stringify(headStr)}, diff --git a/packages/cli/src/create.ts b/packages/cli/src/create.ts index d170d2e8..cc9614f8 100644 --- a/packages/cli/src/create.ts +++ b/packages/cli/src/create.ts @@ -205,6 +205,8 @@ const config: AppConfig = { seo: { title: "APP_NAME", titleTemplate: "%s | APP_NAME", + // Set WRNEXUS_PUBLIC_ORIGIN in production when TLS terminates at a proxy. + canonicalBase: process.env.WRNEXUS_PUBLIC_ORIGIN, description: "An SSR-first WrNexus app.", robots: "index,follow", themeColor: "#6366f1", diff --git a/packages/compiler/package.json b/packages/compiler/package.json index 91fd875c..6a42ba71 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/compiler", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/core/package.json b/packages/core/package.json index 950dde19..0b106590 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/core", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/core/src/headers.ts b/packages/core/src/headers.ts index 5aa4dab4..2e7b0c5f 100644 --- a/packages/core/src/headers.ts +++ b/packages/core/src/headers.ts @@ -178,9 +178,12 @@ export function createCorsPreflightResponse( export function resolveRequestUrl(req: Request, trustProxy?: boolean): URL { const url = new URL(req.url); if (!trustProxy) return url; - const proto = req.headers.get("x-forwarded-proto"); + const forwarded = req.headers.get("forwarded")?.split(",")[0] ?? ""; + const forwardedProto = /(?:^|;)\s*proto=(?:"([^"]+)"|([^;\s]+))/i.exec(forwarded); + const forwardedHost = /(?:^|;)\s*host=(?:"([^"]+)"|([^;\s]+))/i.exec(forwarded); + const proto = req.headers.get("x-forwarded-proto") ?? forwardedProto?.[1] ?? forwardedProto?.[2]; if (proto) url.protocol = (proto.split(",")[0] ?? "").trim() + ":"; - const host = req.headers.get("x-forwarded-host"); + const host = req.headers.get("x-forwarded-host") ?? forwardedHost?.[1] ?? forwardedHost?.[2]; if (host) { const h = (host.split(",")[0] ?? "").trim(); url.host = h; diff --git a/packages/core/test/headers.test.ts b/packages/core/test/headers.test.ts index 27d0d480..47be9289 100644 --- a/packages/core/test/headers.test.ts +++ b/packages/core/test/headers.test.ts @@ -1,5 +1,5 @@ import { test, expect } from "bun:test"; -import { withSecurityHeaders, isWebSocketOriginAllowed } from "../src/index.ts"; +import { withSecurityHeaders, isWebSocketOriginAllowed, resolveRequestUrl } from "../src/index.ts"; const req = (headers: Record = {}) => new Request("https://x/", { headers }); @@ -64,3 +64,11 @@ test("isWebSocketOriginAllowed blocks cross-site WS (CSWSH), allows same-origin" }), ).toBe(true); }); + +test("resolveRequestUrl honors standard Forwarded headers behind trusted proxies", () => { + const request = new Request("http://127.0.0.1:3000/path", { + headers: { forwarded: 'for=192.0.2.1;proto=https;host="workroot.in"' }, + }); + expect(resolveRequestUrl(request, true).href).toBe("https://workroot.in/path"); + expect(resolveRequestUrl(request, false).href).toBe("http://127.0.0.1:3000/path"); +}); diff --git a/packages/csr/package.json b/packages/csr/package.json index 654fdd5d..e462ba7d 100644 --- a/packages/csr/package.json +++ b/packages/csr/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/csr", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/db/package.json b/packages/db/package.json index 194a479e..99828a7c 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/db", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/dev-server/package.json b/packages/dev-server/package.json index f4cb4171..5fe47234 100644 --- a/packages/dev-server/package.json +++ b/packages/dev-server/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/dev-server", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/dev-server/src/prod.ts b/packages/dev-server/src/prod.ts index 732db494..ae712704 100644 --- a/packages/dev-server/src/prod.ts +++ b/packages/dev-server/src/prod.ts @@ -65,6 +65,8 @@ export interface ProdOptions { stylesPath?: string; /** Small production stylesheet inlined into the document head. */ inlineStyles?: string; + /** `stylesPath` contains theme + UI + app CSS in cascade order. */ + stylesIncludeFramework?: boolean; /** Absolute path to the pre-built reactive runtime. */ reactivePath?: string; /** Absolute path to the pre-built theme stylesheet (`theme.css`). */ @@ -287,6 +289,7 @@ export function createProductionHandlers( theme: opts.theme, i18n: opts.i18n, inlineStyles: opts.inlineStyles, + stylesIncludeFramework: opts.stylesIncludeFramework, assetVersion: opts.assetVersion, head: opts.head, seo: opts.seo, diff --git a/packages/dev-server/src/public.ts b/packages/dev-server/src/public.ts index b7bb5f37..bf3afadb 100644 --- a/packages/dev-server/src/public.ts +++ b/packages/dev-server/src/public.ts @@ -33,6 +33,9 @@ function cachePolicy(filePath: string, mode: Mode): string { if (mode !== "production") return "no-cache"; const name = filePath.split(/[\\/]/).pop() ?? ""; if (/\.html?$/i.test(name)) return REVALIDATE_CACHE; + // Font URLs are content assets with expensive transfer costs and are almost + // always renamed when changed. Cache them like fingerprinted build assets. + if (/\.(?:woff2?|ttf|otf|eot)$/i.test(name)) return IMMUTABLE_CACHE; return /(?:^|[.-])[a-f0-9]{8,}(?:[.-]|$)/i.test(name) ? IMMUTABLE_CACHE : "public, max-age=3600"; } diff --git a/packages/dev-server/src/runtime.ts b/packages/dev-server/src/runtime.ts index 8ac86c52..a9770c05 100644 --- a/packages/dev-server/src/runtime.ts +++ b/packages/dev-server/src/runtime.ts @@ -103,6 +103,8 @@ export interface RuntimeDeps { hasUi?: boolean; /** Production build combined theme + UI stylesheet. */ hasFrameworkStyles?: boolean; + /** App stylesheet already contains theme + UI CSS and is the only CSS request needed. */ + stylesIncludeFramework?: boolean; /** Resolved theme config: enables `/__wrnexus/theme.css` + ``. */ theme?: ResolvedTheme; /** Resolved i18n bundle: enables `ctx.t`, ``, and `{t:key}` markers. */ @@ -569,15 +571,15 @@ export function createHandlers(deps: RuntimeDeps): Handlers { // Order: theme tokens, then Wire UI, then the app stylesheet — so the app's // own CSS (loaded last) can override both the tokens and the UI classes. const headParts: string[] = []; - if (deps.hasFrameworkStyles) { + if (deps.hasFrameworkStyles && !deps.stylesIncludeFramework) { headParts.push( ``, ); - } else if (deps.theme) { + } else if (deps.theme && !deps.stylesIncludeFramework) { const themeHref = versionAssetUrl(THEME_CSS_HREF, deps.assetVersion); headParts.push(``); } - if (deps.hasUi && !deps.hasFrameworkStyles) { + if (deps.hasUi && !deps.hasFrameworkStyles && !deps.stylesIncludeFramework) { headParts.push( ``, ); diff --git a/packages/dev-server/test/public.test.ts b/packages/dev-server/test/public.test.ts index 725a5c96..9a5a7cbf 100644 --- a/packages/dev-server/test/public.test.ts +++ b/packages/dev-server/test/public.test.ts @@ -9,11 +9,14 @@ test("production HTML revalidates while fingerprinted assets are immutable", asy mkdirSync(join(root, "assets")); writeFileSync(join(root, "index.html"), "home"); writeFileSync(join(root, "assets", "app.abcdef1234.js"), "app"); + writeFileSync(join(root, "brand.woff2"), "font"); const html = await servePublicAsset(root, "/index.html", "production"); const asset = await servePublicAsset(root, "/assets/app.abcdef1234.js", "production"); + const font = await servePublicAsset(root, "/brand.woff2", "production"); expect(html?.headers.get("cache-control")).toBe("public, max-age=0, must-revalidate"); expect(asset?.headers.get("cache-control")).toBe("public, max-age=31536000, immutable"); expect(asset?.headers.get("x-content-type-options")).toBe("nosniff"); + expect(font?.headers.get("cache-control")).toBe("public, max-age=31536000, immutable"); }); test("public server rejects encoded traversal", async () => { diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 56edb135..9c31833e 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/encryption", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 5914a1ca..36ea7a8a 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/i18n", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/jwt/package.json b/packages/jwt/package.json index 28ed9343..42334757 100644 --- a/packages/jwt/package.json +++ b/packages/jwt/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/jwt", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/mobile/package.json b/packages/mobile/package.json index 1d1efc47..8f714751 100644 --- a/packages/mobile/package.json +++ b/packages/mobile/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/mobile", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/native/package.json b/packages/native/package.json index 15cce6bd..8a03827b 100644 --- a/packages/native/package.json +++ b/packages/native/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/native", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/oauth/package.json b/packages/oauth/package.json index d1f658c5..dd47488e 100644 --- a/packages/oauth/package.json +++ b/packages/oauth/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/oauth", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index 4d70f6c1..591b96cb 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/pubsub", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/queue/package.json b/packages/queue/package.json index fe3ea194..e4d922c1 100644 --- a/packages/queue/package.json +++ b/packages/queue/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/queue", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/reactive/package.json b/packages/reactive/package.json index c219287e..6240e633 100644 --- a/packages/reactive/package.json +++ b/packages/reactive/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/reactive", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/router/package.json b/packages/router/package.json index 97d63b5f..12fe977b 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/router", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/ssr/package.json b/packages/ssr/package.json index db7c82f7..346f9de3 100644 --- a/packages/ssr/package.json +++ b/packages/ssr/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ssr", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/styles/package.json b/packages/styles/package.json index d53232f8..7c8874ec 100644 --- a/packages/styles/package.json +++ b/packages/styles/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/styles", - "version": "0.2.14", + "version": "0.2.15", "type": "module", "main": "src/index.ts", "exports": { diff --git a/packages/test/package.json b/packages/test/package.json index 2995a81c..3fafac1a 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/test", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/tracking/package.json b/packages/tracking/package.json index 35ef1a46..259979fc 100644 --- a/packages/tracking/package.json +++ b/packages/tracking/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/tracking", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/ui/package.json b/packages/ui/package.json index 247b0529..069500b7 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/ui", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/uploader/package.json b/packages/uploader/package.json index 104dcb10..8c4078d3 100644 --- a/packages/uploader/package.json +++ b/packages/uploader/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/uploader", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/validation/package.json b/packages/validation/package.json index 2ea543cd..38446bbb 100644 --- a/packages/validation/package.json +++ b/packages/validation/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/validation", - "version": "0.2.14", + "version": "0.2.15", "private": true, "type": "module", "main": "src/index.ts",