@webtypen/webframez-react 0.0.24 → 0.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -1
- package/defaults/webpack.client.cjs +8 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/http.cjs +133 -16
- package/dist/http.js +133 -16
- package/dist/index.cjs +133 -16
- package/dist/index.js +133 -16
- package/dist/router.cjs +68 -7
- package/dist/router.js +68 -7
- package/dist/types.d.ts +7 -6
- package/dist/webframez-core.cjs +133 -16
- package/dist/webframez-core.js +133 -16
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ React Server Components (RSC) extension for `@webtypen/webframez-core`.
|
|
|
14
14
|
|
|
15
15
|
- Node.js `>= 20`
|
|
16
16
|
- `@webtypen/webframez-core`
|
|
17
|
-
- React
|
|
17
|
+
- React 19.x with matching `react-dom` and `react-server-dom-webpack`
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
@@ -130,6 +130,25 @@ Route.renderReact("/app", {
|
|
|
130
130
|
- Additional route options forwarded to `webframez-core`.
|
|
131
131
|
- Typical use case: middleware.
|
|
132
132
|
|
|
133
|
+
## `Head()` Assets
|
|
134
|
+
|
|
135
|
+
Inside a page, layout, or error `Head()` method you can set `assetsBaseUrl`.
|
|
136
|
+
That base URL is applied to `favicon` and `links[].href`, which is useful for CSS
|
|
137
|
+
files and other head assets served from a CDN or shared asset host.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
export function Head() {
|
|
141
|
+
return {
|
|
142
|
+
title: "Dashboard",
|
|
143
|
+
assetsBaseUrl: "https://cdn.example.com/app",
|
|
144
|
+
favicon: "/favicon.ico",
|
|
145
|
+
links: [{ rel: "stylesheet", href: "/styles/dashboard.css" }],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Absolute URLs like `https://...` or `//...` stay unchanged.
|
|
151
|
+
|
|
133
152
|
## Recommended Project Structure
|
|
134
153
|
|
|
135
154
|
```txt
|
|
@@ -6,9 +6,14 @@ const frameworkDistDir = path.resolve(__dirname, "..", "dist");
|
|
|
6
6
|
const clientEntry = process.env.WEBFRAMEZ_REACT_CLIENT_ENTRY
|
|
7
7
|
? path.resolve(projectRoot, process.env.WEBFRAMEZ_REACT_CLIENT_ENTRY)
|
|
8
8
|
: path.resolve(projectRoot, "src/client.tsx");
|
|
9
|
+
const isWatchMode = process.argv.includes("--watch");
|
|
10
|
+
const mode =
|
|
11
|
+
process.env.NODE_ENV === "production" || (typeof process.env.NODE_ENV === "undefined" && !isWatchMode)
|
|
12
|
+
? "production"
|
|
13
|
+
: "development";
|
|
9
14
|
|
|
10
15
|
module.exports = {
|
|
11
|
-
mode
|
|
16
|
+
mode,
|
|
12
17
|
entry: {
|
|
13
18
|
client: clientEntry,
|
|
14
19
|
},
|
|
@@ -38,6 +43,8 @@ module.exports = {
|
|
|
38
43
|
optimization: {
|
|
39
44
|
splitChunks: false,
|
|
40
45
|
runtimeChunk: false,
|
|
46
|
+
moduleIds: "named",
|
|
47
|
+
chunkIds: "named",
|
|
41
48
|
},
|
|
42
49
|
plugins: [
|
|
43
50
|
new ReactFlightWebpackPlugin({
|
package/dist/client.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var H=Object.create;var f=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var W=(e,n)=>{for(var t in n)f(e,t,{get:n[t],enumerable:!0})},v=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of z(n))!M.call(e,r)&&r!==t&&f(e,r,{get:()=>n[r],enumerable:!(o=N(n,r))||o.enumerable});return e};var D=(e,n,t)=>(t=e!=null?H(B(e)):{},v(n||!e||!e.__esModule?f(t,"default",{value:e,enumerable:!0}):t,e)),F=e=>v(f({},"__esModule",{value:!0}),e);var oe={};W(oe,{mountWebframezClient:()=>ne,useCookie:()=>X,useRouter:()=>K});module.exports=F(oe);var i=D(require("react"),1),L=require("react-dom/client"),u=require("react-server-dom-webpack/client");var G=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function g(e){let n=e?.trim();if(n)return n==="/"?"/":n.replace(/\/+$/,"")}function x(e,n){let t=e.trim(),o=g(n);return!t||!o||G.test(t)||o!=="/"&&(t===o||t.startsWith(`${o}/`))?t:o==="/"?t.startsWith("/")?t:`/${t}`:t.startsWith("/")?`${o}${t}`:`${o}/${t}`}function E(e,n){if(!e)return;let t=g(e.assetsBaseUrl)??g(n),o={...e,...t?{assetsBaseUrl:t}:{}};return o.favicon&&(o.favicon=x(o.favicon,t)),o.links&&(o.links=o.links.map(r=>({...r,href:x(r.href,t)}))),o}var s=require("react/jsx-runtime"),Y={push:()=>{},replace:()=>{},refresh:()=>{}},p=typeof i.default.createContext=="function"?i.default.createContext(null):null,U="__WEBFRAMEZ_ROUTER__",Z="[data-webframez-head='true']";function q(){return typeof window>"u"?null:window[U]??null}function j(e){typeof window>"u"||(window[U]=e)}function S(){let e={},n=typeof document>"u"?"":document.cookie;if(!n||n.trim()==="")return e;for(let t of n.split(";")){let o=t.trim();if(!o)continue;let r=o.indexOf("="),d=r>=0?o.slice(0,r).trim():o,c=r>=0?o.slice(r+1):"";d&&(e[d]=decodeURIComponent(c))}return e}function k(e,n,t={}){let o=[`${e}=${encodeURIComponent(n)}`];return t.path&&o.push(`Path=${t.path}`),t.domain&&o.push(`Domain=${t.domain}`),typeof t.maxAge=="number"&&o.push(`Max-Age=${Math.floor(t.maxAge)}`),t.expires&&o.push(`Expires=${t.expires.toUTCString()}`),t.sameSite&&o.push(`SameSite=${t.sameSite}`),t.secure&&o.push("Secure"),o.join("; ")}function X(){return i.default.useMemo(()=>({all:()=>S(),get:e=>S()[e],set:(e,n,t)=>{typeof document>"u"||(document.cookie=k(e,n,t))},remove:(e,n)=>{typeof document>"u"||(document.cookie=k(e,"",{...n??{},maxAge:0}))}}),[])}function K(){let e=p?i.default.useContext(p):null;if(!e){let n=q();if(n)return n;if(typeof window>"u")return Y;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function V({active:e}){return(0,s.jsx)("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:e?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function I(e){let n=document.createElement("meta");n.setAttribute("data-webframez-head","true");let t=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of t)n.setAttribute(o,String(r));document.head.appendChild(n)}function b(e){let n=document.createElement("link");n.setAttribute("data-webframez-head","true");let t=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of t)n.setAttribute(o,String(r));document.head.appendChild(n)}function P(e){if(typeof document>"u")return;let n=E(e)??e;document.title=n.title||"Webframez React";for(let t of document.head.querySelectorAll(Z))t.remove();n.description&&I({name:"description",content:n.description}),n.favicon&&b({rel:"icon",href:n.favicon});for(let t of n.meta??[])I(t);for(let t of n.links??[])b(t)}function J(e){let n=new TextEncoder;return new ReadableStream({start(t){t.enqueue(n.encode(e)),t.close()}})}function Q(){if(typeof window>"u")return null;let e=window.__RSC_INITIAL_PAYLOAD;return typeof e!="string"||e===""?null:(delete window.__RSC_INITIAL_PAYLOAD,(0,u.createFromReadableStream)(J(e)))}function ee(e){return Q()??(0,u.createFromFetch)(fetch(`${e}?path=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function te(e,n){return function(){let o=i.default.use(e),[r,d]=(0,i.useState)(o.model),[c,h]=(0,i.useState)(o.head),[O,w]=(0,i.useState)(!1),[T,$]=(0,i.useState)(!1);async function l(a,A="push"){w(!0);try{let m=await(0,u.createFromFetch)(fetch(`${n}?path=${encodeURIComponent(a.pathname)}&search=${encodeURIComponent(a.search)}`,{headers:{Accept:"text/x-component"}}));P(m.head),h(m.head),d(m.model);let _=`${a.pathname}${a.search}`;A==="replace"?history.replaceState(null,"",_):A==="push"&&history.pushState(null,"",_)}catch(y){console.error("[webframez-react] Failed to render route",y),d((0,s.jsx)("p",{children:"Failed to load route."}))}finally{w(!1)}}(0,i.useEffect)(()=>{P(c)},[c]),(0,i.useEffect)(()=>{$(!0);let a=()=>{l(new URL(window.location.href),"none")};return window.addEventListener("popstate",a),()=>{window.removeEventListener("popstate",a)}},[]);let R=i.default.useMemo(()=>({push:a=>{l(new URL(a,window.location.origin),"push")},replace:a=>{l(new URL(a,window.location.origin),"replace")},refresh:()=>{l(new URL(window.location.href),"none")}}),[]);j(R);let C=(0,s.jsxs)(s.Fragment,{children:[T?(0,s.jsx)(V,{active:O}):null,r??(0,s.jsx)("p",{style:{padding:24},children:"Loading..."})]});return p?(0,s.jsx)(p.Provider,{value:R,children:C}):C}}function ne(e={}){let n=e.rootId??"root",t=document.getElementById(n);if(!t)throw new Error(`Missing #${n} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??o??"/rsc",d=ee(r),c=te(d,r);return(0,L.hydrateRoot)(t,(0,s.jsx)(c,{}))}
|
package/dist/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import c,{useEffect as x,useState as l}from"react";import{hydrateRoot as H}from"react-dom/client";import{createFromFetch as P,createFromReadableStream as N}from"react-server-dom-webpack/client";var $=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function m(t){let n=t?.trim();if(n)return n==="/"?"/":n.replace(/\/+$/,"")}function _(t,n){let e=t.trim(),o=m(n);return!e||!o||$.test(e)||o!=="/"&&(e===o||e.startsWith(`${o}/`))?e:o==="/"?e.startsWith("/")?e:`/${e}`:e.startsWith("/")?`${o}${e}`:`${o}/${e}`}function v(t,n){if(!t)return;let e=m(t.assetsBaseUrl)??m(n),o={...t,...e?{assetsBaseUrl:e}:{}};return o.favicon&&(o.favicon=_(o.favicon,e)),o.links&&(o.links=o.links.map(r=>({...r,href:_(r.href,e)}))),o}import{Fragment as q,jsx as d,jsxs as j}from"react/jsx-runtime";var z={push:()=>{},replace:()=>{},refresh:()=>{}},f=typeof c.createContext=="function"?c.createContext(null):null,L="__WEBFRAMEZ_ROUTER__",B="[data-webframez-head='true']";function M(){return typeof window>"u"?null:window[L]??null}function W(t){typeof window>"u"||(window[L]=t)}function E(){let t={},n=typeof document>"u"?"":document.cookie;if(!n||n.trim()==="")return t;for(let e of n.split(";")){let o=e.trim();if(!o)continue;let r=o.indexOf("="),a=r>=0?o.slice(0,r).trim():o,s=r>=0?o.slice(r+1):"";a&&(t[a]=decodeURIComponent(s))}return t}function S(t,n,e={}){let o=[`${t}=${encodeURIComponent(n)}`];return e.path&&o.push(`Path=${e.path}`),e.domain&&o.push(`Domain=${e.domain}`),typeof e.maxAge=="number"&&o.push(`Max-Age=${Math.floor(e.maxAge)}`),e.expires&&o.push(`Expires=${e.expires.toUTCString()}`),e.sameSite&&o.push(`SameSite=${e.sameSite}`),e.secure&&o.push("Secure"),o.join("; ")}function ee(){return c.useMemo(()=>({all:()=>E(),get:t=>E()[t],set:(t,n,e)=>{typeof document>"u"||(document.cookie=S(t,n,e))},remove:(t,n)=>{typeof document>"u"||(document.cookie=S(t,"",{...n??{},maxAge:0}))}}),[])}function te(){let t=f?c.useContext(f):null;if(!t){let n=M();if(n)return n;if(typeof window>"u")return z;throw new Error("useRouter must be used inside mountWebframezClient()")}return t}function D({active:t}){return d("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:t?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function k(t){let n=document.createElement("meta");n.setAttribute("data-webframez-head","true");let e=Object.entries(t).filter(([,o])=>!!o);for(let[o,r]of e)n.setAttribute(o,String(r));document.head.appendChild(n)}function I(t){let n=document.createElement("link");n.setAttribute("data-webframez-head","true");let e=Object.entries(t).filter(([,o])=>!!o);for(let[o,r]of e)n.setAttribute(o,String(r));document.head.appendChild(n)}function b(t){if(typeof document>"u")return;let n=v(t)??t;document.title=n.title||"Webframez React";for(let e of document.head.querySelectorAll(B))e.remove();n.description&&k({name:"description",content:n.description}),n.favicon&&I({rel:"icon",href:n.favicon});for(let e of n.meta??[])k(e);for(let e of n.links??[])I(e)}function F(t){let n=new TextEncoder;return new ReadableStream({start(e){e.enqueue(n.encode(t)),e.close()}})}function G(){if(typeof window>"u")return null;let t=window.__RSC_INITIAL_PAYLOAD;return typeof t!="string"||t===""?null:(delete window.__RSC_INITIAL_PAYLOAD,N(F(t)))}function Y(t){return G()??P(fetch(`${t}?path=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function Z(t,n){return function(){let o=c.use(t),[r,a]=l(o.model),[s,g]=l(o.head),[U,h]=l(!1),[O,T]=l(!1);async function u(i,C="push"){h(!0);try{let p=await P(fetch(`${n}?path=${encodeURIComponent(i.pathname)}&search=${encodeURIComponent(i.search)}`,{headers:{Accept:"text/x-component"}}));b(p.head),g(p.head),a(p.model);let y=`${i.pathname}${i.search}`;C==="replace"?history.replaceState(null,"",y):C==="push"&&history.pushState(null,"",y)}catch(A){console.error("[webframez-react] Failed to render route",A),a(d("p",{children:"Failed to load route."}))}finally{h(!1)}}x(()=>{b(s)},[s]),x(()=>{T(!0);let i=()=>{u(new URL(window.location.href),"none")};return window.addEventListener("popstate",i),()=>{window.removeEventListener("popstate",i)}},[]);let w=c.useMemo(()=>({push:i=>{u(new URL(i,window.location.origin),"push")},replace:i=>{u(new URL(i,window.location.origin),"replace")},refresh:()=>{u(new URL(window.location.href),"none")}}),[]);W(w);let R=j(q,{children:[O?d(D,{active:U}):null,r??d("p",{style:{padding:24},children:"Loading..."})]});return f?d(f.Provider,{value:w,children:R}):R}}function ne(t={}){let n=t.rootId??"root",e=document.getElementById(n);if(!e)throw new Error(`Missing #${n} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=t.rscEndpoint??o??"/rsc",a=Y(r),s=Z(a,r);return H(e,d(s,{}))}export{ne as mountWebframezClient,ee as useCookie,te as useRouter};
|
package/dist/http.cjs
CHANGED
|
@@ -150,6 +150,62 @@ var import_node_fs = __toESM(require("node:fs"), 1);
|
|
|
150
150
|
var import_node_module2 = __toESM(require("node:module"), 1);
|
|
151
151
|
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
152
152
|
|
|
153
|
+
// src/head.ts
|
|
154
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
155
|
+
function normalizeAssetsBaseUrl(value) {
|
|
156
|
+
const trimmed = value?.trim();
|
|
157
|
+
if (!trimmed) {
|
|
158
|
+
return void 0;
|
|
159
|
+
}
|
|
160
|
+
if (trimmed === "/") {
|
|
161
|
+
return "/";
|
|
162
|
+
}
|
|
163
|
+
return trimmed.replace(/\/+$/, "");
|
|
164
|
+
}
|
|
165
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
166
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
167
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
168
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
169
|
+
return normalizedAssetUrl;
|
|
170
|
+
}
|
|
171
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
172
|
+
return normalizedAssetUrl;
|
|
173
|
+
}
|
|
174
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
175
|
+
return normalizedAssetUrl;
|
|
176
|
+
}
|
|
177
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
178
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
179
|
+
}
|
|
180
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
181
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
182
|
+
}
|
|
183
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
184
|
+
}
|
|
185
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
186
|
+
if (!head) {
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
190
|
+
const normalizedHead = {
|
|
191
|
+
...head,
|
|
192
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
193
|
+
};
|
|
194
|
+
if (normalizedHead.favicon) {
|
|
195
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
196
|
+
normalizedHead.favicon,
|
|
197
|
+
effectiveAssetsBaseUrl
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
if (normalizedHead.links) {
|
|
201
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
202
|
+
...link,
|
|
203
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
return normalizedHead;
|
|
207
|
+
}
|
|
208
|
+
|
|
153
209
|
// src/router-runtime.tsx
|
|
154
210
|
var import_react = __toESM(require("react"), 1);
|
|
155
211
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -365,7 +421,8 @@ function mergeHead(...configs) {
|
|
|
365
421
|
meta: [],
|
|
366
422
|
links: []
|
|
367
423
|
};
|
|
368
|
-
for (const
|
|
424
|
+
for (const candidate of configs) {
|
|
425
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
369
426
|
if (!config) {
|
|
370
427
|
continue;
|
|
371
428
|
}
|
|
@@ -375,6 +432,9 @@ function mergeHead(...configs) {
|
|
|
375
432
|
if (config.description) {
|
|
376
433
|
merged.description = config.description;
|
|
377
434
|
}
|
|
435
|
+
if (config.assetsBaseUrl) {
|
|
436
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
437
|
+
}
|
|
378
438
|
if (config.favicon) {
|
|
379
439
|
merged.favicon = config.favicon;
|
|
380
440
|
}
|
|
@@ -388,22 +448,23 @@ function mergeHead(...configs) {
|
|
|
388
448
|
return merged;
|
|
389
449
|
}
|
|
390
450
|
function renderHeadToString(head) {
|
|
451
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
391
452
|
const tags = [];
|
|
392
|
-
if (
|
|
453
|
+
if (normalizedHead.description) {
|
|
393
454
|
tags.push(
|
|
394
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
455
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
395
456
|
);
|
|
396
457
|
}
|
|
397
|
-
if (
|
|
458
|
+
if (normalizedHead.favicon) {
|
|
398
459
|
tags.push(
|
|
399
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
460
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
400
461
|
);
|
|
401
462
|
}
|
|
402
|
-
for (const meta of
|
|
463
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
403
464
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
404
465
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
405
466
|
}
|
|
406
|
-
for (const link of
|
|
467
|
+
for (const link of normalizedHead.links ?? []) {
|
|
407
468
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
408
469
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
409
470
|
}
|
|
@@ -732,7 +793,21 @@ globalThis.__webpack_require__ = function __webframezNodeRequire(id) {
|
|
|
732
793
|
}
|
|
733
794
|
|
|
734
795
|
if (id.startsWith("./")) {
|
|
735
|
-
|
|
796
|
+
const relativeId = id.slice(2);
|
|
797
|
+
const candidates = [
|
|
798
|
+
path.resolve(process.cwd(), relativeId),
|
|
799
|
+
path.resolve(process.cwd(), "..", relativeId)
|
|
800
|
+
];
|
|
801
|
+
for (const candidate of candidates) {
|
|
802
|
+
try {
|
|
803
|
+
return require(candidate);
|
|
804
|
+
} catch (error) {
|
|
805
|
+
const missingCandidate = error && error.code === "MODULE_NOT_FOUND" && typeof error.message === "string" && error.message.includes("'" + candidate + "'");
|
|
806
|
+
if (!missingCandidate) {
|
|
807
|
+
throw error;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
736
811
|
}
|
|
737
812
|
|
|
738
813
|
return require(id);
|
|
@@ -1036,22 +1111,64 @@ function normalizeClientManifest(manifest, options) {
|
|
|
1036
1111
|
}
|
|
1037
1112
|
function createServerConsumerManifest(manifest) {
|
|
1038
1113
|
const consumerManifest = {};
|
|
1114
|
+
const normalizeWorkerModuleId = (requestKey, rawModuleId) => {
|
|
1115
|
+
if (typeof rawModuleId === "string" && rawModuleId.trim() !== "") {
|
|
1116
|
+
return rawModuleId;
|
|
1117
|
+
}
|
|
1118
|
+
if (typeof rawModuleId !== "number" || !Number.isFinite(rawModuleId)) {
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
if (!requestKey || requestKey.trim() === "") {
|
|
1122
|
+
return String(rawModuleId);
|
|
1123
|
+
}
|
|
1124
|
+
if (requestKey.startsWith("file://")) {
|
|
1125
|
+
try {
|
|
1126
|
+
return (0, import_node_url.fileURLToPath)(requestKey);
|
|
1127
|
+
} catch {
|
|
1128
|
+
return String(rawModuleId);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
if (requestKey.startsWith("/")) {
|
|
1132
|
+
return requestKey;
|
|
1133
|
+
}
|
|
1134
|
+
if (requestKey.startsWith("./")) {
|
|
1135
|
+
return requestKey;
|
|
1136
|
+
}
|
|
1137
|
+
if (requestKey.startsWith("node_modules/") || requestKey.startsWith("build/")) {
|
|
1138
|
+
return `./${requestKey}`;
|
|
1139
|
+
}
|
|
1140
|
+
return requestKey;
|
|
1141
|
+
};
|
|
1142
|
+
const addReference = (lookupKey, reference) => {
|
|
1143
|
+
if (!lookupKey || lookupKey.trim() === "") {
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
if (lookupKey in consumerManifest) {
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
consumerManifest[lookupKey] = {
|
|
1150
|
+
"*": reference
|
|
1151
|
+
};
|
|
1152
|
+
};
|
|
1039
1153
|
for (const [key, value] of Object.entries(manifest)) {
|
|
1040
1154
|
if (!value || typeof value !== "object") {
|
|
1041
1155
|
continue;
|
|
1042
1156
|
}
|
|
1043
1157
|
const entry = value;
|
|
1044
|
-
|
|
1158
|
+
const workerModuleId = normalizeWorkerModuleId(key, entry.id);
|
|
1159
|
+
if (!workerModuleId) {
|
|
1045
1160
|
continue;
|
|
1046
1161
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
...entry.async ? { async: entry.async } : {}
|
|
1053
|
-
}
|
|
1162
|
+
const reference = {
|
|
1163
|
+
id: workerModuleId,
|
|
1164
|
+
chunks: Array.isArray(entry.chunks) ? entry.chunks : [],
|
|
1165
|
+
name: entry.name ?? "*",
|
|
1166
|
+
...entry.async ? { async: entry.async } : {}
|
|
1054
1167
|
};
|
|
1168
|
+
addReference(key, reference);
|
|
1169
|
+
if (typeof entry.id === "number" && Number.isFinite(entry.id)) {
|
|
1170
|
+
addReference(String(entry.id), reference);
|
|
1171
|
+
}
|
|
1055
1172
|
}
|
|
1056
1173
|
return consumerManifest;
|
|
1057
1174
|
}
|
package/dist/http.js
CHANGED
|
@@ -125,6 +125,62 @@ import fs from "node:fs";
|
|
|
125
125
|
import Module from "node:module";
|
|
126
126
|
import path2 from "node:path";
|
|
127
127
|
|
|
128
|
+
// src/head.ts
|
|
129
|
+
var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
|
|
130
|
+
function normalizeAssetsBaseUrl(value) {
|
|
131
|
+
const trimmed = value?.trim();
|
|
132
|
+
if (!trimmed) {
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
if (trimmed === "/") {
|
|
136
|
+
return "/";
|
|
137
|
+
}
|
|
138
|
+
return trimmed.replace(/\/+$/, "");
|
|
139
|
+
}
|
|
140
|
+
function resolveHeadAssetUrl(assetUrl, assetsBaseUrl) {
|
|
141
|
+
const normalizedAssetUrl = assetUrl.trim();
|
|
142
|
+
const normalizedAssetsBaseUrl = normalizeAssetsBaseUrl(assetsBaseUrl);
|
|
143
|
+
if (!normalizedAssetUrl || !normalizedAssetsBaseUrl) {
|
|
144
|
+
return normalizedAssetUrl;
|
|
145
|
+
}
|
|
146
|
+
if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
|
|
147
|
+
return normalizedAssetUrl;
|
|
148
|
+
}
|
|
149
|
+
if (normalizedAssetsBaseUrl !== "/" && (normalizedAssetUrl === normalizedAssetsBaseUrl || normalizedAssetUrl.startsWith(`${normalizedAssetsBaseUrl}/`))) {
|
|
150
|
+
return normalizedAssetUrl;
|
|
151
|
+
}
|
|
152
|
+
if (normalizedAssetsBaseUrl === "/") {
|
|
153
|
+
return normalizedAssetUrl.startsWith("/") ? normalizedAssetUrl : `/${normalizedAssetUrl}`;
|
|
154
|
+
}
|
|
155
|
+
if (normalizedAssetUrl.startsWith("/")) {
|
|
156
|
+
return `${normalizedAssetsBaseUrl}${normalizedAssetUrl}`;
|
|
157
|
+
}
|
|
158
|
+
return `${normalizedAssetsBaseUrl}/${normalizedAssetUrl}`;
|
|
159
|
+
}
|
|
160
|
+
function normalizeHeadConfig(head, inheritedAssetsBaseUrl) {
|
|
161
|
+
if (!head) {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
const effectiveAssetsBaseUrl = normalizeAssetsBaseUrl(head.assetsBaseUrl) ?? normalizeAssetsBaseUrl(inheritedAssetsBaseUrl);
|
|
165
|
+
const normalizedHead = {
|
|
166
|
+
...head,
|
|
167
|
+
...effectiveAssetsBaseUrl ? { assetsBaseUrl: effectiveAssetsBaseUrl } : {}
|
|
168
|
+
};
|
|
169
|
+
if (normalizedHead.favicon) {
|
|
170
|
+
normalizedHead.favicon = resolveHeadAssetUrl(
|
|
171
|
+
normalizedHead.favicon,
|
|
172
|
+
effectiveAssetsBaseUrl
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (normalizedHead.links) {
|
|
176
|
+
normalizedHead.links = normalizedHead.links.map((link) => ({
|
|
177
|
+
...link,
|
|
178
|
+
href: resolveHeadAssetUrl(link.href, effectiveAssetsBaseUrl)
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
return normalizedHead;
|
|
182
|
+
}
|
|
183
|
+
|
|
128
184
|
// src/router-runtime.tsx
|
|
129
185
|
import React from "react";
|
|
130
186
|
var ROUTE_CHILDREN_TAG = "webframez-route-children";
|
|
@@ -340,7 +396,8 @@ function mergeHead(...configs) {
|
|
|
340
396
|
meta: [],
|
|
341
397
|
links: []
|
|
342
398
|
};
|
|
343
|
-
for (const
|
|
399
|
+
for (const candidate of configs) {
|
|
400
|
+
const config = normalizeHeadConfig(candidate, merged.assetsBaseUrl);
|
|
344
401
|
if (!config) {
|
|
345
402
|
continue;
|
|
346
403
|
}
|
|
@@ -350,6 +407,9 @@ function mergeHead(...configs) {
|
|
|
350
407
|
if (config.description) {
|
|
351
408
|
merged.description = config.description;
|
|
352
409
|
}
|
|
410
|
+
if (config.assetsBaseUrl) {
|
|
411
|
+
merged.assetsBaseUrl = config.assetsBaseUrl;
|
|
412
|
+
}
|
|
353
413
|
if (config.favicon) {
|
|
354
414
|
merged.favicon = config.favicon;
|
|
355
415
|
}
|
|
@@ -363,22 +423,23 @@ function mergeHead(...configs) {
|
|
|
363
423
|
return merged;
|
|
364
424
|
}
|
|
365
425
|
function renderHeadToString(head) {
|
|
426
|
+
const normalizedHead = normalizeHeadConfig(head) ?? head;
|
|
366
427
|
const tags = [];
|
|
367
|
-
if (
|
|
428
|
+
if (normalizedHead.description) {
|
|
368
429
|
tags.push(
|
|
369
|
-
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(
|
|
430
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(normalizedHead.description)}" />`
|
|
370
431
|
);
|
|
371
432
|
}
|
|
372
|
-
if (
|
|
433
|
+
if (normalizedHead.favicon) {
|
|
373
434
|
tags.push(
|
|
374
|
-
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(
|
|
435
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(normalizedHead.favicon)}" />`
|
|
375
436
|
);
|
|
376
437
|
}
|
|
377
|
-
for (const meta of
|
|
438
|
+
for (const meta of normalizedHead.meta ?? []) {
|
|
378
439
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
379
440
|
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
380
441
|
}
|
|
381
|
-
for (const link of
|
|
442
|
+
for (const link of normalizedHead.links ?? []) {
|
|
382
443
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
383
444
|
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
384
445
|
}
|
|
@@ -707,7 +768,21 @@ globalThis.__webpack_require__ = function __webframezNodeRequire(id) {
|
|
|
707
768
|
}
|
|
708
769
|
|
|
709
770
|
if (id.startsWith("./")) {
|
|
710
|
-
|
|
771
|
+
const relativeId = id.slice(2);
|
|
772
|
+
const candidates = [
|
|
773
|
+
path.resolve(process.cwd(), relativeId),
|
|
774
|
+
path.resolve(process.cwd(), "..", relativeId)
|
|
775
|
+
];
|
|
776
|
+
for (const candidate of candidates) {
|
|
777
|
+
try {
|
|
778
|
+
return require(candidate);
|
|
779
|
+
} catch (error) {
|
|
780
|
+
const missingCandidate = error && error.code === "MODULE_NOT_FOUND" && typeof error.message === "string" && error.message.includes("'" + candidate + "'");
|
|
781
|
+
if (!missingCandidate) {
|
|
782
|
+
throw error;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
711
786
|
}
|
|
712
787
|
|
|
713
788
|
return require(id);
|
|
@@ -1011,22 +1086,64 @@ function normalizeClientManifest(manifest, options) {
|
|
|
1011
1086
|
}
|
|
1012
1087
|
function createServerConsumerManifest(manifest) {
|
|
1013
1088
|
const consumerManifest = {};
|
|
1089
|
+
const normalizeWorkerModuleId = (requestKey, rawModuleId) => {
|
|
1090
|
+
if (typeof rawModuleId === "string" && rawModuleId.trim() !== "") {
|
|
1091
|
+
return rawModuleId;
|
|
1092
|
+
}
|
|
1093
|
+
if (typeof rawModuleId !== "number" || !Number.isFinite(rawModuleId)) {
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
if (!requestKey || requestKey.trim() === "") {
|
|
1097
|
+
return String(rawModuleId);
|
|
1098
|
+
}
|
|
1099
|
+
if (requestKey.startsWith("file://")) {
|
|
1100
|
+
try {
|
|
1101
|
+
return fileURLToPath(requestKey);
|
|
1102
|
+
} catch {
|
|
1103
|
+
return String(rawModuleId);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
if (requestKey.startsWith("/")) {
|
|
1107
|
+
return requestKey;
|
|
1108
|
+
}
|
|
1109
|
+
if (requestKey.startsWith("./")) {
|
|
1110
|
+
return requestKey;
|
|
1111
|
+
}
|
|
1112
|
+
if (requestKey.startsWith("node_modules/") || requestKey.startsWith("build/")) {
|
|
1113
|
+
return `./${requestKey}`;
|
|
1114
|
+
}
|
|
1115
|
+
return requestKey;
|
|
1116
|
+
};
|
|
1117
|
+
const addReference = (lookupKey, reference) => {
|
|
1118
|
+
if (!lookupKey || lookupKey.trim() === "") {
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
if (lookupKey in consumerManifest) {
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
consumerManifest[lookupKey] = {
|
|
1125
|
+
"*": reference
|
|
1126
|
+
};
|
|
1127
|
+
};
|
|
1014
1128
|
for (const [key, value] of Object.entries(manifest)) {
|
|
1015
1129
|
if (!value || typeof value !== "object") {
|
|
1016
1130
|
continue;
|
|
1017
1131
|
}
|
|
1018
1132
|
const entry = value;
|
|
1019
|
-
|
|
1133
|
+
const workerModuleId = normalizeWorkerModuleId(key, entry.id);
|
|
1134
|
+
if (!workerModuleId) {
|
|
1020
1135
|
continue;
|
|
1021
1136
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
...entry.async ? { async: entry.async } : {}
|
|
1028
|
-
}
|
|
1137
|
+
const reference = {
|
|
1138
|
+
id: workerModuleId,
|
|
1139
|
+
chunks: Array.isArray(entry.chunks) ? entry.chunks : [],
|
|
1140
|
+
name: entry.name ?? "*",
|
|
1141
|
+
...entry.async ? { async: entry.async } : {}
|
|
1029
1142
|
};
|
|
1143
|
+
addReference(key, reference);
|
|
1144
|
+
if (typeof entry.id === "number" && Number.isFinite(entry.id)) {
|
|
1145
|
+
addReference(String(entry.id), reference);
|
|
1146
|
+
}
|
|
1030
1147
|
}
|
|
1031
1148
|
return consumerManifest;
|
|
1032
1149
|
}
|