@webtypen/webframez-react 0.0.2 → 0.0.3
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 +214 -109
- package/bin/webframez-react.mjs +158 -7
- package/defaults/tsconfig.server.example.json +46 -0
- package/defaults/tsconfig.server.json +13 -0
- package/defaults/webpack.client.cjs +4 -1
- package/defaults/webpack.server.cjs +8 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/dist/http.cjs +35 -11
- package/dist/http.d.ts +18 -7
- package/dist/http.js +35 -11
- package/dist/index.cjs +35 -11
- package/dist/index.d.ts +2 -5
- package/dist/index.js +35 -11
- package/dist/router.cjs +30 -10
- package/dist/router.js +30 -10
- package/dist/types.d.ts +25 -8
- package/dist/webframez-core.cjs +35 -11
- package/dist/webframez-core.d.ts +32 -8
- package/dist/webframez-core.js +35 -11
- package/package.json +2 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"baseUrl": ".",
|
|
7
|
+
"paths": {
|
|
8
|
+
"@webtypen/webframez-react": [
|
|
9
|
+
"./node_modules/@webtypen/webframez-react/dist/index.d.ts"
|
|
10
|
+
],
|
|
11
|
+
"@webtypen/webframez-react/types": [
|
|
12
|
+
"./node_modules/@webtypen/webframez-react/dist/types.d.ts"
|
|
13
|
+
],
|
|
14
|
+
"@webtypen/webframez-react/router": [
|
|
15
|
+
"./node_modules/@webtypen/webframez-react/dist/router.d.ts"
|
|
16
|
+
],
|
|
17
|
+
"@webtypen/webframez-react/client": [
|
|
18
|
+
"./node_modules/@webtypen/webframez-react/dist/client.d.ts"
|
|
19
|
+
],
|
|
20
|
+
"@webtypen/webframez-react/navigation": [
|
|
21
|
+
"./node_modules/@webtypen/webframez-react/dist/navigation.d.ts"
|
|
22
|
+
],
|
|
23
|
+
"@webtypen/webframez-react/webframez-core": [
|
|
24
|
+
"./node_modules/@webtypen/webframez-react/dist/webframez-core.d.ts"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"jsx": "react-jsx",
|
|
28
|
+
"strict": true,
|
|
29
|
+
"esModuleInterop": true,
|
|
30
|
+
"skipLibCheck": true,
|
|
31
|
+
"outDir": "dist",
|
|
32
|
+
"rootDir": "."
|
|
33
|
+
},
|
|
34
|
+
"include": [
|
|
35
|
+
"src/server.ts",
|
|
36
|
+
"src/server.tsx",
|
|
37
|
+
"src/components/**/*.tsx",
|
|
38
|
+
"pages/**/*.tsx",
|
|
39
|
+
"src/types.d.ts"
|
|
40
|
+
],
|
|
41
|
+
"exclude": [
|
|
42
|
+
"src/client.tsx",
|
|
43
|
+
"dist",
|
|
44
|
+
"node_modules"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
"moduleResolution": "Node",
|
|
6
6
|
"baseUrl": ".",
|
|
7
7
|
"paths": {
|
|
8
|
+
"@webtypen/webframez-react": [
|
|
9
|
+
"./node_modules/@webtypen/webframez-react/dist/index.d.ts"
|
|
10
|
+
],
|
|
8
11
|
"@webtypen/webframez-react/types": [
|
|
9
12
|
"./node_modules/@webtypen/webframez-react/dist/types.d.ts"
|
|
10
13
|
],
|
|
@@ -17,6 +20,12 @@
|
|
|
17
20
|
"@webtypen/webframez-react/navigation": [
|
|
18
21
|
"./node_modules/@webtypen/webframez-react/dist/navigation.d.ts"
|
|
19
22
|
],
|
|
23
|
+
"@webtypen/webframez-react/webframez-core": [
|
|
24
|
+
"./node_modules/@webtypen/webframez-react/dist/webframez-core.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"webframez-react": [
|
|
27
|
+
"./node_modules/@webtypen/webframez-react/dist/index.d.ts"
|
|
28
|
+
],
|
|
20
29
|
"webframez-react/types": [
|
|
21
30
|
"./node_modules/@webtypen/webframez-react/dist/types.d.ts"
|
|
22
31
|
],
|
|
@@ -28,6 +37,9 @@
|
|
|
28
37
|
],
|
|
29
38
|
"webframez-react/navigation": [
|
|
30
39
|
"./node_modules/@webtypen/webframez-react/dist/navigation.d.ts"
|
|
40
|
+
],
|
|
41
|
+
"webframez-react/webframez-core": [
|
|
42
|
+
"./node_modules/@webtypen/webframez-react/dist/webframez-core.d.ts"
|
|
31
43
|
]
|
|
32
44
|
},
|
|
33
45
|
"jsx": "react-jsx",
|
|
@@ -39,6 +51,7 @@
|
|
|
39
51
|
},
|
|
40
52
|
"include": [
|
|
41
53
|
"src/server.ts",
|
|
54
|
+
"src/server.tsx",
|
|
42
55
|
"src/components/**/*.tsx",
|
|
43
56
|
"pages/**/*.tsx",
|
|
44
57
|
"src/types.d.ts"
|
|
@@ -3,11 +3,14 @@ const ReactFlightWebpackPlugin = require("react-server-dom-webpack/plugin");
|
|
|
3
3
|
|
|
4
4
|
const projectRoot = process.cwd();
|
|
5
5
|
const frameworkDistDir = path.resolve(__dirname, "..", "dist");
|
|
6
|
+
const clientEntry = process.env.WEBFRAMEZ_REACT_CLIENT_ENTRY
|
|
7
|
+
? path.resolve(projectRoot, process.env.WEBFRAMEZ_REACT_CLIENT_ENTRY)
|
|
8
|
+
: path.resolve(projectRoot, "src/client.tsx");
|
|
6
9
|
|
|
7
10
|
module.exports = {
|
|
8
11
|
mode: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
9
12
|
entry: {
|
|
10
|
-
client:
|
|
13
|
+
client: clientEntry,
|
|
11
14
|
},
|
|
12
15
|
output: {
|
|
13
16
|
path: path.resolve(projectRoot, "dist"),
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
+
const fs = require("fs");
|
|
2
3
|
|
|
3
4
|
const projectRoot = process.cwd();
|
|
5
|
+
const defaultServerEntry = fs.existsSync(path.resolve(projectRoot, "src/server.ts"))
|
|
6
|
+
? path.resolve(projectRoot, "src/server.ts")
|
|
7
|
+
: path.resolve(projectRoot, "src/server.tsx");
|
|
8
|
+
const serverEntry = process.env.WEBFRAMEZ_REACT_SERVER_ENTRY
|
|
9
|
+
? path.resolve(projectRoot, process.env.WEBFRAMEZ_REACT_SERVER_ENTRY)
|
|
10
|
+
: defaultServerEntry;
|
|
4
11
|
|
|
5
12
|
module.exports = {
|
|
6
13
|
mode: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
7
14
|
target: "node",
|
|
8
|
-
entry:
|
|
15
|
+
entry: serverEntry,
|
|
9
16
|
output: {
|
|
10
17
|
path: path.resolve(projectRoot, "dist"),
|
|
11
18
|
filename: "server.cjs",
|
package/dist/client.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var k=Object.create;var d=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,L=Object.prototype.hasOwnProperty;var T=(e,t)=>{for(var n in t)d(e,n,{get:t[n],enumerable:!0})},R=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of O(t))!L.call(e,r)&&r!==n&&d(e,r,{get:()=>t[r],enumerable:!(o=A(t,r))||o.enumerable});return e};var U=(e,t,n)=>(n=e!=null?k(S(e)):{},R(t||!e||!e.__esModule?d(n,"default",{value:e,enumerable:!0}):n,e)),M=e=>R(d({},"__esModule",{value:!0}),e);var D={};T(D,{mountWebframezClient:()=>F,useCookie:()=>B,useRouter:()=>H});module.exports=M(D);var s=U(require("react"),1),E=require("react-dom/client"),_=require("react-server-dom-webpack/client"),i=require("react/jsx-runtime"),$={push:()=>{},replace:()=>{},refresh:()=>{}},l=typeof s.default.createContext=="function"?s.default.createContext(null):null,b="__WEBFRAMEZ_ROUTER__",I="[data-webframez-head='true']";function P(){return typeof window>"u"?null:window[b]??null}function N(e){typeof window>"u"||(window[b]=e)}function h(){let e={},t=typeof document>"u"?"":document.cookie;if(!t||t.trim()==="")return e;for(let n of t.split(";")){let o=n.trim();if(!o)continue;let r=o.indexOf("="),u=r>=0?o.slice(0,r).trim():o,c=r>=0?o.slice(r+1):"";u&&(e[u]=decodeURIComponent(c))}return e}function C(e,t,n={}){let o=[`${e}=${encodeURIComponent(t)}`];return n.path&&o.push(`Path=${n.path}`),n.domain&&o.push(`Domain=${n.domain}`),typeof n.maxAge=="number"&&o.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&o.push(`Expires=${n.expires.toUTCString()}`),n.sameSite&&o.push(`SameSite=${n.sameSite}`),n.secure&&o.push("Secure"),o.join("; ")}function B(){return s.default.useMemo(()=>({all:()=>h(),get:e=>h()[e],set:(e,t,n)=>{typeof document>"u"||(document.cookie=C(e,t,n))},remove:(e,t)=>{typeof document>"u"||(document.cookie=C(e,"",{...t??{},maxAge:0}))}}),[])}function H(){let e=l?s.default.useContext(l):null;if(!e){let t=P();if(t)return t;if(typeof window>"u")return $;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function v({active:e}){return(0,i.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 y(e){let t=document.createElement("meta");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function x(e){let t=document.createElement("link");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function W(e){if(!(typeof document>"u")){document.title=e.title||"Webframez React";for(let t of document.head.querySelectorAll(I))t.remove();e.description&&y({name:"description",content:e.description}),e.favicon&&x({rel:"icon",href:e.favicon});for(let t of e.meta??[])y(t);for(let t of e.links??[])x(t)}}function z(e){return function(){let[n,o]=(0,s.useState)(null),[r,u]=(0,s.useState)(!1);async function c(a,p="push"){u(!0);try{let g=await(0,_.createFromFetch)(fetch(`${e}?path=${encodeURIComponent(a.pathname)}&search=${encodeURIComponent(a.search)}`,{headers:{Accept:"text/x-component"}}));W(g.head),o(g.model);let w=`${a.pathname}${a.search}`;p==="replace"?history.replaceState(null,"",w):p==="push"&&history.pushState(null,"",w)}catch(m){console.error("[webframez-react] Failed to render route",m),o((0,i.jsx)("p",{children:"Failed to load route."}))}finally{u(!1)}}(0,s.useEffect)(()=>{let a=()=>{c(new URL(window.location.href),"none")};return window.addEventListener("popstate",a),c(new URL(window.location.href),"none"),()=>{window.removeEventListener("popstate",a)}},[]);let f=s.default.useMemo(()=>({push:a=>{c(new URL(a,window.location.origin),"push")},replace:a=>{c(new URL(a,window.location.origin),"replace")},refresh:()=>{c(new URL(window.location.href),"none")}}),[]);return N(f),l?(0,i.jsxs)(l.Provider,{value:f,children:[(0,i.jsx)(v,{active:r}),n??(0,i.jsx)("p",{style:{padding:24},children:"Loading..."})]}):(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(v,{active:r}),n??(0,i.jsx)("p",{style:{padding:24},children:"Loading..."})]})}}function F(e={}){let t=e.rootId??"root",n=document.getElementById(t);if(!n)throw new Error(`Missing #${t} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??o??"/rsc",u=z(r),c=(0,E.createRoot)(n);return c.render((0,i.jsx)(u,{})),c}
|
package/dist/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import u,{useEffect as _,useState as w}from"react";import{createRoot as b}from"react-dom/client";import{createFromFetch as k}from"react-server-dom-webpack/client";import{Fragment as M,jsx as c,jsxs as x}from"react/jsx-runtime";var A={push:()=>{},replace:()=>{},refresh:()=>{}},d=typeof u.createContext=="function"?u.createContext(null):null,E="__WEBFRAMEZ_ROUTER__",O="[data-webframez-head='true']";function S(){return typeof window>"u"?null:window[E]??null}function L(e){typeof window>"u"||(window[E]=e)}function R(){let e={},t=typeof document>"u"?"":document.cookie;if(!t||t.trim()==="")return e;for(let o of t.split(";")){let n=o.trim();if(!n)continue;let r=n.indexOf("="),s=r>=0?n.slice(0,r).trim():n,a=r>=0?n.slice(r+1):"";s&&(e[s]=decodeURIComponent(a))}return e}function h(e,t,o={}){let n=[`${e}=${encodeURIComponent(t)}`];return o.path&&n.push(`Path=${o.path}`),o.domain&&n.push(`Domain=${o.domain}`),typeof o.maxAge=="number"&&n.push(`Max-Age=${Math.floor(o.maxAge)}`),o.expires&&n.push(`Expires=${o.expires.toUTCString()}`),o.sameSite&&n.push(`SameSite=${o.sameSite}`),o.secure&&n.push("Secure"),n.join("; ")}function N(){return u.useMemo(()=>({all:()=>R(),get:e=>R()[e],set:(e,t,o)=>{typeof document>"u"||(document.cookie=h(e,t,o))},remove:(e,t)=>{typeof document>"u"||(document.cookie=h(e,"",{...t??{},maxAge:0}))}}),[])}function B(){let e=d?u.useContext(d):null;if(!e){let t=S();if(t)return t;if(typeof window>"u")return A;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function C({active:e}){return c("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 v(e){let t=document.createElement("meta");t.setAttribute("data-webframez-head","true");let o=Object.entries(e).filter(([,n])=>!!n);for(let[n,r]of o)t.setAttribute(n,String(r));document.head.appendChild(t)}function y(e){let t=document.createElement("link");t.setAttribute("data-webframez-head","true");let o=Object.entries(e).filter(([,n])=>!!n);for(let[n,r]of o)t.setAttribute(n,String(r));document.head.appendChild(t)}function T(e){if(!(typeof document>"u")){document.title=e.title||"Webframez React";for(let t of document.head.querySelectorAll(O))t.remove();e.description&&v({name:"description",content:e.description}),e.favicon&&y({rel:"icon",href:e.favicon});for(let t of e.meta??[])v(t);for(let t of e.links??[])y(t)}}function U(e){return function(){let[o,n]=w(null),[r,s]=w(!1);async function a(i,f="push"){s(!0);try{let m=await k(fetch(`${e}?path=${encodeURIComponent(i.pathname)}&search=${encodeURIComponent(i.search)}`,{headers:{Accept:"text/x-component"}}));T(m.head),n(m.model);let g=`${i.pathname}${i.search}`;f==="replace"?history.replaceState(null,"",g):f==="push"&&history.pushState(null,"",g)}catch(p){console.error("[webframez-react] Failed to render route",p),n(c("p",{children:"Failed to load route."}))}finally{s(!1)}}_(()=>{let i=()=>{a(new URL(window.location.href),"none")};return window.addEventListener("popstate",i),a(new URL(window.location.href),"none"),()=>{window.removeEventListener("popstate",i)}},[]);let l=u.useMemo(()=>({push:i=>{a(new URL(i,window.location.origin),"push")},replace:i=>{a(new URL(i,window.location.origin),"replace")},refresh:()=>{a(new URL(window.location.href),"none")}}),[]);return L(l),d?x(d.Provider,{value:l,children:[c(C,{active:r}),o??c("p",{style:{padding:24},children:"Loading..."})]}):x(M,{children:[c(C,{active:r}),o??c("p",{style:{padding:24},children:"Loading..."})]})}}function H(e={}){let t=e.rootId??"root",o=document.getElementById(t);if(!o)throw new Error(`Missing #${t} element`);let n=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??n??"/rsc",s=U(r),a=b(o);return a.render(c(s,{})),a}export{H as mountWebframezClient,N as useCookie,B as useRouter};
|
package/dist/http.cjs
CHANGED
|
@@ -223,6 +223,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
223
223
|
function escapeHtml(value) {
|
|
224
224
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
225
225
|
}
|
|
226
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
227
|
+
function createManagedAttributes() {
|
|
228
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
229
|
+
}
|
|
226
230
|
function toRouteEntry(pagesDir, filePath) {
|
|
227
231
|
const normalized = filePath.replace(/\\/g, "/");
|
|
228
232
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -291,19 +295,21 @@ function renderHeadToString(head) {
|
|
|
291
295
|
const tags = [];
|
|
292
296
|
if (head.description) {
|
|
293
297
|
tags.push(
|
|
294
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
298
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
295
299
|
);
|
|
296
300
|
}
|
|
297
301
|
if (head.favicon) {
|
|
298
|
-
tags.push(
|
|
302
|
+
tags.push(
|
|
303
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
304
|
+
);
|
|
299
305
|
}
|
|
300
306
|
for (const meta of head.meta ?? []) {
|
|
301
307
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
302
|
-
tags.push(`<meta ${attrs} />`);
|
|
308
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
303
309
|
}
|
|
304
310
|
for (const link of head.links ?? []) {
|
|
305
311
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
306
|
-
tags.push(`<link ${attrs} />`);
|
|
312
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
307
313
|
}
|
|
308
314
|
return tags.join("\n");
|
|
309
315
|
}
|
|
@@ -317,6 +323,12 @@ async function resolveHead(candidate, context) {
|
|
|
317
323
|
}
|
|
318
324
|
return candidate.Head(context);
|
|
319
325
|
}
|
|
326
|
+
async function resolvePageData(candidate, context) {
|
|
327
|
+
if (!candidate.Data) {
|
|
328
|
+
return void 0;
|
|
329
|
+
}
|
|
330
|
+
return candidate.Data(context);
|
|
331
|
+
}
|
|
320
332
|
function findBestMatch(entries, pathname) {
|
|
321
333
|
const matches = [];
|
|
322
334
|
for (const entry of entries) {
|
|
@@ -396,10 +408,11 @@ function createFileRouter(options) {
|
|
|
396
408
|
};
|
|
397
409
|
}
|
|
398
410
|
const errorModule = resolveModule(errorPath);
|
|
399
|
-
const errorNode = errorModule.default(errorProps);
|
|
411
|
+
const errorNode = await errorModule.default(errorProps);
|
|
400
412
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
401
413
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
402
|
-
const
|
|
414
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
415
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
403
416
|
return {
|
|
404
417
|
statusCode,
|
|
405
418
|
model,
|
|
@@ -431,10 +444,17 @@ function createFileRouter(options) {
|
|
|
431
444
|
activeContext = context;
|
|
432
445
|
const pageModule = resolveModule(match.entry.filePath);
|
|
433
446
|
const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
434
|
-
const
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
447
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
448
|
+
const pageContext = {
|
|
449
|
+
...context,
|
|
450
|
+
data: pageData
|
|
451
|
+
};
|
|
452
|
+
activeContext = pageContext;
|
|
453
|
+
const pageNode = await pageModule.default(pageContext);
|
|
454
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
455
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
456
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
457
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
438
458
|
return {
|
|
439
459
|
statusCode: 200,
|
|
440
460
|
model,
|
|
@@ -649,7 +669,11 @@ function createNodeRequestHandler(options) {
|
|
|
649
669
|
cookies: requestCookies
|
|
650
670
|
})
|
|
651
671
|
);
|
|
652
|
-
|
|
672
|
+
const payload = {
|
|
673
|
+
model: resolved2.model,
|
|
674
|
+
head: resolved2.head
|
|
675
|
+
};
|
|
676
|
+
sendRSC(res, payload, {
|
|
653
677
|
moduleMap,
|
|
654
678
|
statusCode: resolved2.statusCode
|
|
655
679
|
});
|
package/dist/http.d.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type WebframezReactRoutePath = `/${string}` | "/";
|
|
4
|
+
export type WebframezReactAssetsPrefix = `${WebframezReactRoutePath}/` | "/";
|
|
5
|
+
|
|
6
|
+
export interface CreateNodeHandlerPathsOptions {
|
|
4
7
|
distRootDir: string;
|
|
5
8
|
pagesDir?: string;
|
|
6
9
|
manifestPath?: string;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CreateNodeHandlerRoutingOptions {
|
|
13
|
+
assetsPrefix?: WebframezReactAssetsPrefix;
|
|
14
|
+
rscPath?: WebframezReactRoutePath;
|
|
15
|
+
clientScriptUrl?: WebframezReactRoutePath;
|
|
16
|
+
basePath?: WebframezReactRoutePath;
|
|
17
|
+
liveReloadPath?: WebframezReactRoutePath | false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CreateNodeHandlerOptions
|
|
21
|
+
extends CreateNodeHandlerPathsOptions,
|
|
22
|
+
CreateNodeHandlerRoutingOptions {
|
|
23
|
+
}
|
|
13
24
|
|
|
14
25
|
export function createNodeRequestHandler(
|
|
15
26
|
options: CreateNodeHandlerOptions
|
package/dist/http.js
CHANGED
|
@@ -198,6 +198,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
198
198
|
function escapeHtml(value) {
|
|
199
199
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
200
200
|
}
|
|
201
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
202
|
+
function createManagedAttributes() {
|
|
203
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
204
|
+
}
|
|
201
205
|
function toRouteEntry(pagesDir, filePath) {
|
|
202
206
|
const normalized = filePath.replace(/\\/g, "/");
|
|
203
207
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -266,19 +270,21 @@ function renderHeadToString(head) {
|
|
|
266
270
|
const tags = [];
|
|
267
271
|
if (head.description) {
|
|
268
272
|
tags.push(
|
|
269
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
273
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
270
274
|
);
|
|
271
275
|
}
|
|
272
276
|
if (head.favicon) {
|
|
273
|
-
tags.push(
|
|
277
|
+
tags.push(
|
|
278
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
279
|
+
);
|
|
274
280
|
}
|
|
275
281
|
for (const meta of head.meta ?? []) {
|
|
276
282
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
277
|
-
tags.push(`<meta ${attrs} />`);
|
|
283
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
278
284
|
}
|
|
279
285
|
for (const link of head.links ?? []) {
|
|
280
286
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
281
|
-
tags.push(`<link ${attrs} />`);
|
|
287
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
282
288
|
}
|
|
283
289
|
return tags.join("\n");
|
|
284
290
|
}
|
|
@@ -292,6 +298,12 @@ async function resolveHead(candidate, context) {
|
|
|
292
298
|
}
|
|
293
299
|
return candidate.Head(context);
|
|
294
300
|
}
|
|
301
|
+
async function resolvePageData(candidate, context) {
|
|
302
|
+
if (!candidate.Data) {
|
|
303
|
+
return void 0;
|
|
304
|
+
}
|
|
305
|
+
return candidate.Data(context);
|
|
306
|
+
}
|
|
295
307
|
function findBestMatch(entries, pathname) {
|
|
296
308
|
const matches = [];
|
|
297
309
|
for (const entry of entries) {
|
|
@@ -371,10 +383,11 @@ function createFileRouter(options) {
|
|
|
371
383
|
};
|
|
372
384
|
}
|
|
373
385
|
const errorModule = resolveModule(errorPath);
|
|
374
|
-
const errorNode = errorModule.default(errorProps);
|
|
386
|
+
const errorNode = await errorModule.default(errorProps);
|
|
375
387
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
376
388
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
377
|
-
const
|
|
389
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
390
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
378
391
|
return {
|
|
379
392
|
statusCode,
|
|
380
393
|
model,
|
|
@@ -406,10 +419,17 @@ function createFileRouter(options) {
|
|
|
406
419
|
activeContext = context;
|
|
407
420
|
const pageModule = resolveModule(match.entry.filePath);
|
|
408
421
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
409
|
-
const
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
422
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
423
|
+
const pageContext = {
|
|
424
|
+
...context,
|
|
425
|
+
data: pageData
|
|
426
|
+
};
|
|
427
|
+
activeContext = pageContext;
|
|
428
|
+
const pageNode = await pageModule.default(pageContext);
|
|
429
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
430
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
431
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
432
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
413
433
|
return {
|
|
414
434
|
statusCode: 200,
|
|
415
435
|
model,
|
|
@@ -624,7 +644,11 @@ function createNodeRequestHandler(options) {
|
|
|
624
644
|
cookies: requestCookies
|
|
625
645
|
})
|
|
626
646
|
);
|
|
627
|
-
|
|
647
|
+
const payload = {
|
|
648
|
+
model: resolved2.model,
|
|
649
|
+
head: resolved2.head
|
|
650
|
+
};
|
|
651
|
+
sendRSC(res, payload, {
|
|
628
652
|
moduleMap,
|
|
629
653
|
statusCode: resolved2.statusCode
|
|
630
654
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -257,6 +257,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
257
257
|
function escapeHtml(value) {
|
|
258
258
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
259
259
|
}
|
|
260
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
261
|
+
function createManagedAttributes() {
|
|
262
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
263
|
+
}
|
|
260
264
|
function toRouteEntry(pagesDir, filePath) {
|
|
261
265
|
const normalized = filePath.replace(/\\/g, "/");
|
|
262
266
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -325,19 +329,21 @@ function renderHeadToString(head) {
|
|
|
325
329
|
const tags = [];
|
|
326
330
|
if (head.description) {
|
|
327
331
|
tags.push(
|
|
328
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
332
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
329
333
|
);
|
|
330
334
|
}
|
|
331
335
|
if (head.favicon) {
|
|
332
|
-
tags.push(
|
|
336
|
+
tags.push(
|
|
337
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
338
|
+
);
|
|
333
339
|
}
|
|
334
340
|
for (const meta of head.meta ?? []) {
|
|
335
341
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
336
|
-
tags.push(`<meta ${attrs} />`);
|
|
342
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
337
343
|
}
|
|
338
344
|
for (const link of head.links ?? []) {
|
|
339
345
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
340
|
-
tags.push(`<link ${attrs} />`);
|
|
346
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
341
347
|
}
|
|
342
348
|
return tags.join("\n");
|
|
343
349
|
}
|
|
@@ -351,6 +357,12 @@ async function resolveHead(candidate, context) {
|
|
|
351
357
|
}
|
|
352
358
|
return candidate.Head(context);
|
|
353
359
|
}
|
|
360
|
+
async function resolvePageData(candidate, context) {
|
|
361
|
+
if (!candidate.Data) {
|
|
362
|
+
return void 0;
|
|
363
|
+
}
|
|
364
|
+
return candidate.Data(context);
|
|
365
|
+
}
|
|
354
366
|
function findBestMatch(entries, pathname) {
|
|
355
367
|
const matches = [];
|
|
356
368
|
for (const entry of entries) {
|
|
@@ -430,10 +442,11 @@ function createFileRouter(options) {
|
|
|
430
442
|
};
|
|
431
443
|
}
|
|
432
444
|
const errorModule = resolveModule(errorPath);
|
|
433
|
-
const errorNode = errorModule.default(errorProps);
|
|
445
|
+
const errorNode = await errorModule.default(errorProps);
|
|
434
446
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
435
447
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
436
|
-
const
|
|
448
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
449
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
437
450
|
return {
|
|
438
451
|
statusCode,
|
|
439
452
|
model,
|
|
@@ -465,10 +478,17 @@ function createFileRouter(options) {
|
|
|
465
478
|
activeContext = context;
|
|
466
479
|
const pageModule = resolveModule(match.entry.filePath);
|
|
467
480
|
const layoutModule = import_node_fs.default.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
468
|
-
const
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
481
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
482
|
+
const pageContext = {
|
|
483
|
+
...context,
|
|
484
|
+
data: pageData
|
|
485
|
+
};
|
|
486
|
+
activeContext = pageContext;
|
|
487
|
+
const pageNode = await pageModule.default(pageContext);
|
|
488
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
489
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
490
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
491
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
472
492
|
return {
|
|
473
493
|
statusCode: 200,
|
|
474
494
|
model,
|
|
@@ -686,7 +706,11 @@ function createNodeRequestHandler(options) {
|
|
|
686
706
|
cookies: requestCookies
|
|
687
707
|
})
|
|
688
708
|
);
|
|
689
|
-
|
|
709
|
+
const payload = {
|
|
710
|
+
model: resolved2.model,
|
|
711
|
+
head: resolved2.head
|
|
712
|
+
};
|
|
713
|
+
sendRSC(res, payload, {
|
|
690
714
|
moduleMap,
|
|
691
715
|
statusCode: resolved2.statusCode
|
|
692
716
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import type { CreateHtmlShellOptions, SendRSCOptions } from "./types";
|
|
3
3
|
import type { CreateNodeHandlerOptions } from "./http";
|
|
4
|
+
import "./webframez-core";
|
|
4
5
|
|
|
5
6
|
export * from "./types";
|
|
6
7
|
export { createFileRouter, parseSearchParams, renderHeadToString, RouteChildren } from "./router";
|
|
7
8
|
export type { ResolvedRoute } from "./router";
|
|
8
|
-
export
|
|
9
|
-
export type {
|
|
10
|
-
WebframezCoreRouteMethod,
|
|
11
|
-
WebframezCoreReactRenderRouteOptions,
|
|
12
|
-
} from "./webframez-core";
|
|
9
|
+
export * from "./webframez-core";
|
|
13
10
|
|
|
14
11
|
export function createHTMLShell(options?: CreateHtmlShellOptions): string;
|
|
15
12
|
export function sendRSC(
|
package/dist/index.js
CHANGED
|
@@ -221,6 +221,10 @@ function readSearchParams(urlSearchParams) {
|
|
|
221
221
|
function escapeHtml(value) {
|
|
222
222
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
223
223
|
}
|
|
224
|
+
var MANAGED_HEAD_ATTR = "data-webframez-head";
|
|
225
|
+
function createManagedAttributes() {
|
|
226
|
+
return `${MANAGED_HEAD_ATTR}="true"`;
|
|
227
|
+
}
|
|
224
228
|
function toRouteEntry(pagesDir, filePath) {
|
|
225
229
|
const normalized = filePath.replace(/\\/g, "/");
|
|
226
230
|
if (!normalized.endsWith("/index.js")) {
|
|
@@ -289,19 +293,21 @@ function renderHeadToString(head) {
|
|
|
289
293
|
const tags = [];
|
|
290
294
|
if (head.description) {
|
|
291
295
|
tags.push(
|
|
292
|
-
`<meta name="description" content="${escapeHtml(head.description)}" />`
|
|
296
|
+
`<meta ${createManagedAttributes()} name="description" content="${escapeHtml(head.description)}" />`
|
|
293
297
|
);
|
|
294
298
|
}
|
|
295
299
|
if (head.favicon) {
|
|
296
|
-
tags.push(
|
|
300
|
+
tags.push(
|
|
301
|
+
`<link ${createManagedAttributes()} rel="icon" href="${escapeHtml(head.favicon)}" />`
|
|
302
|
+
);
|
|
297
303
|
}
|
|
298
304
|
for (const meta of head.meta ?? []) {
|
|
299
305
|
const attrs = Object.entries(meta).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
300
|
-
tags.push(`<meta ${attrs} />`);
|
|
306
|
+
tags.push(`<meta ${createManagedAttributes()} ${attrs} />`);
|
|
301
307
|
}
|
|
302
308
|
for (const link of head.links ?? []) {
|
|
303
309
|
const attrs = Object.entries(link).filter(([, value]) => Boolean(value)).map(([key, value]) => `${key}="${escapeHtml(String(value))}"`).join(" ");
|
|
304
|
-
tags.push(`<link ${attrs} />`);
|
|
310
|
+
tags.push(`<link ${createManagedAttributes()} ${attrs} />`);
|
|
305
311
|
}
|
|
306
312
|
return tags.join("\n");
|
|
307
313
|
}
|
|
@@ -315,6 +321,12 @@ async function resolveHead(candidate, context) {
|
|
|
315
321
|
}
|
|
316
322
|
return candidate.Head(context);
|
|
317
323
|
}
|
|
324
|
+
async function resolvePageData(candidate, context) {
|
|
325
|
+
if (!candidate.Data) {
|
|
326
|
+
return void 0;
|
|
327
|
+
}
|
|
328
|
+
return candidate.Data(context);
|
|
329
|
+
}
|
|
318
330
|
function findBestMatch(entries, pathname) {
|
|
319
331
|
const matches = [];
|
|
320
332
|
for (const entry of entries) {
|
|
@@ -394,10 +406,11 @@ function createFileRouter(options) {
|
|
|
394
406
|
};
|
|
395
407
|
}
|
|
396
408
|
const errorModule = resolveModule(errorPath);
|
|
397
|
-
const errorNode = errorModule.default(errorProps);
|
|
409
|
+
const errorNode = await errorModule.default(errorProps);
|
|
398
410
|
const layoutHead = layoutModule ? await resolveHead(layoutModule, context) : void 0;
|
|
399
411
|
const errorHead = await resolveHead(errorModule, errorProps);
|
|
400
|
-
const
|
|
412
|
+
const layoutNode = layoutModule ? await layoutModule.default(context) : null;
|
|
413
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
|
|
401
414
|
return {
|
|
402
415
|
statusCode,
|
|
403
416
|
model,
|
|
@@ -429,10 +442,17 @@ function createFileRouter(options) {
|
|
|
429
442
|
activeContext = context;
|
|
430
443
|
const pageModule = resolveModule(match.entry.filePath);
|
|
431
444
|
const layoutModule = fs.existsSync(layoutPath) ? resolveModule(layoutPath) : null;
|
|
432
|
-
const
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
445
|
+
const pageData = await resolvePageData(pageModule, context);
|
|
446
|
+
const pageContext = {
|
|
447
|
+
...context,
|
|
448
|
+
data: pageData
|
|
449
|
+
};
|
|
450
|
+
activeContext = pageContext;
|
|
451
|
+
const pageNode = await pageModule.default(pageContext);
|
|
452
|
+
const layoutHead = layoutModule ? await resolveHead(layoutModule, pageContext) : void 0;
|
|
453
|
+
const pageHead = await resolveHead(pageModule, pageContext);
|
|
454
|
+
const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
|
|
455
|
+
const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
|
|
436
456
|
return {
|
|
437
457
|
statusCode: 200,
|
|
438
458
|
model,
|
|
@@ -650,7 +670,11 @@ function createNodeRequestHandler(options) {
|
|
|
650
670
|
cookies: requestCookies
|
|
651
671
|
})
|
|
652
672
|
);
|
|
653
|
-
|
|
673
|
+
const payload = {
|
|
674
|
+
model: resolved2.model,
|
|
675
|
+
head: resolved2.head
|
|
676
|
+
};
|
|
677
|
+
sendRSC(res, payload, {
|
|
654
678
|
moduleMap,
|
|
655
679
|
statusCode: resolved2.statusCode
|
|
656
680
|
});
|