@devlusoft/devix 0.2.1 → 0.3.0-beta.1
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/dist/cli/build.js +16 -8
- package/dist/cli/build.js.map +2 -2
- package/dist/cli/dev.js +37 -29
- package/dist/cli/dev.js.map +3 -3
- package/dist/cli/generate.js +17 -9
- package/dist/cli/generate.js.map +2 -2
- package/dist/cli/index.js +16 -8
- package/dist/cli/index.js.map +2 -2
- package/dist/runtime/api-context.d.ts +10 -7
- package/dist/runtime/api-context.js +1 -1
- package/dist/runtime/api-context.js.map +2 -2
- package/dist/runtime/create-handler.d.ts +10 -0
- package/dist/runtime/create-handler.js +2 -0
- package/dist/runtime/create-handler.js.map +7 -0
- package/dist/runtime/fetch.d.ts +16 -5
- package/dist/runtime/fetch.js +1 -1
- package/dist/runtime/fetch.js.map +2 -2
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/index.js.map +4 -4
- package/dist/server/api.js +1 -1
- package/dist/server/api.js.map +4 -4
- package/dist/server/handler-store.d.ts +10 -0
- package/dist/server/handler-store.js +2 -0
- package/dist/server/handler-store.js.map +7 -0
- package/dist/server/public-index.d.ts +1 -0
- package/dist/server/public-index.js +2 -0
- package/dist/server/public-index.js.map +7 -0
- package/dist/utils/response.d.ts +1 -1
- package/dist/utils/response.js.map +2 -2
- package/dist/vite/codegen/routes-dts.js +16 -8
- package/dist/vite/codegen/routes-dts.js.map +2 -2
- package/dist/vite/codegen/scan-api.js +1 -1
- package/dist/vite/codegen/scan-api.js.map +1 -1
- package/dist/vite/index.js +17 -9
- package/dist/vite/index.js.map +2 -2
- package/package.json +5 -1
package/dist/cli/index.js
CHANGED
|
@@ -121,9 +121,9 @@ const _glob = {
|
|
|
121
121
|
export function handleApiRequest(url, request) {
|
|
122
122
|
return _handleApiRequest(url, request, _glob)
|
|
123
123
|
}
|
|
124
|
-
`}var se=s(()=>{"use strict"});function
|
|
124
|
+
`}var se=s(()=>{"use strict"});function _(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}var S=s(()=>{"use strict"});function D(){Ie=null}var Ie,ae=s(()=>{"use strict";S();Ie=null});function ce(e,t){let r=e.slice(t.length+1).replace(/\\/g,"/"),n=_(r);return n==="/"?"/api":`/api/${n}`.replace("/api//","/api/")}function b(){Ue=null}var Ue,A=s(()=>{"use strict";S();Ue=null});function le(){return`
|
|
125
125
|
export {RouterContext} from '@devlusoft/devix/runtime/context'
|
|
126
|
-
`}var ue=s(()=>{"use strict"});function He(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function pe(e){let t=new Set;for(let r of He(e).matchAll(je))t.add(r[1]);return[...t]}var je,de=s(()=>{"use strict";je=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g});function qe(e,t){return"_api_"+e.slice(`${t}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function me(e,t,r){return{filePath:e,urlPattern:ce(e,t),identifier:qe(e,t),methods:r}}function
|
|
126
|
+
`}var ue=s(()=>{"use strict"});function He(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function pe(e){let t=new Set;for(let r of He(e).matchAll(je))t.add(r[1]);return[...t]}var je,de=s(()=>{"use strict";je=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g});function qe(e,t){return"_api_"+e.slice(`${t}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function me(e,t,r){return{filePath:e,urlPattern:ce(e,t),identifier:qe(e,t),methods:r}}function C(e,t){if(e.length===0)return`// auto-generado por devix \u2014 no editar
|
|
127
127
|
declare module '@devlusoft/devix' {
|
|
128
128
|
interface ApiRoutes {}
|
|
129
129
|
}
|
|
@@ -133,20 +133,28 @@ declare module '@devlusoft/devix' {
|
|
|
133
133
|
${r}
|
|
134
134
|
|
|
135
135
|
type JsonResponse<T> = Response & { readonly __body: T }
|
|
136
|
-
type
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
type UnwrapJson<T> = T extends JsonResponse<infer U> ? U : never
|
|
137
|
+
type InferFnReturn<T> = T extends (...args: any[]) => any
|
|
138
|
+
? [UnwrapJson<Awaited<ReturnType<T>>>] extends [never]
|
|
139
|
+
? Exclude<Awaited<ReturnType<T>>, Response | null | void>
|
|
140
|
+
: UnwrapJson<Awaited<ReturnType<T>>>
|
|
140
141
|
: never
|
|
142
|
+
type InferRoute<T> =
|
|
143
|
+
T extends { readonly __return?: infer TReturn; readonly __body?: infer TBody }
|
|
144
|
+
? {
|
|
145
|
+
__body: [TBody] extends [undefined] ? never : Exclude<TBody, undefined>
|
|
146
|
+
__response: InferFnReturn<() => TReturn>
|
|
147
|
+
}
|
|
148
|
+
: InferFnReturn<T>
|
|
141
149
|
|
|
142
150
|
declare module '@devlusoft/devix' {
|
|
143
151
|
interface ApiRoutes {
|
|
144
152
|
${n}
|
|
145
153
|
}
|
|
146
154
|
}
|
|
147
|
-
`}var M=s(()=>{"use strict";
|
|
155
|
+
`}var M=s(()=>{"use strict";A()});import{readFileSync as Fe,readdirSync as Ne,statSync as Ve}from"node:fs";import{join as O,relative as We}from"node:path";function fe(e,t){let r=[];for(let n of Ne(e)){let o=O(e,n);Ve(o).isDirectory()?r.push(...fe(o,t)):/\.(ts|tsx)$/.test(n)&&r.push(We(t,o).replace(/\\/g,"/"))}return r}function k(e,t){let r=O(t,e,"api"),n;try{n=fe(r,t)}catch{return[]}return n.filter(o=>!o.endsWith("middleware.ts")&&!o.endsWith("middleware.tsx")).flatMap(o=>{try{let a=Fe(O(t,o),"utf-8"),l=pe(a);return l.length===0?[]:[me(o,`${e}/api`,l)]}catch{return[]}})}var ge=s(()=>{"use strict";de();M()});import{mkdirSync as Je,readFileSync as Be,writeFileSync as Ge,existsSync as Ye}from"node:fs";import{join as he}from"node:path";function L(e,t){let r=he(t,".devix"),n=he(r,"routes.d.ts");return Je(r,{recursive:!0}),Ye(n)&&Be(n,"utf-8")===e?!1:(Ge(n,e,"utf-8"),!0)}var xe=s(()=>{"use strict"});import{mergeConfig as Xe}from"vite";import ze from"@vitejs/plugin-react";import{fileURLToPath as Ze}from"node:url";import{dirname as Ke,resolve as x}from"node:path";function y(e){let t=e.appDir??"app",r=`${t}/pages`,n=(e.css??[]).map(i=>i.startsWith("/")?i:`/${i.replace(/^\.\//,"")}`),o=x(I,"../server/render.js").replace(/\\/g,"/"),a=x(I,"../server/api.js").replace(/\\/g,"/"),l=x(I,"../runtime/client-router.js").replace(/\\/g,"/"),f={name:"devix",enforce:"pre",resolveId(i){if(i===U)return`\0${U}`;if(i===j)return`\0${j}`;if(i===H)return`\0${H}`;if(i===q)return`\0${q}`;if(i===F)return`\0${F}`},load(i){if(i===`\0${U}`)return Q({cssUrls:n});if(i===`\0${j}`)return te({pagesDir:r,matcherPath:l});if(i===`\0${H}`)return oe({pagesDir:r,renderPath:o});if(i===`\0${q}`)return ie({apiPath:a,appDir:t});if(i===`\0${F}`)return le()},buildStart(){let i=process.cwd(),u=k(t,i);L(C(u,`${t}/api`),i)},configureServer(i){let u=process.cwd(),P=()=>{let p=k(t,u);L(C(p,`${t}/api`),u)};i.watcher.on("add",p=>{p.startsWith(x(u,r))&&D(),p.includes(`${t}/api`)&&(b(),P())}),i.watcher.on("unlink",p=>{p.startsWith(x(u,r))&&D(),p.includes(`${t}/api`)&&(b(),P())}),i.watcher.on("change",p=>{p.includes(`${t}/api`)&&!p.endsWith("middleware.ts")&&P()})}},d={plugins:[ze(),f],ssr:{noExternal:["@devlusoft/devix"]},...e.envPrefix?{envPrefix:e.envPrefix}:{}};return Xe(d,e.vite??{})}var I,U,j,H,q,F,N=s(()=>{"use strict";ee();re();ne();se();ae();A();ue();ge();M();xe();I=Ke(Ze(import.meta.url)),U="virtual:devix/entry-client",j="virtual:devix/client-routes",H="virtual:devix/render",q="virtual:devix/api",F="virtual:devix/context"});function R(e,{apiModule:t,renderModule:r,loaderTimeout:n}){e.all("/api/*",async o=>{try{return await t.handleApiRequest(o.req.url,o.req.raw)}catch(a){return console.error(a),o.json({error:"internal error"},500)}}),e.get("/_data/*",async o=>{try{let{pathname:a,search:l}=new URL(o.req.url,"http://localhost"),f=a.replace(/^\/_data/,"")+l,d=await r.runLoader(f,o.req.raw,{loaderTimeout:n});return o.json(d)}catch(a){return console.error(a),o.json({error:"internal error"},500)}})}function ve(e,{renderModule:t,manifest:r,loaderTimeout:n}){e.get("*",async o=>{try{let{html:a,statusCode:l,headers:f}=await t.render(o.req.url,o.req.raw,{manifest:r,loaderTimeout:n}),d=o.html(`<!DOCTYPE html>${a}`,l);for(let[i,u]of Object.entries(f))d.headers.set(i,u);return d}catch(a){return console.error(a),o.text("Internal Server Error",500)}})}var V=s(()=>{"use strict"});import c from"picocolors";import{networkInterfaces as Qe}from"node:os";import{createRequire as et}from"node:module";function tt(e){let t=Qe();for(let r of Object.values(t))for(let n of r??[])if(n.family==="IPv4"&&!n.internal)return`http://${n.address}:${e}/`;return null}function ye(e){let r=et(import.meta.url)("../../package.json").version,n=tt(e);console.log(),console.log(` ${c.bold(c.yellow("devix"))} ${c.dim(`v${r}`)}`),console.log(),console.log(` ${c.green("\u279C")} ${c.bold("Local:")} ${c.cyan(`http://localhost:${e}/`)}`),console.log(n?` ${c.green("\u279C")} ${c.bold("Network:")} ${c.cyan(n)}`:` ${c.green("\u279C")} ${c.bold("Network:")} ${c.dim("use --host to expose")}`),console.log()}var Re=s(()=>{"use strict"});async function we(e){let t=new Set;for(let[,r]of e.moduleGraph.idToModuleMap)r.id&&(r.id.endsWith(".css")||r.id.includes(".css?"))&&t.add(r.url);return[...t]}var $e=s(()=>{"use strict"});function w(e){if(typeof e=="number")return e;let t=e.trim().match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h)?$/);if(!t)throw new Error(`[devix] Invalid duration: "${e}". Use a number (ms) or a string like "5s", "2m", "500ms".`);let r=parseFloat(t[1]);switch(t[2]){case"h":return r*36e5;case"m":return r*6e4;case"s":return r*1e3;default:return r}}var W=s(()=>{"use strict"});import{loadEnv as rt}from"vite";function $(e){let t=rt(e,process.cwd(),"");for(let[r,n]of Object.entries(t))process.env[r]===void 0&&(process.env[r]=n)}var J=s(()=>{"use strict"});var pt={};import{createServer as ot}from"node:http";import{createServer as nt}from"vite";import{getRequestListener as it}from"@hono/node-server";import{Hono as st}from"hono";var Te,at,h,Ee,ct,g,Pe,lt,B,ut,_e=s(async()=>{"use strict";N();V();Re();$e();W();J();$("development");Te="virtual:devix/render",at="virtual:devix/api",h=(await import(`${process.cwd()}/devix.config.ts`)).default,Ee=Number(process.env.PORT)||h.port||3e3,ct=typeof h.host=="string"?h.host:h.host?"0.0.0.0":"localhost",g=await nt({...y(h),configFile:!1,appType:"custom",server:{middlewareMode:!0}}),Pe={render:async(...e)=>(await g.ssrLoadModule(Te)).render(...e),runLoader:async(...e)=>(await g.ssrLoadModule(Te)).runLoader(...e)},lt={handleApiRequest:async(...e)=>(await g.ssrLoadModule(at)).handleApiRequest(...e)},B=new st;R(B,{renderModule:Pe,apiModule:lt});B.get("*",async e=>{try{let{html:t,statusCode:r,headers:n}=await Pe.render(e.req.url,e.req.raw,{loaderTimeout:w(h.loaderTimeout??1e4)}),a=(await we(g)).map(i=>`<link rel="stylesheet" href="${i}">`).join(`
|
|
148
156
|
`),l=a?t.replace("</head>",`${a}
|
|
149
|
-
</head>`):t,f=await g.transformIndexHtml(e.req.url,`<!DOCTYPE html>${l}`),d=e.html(f,r);for(let[i,u]of Object.entries(n))d.headers.set(i,u);return d}catch(t){return g.ssrFixStacktrace(t),console.error(t),e.text("Internal Server Error",500)}});ut=it(
|
|
157
|
+
</head>`):t,f=await g.transformIndexHtml(e.req.url,`<!DOCTYPE html>${l}`),d=e.html(f,r);for(let[i,u]of Object.entries(n))d.headers.set(i,u);return d}catch(t){return g.ssrFixStacktrace(t),console.error(t),e.text("Internal Server Error",500)}});ut=it(B.fetch);ot(async(e,t)=>{await new Promise(r=>g.middlewares(e,t,r)),t.writableEnded||await ut(e,t)}).listen(Ee,ct,()=>{ye(Ee)})});var be={};import{writeFileSync as dt}from"node:fs";import{resolve as mt}from"node:path";import{build as Se}from"vite";var v,De,ft,G=s(async()=>{"use strict";N();W();v=(await import(`${process.cwd()}/devix.config.ts`)).default,De=y(v);await Se({...De,configFile:!1,build:{outDir:"dist/client",manifest:!0,rolldownOptions:{input:"virtual:devix/entry-client"}}});await Se({...De,configFile:!1,build:{ssr:!0,outDir:"dist/server",rolldownOptions:{input:{render:"virtual:devix/render",api:"virtual:devix/api"}}}});ft={port:v.port??3e3,host:v.host??!1,loaderTimeout:w(v.loaderTimeout??1e4),output:v.output??"server"};dt(mt(process.cwd(),"dist/devix.config.json"),JSON.stringify(ft,null,2),"utf-8")});var wt={};import{readFileSync as gt,mkdirSync as ht,writeFileSync as xt}from"node:fs";import{resolve as Ae,join as Y}from"node:path";var vt,yt,Ce,Rt,X,Me=s(async()=>{"use strict";vt=(await import(`${process.cwd()}/devix.config.ts`)).default;vt.output!=="static"&&console.warn('[devix] Tip: set output: "static" in devix.config.ts to skip the SSR server at runtime.');await G().then(()=>be);yt=Date.now(),Ce=await import(Ae(process.cwd(),"dist/server/render.js")+`?t=${yt}`),Rt=JSON.parse(gt(Ae(process.cwd(),"dist/client/.vite/manifest.json"),"utf-8")),X=await Ce.getStaticRoutes();console.log(`[devix] Generating ${X.length} static page${X.length===1?"":"s"}...`);for(let e of X){let t=`http://localhost${e}`,{html:r,statusCode:n}=await Ce.render(t,new Request(t),{manifest:Rt});if(n!==200){console.warn(`[devix] Skipping ${e} \u2014 status ${n}`);continue}let o=e==="/"?Y(process.cwd(),"dist/client/index.html"):Y(process.cwd(),"dist/client",e,"index.html");ht(Y(o,".."),{recursive:!0}),xt(o,`<!DOCTYPE html>${r}`,"utf-8"),console.log(` \u2713 ${e}`)}console.log("[devix] Generation complete.")});var St={};import{readFileSync as Oe}from"node:fs";import{serve as $t}from"@hono/node-server";import{serveStatic as Tt}from"@hono/node-server/serve-static";import{Hono as Et}from"hono";import{resolve as T}from"node:path";var z,Z,K,m,Pt,_t,E,ke=s(async()=>{"use strict";V();J();$("production");try{m=JSON.parse(Oe(T(process.cwd(),"dist/devix.config.json"),"utf-8")),m.output!=="static"&&(z=await import(T(process.cwd(),"dist/server/render.js")),Z=await import(T(process.cwd(),"dist/server/api.js"))),K=JSON.parse(Oe(T(process.cwd(),"dist/client/.vite/manifest.json"),"utf-8"))}catch{console.error('[devix] Build not found. Run "devix build" first.'),process.exit(1)}Pt=Number(process.env.PORT)||m.port||3e3,_t=typeof m.host=="string"?m.host:m.host?"0.0.0.0":process.env.HOST||"0.0.0.0",E=new Et;E.use("/*",Tt({root:"./dist/client",onFound:(e,t)=>{t.header("Cache-Control",e.includes("/assets/")?"public, immutable, max-age=31536000":"no-cache")}}));m.output==="static"?console.log("[devix] Static mode \u2014 serving pre-generated files from dist/client"):(R(E,{renderModule:z,apiModule:Z,manifest:K}),ve(E,{renderModule:z,apiModule:Z,manifest:K,loaderTimeout:m.loaderTimeout}));$t({fetch:E.fetch,port:Pt,hostname:_t},e=>console.log(`http://${e.address}:${e.port}`))});import{readFileSync as Dt}from"node:fs";import{join as bt,dirname as At}from"node:path";import{fileURLToPath as Ct}from"node:url";var Le=process.argv[2];switch(Le){case"dev":await _e().then(()=>pt);break;case"build":await G().then(()=>be);break;case"generate":await Me().then(()=>wt);break;case"start":await ke().then(()=>St);break;case"--version":case"-v":{let e=JSON.parse(Dt(bt(At(Ct(import.meta.url)),"../../package.json"),"utf-8"));console.log(e.version);break}case"--help":case"-h":console.log(`
|
|
150
158
|
devix \u2014 a lightweight SSR framework
|
|
151
159
|
|
|
152
160
|
Usage:
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/vite/codegen/entry-client.ts", "../../src/vite/codegen/client-routes.ts", "../../src/vite/codegen/render.ts", "../../src/vite/codegen/api.ts", "../../src/utils/patterns.ts", "../../src/server/pages-router.ts", "../../src/server/api-router.ts", "../../src/vite/codegen/context.ts", "../../src/vite/codegen/extract-methods.ts", "../../src/vite/codegen/routes-dts.ts", "../../src/vite/codegen/scan-api.ts", "../../src/vite/codegen/write-routes-dts.ts", "../../src/vite/index.ts", "../../src/server/routes.ts", "../../src/utils/banner.ts", "../../src/server/collect-css.ts", "../../src/utils/duration.ts", "../../src/utils/env.ts", "../../src/cli/dev.ts", "../../src/cli/build.ts", "../../src/cli/generate.ts", "../../src/cli/start.ts", "../../src/cli/index.ts"],
|
|
4
|
-
"sourcesContent": ["interface EntryClientOptions {\n cssUrls: string[]\n}\n\nexport function generateEntryClient({cssUrls}: EntryClientOptions): string {\n const cssImports = cssUrls.map(u => `import '${u}'`).join('\\n')\n\n return `\n${cssImports}\nimport \"@vitejs/plugin-react/preamble\"\nimport React from \"react\"\nimport {hydrateRoot, createRoot} from 'react-dom/client'\nimport {matchClientRoute, loadErrorPage, getDefaultErrorPage} from 'virtual:devix/client-routes'\nimport {RouterProvider} from '@devlusoft/devix'\n\nconst root = document.getElementById('devix-root')\n\nif (!window.__DEVIX__) {\n const ErrorPage = getDefaultErrorPage()\n createRoot(root).render(React.createElement(ErrorPage, {statusCode: 500, message: 'Server error'}))\n} else {\n const {metadata, viewport, clientEntry} = window.__DEVIX__\n const loaderData = window.__LOADER_DATA__\n const layoutsData = window.__LAYOUTS_DATA__ ?? []\n\n const matched = matchClientRoute(window.location.pathname)\n\n if (matched) {\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n hydrateRoot(\n root,\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: loaderData,\n initialParams: matched.params,\n initialPage: pageMod.default,\n initialLayouts: layoutMods.map(m => m.default),\n initialLayoutsData: layoutsData,\n initialMeta: metadata,\n initialViewport: viewport,\n })\n )\n } else {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n createRoot(root).render(\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: null,\n initialParams: {},\n initialPage: () => null,\n initialLayouts: [],\n initialLayoutsData: [],\n initialMeta: null,\n initialError: {statusCode: 404, message: 'Not found'},\n initialErrorPage: ErrorPage,\n })\n )\n }\n}\n`\n}", "interface ClientRoutesOptions {\n pagesDir: string\n matcherPath: string\n}\n\nexport function generateClientRoutes({pagesDir, matcherPath}: ClientRoutesOptions) {\n return `\nimport React from 'react'\nimport { createMatcher } from '${matcherPath}'\nconst pageFiles = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst layoutFiles = import.meta.glob('/${pagesDir}/**/layout.tsx')\nconst errorFiles = import.meta.glob('/${pagesDir}/**/error.tsx')\n\nexport const matchClientRoute = createMatcher(pageFiles, layoutFiles)\n\nexport async function loadErrorPage() {\n const key = Object.keys(errorFiles)[0]\n if (!key) return null\n const mod = await errorFiles[key]()\n return mod?.default ?? null\n}\n\nexport function getDefaultErrorPage() {\n return function DefaultError({ statusCode, message }) {\n return React.createElement('main', {\n style: { minHeight: '100dvh', display: 'flex', flexDirection: 'column', \n alignItems: 'center', justifyContent: 'center', gap: '8px',\n fontFamily: 'system-ui, sans-serif' }\n },\n React.createElement('h1', {style: {fontSize: '4rem', fontWeight: 700}}, statusCode),\n React.createElement('p', {style: {color: '#666'}}, message ?? 'An unexpected error occurred'),\n )\n }\n}\n`\n}", "interface RenderOptions {\n pagesDir: string\n renderPath: string\n}\n\nexport function generateRender({pagesDir, renderPath}: RenderOptions): string {\n return `\nimport { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${renderPath}'\n\nconst _pages = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst _layouts = import.meta.glob('/${pagesDir}/**/layout.tsx')\n\nconst _glob = {\n pages: _pages,\n layouts: _layouts,\n pagesDir: '/${pagesDir}',\n}\n\nexport function render(url, request, options) {\n return _render(url, request, _glob, options)\n}\n\nexport function runLoader(url, request, options) {\n return _runLoader(url, request, _glob, options)\n}\n\nexport function getStaticRoutes() {\n return _getStaticRoutes(_glob)\n}\n`\n}\n", "interface ApiOptions {\n apiPath: string\n appDir: string\n}\n\nexport function generateApi({apiPath, appDir}: ApiOptions): string {\n return `\nimport { handleApiRequest as _handleApiRequest } from '${apiPath}'\n\nconst _routes = import.meta.glob(['/${appDir}/api/**/*.ts', '!**/middleware.ts'])\nconst _middlewares = import.meta.glob('/${appDir}/api/**/middleware.ts')\n\nconst _glob = {\n routes: _routes,\n middlewares: _middlewares,\n apiDir: '/${appDir}/api',\n}\n\nexport function handleApiRequest(url, request) {\n return _handleApiRequest(url, request, _glob)\n}\n`\n}\n", "export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface Page {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface Layout {\n dir: string\n key: string\n}\n\nexport interface PagesResult {\n pages: Page[]\n layouts: Layout[]\n}\n\nfunction keyToRoutePattern(key: string, pagesDir: string): string {\n const rel = key.slice(pagesDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === \"/\" ? \"/\" : `/${pattern}`\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: PagesResult | null = null\n\nexport function invalidatePagesCache() {\n cache = null\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n if (cache) return cache\n\n const pages: Page[] = []\n const layouts: Layout[] = []\n\n for (const key of layoutKeys) {\n layouts.push({dir: keyToDir(key), key})\n }\n\n for (const key of pageKeys) {\n const pattern = keyToRoutePattern(key, pagesDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n pages.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n\n pages.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {pages, layouts}\n return cache\n}\n\nexport function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[] {\n const pageDir = keyToDir(pageKey)\n\n return layouts\n .filter(layout => pageDir.startsWith(layout.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchPage(pathname: string, pages: Page[]): {\n page: Page\n params: Record<string, string>\n} | null {\n for (const page of pages) {\n const match = pathname.match(page.regex)\n if (match) {\n const params: Record<string, string> = {}\n page.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {page, params}\n }\n }\n return null\n}\n", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: ApiResult | null = null\n\nexport function invalidateApiCache() {\n cache = null\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n if (cache) return cache\n\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {routes, middlewares}\n return cache\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): {route: ApiRoute; params: Record<string, string>} | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "export function generateContext(): string {\n return `\nexport {RouterContext} from '@devlusoft/devix/runtime/context'\n`\n}", "const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const\nexport type HttpMethod = (typeof HTTP_METHODS)[number]\n\nconst METHOD_EXPORT_RE = /export\\s+(?:const|async\\s+function|function)\\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b/g\n\nfunction stripComments(content: string): string {\n return content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/.*$/gm, '')\n}\n\nexport function extractHttpMethods(content: string): HttpMethod[] {\n const found = new Set<HttpMethod>()\n for (const match of stripComments(content).matchAll(METHOD_EXPORT_RE)) {\n found.add(match[1] as HttpMethod)\n }\n return [...found]\n}\n", "import { keyToRoutePattern } from '../../server/api-router'\nimport type { HttpMethod } from './extract-methods'\n\nexport interface RouteEntry {\n filePath: string\n urlPattern: string\n identifier: string\n methods: HttpMethod[]\n}\n\nexport function filePathToIdentifier(filePath: string, apiDir: string): string {\n return '_api_' + filePath\n .slice(`${apiDir}/`.length)\n .replace(/\\.(ts|tsx)$/, '')\n .replace(/[^a-zA-Z0-9]/g, '_')\n}\n\nexport function buildRouteEntry(filePath: string, apiDir: string, methods: HttpMethod[]): RouteEntry {\n return {\n filePath,\n urlPattern: keyToRoutePattern(filePath, apiDir),\n identifier: filePathToIdentifier(filePath, apiDir),\n methods,\n }\n}\n\nexport function generateRoutesDts(entries: RouteEntry[], apiDir: string): string {\n if (entries.length === 0) {\n return `// auto-generado por devix \u2014 no editar\\ndeclare module '@devlusoft/devix' {\\n interface ApiRoutes {}\\n}\\n`\n }\n\n const imports = entries\n .map(e => {\n const importPath = '../' + e.filePath.replace(/\\.(ts|tsx)$/, '')\n return `import type * as ${e.identifier} from '${importPath}'`\n })\n .join('\\n')\n\n const routeLines = entries.flatMap(e =>\n e.methods.map(m =>\n ` '${m} ${e.urlPattern}': InferRoute<(typeof ${e.identifier})['${m}']>`\n )\n ).join('\\n')\n\n return `// auto-generado por devix \u2014 no editar\n${imports}\n\ntype JsonResponse<T> = Response & { readonly __body: T }\ntype InferRoute<T> = T extends (...args: any[]) => any\n ? Awaited<ReturnType<T>> extends JsonResponse<infer U>\n ? U\n : Exclude<Awaited<ReturnType<T>>, Response | null | void>\n : never\n\ndeclare module '@devlusoft/devix' {\n interface ApiRoutes {\n${routeLines}\n }\n}\n`\n}\n", "import {readFileSync, readdirSync, statSync} from 'node:fs'\nimport {join, relative} from 'node:path'\nimport {extractHttpMethods} from './extract-methods'\nimport {buildRouteEntry} from './routes-dts'\nimport type {RouteEntry} from './routes-dts'\n\nfunction walkDir(dir: string, root: string): string[] {\n const entries: string[] = []\n for (const name of readdirSync(dir)) {\n const full = join(dir, name)\n if (statSync(full).isDirectory()) {\n entries.push(...walkDir(full, root))\n } else if (/\\.(ts|tsx)$/.test(name)) {\n entries.push(relative(root, full).replace(/\\\\/g, '/'))\n }\n }\n return entries\n}\n\nexport function scanApiFiles(appDir: string, projectRoot: string): RouteEntry[] {\n const apiDir = join(projectRoot, appDir, 'api')\n\n let files: string[]\n try {\n files = walkDir(apiDir, projectRoot)\n } catch {\n return []\n }\n\n return files\n .filter(f => !f.endsWith('middleware.ts') && !f.endsWith('middleware.tsx'))\n .flatMap(filePath => {\n try {\n const content = readFileSync(join(projectRoot, filePath), 'utf-8')\n const methods = extractHttpMethods(content)\n if (methods.length === 0) return []\n return [buildRouteEntry(filePath, `${appDir}/api`, methods)]\n } catch {\n return []\n }\n })\n}\n", "import {mkdirSync, readFileSync, writeFileSync, existsSync} from 'node:fs'\nimport {join} from 'node:path'\n\nexport function writeRoutesDts(content: string, projectRoot: string): boolean {\n const devixDir = join(projectRoot, '.devix')\n const outPath = join(devixDir, 'routes.d.ts')\n\n mkdirSync(devixDir, {recursive: true})\n\n if (existsSync(outPath) && readFileSync(outPath, 'utf-8') === content) {\n return false\n }\n\n writeFileSync(outPath, content, 'utf-8')\n return true\n}\n", "import {UserConfig, Plugin, mergeConfig} from 'vite'\nimport type {DevixConfig} from '../config'\nimport react from '@vitejs/plugin-react'\nimport {fileURLToPath} from 'node:url'\nimport {dirname, resolve} from 'node:path'\nimport {generateEntryClient} from './codegen/entry-client'\nimport {generateClientRoutes} from './codegen/client-routes'\nimport {generateRender} from './codegen/render'\nimport {generateApi} from './codegen/api'\nimport {invalidatePagesCache} from \"../server/pages-router\";\nimport {invalidateApiCache} from \"../server/api-router\";\nimport {generateContext} from \"./codegen/context\";\nimport {scanApiFiles} from \"./codegen/scan-api\";\nimport {generateRoutesDts} from \"./codegen/routes-dts\";\nimport {writeRoutesDts} from \"./codegen/write-routes-dts\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst VIRTUAL_ENTRY_CLIENT = 'virtual:devix/entry-client'\nconst VIRTUAL_CLIENT_ROUTES = 'virtual:devix/client-routes'\nconst VIRTUAL_RENDER = 'virtual:devix/render'\nconst VIRTUAL_API = 'virtual:devix/api'\nconst VIRTUAL_CONTEXT = 'virtual:devix/context'\n\nexport function devix(config: DevixConfig): UserConfig {\n const appDir = config.appDir ?? 'app'\n const pagesDir = `${appDir}/pages`\n const cssUrls = (config.css ?? []).map(u => u.startsWith('/') ? u : `/${u.replace(/^\\.\\//, '')}`)\n\n const renderPath = resolve(__dirname, '../server/render.js').replace(/\\\\/g, '/')\n const apiPath = resolve(__dirname, '../server/api.js').replace(/\\\\/g, '/')\n const matcherPath = resolve(__dirname, '../runtime/client-router.js').replace(/\\\\/g, '/')\n\n const virtualPlugin: Plugin = {\n name: 'devix',\n enforce: 'pre',\n\n resolveId(id) {\n if (id === VIRTUAL_ENTRY_CLIENT) return `\\0${VIRTUAL_ENTRY_CLIENT}`\n if (id === VIRTUAL_CLIENT_ROUTES) return `\\0${VIRTUAL_CLIENT_ROUTES}`\n if (id === VIRTUAL_RENDER) return `\\0${VIRTUAL_RENDER}`\n if (id === VIRTUAL_API) return `\\0${VIRTUAL_API}`\n if (id === VIRTUAL_CONTEXT) return `\\0${VIRTUAL_CONTEXT}`\n },\n\n load(id) {\n if (id === `\\0${VIRTUAL_ENTRY_CLIENT}`)\n return generateEntryClient({cssUrls})\n if (id === `\\0${VIRTUAL_CLIENT_ROUTES}`)\n return generateClientRoutes({pagesDir, matcherPath})\n if (id === `\\0${VIRTUAL_RENDER}`)\n return generateRender({pagesDir, renderPath})\n if (id === `\\0${VIRTUAL_API}`)\n return generateApi({apiPath, appDir})\n if (id === `\\0${VIRTUAL_CONTEXT}`)\n return generateContext()\n },\n\n buildStart() {\n const root = process.cwd()\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n },\n\n configureServer(server) {\n const root = process.cwd()\n\n const regenerateDts = () => {\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n }\n\n server.watcher.on('add', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('unlink', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('change', (file) => {\n if (file.includes(`${appDir}/api`) && !file.endsWith('middleware.ts')) {\n regenerateDts()\n }\n })\n },\n }\n\n const base: UserConfig = {\n plugins: [react(), virtualPlugin],\n ssr: {noExternal: ['@devlusoft/devix']},\n ...(config.envPrefix ? {envPrefix: config.envPrefix} : {}),\n }\n\n return mergeConfig(base, config.vite ?? {})\n}", "import type {Hono} from 'hono'\nimport type {Manifest} from 'vite'\n\ninterface ServerOptions {\n renderModule: any\n apiModule: any\n manifest?: Manifest\n loaderTimeout?: number\n}\n\nexport function registerApiRoutes(app: Hono, {apiModule, renderModule, loaderTimeout}: ServerOptions) {\n app.all('/api/*', async (c) => {\n try {\n return await apiModule.handleApiRequest(c.req.url, c.req.raw)\n } catch (e) {\n console.error(e)\n return c.json({error: 'internal error'}, 500)\n }\n })\n\n app.get('/_data/*', async (c) => {\n try {\n const {pathname, search} = new URL(c.req.url, 'http://localhost')\n const url = pathname.replace(/^\\/_data/, '') + search\n\n const data = await renderModule.runLoader(url, c.req.raw, {loaderTimeout})\n return c.json(data)\n } catch (e) {\n console.error(e)\n return c.json({error: 'internal error'}, 500)\n }\n })\n}\n\nexport function registerSsrRoute(app: Hono, {renderModule, manifest, loaderTimeout}: ServerOptions) {\n app.get('*', async (c) => {\n try {\n const {html, statusCode, headers} = await renderModule.render(c.req.url, c.req.raw, {manifest, loaderTimeout})\n const res = c.html(`<!DOCTYPE html>${html}`, statusCode)\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n res.headers.set(key, value)\n }\n return res\n } catch (e) {\n console.error(e)\n return c.text('Internal Server Error', 500)\n }\n })\n}", "import pc from 'picocolors'\nimport {networkInterfaces} from 'node:os'\nimport {createRequire} from 'node:module'\n\nfunction getNetworkUrl(port: number): string | null {\n const nets = networkInterfaces()\n for (const interfaces of Object.values(nets)) {\n for (const net of interfaces ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return `http://${net.address}:${port}/`\n }\n }\n }\n return null\n}\n\nexport function printDevBanner(port: number) {\n const req = createRequire(import.meta.url)\n const version = req('../../package.json').version\n const networkUrl = getNetworkUrl(port)\n\n console.log()\n console.log(` ${pc.bold(pc.yellow('devix'))} ${pc.dim(`v${version}`)}`)\n console.log()\n console.log(` ${pc.green('\u279C')} ${pc.bold('Local:')} ${pc.cyan(`http://localhost:${port}/`)}`)\n if (networkUrl) {\n console.log(` ${pc.green('\u279C')} ${pc.bold('Network:')} ${pc.cyan(networkUrl)}`)\n } else {\n console.log(` ${pc.green('\u279C')} ${pc.bold('Network:')} ${pc.dim('use --host to expose')}`)\n }\n console.log()\n}", "import type {ViteDevServer} from 'vite'\n\nexport async function collectCss(vite: ViteDevServer): Promise<string[]> {\n const cssUrls = new Set<string>()\n\n for (const [, mod] of vite.moduleGraph.idToModuleMap) {\n if (!mod.id) continue\n if (mod.id.endsWith('.css') || mod.id.includes('.css?')) {\n cssUrls.add(mod.url)\n }\n }\n\n return [...cssUrls]\n}", "export function parseDuration(value: number | string): number {\n if (typeof value === 'number') return value\n const match = value.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h)?$/)\n if (!match) throw new Error(`[devix] Invalid duration: \"${value}\". Use a number (ms) or a string like \"5s\", \"2m\", \"500ms\".`)\n const n = parseFloat(match[1])\n switch (match[2]) {\n case 'h': return n * 3_600_000\n case 'm': return n * 60_000\n case 's': return n * 1_000\n case 'ms':\n default: return n\n }\n}\n", "import {loadEnv} from 'vite'\n\nexport function loadDotenv(mode: string) {\n const env = loadEnv(mode, process.cwd(), '')\n for (const [key, value] of Object.entries(env)) {\n if (process.env[key] === undefined) {\n process.env[key] = value\n }\n }\n}\n", "import {createServer} from 'node:http'\nimport {createServer as createViteServer} from 'vite'\nimport {getRequestListener} from '@hono/node-server'\nimport {Hono} from 'hono'\nimport type {DevixConfig} from '../config'\nimport {devix} from '../vite'\nimport {registerApiRoutes} from '../server/routes'\nimport {printDevBanner} from \"../utils/banner\";\nimport {collectCss} from \"../server/collect-css\";\nimport {parseDuration} from \"../utils/duration\";\nimport {loadDotenv} from \"../utils/env\";\n\nloadDotenv('development')\n\nconst VIRTUAL_RENDER = 'virtual:devix/render'\nconst VIRTUAL_API = 'virtual:devix/api'\n\nconst config: DevixConfig = (await import(`${process.cwd()}/devix.config.ts`)).default\nconst port = Number(process.env.PORT) || config.port || 3000\nconst host = typeof config.host === 'string' ? config.host : config.host ? '0.0.0.0' : 'localhost'\n\nconst vite = await createViteServer({\n ...devix(config),\n configFile: false,\n appType: 'custom',\n server: {middlewareMode: true},\n})\n\nconst renderModule = {\n render: async (...args: any[]) => (await vite.ssrLoadModule(VIRTUAL_RENDER)).render(...args),\n runLoader: async (...args: any[]) => (await vite.ssrLoadModule(VIRTUAL_RENDER)).runLoader(...args),\n}\n\nconst apiModule = {\n handleApiRequest: async (...args: any[]) => (await vite.ssrLoadModule(VIRTUAL_API)).handleApiRequest(...args),\n}\n\nconst app = new Hono()\n\nregisterApiRoutes(app, {renderModule, apiModule})\n\napp.get('*', async (c) => {\n try {\n const {html, statusCode, headers} = await renderModule.render(c.req.url, c.req.raw, {loaderTimeout: parseDuration(config.loaderTimeout ?? 10_000)})\n\n const cssUrls = await collectCss(vite)\n const cssLinks = cssUrls.map(url => `<link rel=\"stylesheet\" href=\"${url}\">`).join('\\n')\n\n const htmlWithCss = cssLinks ? html.replace('</head>', `${cssLinks}\\n</head>`) : html\n const transformed = await vite.transformIndexHtml(c.req.url, `<!DOCTYPE html>${htmlWithCss}`)\n\n const res = c.html(transformed, statusCode)\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n res.headers.set(key, value)\n }\n return res\n } catch (e) {\n vite.ssrFixStacktrace(e as Error)\n console.error(e)\n return c.text('Internal Server Error', 500)\n }\n})\n\nconst honoHandler = getRequestListener(app.fetch)\n\ncreateServer(async (req, res) => {\n await new Promise<void>(resolve => vite.middlewares(req, res, resolve))\n if (!res.writableEnded) await honoHandler(req, res)\n}).listen(port, host, () => {\n printDevBanner(port)\n})\n\nexport {}", "import {writeFileSync} from 'node:fs'\nimport {resolve} from 'node:path'\nimport {build} from 'vite'\nimport type {DevixConfig} from '../config'\nimport {devix} from '../vite'\nimport {parseDuration} from '../utils/duration'\n\nconst config: DevixConfig = (await import(`${process.cwd()}/devix.config.ts`)).default\nconst baseConfig = devix(config)\n\nawait build({\n ...baseConfig,\n configFile: false,\n build: {\n outDir: 'dist/client',\n manifest: true,\n rolldownOptions: {\n input: 'virtual:devix/entry-client',\n },\n },\n})\n\nawait build({\n ...baseConfig,\n configFile: false,\n build: {\n ssr: true,\n outDir: 'dist/server',\n rolldownOptions: {\n input: {\n render: 'virtual:devix/render',\n api: 'virtual:devix/api',\n },\n },\n },\n})\n\nconst runtimeConfig = {\n port: config.port ?? 3000,\n host: config.host ?? false,\n loaderTimeout: parseDuration(config.loaderTimeout ?? 10_000),\n output: config.output ?? 'server',\n}\n\nwriteFileSync(\n resolve(process.cwd(), 'dist/devix.config.json'),\n JSON.stringify(runtimeConfig, null, 2),\n 'utf-8'\n)\n\n\nexport {}", "import {readFileSync, mkdirSync, writeFileSync} from 'node:fs'\nimport {resolve, join} from 'node:path'\nimport type {Manifest} from 'vite'\nimport type {DevixConfig} from '../config'\n\nconst userConfig: DevixConfig = (await import(`${process.cwd()}/devix.config.ts`)).default\nif (userConfig.output !== 'static') {\n console.warn('[devix] Tip: set output: \"static\" in devix.config.ts to skip the SSR server at runtime.')\n}\n\nawait import('./build.js')\n\nconst t = Date.now()\nconst renderModule = await import(resolve(process.cwd(), 'dist/server/render.js') + `?t=${t}`)\n\nconst manifest: Manifest = JSON.parse(\n readFileSync(resolve(process.cwd(), 'dist/client/.vite/manifest.json'), 'utf-8')\n)\n\nconst urls: string[] = await renderModule.getStaticRoutes()\n\nconsole.log(`[devix] Generating ${urls.length} static page${urls.length === 1 ? '' : 's'}...`)\n\nfor (const url of urls) {\n const fullUrl = `http://localhost${url}`\n const {html, statusCode} = await renderModule.render(fullUrl, new Request(fullUrl), {manifest})\n\n if (statusCode !== 200) {\n console.warn(`[devix] Skipping ${url} \u2014 status ${statusCode}`)\n continue\n }\n\n const outPath = url === '/'\n ? join(process.cwd(), 'dist/client/index.html')\n : join(process.cwd(), 'dist/client', url, 'index.html')\n\n mkdirSync(join(outPath, '..'), {recursive: true})\n writeFileSync(outPath, `<!DOCTYPE html>${html}`, 'utf-8')\n console.log(` \u2713 ${url}`)\n}\n\nconsole.log('[devix] Generation complete.')\n\nexport {}\n", "import {readFileSync} from 'node:fs'\nimport {serve} from '@hono/node-server'\nimport {serveStatic} from '@hono/node-server/serve-static'\nimport {Hono} from 'hono'\nimport {resolve} from 'node:path'\nimport type {Manifest} from 'vite'\nimport {registerApiRoutes, registerSsrRoute} from '../server/routes'\nimport {loadDotenv} from '../utils/env'\n\nloadDotenv('production')\n\nlet renderModule: any\nlet apiModule: any\nlet manifest: Manifest\nlet runtimeConfig: { port: number, host: string | boolean, loaderTimeout: number, output: 'server' | 'static' }\n\ntry {\n runtimeConfig = JSON.parse(readFileSync(resolve(process.cwd(), 'dist/devix.config.json'), 'utf-8'))\n if (runtimeConfig.output !== 'static') {\n renderModule = await import(resolve(process.cwd(), 'dist/server/render.js'))\n apiModule = await import(resolve(process.cwd(), 'dist/server/api.js'))\n }\n manifest = JSON.parse(readFileSync(resolve(process.cwd(), 'dist/client/.vite/manifest.json'), 'utf-8'))\n} catch {\n console.error('[devix] Build not found. Run \"devix build\" first.')\n process.exit(1)\n}\n\nconst port = Number(process.env.PORT) || runtimeConfig!.port || 3000\nconst host = typeof runtimeConfig!.host === 'string'\n ? runtimeConfig!.host\n : runtimeConfig!.host ? '0.0.0.0' : (process.env.HOST || '0.0.0.0')\n\nconst app = new Hono()\n\napp.use('/*', serveStatic({\n root: './dist/client',\n onFound: (_path, c) => {\n c.header('Cache-Control', _path.includes('/assets/')\n ? 'public, immutable, max-age=31536000'\n : 'no-cache')\n }\n}))\n\nif (runtimeConfig!.output === 'static') {\n console.log('[devix] Static mode \u2014 serving pre-generated files from dist/client')\n} else {\n registerApiRoutes(app, {renderModule, apiModule, manifest})\n registerSsrRoute(app, {renderModule, apiModule, manifest, loaderTimeout: runtimeConfig!.loaderTimeout})\n}\n\nserve({fetch: app.fetch, port, hostname: host}, (info) => console.log(`http://${info.address}:${info.port}`))\n\nexport {}", "#!/usr/bin/env node\nimport {readFileSync} from 'node:fs'\nimport {join, dirname} from 'node:path'\nimport {fileURLToPath} from 'node:url'\n\nconst command = process.argv[2]\n\nswitch (command) {\n case 'dev':\n await import(\"./dev.js\")\n break\n case \"build\":\n await import(\"./build.js\")\n break\n case \"generate\":\n await import(\"./generate.js\")\n break\n case \"start\":\n await import(\"./start.js\")\n break\n case '--version':\n case '-v': {\n const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../package.json'), 'utf-8'))\n console.log(pkg.version)\n break\n }\n case '--help':\n case '-h':\n console.log(`\ndevix \u2014 a lightweight SSR framework\n\nUsage:\n devix dev Start development server\n devix build Build for production\n devix generate Build and generate static HTML (SSG)\n devix start Start production server\n\nOptions:\n -v, --version Show version\n -h, --help Show this help\n\nOutput modes (set in devix.config.ts):\n output: \"server\" SSR mode \u2014 devix start handles requests dynamically (default)\n output: \"static\" SSG mode \u2014 devix generate pre-renders all pages; devix start serves static files only\n `.trim())\n break\n default:\n console.error(`Unknown command: ${command}`)\n console.error('Usage: devix <dev|build|generate|start>')\n process.exit(1)\n}\n\nexport {}"],
|
|
5
|
-
"mappings": ";mCAIO,SAASA,EAAoB,CAAC,QAAAC,CAAO,EAA+B,CAGvE,MAAO;AAAA,EAFYA,EAAQ,IAAIC,GAAK,WAAWA,CAAC,GAAG,EAAE,KAAK;AAAA,CAAI,CAGtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAuDZ,CA/DA,IAAAC,GAAAC,EAAA,oBCKO,SAASC,GAAqB,CAAC,SAAAC,EAAU,YAAAC,CAAW,EAAwB,CAC/E,MAAO;AAAA;AAAA,iCAEsBA,CAAW;AAAA,wCACJD,CAAQ;AAAA,yCACPA,CAAQ;AAAA,wCACTA,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAwBhD,CAnCA,IAAAE,GAAAC,EAAA,oBCKO,SAASC,GAAe,CAAC,SAAAC,EAAU,WAAAC,CAAU,EAA0B,CAC1E,MAAO;AAAA,mGACwFA,CAAU;AAAA;AAAA,qCAExED,CAAQ;AAAA,sCACPA,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,kBAK5BA,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAe1B,CA9BA,IAAAE,GAAAC,EAAA,oBCKO,SAASC,GAAY,CAAC,QAAAC,EAAS,OAAAC,CAAM,EAAuB,CAC/D,MAAO;AAAA,yDAC8CD,CAAO;AAAA;AAAA,sCAE1BC,CAAM;AAAA,0CACFA,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKhCA,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAOtB,CAtBA,IAAAC,GAAAC,EAAA,oBCAO,SAASC,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CAPA,IAAAC,EAAAC,EAAA,oBC+BO,SAASC,GAAuB,CACnCC,GAAQ,IACZ,CAjCA,IA6BIA,GA7BJC,GAAAC,EAAA,kBAAAC,IA6BIH,GAA4B,OCVzB,SAASI,GAAkBC,EAAaC,EAAwB,CACnE,IAAMC,EAAMF,EAAI,MAAMC,EAAO,OAAS,CAAC,EAAE,QAAQ,MAAO,GAAG,EACrDE,EAAUC,EAAaF,CAAG,EAChC,OAAOC,IAAY,IAAM,OAAS,QAAQA,CAAO,GAAG,QAAQ,SAAU,OAAO,CACjF,CAQO,SAASE,GAAqB,CACjCC,GAAQ,IACZ,CAjCA,IA6BIA,GA7BJC,EAAAC,EAAA,kBAAAC,IA6BIH,GAA0B,OC7BvB,SAASI,IAA0B,CACtC,MAAO;AAAA;AAAA,CAGX,CAJA,IAAAC,GAAAC,EAAA,oBCKA,SAASC,GAAcC,EAAyB,CAC5C,OAAOA,EACF,QAAQ,oBAAqB,EAAE,EAC/B,QAAQ,YAAa,EAAE,CAChC,CAEO,SAASC,GAAmBD,EAA+B,CAC9D,IAAME,EAAQ,IAAI,IAClB,QAAWC,KAASJ,GAAcC,CAAO,EAAE,SAASI,EAAgB,EAChEF,EAAM,IAAIC,EAAM,CAAC,CAAe,EAEpC,MAAO,CAAC,GAAGD,CAAK,CACpB,CAjBA,IAGME,GAHNC,GAAAC,EAAA,kBAGMF,GAAmB,+FCOlB,SAASG,GAAqBC,EAAkBC,EAAwB,CAC3E,MAAO,QAAUD,EACZ,MAAM,GAAGC,CAAM,IAAI,MAAM,EACzB,QAAQ,cAAe,EAAE,EACzB,QAAQ,gBAAiB,GAAG,CACrC,CAEO,SAASC,GAAgBF,EAAkBC,EAAgBE,EAAmC,CACjG,MAAO,CACH,SAAAH,EACA,WAAYI,GAAkBJ,EAAUC,CAAM,EAC9C,WAAYF,GAAqBC,EAAUC,CAAM,EACjD,QAAAE,CACJ,CACJ,CAEO,SAASE,EAAkBC,EAAuBL,EAAwB,CAC7E,GAAIK,EAAQ,SAAW,EACnB,MAAO;AAAA;AAAA;AAAA;AAAA,EAGX,IAAMC,EAAUD,EACX,IAAIE,GAAK,CACN,IAAMC,EAAa,MAAQD,EAAE,SAAS,QAAQ,cAAe,EAAE,EAC/D,MAAO,oBAAoBA,EAAE,UAAU,UAAUC,CAAU,GAC/D,CAAC,EACA,KAAK;AAAA,CAAI,EAERC,EAAaJ,EAAQ,QAAQE,GAC/BA,EAAE,QAAQ,IAAIG,GACV,QAAQA,CAAC,IAAIH,EAAE,UAAU,yBAAyBA,EAAE,UAAU,MAAMG,CAAC,KACzE,CACJ,EAAE,KAAK;AAAA,CAAI,EAEX,MAAO;AAAA,EACTJ,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWPG,CAAU;AAAA;AAAA;AAAA,CAIZ,CA5DA,IAAAE,EAAAC,EAAA,kBAAAC,MCAA,OAAQ,gBAAAC,GAAc,eAAAC,GAAa,YAAAC,OAAe,UAClD,OAAQ,QAAAC,EAAM,YAAAC,OAAe,YAK7B,SAASC,GAAQC,EAAaC,EAAwB,CAClD,IAAMC,EAAoB,CAAC,EAC3B,QAAWC,KAAQR,GAAYK,CAAG,EAAG,CACjC,IAAMI,EAAOP,EAAKG,EAAKG,CAAI,EACvBP,GAASQ,CAAI,EAAE,YAAY,EAC3BF,EAAQ,KAAK,GAAGH,GAAQK,EAAMH,CAAI,CAAC,EAC5B,cAAc,KAAKE,CAAI,GAC9BD,EAAQ,KAAKJ,GAASG,EAAMG,CAAI,EAAE,QAAQ,MAAO,GAAG,CAAC,CAE7D,CACA,OAAOF,CACX,CAEO,SAASG,EAAaC,EAAgBC,EAAmC,CAC5E,IAAMC,EAASX,EAAKU,EAAaD,EAAQ,KAAK,EAE1CG,EACJ,GAAI,CACAA,EAAQV,GAAQS,EAAQD,CAAW,CACvC,MAAQ,CACJ,MAAO,CAAC,CACZ,CAEA,OAAOE,EACF,OAAOC,GAAK,CAACA,EAAE,SAAS,eAAe,GAAK,CAACA,EAAE,SAAS,gBAAgB,CAAC,EACzE,QAAQC,GAAY,CACjB,GAAI,CACA,IAAMC,EAAUlB,GAAaG,EAAKU,EAAaI,CAAQ,EAAG,OAAO,EAC3DE,EAAUC,GAAmBF,CAAO,EAC1C,OAAIC,EAAQ,SAAW,EAAU,CAAC,EAC3B,CAACE,GAAgBJ,EAAU,GAAGL,CAAM,OAAQO,CAAO,CAAC,CAC/D,MAAQ,CACJ,MAAO,CAAC,CACZ,CACJ,CAAC,CACT,CAzCA,IAAAG,GAAAC,EAAA,kBAEAC,KACAC,MCHA,OAAQ,aAAAC,GAAW,gBAAAC,GAAc,iBAAAC,GAAe,cAAAC,OAAiB,UACjE,OAAQ,QAAAC,OAAW,YAEZ,SAASC,EAAeC,EAAiBC,EAA8B,CAC1E,IAAMC,EAAWJ,GAAKG,EAAa,QAAQ,EACrCE,EAAUL,GAAKI,EAAU,aAAa,EAI5C,OAFAR,GAAUQ,EAAU,CAAC,UAAW,EAAI,CAAC,EAEjCL,GAAWM,CAAO,GAAKR,GAAaQ,EAAS,OAAO,IAAMH,EACnD,IAGXJ,GAAcO,EAASH,EAAS,OAAO,EAChC,GACX,CAfA,IAAAI,GAAAC,EAAA,oBCAA,OAA4B,eAAAC,OAAkB,OAE9C,OAAOC,OAAW,uBAClB,OAAQ,iBAAAC,OAAoB,WAC5B,OAAQ,WAAAC,GAAS,WAAAC,MAAc,YAoBxB,SAASC,EAAMC,EAAiC,CACnD,IAAMC,EAASD,EAAO,QAAU,MAC1BE,EAAW,GAAGD,CAAM,SACpBE,GAAWH,EAAO,KAAO,CAAC,GAAG,IAAII,GAAKA,EAAE,WAAW,GAAG,EAAIA,EAAI,IAAIA,EAAE,QAAQ,QAAS,EAAE,CAAC,EAAE,EAE1FC,EAAaP,EAAQQ,EAAW,qBAAqB,EAAE,QAAQ,MAAO,GAAG,EACzEC,EAAUT,EAAQQ,EAAW,kBAAkB,EAAE,QAAQ,MAAO,GAAG,EACnEE,EAAcV,EAAQQ,EAAW,6BAA6B,EAAE,QAAQ,MAAO,GAAG,EAElFG,EAAwB,CAC1B,KAAM,QACN,QAAS,MAET,UAAUC,EAAI,CACV,GAAIA,IAAOC,EAAsB,MAAO,KAAKA,CAAoB,GACjE,GAAID,IAAOE,EAAuB,MAAO,KAAKA,CAAqB,GACnE,GAAIF,IAAOG,EAAgB,MAAO,KAAKA,CAAc,GACrD,GAAIH,IAAOI,EAAa,MAAO,KAAKA,CAAW,GAC/C,GAAIJ,IAAOK,EAAiB,MAAO,KAAKA,CAAe,EAC3D,EAEA,KAAKL,EAAI,CACL,GAAIA,IAAO,KAAKC,CAAoB,GAChC,OAAOK,EAAoB,CAAC,QAAAb,CAAO,CAAC,EACxC,GAAIO,IAAO,KAAKE,CAAqB,GACjC,OAAOK,GAAqB,CAAC,SAAAf,EAAU,YAAAM,CAAW,CAAC,EACvD,GAAIE,IAAO,KAAKG,CAAc,GAC1B,OAAOK,GAAe,CAAC,SAAAhB,EAAU,WAAAG,CAAU,CAAC,EAChD,GAAIK,IAAO,KAAKI,CAAW,GACvB,OAAOK,GAAY,CAAC,QAAAZ,EAAS,OAAAN,CAAM,CAAC,EACxC,GAAIS,IAAO,KAAKK,CAAe,GAC3B,OAAOK,GAAgB,CAC/B,EAEA,YAAa,CACT,IAAMC,EAAO,QAAQ,IAAI,EACnBC,EAAUC,EAAatB,EAAQoB,CAAI,EACzCG,EAAeC,EAAkBH,EAAS,GAAGrB,CAAM,MAAM,EAAGoB,CAAI,CACpE,EAEA,gBAAgBK,EAAQ,CACpB,IAAML,EAAO,QAAQ,IAAI,EAEnBM,EAAgB,IAAM,CACxB,IAAML,EAAUC,EAAatB,EAAQoB,CAAI,EACzCG,EAAeC,EAAkBH,EAAS,GAAGrB,CAAM,MAAM,EAAGoB,CAAI,CACpE,EAEAK,EAAO,QAAQ,GAAG,MAAQE,GAAS,CAC3BA,EAAK,WAAW9B,EAAQuB,EAAMnB,CAAQ,CAAC,GAAG2B,EAAqB,EAC/DD,EAAK,SAAS,GAAG3B,CAAM,MAAM,IAAK6B,EAAmB,EAAGH,EAAc,EAC9E,CAAC,EACDD,EAAO,QAAQ,GAAG,SAAWE,GAAS,CAC9BA,EAAK,WAAW9B,EAAQuB,EAAMnB,CAAQ,CAAC,GAAG2B,EAAqB,EAC/DD,EAAK,SAAS,GAAG3B,CAAM,MAAM,IAAK6B,EAAmB,EAAGH,EAAc,EAC9E,CAAC,EACDD,EAAO,QAAQ,GAAG,SAAWE,GAAS,CAC9BA,EAAK,SAAS,GAAG3B,CAAM,MAAM,GAAK,CAAC2B,EAAK,SAAS,eAAe,GAChED,EAAc,CAEtB,CAAC,CACL,CACJ,EAEMI,EAAmB,CACrB,QAAS,CAACpC,GAAM,EAAGc,CAAa,EAChC,IAAK,CAAC,WAAY,CAAC,kBAAkB,CAAC,EACtC,GAAIT,EAAO,UAAY,CAAC,UAAWA,EAAO,SAAS,EAAI,CAAC,CAC5D,EAEA,OAAON,GAAYqC,EAAM/B,EAAO,MAAQ,CAAC,CAAC,CAC9C,CA/FA,IAgBMM,EAEAK,EACAC,EACAC,EACAC,EACAC,EAtBNiB,EAAAC,EAAA,kBAKAC,KACAC,KACAC,KACAC,KACAC,KACAC,IACAC,KACAC,KACAC,IACAC,KAEMrC,EAAYT,GAAQD,GAAc,YAAY,GAAG,CAAC,EAElDe,EAAuB,6BACvBC,EAAwB,8BACxBC,EAAiB,uBACjBC,EAAc,oBACdC,EAAkB,0BCZjB,SAAS6B,EAAkBC,EAAW,CAAC,UAAAC,EAAW,aAAAC,EAAc,cAAAC,CAAa,EAAkB,CAClGH,EAAI,IAAI,SAAU,MAAOI,GAAM,CAC3B,GAAI,CACA,OAAO,MAAMH,EAAU,iBAAiBG,EAAE,IAAI,IAAKA,EAAE,IAAI,GAAG,CAChE,OAASC,EAAG,CACR,eAAQ,MAAMA,CAAC,EACRD,EAAE,KAAK,CAAC,MAAO,gBAAgB,EAAG,GAAG,CAChD,CACJ,CAAC,EAEDJ,EAAI,IAAI,WAAY,MAAOI,GAAM,CAC7B,GAAI,CACA,GAAM,CAAC,SAAAE,EAAU,OAAAC,CAAM,EAAI,IAAI,IAAIH,EAAE,IAAI,IAAK,kBAAkB,EAC1DI,EAAMF,EAAS,QAAQ,WAAY,EAAE,EAAIC,EAEzCE,EAAO,MAAMP,EAAa,UAAUM,EAAKJ,EAAE,IAAI,IAAK,CAAC,cAAAD,CAAa,CAAC,EACzE,OAAOC,EAAE,KAAKK,CAAI,CACtB,OAASJ,EAAG,CACR,eAAQ,MAAMA,CAAC,EACRD,EAAE,KAAK,CAAC,MAAO,gBAAgB,EAAG,GAAG,CAChD,CACJ,CAAC,CACL,CAEO,SAASM,GAAiBV,EAAW,CAAC,aAAAE,EAAc,SAAAS,EAAU,cAAAR,CAAa,EAAkB,CAChGH,EAAI,IAAI,IAAK,MAAOI,GAAM,CACtB,GAAI,CACA,GAAM,CAAC,KAAAQ,EAAM,WAAAC,EAAY,QAAAC,CAAO,EAAI,MAAMZ,EAAa,OAAOE,EAAE,IAAI,IAAKA,EAAE,IAAI,IAAK,CAAC,SAAAO,EAAU,cAAAR,CAAa,CAAC,EACvGY,EAAMX,EAAE,KAAK,kBAAkBQ,CAAI,GAAIC,CAAU,EACvD,OAAW,CAACG,EAAKC,CAAK,IAAK,OAAO,QAAQH,CAAiC,EACvEC,EAAI,QAAQ,IAAIC,EAAKC,CAAK,EAE9B,OAAOF,CACX,OAASV,EAAG,CACR,eAAQ,MAAMA,CAAC,EACRD,EAAE,KAAK,wBAAyB,GAAG,CAC9C,CACJ,CAAC,CACL,CAhDA,IAAAc,EAAAC,EAAA,oBCAA,OAAOC,MAAQ,aACf,OAAQ,qBAAAC,OAAwB,UAChC,OAAQ,iBAAAC,OAAoB,cAE5B,SAASC,GAAcC,EAA6B,CAChD,IAAMC,EAAOJ,GAAkB,EAC/B,QAAWK,KAAc,OAAO,OAAOD,CAAI,EACvC,QAAWE,KAAOD,GAAc,CAAC,EAC7B,GAAIC,EAAI,SAAW,QAAU,CAACA,EAAI,SAC9B,MAAO,UAAUA,EAAI,OAAO,IAAIH,CAAI,IAIhD,OAAO,IACX,CAEO,SAASI,GAAeJ,EAAc,CAEzC,IAAMK,EADMP,GAAc,YAAY,GAAG,EACrB,oBAAoB,EAAE,QACpCQ,EAAaP,GAAcC,CAAI,EAErC,QAAQ,IAAI,EACZ,QAAQ,IAAI,KAAKJ,EAAG,KAAKA,EAAG,OAAO,OAAO,CAAC,CAAC,IAAIA,EAAG,IAAI,IAAIS,CAAO,EAAE,CAAC,EAAE,EACvE,QAAQ,IAAI,EACZ,QAAQ,IAAI,KAAKT,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,QAAQ,CAAC,MAAMA,EAAG,KAAK,oBAAoBI,CAAI,GAAG,CAAC,EAAE,EAE5F,QAAQ,IADRM,EACY,KAAKV,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,UAAU,CAAC,IAAIA,EAAG,KAAKU,CAAU,CAAC,GAEjE,KAAKV,EAAG,MAAM,QAAG,CAAC,KAAKA,EAAG,KAAK,UAAU,CAAC,IAAIA,EAAG,IAAI,sBAAsB,CAAC,EAFT,EAInF,QAAQ,IAAI,CAChB,CA/BA,IAAAW,GAAAC,EAAA,oBCEA,eAAsBC,GAAWC,EAAwC,CACrE,IAAMC,EAAU,IAAI,IAEpB,OAAW,CAAC,CAAEC,CAAG,IAAKF,EAAK,YAAY,cAC9BE,EAAI,KACLA,EAAI,GAAG,SAAS,MAAM,GAAKA,EAAI,GAAG,SAAS,OAAO,IAClDD,EAAQ,IAAIC,EAAI,GAAG,EAI3B,MAAO,CAAC,GAAGD,CAAO,CACtB,CAbA,IAAAE,GAAAC,EAAA,oBCAO,SAASC,EAAcC,EAAgC,CAC1D,GAAI,OAAOA,GAAU,SAAU,OAAOA,EACtC,IAAMC,EAAQD,EAAM,KAAK,EAAE,MAAM,iCAAiC,EAClE,GAAI,CAACC,EAAO,MAAM,IAAI,MAAM,8BAA8BD,CAAK,4DAA4D,EAC3H,IAAME,EAAI,WAAWD,EAAM,CAAC,CAAC,EAC7B,OAAQA,EAAM,CAAC,EAAG,CACd,IAAK,IAAM,OAAOC,EAAI,KACtB,IAAK,IAAM,OAAOA,EAAI,IACtB,IAAK,IAAM,OAAOA,EAAI,IAEtB,QAAW,OAAOA,CACtB,CACJ,CAZA,IAAAC,EAAAC,EAAA,oBCAA,OAAQ,WAAAC,OAAc,OAEf,SAASC,EAAWC,EAAc,CACrC,IAAMC,EAAMH,GAAQE,EAAM,QAAQ,IAAI,EAAG,EAAE,EAC3C,OAAW,CAACE,EAAKC,CAAK,IAAK,OAAO,QAAQF,CAAG,EACrC,QAAQ,IAAIC,CAAG,IAAM,SACrB,QAAQ,IAAIA,CAAG,EAAIC,EAG/B,CATA,IAAAC,EAAAC,EAAA,oBCAA,IAAAC,GAAA,UAAQ,gBAAAC,OAAmB,YAC3B,OAAQ,gBAAgBC,OAAuB,OAC/C,OAAQ,sBAAAC,OAAyB,oBACjC,OAAQ,QAAAC,OAAW,OAHnB,IAcMC,GACAC,GAEAC,EACAC,GACAC,GAEAC,EAOAC,GAKAC,GAIAC,EA0BAC,GA/DNC,GAAAC,EAAA,uBAKAC,IACAC,IACAC,KACAC,KACAC,IACAC,IAEAC,EAAW,aAAa,EAElBlB,GAAiB,uBACjBC,GAAc,oBAEdC,GAAuB,MAAM,OAAO,GAAG,QAAQ,IAAI,CAAC,qBAAqB,QACzEC,GAAO,OAAO,QAAQ,IAAI,IAAI,GAAKD,EAAO,MAAQ,IAClDE,GAAO,OAAOF,EAAO,MAAS,SAAWA,EAAO,KAAOA,EAAO,KAAO,UAAY,YAEjFG,EAAO,MAAMR,GAAiB,CAChC,GAAGsB,EAAMjB,CAAM,EACf,WAAY,GACZ,QAAS,SACT,OAAQ,CAAC,eAAgB,EAAI,CACjC,CAAC,EAEKI,GAAe,CACjB,OAAQ,SAAUc,KAAiB,MAAMf,EAAK,cAAcL,EAAc,GAAG,OAAO,GAAGoB,CAAI,EAC3F,UAAW,SAAUA,KAAiB,MAAMf,EAAK,cAAcL,EAAc,GAAG,UAAU,GAAGoB,CAAI,CACrG,EAEMb,GAAY,CACd,iBAAkB,SAAUa,KAAiB,MAAMf,EAAK,cAAcJ,EAAW,GAAG,iBAAiB,GAAGmB,CAAI,CAChH,EAEMZ,EAAM,IAAIT,GAEhBsB,EAAkBb,EAAK,CAAC,aAAAF,GAAc,UAAAC,EAAS,CAAC,EAEhDC,EAAI,IAAI,IAAK,MAAOc,GAAM,CACtB,GAAI,CACA,GAAM,CAAC,KAAAC,EAAM,WAAAC,EAAY,QAAAC,CAAO,EAAI,MAAMnB,GAAa,OAAOgB,EAAE,IAAI,IAAKA,EAAE,IAAI,IAAK,CAAC,cAAeI,EAAcxB,EAAO,eAAiB,GAAM,CAAC,CAAC,EAG5IyB,GADU,MAAMC,GAAWvB,CAAI,GACZ,IAAIwB,GAAO,gCAAgCA,CAAG,IAAI,EAAE,KAAK;AAAA,CAAI,EAEhFC,EAAcH,EAAWJ,EAAK,QAAQ,UAAW,GAAGI,CAAQ;AAAA,QAAW,EAAIJ,EAC3EQ,EAAc,MAAM1B,EAAK,mBAAmBiB,EAAE,IAAI,IAAK,kBAAkBQ,CAAW,EAAE,EAEtFE,EAAMV,EAAE,KAAKS,EAAaP,CAAU,EAC1C,OAAW,CAACS,EAAKC,CAAK,IAAK,OAAO,QAAQT,CAAiC,EACvEO,EAAI,QAAQ,IAAIC,EAAKC,CAAK,EAE9B,OAAOF,CACX,OAASG,EAAG,CACR,OAAA9B,EAAK,iBAAiB8B,CAAU,EAChC,QAAQ,MAAMA,CAAC,EACRb,EAAE,KAAK,wBAAyB,GAAG,CAC9C,CACJ,CAAC,EAEKb,GAAcX,GAAmBU,EAAI,KAAK,EAEhDZ,GAAa,MAAOwC,EAAKJ,IAAQ,CAC7B,MAAM,IAAI,QAAcK,GAAWhC,EAAK,YAAY+B,EAAKJ,EAAKK,CAAO,CAAC,EACjEL,EAAI,eAAe,MAAMvB,GAAY2B,EAAKJ,CAAG,CACtD,CAAC,EAAE,OAAO7B,GAAMC,GAAM,IAAM,CACxBkC,GAAenC,EAAI,CACvB,CAAC,ICtED,IAAAoC,GAAA,UAAQ,iBAAAC,OAAoB,UAC5B,OAAQ,WAAAC,OAAc,YACtB,OAAQ,SAAAC,OAAY,OAFpB,IAOMC,EACAC,GA6BAC,GArCNC,EAAAC,EAAA,uBAIAC,IACAC,IAEMN,GAAuB,MAAM,OAAO,GAAG,QAAQ,IAAI,CAAC,qBAAqB,QACzEC,GAAaM,EAAMP,CAAM,EAE/B,MAAMD,GAAM,CACR,GAAGE,GACH,WAAY,GACZ,MAAO,CACH,OAAQ,cACR,SAAU,GACV,gBAAiB,CACb,MAAO,4BACX,CACJ,CACJ,CAAC,EAED,MAAMF,GAAM,CACR,GAAGE,GACH,WAAY,GACZ,MAAO,CACH,IAAK,GACL,OAAQ,cACR,gBAAiB,CACb,MAAO,CACH,OAAQ,uBACR,IAAK,mBACT,CACJ,CACJ,CACJ,CAAC,EAEKC,GAAgB,CAClB,KAAMF,EAAO,MAAQ,IACrB,KAAMA,EAAO,MAAQ,GACrB,cAAeQ,EAAcR,EAAO,eAAiB,GAAM,EAC3D,OAAQA,EAAO,QAAU,QAC7B,EAEAH,GACIC,GAAQ,QAAQ,IAAI,EAAG,wBAAwB,EAC/C,KAAK,UAAUI,GAAe,KAAM,CAAC,EACrC,OACJ,IChDA,IAAAO,GAAA,UAAQ,gBAAAC,GAAc,aAAAC,GAAW,iBAAAC,OAAoB,UACrD,OAAQ,WAAAC,GAAS,QAAAC,MAAW,YAD5B,IAKMC,GAOAC,GACAC,GAEAC,GAIAC,EAnBNC,GAAAC,EAAA,uBAKMN,IAA2B,MAAM,OAAO,GAAG,QAAQ,IAAI,CAAC,qBAAqB,QAC/EA,GAAW,SAAW,UACtB,QAAQ,KAAK,yFAAyF,EAG1G,KAAM,kBAEAC,GAAI,KAAK,IAAI,EACbC,GAAe,MAAM,OAAOJ,GAAQ,QAAQ,IAAI,EAAG,uBAAuB,EAAI,MAAMG,EAAC,IAErFE,GAAqB,KAAK,MAC5BR,GAAaG,GAAQ,QAAQ,IAAI,EAAG,iCAAiC,EAAG,OAAO,CACnF,EAEMM,EAAiB,MAAMF,GAAa,gBAAgB,EAE1D,QAAQ,IAAI,sBAAsBE,EAAK,MAAM,eAAeA,EAAK,SAAW,EAAI,GAAK,GAAG,KAAK,EAE7F,QAAWG,KAAOH,EAAM,CACpB,IAAMI,EAAU,mBAAmBD,CAAG,GAChC,CAAC,KAAAE,EAAM,WAAAC,CAAU,EAAI,MAAMR,GAAa,OAAOM,EAAS,IAAI,QAAQA,CAAO,EAAG,CAAC,SAAAL,EAAQ,CAAC,EAE9F,GAAIO,IAAe,IAAK,CACpB,QAAQ,KAAK,oBAAoBH,CAAG,kBAAaG,CAAU,EAAE,EAC7D,QACJ,CAEA,IAAMC,EAAUJ,IAAQ,IAClBR,EAAK,QAAQ,IAAI,EAAG,wBAAwB,EAC5CA,EAAK,QAAQ,IAAI,EAAG,cAAeQ,EAAK,YAAY,EAE1DX,GAAUG,EAAKY,EAAS,IAAI,EAAG,CAAC,UAAW,EAAI,CAAC,EAChDd,GAAcc,EAAS,kBAAkBF,CAAI,GAAI,OAAO,EACxD,QAAQ,IAAI,YAAOF,CAAG,EAAE,CAC5B,CAEA,QAAQ,IAAI,8BAA8B,ICzC1C,IAAAK,GAAA,UAAQ,gBAAAC,OAAmB,UAC3B,OAAQ,SAAAC,OAAY,oBACpB,OAAQ,eAAAC,OAAkB,iCAC1B,OAAQ,QAAAC,OAAW,OACnB,OAAQ,WAAAC,MAAc,YAJtB,IAWIC,EACAC,EACAC,EACAC,EAcEC,GACAC,GAIAC,EAjCNC,GAAAC,EAAA,uBAMAC,IACAC,IAEAC,EAAW,YAAY,EAOvB,GAAI,CACAR,EAAgB,KAAK,MAAMR,GAAaI,EAAQ,QAAQ,IAAI,EAAG,wBAAwB,EAAG,OAAO,CAAC,EAC9FI,EAAc,SAAW,WACzBH,EAAe,MAAM,OAAOD,EAAQ,QAAQ,IAAI,EAAG,uBAAuB,GAC1EE,EAAY,MAAM,OAAOF,EAAQ,QAAQ,IAAI,EAAG,oBAAoB,IAExEG,EAAW,KAAK,MAAMP,GAAaI,EAAQ,QAAQ,IAAI,EAAG,iCAAiC,EAAG,OAAO,CAAC,CAC1G,MAAQ,CACJ,QAAQ,MAAM,mDAAmD,EACjE,QAAQ,KAAK,CAAC,CAClB,CAEMK,GAAO,OAAO,QAAQ,IAAI,IAAI,GAAKD,EAAe,MAAQ,IAC1DE,GAAO,OAAOF,EAAe,MAAS,SACtCA,EAAe,KACfA,EAAe,KAAO,UAAa,QAAQ,IAAI,MAAQ,UAEvDG,EAAM,IAAIR,GAEhBQ,EAAI,IAAI,KAAMT,GAAY,CACtB,KAAM,gBACN,QAAS,CAACe,EAAOC,IAAM,CACnBA,EAAE,OAAO,gBAAiBD,EAAM,SAAS,UAAU,EAC7C,sCACA,UAAU,CACpB,CACJ,CAAC,CAAC,EAEET,EAAe,SAAW,SAC1B,QAAQ,IAAI,yEAAoE,GAEhFW,EAAkBR,EAAK,CAAC,aAAAN,EAAc,UAAAC,EAAW,SAAAC,CAAQ,CAAC,EAC1Da,GAAiBT,EAAK,CAAC,aAAAN,EAAc,UAAAC,EAAW,SAAAC,EAAU,cAAeC,EAAe,aAAa,CAAC,GAG1GP,GAAM,CAAC,MAAOU,EAAI,MAAO,KAAAF,GAAM,SAAUC,EAAI,EAAIW,GAAS,QAAQ,IAAI,UAAUA,EAAK,OAAO,IAAIA,EAAK,IAAI,EAAE,CAAC,IClD5G,OAAQ,gBAAAC,OAAmB,UAC3B,OAAQ,QAAAC,GAAM,WAAAC,OAAc,YAC5B,OAAQ,iBAAAC,OAAoB,WAE5B,IAAMC,GAAU,QAAQ,KAAK,CAAC,EAE9B,OAAQA,GAAS,CACb,IAAK,MACD,KAAM,mBACN,MACJ,IAAK,QACD,KAAM,kBACN,MACJ,IAAK,WACD,KAAM,mBACN,MACJ,IAAK,QACD,KAAM,mBACN,MACJ,IAAK,YACL,IAAK,KAAM,CACP,IAAMC,EAAM,KAAK,MAAML,GAAaC,GAAKC,GAAQC,GAAc,YAAY,GAAG,CAAC,EAAG,oBAAoB,EAAG,OAAO,CAAC,EACjH,QAAQ,IAAIE,EAAI,OAAO,EACvB,KACJ,CACA,IAAK,SACL,IAAK,KACD,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAgBV,KAAK,CAAC,EACR,MACJ,QACI,QAAQ,MAAM,oBAAoBD,EAAO,EAAE,EAC3C,QAAQ,MAAM,yCAAyC,EACvD,QAAQ,KAAK,CAAC,CACtB",
|
|
4
|
+
"sourcesContent": ["interface EntryClientOptions {\n cssUrls: string[]\n}\n\nexport function generateEntryClient({cssUrls}: EntryClientOptions): string {\n const cssImports = cssUrls.map(u => `import '${u}'`).join('\\n')\n\n return `\n${cssImports}\nimport \"@vitejs/plugin-react/preamble\"\nimport React from \"react\"\nimport {hydrateRoot, createRoot} from 'react-dom/client'\nimport {matchClientRoute, loadErrorPage, getDefaultErrorPage} from 'virtual:devix/client-routes'\nimport {RouterProvider} from '@devlusoft/devix'\n\nconst root = document.getElementById('devix-root')\n\nif (!window.__DEVIX__) {\n const ErrorPage = getDefaultErrorPage()\n createRoot(root).render(React.createElement(ErrorPage, {statusCode: 500, message: 'Server error'}))\n} else {\n const {metadata, viewport, clientEntry} = window.__DEVIX__\n const loaderData = window.__LOADER_DATA__\n const layoutsData = window.__LAYOUTS_DATA__ ?? []\n\n const matched = matchClientRoute(window.location.pathname)\n\n if (matched) {\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n hydrateRoot(\n root,\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: loaderData,\n initialParams: matched.params,\n initialPage: pageMod.default,\n initialLayouts: layoutMods.map(m => m.default),\n initialLayoutsData: layoutsData,\n initialMeta: metadata,\n initialViewport: viewport,\n })\n )\n } else {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n createRoot(root).render(\n React.createElement(RouterProvider, {\n clientEntry,\n initialData: null,\n initialParams: {},\n initialPage: () => null,\n initialLayouts: [],\n initialLayoutsData: [],\n initialMeta: null,\n initialError: {statusCode: 404, message: 'Not found'},\n initialErrorPage: ErrorPage,\n })\n )\n }\n}\n`\n}", "interface ClientRoutesOptions {\n pagesDir: string\n matcherPath: string\n}\n\nexport function generateClientRoutes({pagesDir, matcherPath}: ClientRoutesOptions) {\n return `\nimport React from 'react'\nimport { createMatcher } from '${matcherPath}'\nconst pageFiles = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst layoutFiles = import.meta.glob('/${pagesDir}/**/layout.tsx')\nconst errorFiles = import.meta.glob('/${pagesDir}/**/error.tsx')\n\nexport const matchClientRoute = createMatcher(pageFiles, layoutFiles)\n\nexport async function loadErrorPage() {\n const key = Object.keys(errorFiles)[0]\n if (!key) return null\n const mod = await errorFiles[key]()\n return mod?.default ?? null\n}\n\nexport function getDefaultErrorPage() {\n return function DefaultError({ statusCode, message }) {\n return React.createElement('main', {\n style: { minHeight: '100dvh', display: 'flex', flexDirection: 'column', \n alignItems: 'center', justifyContent: 'center', gap: '8px',\n fontFamily: 'system-ui, sans-serif' }\n },\n React.createElement('h1', {style: {fontSize: '4rem', fontWeight: 700}}, statusCode),\n React.createElement('p', {style: {color: '#666'}}, message ?? 'An unexpected error occurred'),\n )\n }\n}\n`\n}", "interface RenderOptions {\n pagesDir: string\n renderPath: string\n}\n\nexport function generateRender({pagesDir, renderPath}: RenderOptions): string {\n return `\nimport { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${renderPath}'\n\nconst _pages = import.meta.glob(['/${pagesDir}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])\nconst _layouts = import.meta.glob('/${pagesDir}/**/layout.tsx')\n\nconst _glob = {\n pages: _pages,\n layouts: _layouts,\n pagesDir: '/${pagesDir}',\n}\n\nexport function render(url, request, options) {\n return _render(url, request, _glob, options)\n}\n\nexport function runLoader(url, request, options) {\n return _runLoader(url, request, _glob, options)\n}\n\nexport function getStaticRoutes() {\n return _getStaticRoutes(_glob)\n}\n`\n}\n", "interface ApiOptions {\n apiPath: string\n appDir: string\n}\n\nexport function generateApi({apiPath, appDir}: ApiOptions): string {\n return `\nimport { handleApiRequest as _handleApiRequest } from '${apiPath}'\n\nconst _routes = import.meta.glob(['/${appDir}/api/**/*.ts', '!**/middleware.ts'])\nconst _middlewares = import.meta.glob('/${appDir}/api/**/middleware.ts')\n\nconst _glob = {\n routes: _routes,\n middlewares: _middlewares,\n apiDir: '/${appDir}/api',\n}\n\nexport function handleApiRequest(url, request) {\n return _handleApiRequest(url, request, _glob)\n}\n`\n}\n", "export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface Page {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface Layout {\n dir: string\n key: string\n}\n\nexport interface PagesResult {\n pages: Page[]\n layouts: Layout[]\n}\n\nfunction keyToRoutePattern(key: string, pagesDir: string): string {\n const rel = key.slice(pagesDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === \"/\" ? \"/\" : `/${pattern}`\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: PagesResult | null = null\n\nexport function invalidatePagesCache() {\n cache = null\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n if (cache) return cache\n\n const pages: Page[] = []\n const layouts: Layout[] = []\n\n for (const key of layoutKeys) {\n layouts.push({dir: keyToDir(key), key})\n }\n\n for (const key of pageKeys) {\n const pattern = keyToRoutePattern(key, pagesDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n pages.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n\n pages.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {pages, layouts}\n return cache\n}\n\nexport function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[] {\n const pageDir = keyToDir(pageKey)\n\n return layouts\n .filter(layout => pageDir.startsWith(layout.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchPage(pathname: string, pages: Page[]): {\n page: Page\n params: Record<string, string>\n} | null {\n for (const page of pages) {\n const match = pathname.match(page.regex)\n if (match) {\n const params: Record<string, string> = {}\n page.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {page, params}\n }\n }\n return null\n}\n", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: ApiResult | null = null\n\nexport function invalidateApiCache() {\n cache = null\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n if (cache) return cache\n\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {routes, middlewares}\n return cache\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): {route: ApiRoute; params: Record<string, string>} | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "export function generateContext(): string {\n return `\nexport {RouterContext} from '@devlusoft/devix/runtime/context'\n`\n}", "const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const\nexport type HttpMethod = (typeof HTTP_METHODS)[number]\n\nconst METHOD_EXPORT_RE = /export\\s+(?:const|async\\s+function|function)\\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b/g\n\nfunction stripComments(content: string): string {\n return content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/.*$/gm, '')\n}\n\nexport function extractHttpMethods(content: string): HttpMethod[] {\n const found = new Set<HttpMethod>()\n for (const match of stripComments(content).matchAll(METHOD_EXPORT_RE)) {\n found.add(match[1] as HttpMethod)\n }\n return [...found]\n}\n", "import { keyToRoutePattern } from '../../server/api-router'\nimport type { HttpMethod } from './extract-methods'\n\nexport interface RouteEntry {\n filePath: string\n urlPattern: string\n identifier: string\n methods: HttpMethod[]\n}\n\nexport function filePathToIdentifier(filePath: string, apiDir: string): string {\n return '_api_' + filePath\n .slice(`${apiDir}/`.length)\n .replace(/\\.(ts|tsx)$/, '')\n .replace(/[^a-zA-Z0-9]/g, '_')\n}\n\nexport function buildRouteEntry(filePath: string, apiDir: string, methods: HttpMethod[]): RouteEntry {\n return {\n filePath,\n urlPattern: keyToRoutePattern(filePath, apiDir),\n identifier: filePathToIdentifier(filePath, apiDir),\n methods,\n }\n}\n\nexport function generateRoutesDts(entries: RouteEntry[], apiDir: string): string {\n if (entries.length === 0) {\n return `// auto-generado por devix \u2014 no editar\\ndeclare module '@devlusoft/devix' {\\n interface ApiRoutes {}\\n}\\n`\n }\n\n const imports = entries\n .map(e => {\n const importPath = '../' + e.filePath.replace(/\\.(ts|tsx)$/, '')\n return `import type * as ${e.identifier} from '${importPath}'`\n })\n .join('\\n')\n\n const routeLines = entries.flatMap(e =>\n e.methods.map(m =>\n ` '${m} ${e.urlPattern}': InferRoute<(typeof ${e.identifier})['${m}']>`\n )\n ).join('\\n')\n\n return `// auto-generado por devix \u2014 no editar\n${imports}\n\ntype JsonResponse<T> = Response & { readonly __body: T }\ntype UnwrapJson<T> = T extends JsonResponse<infer U> ? U : never\ntype InferFnReturn<T> = T extends (...args: any[]) => any\n ? [UnwrapJson<Awaited<ReturnType<T>>>] extends [never]\n ? Exclude<Awaited<ReturnType<T>>, Response | null | void>\n : UnwrapJson<Awaited<ReturnType<T>>>\n : never\ntype InferRoute<T> =\n T extends { readonly __return?: infer TReturn; readonly __body?: infer TBody }\n ? {\n __body: [TBody] extends [undefined] ? never : Exclude<TBody, undefined>\n __response: InferFnReturn<() => TReturn>\n }\n : InferFnReturn<T>\n\ndeclare module '@devlusoft/devix' {\n interface ApiRoutes {\n${routeLines}\n }\n}\n`\n}\n", "import {readFileSync, readdirSync, statSync} from 'node:fs'\nimport {join, relative} from 'node:path'\nimport {extractHttpMethods} from './extract-methods'\nimport {buildRouteEntry} from './routes-dts'\nimport type {RouteEntry} from './routes-dts'\n\nfunction walkDir(dir: string, root: string): string[] {\n const entries: string[] = []\n for (const name of readdirSync(dir)) {\n const full = join(dir, name)\n if (statSync(full).isDirectory()) {\n entries.push(...walkDir(full, root))\n } else if (/\\.(ts|tsx)$/.test(name)) {\n entries.push(relative(root, full).replace(/\\\\/g, '/'))\n }\n }\n return entries\n}\n\nexport function scanApiFiles(appDir: string, projectRoot: string): RouteEntry[] {\n const apiDir = join(projectRoot, appDir, 'api')\n\n let files: string[]\n try {\n files = walkDir(apiDir, projectRoot)\n } catch {\n return []\n }\n\n return files\n .filter(f => !f.endsWith('middleware.ts') && !f.endsWith('middleware.tsx'))\n .flatMap(filePath => {\n try {\n const content = readFileSync(join(projectRoot, filePath), 'utf-8')\n const methods = extractHttpMethods(content)\n if (methods.length === 0) return []\n return [buildRouteEntry(filePath, `${appDir}/api`, methods)]\n } catch {\n return []\n }\n })\n}\n", "import {mkdirSync, readFileSync, writeFileSync, existsSync} from 'node:fs'\nimport {join} from 'node:path'\n\nexport function writeRoutesDts(content: string, projectRoot: string): boolean {\n const devixDir = join(projectRoot, '.devix')\n const outPath = join(devixDir, 'routes.d.ts')\n\n mkdirSync(devixDir, {recursive: true})\n\n if (existsSync(outPath) && readFileSync(outPath, 'utf-8') === content) {\n return false\n }\n\n writeFileSync(outPath, content, 'utf-8')\n return true\n}\n", "import {UserConfig, Plugin, mergeConfig} from 'vite'\nimport type {DevixConfig} from '../config'\nimport react from '@vitejs/plugin-react'\nimport {fileURLToPath} from 'node:url'\nimport {dirname, resolve} from 'node:path'\nimport {generateEntryClient} from './codegen/entry-client'\nimport {generateClientRoutes} from './codegen/client-routes'\nimport {generateRender} from './codegen/render'\nimport {generateApi} from './codegen/api'\nimport {invalidatePagesCache} from \"../server/pages-router\";\nimport {invalidateApiCache} from \"../server/api-router\";\nimport {generateContext} from \"./codegen/context\";\nimport {scanApiFiles} from \"./codegen/scan-api\";\nimport {generateRoutesDts} from \"./codegen/routes-dts\";\nimport {writeRoutesDts} from \"./codegen/write-routes-dts\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nconst VIRTUAL_ENTRY_CLIENT = 'virtual:devix/entry-client'\nconst VIRTUAL_CLIENT_ROUTES = 'virtual:devix/client-routes'\nconst VIRTUAL_RENDER = 'virtual:devix/render'\nconst VIRTUAL_API = 'virtual:devix/api'\nconst VIRTUAL_CONTEXT = 'virtual:devix/context'\n\nexport function devix(config: DevixConfig): UserConfig {\n const appDir = config.appDir ?? 'app'\n const pagesDir = `${appDir}/pages`\n const cssUrls = (config.css ?? []).map(u => u.startsWith('/') ? u : `/${u.replace(/^\\.\\//, '')}`)\n\n const renderPath = resolve(__dirname, '../server/render.js').replace(/\\\\/g, '/')\n const apiPath = resolve(__dirname, '../server/api.js').replace(/\\\\/g, '/')\n const matcherPath = resolve(__dirname, '../runtime/client-router.js').replace(/\\\\/g, '/')\n\n const virtualPlugin: Plugin = {\n name: 'devix',\n enforce: 'pre',\n\n resolveId(id) {\n if (id === VIRTUAL_ENTRY_CLIENT) return `\\0${VIRTUAL_ENTRY_CLIENT}`\n if (id === VIRTUAL_CLIENT_ROUTES) return `\\0${VIRTUAL_CLIENT_ROUTES}`\n if (id === VIRTUAL_RENDER) return `\\0${VIRTUAL_RENDER}`\n if (id === VIRTUAL_API) return `\\0${VIRTUAL_API}`\n if (id === VIRTUAL_CONTEXT) return `\\0${VIRTUAL_CONTEXT}`\n },\n\n load(id) {\n if (id === `\\0${VIRTUAL_ENTRY_CLIENT}`)\n return generateEntryClient({cssUrls})\n if (id === `\\0${VIRTUAL_CLIENT_ROUTES}`)\n return generateClientRoutes({pagesDir, matcherPath})\n if (id === `\\0${VIRTUAL_RENDER}`)\n return generateRender({pagesDir, renderPath})\n if (id === `\\0${VIRTUAL_API}`)\n return generateApi({apiPath, appDir})\n if (id === `\\0${VIRTUAL_CONTEXT}`)\n return generateContext()\n },\n\n buildStart() {\n const root = process.cwd()\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n },\n\n configureServer(server) {\n const root = process.cwd()\n\n const regenerateDts = () => {\n const entries = scanApiFiles(appDir, root)\n writeRoutesDts(generateRoutesDts(entries, `${appDir}/api`), root)\n }\n\n server.watcher.on('add', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('unlink', (file) => {\n if (file.startsWith(resolve(root, pagesDir))) invalidatePagesCache()\n if (file.includes(`${appDir}/api`)) { invalidateApiCache(); regenerateDts() }\n })\n server.watcher.on('change', (file) => {\n if (file.includes(`${appDir}/api`) && !file.endsWith('middleware.ts')) {\n regenerateDts()\n }\n })\n },\n }\n\n const base: UserConfig = {\n plugins: [react(), virtualPlugin],\n ssr: {noExternal: ['@devlusoft/devix']},\n ...(config.envPrefix ? {envPrefix: config.envPrefix} : {}),\n }\n\n return mergeConfig(base, config.vite ?? {})\n}", "import type {Hono} from 'hono'\nimport type {Manifest} from 'vite'\n\ninterface ServerOptions {\n renderModule: any\n apiModule: any\n manifest?: Manifest\n loaderTimeout?: number\n}\n\nexport function registerApiRoutes(app: Hono, {apiModule, renderModule, loaderTimeout}: ServerOptions) {\n app.all('/api/*', async (c) => {\n try {\n return await apiModule.handleApiRequest(c.req.url, c.req.raw)\n } catch (e) {\n console.error(e)\n return c.json({error: 'internal error'}, 500)\n }\n })\n\n app.get('/_data/*', async (c) => {\n try {\n const {pathname, search} = new URL(c.req.url, 'http://localhost')\n const url = pathname.replace(/^\\/_data/, '') + search\n\n const data = await renderModule.runLoader(url, c.req.raw, {loaderTimeout})\n return c.json(data)\n } catch (e) {\n console.error(e)\n return c.json({error: 'internal error'}, 500)\n }\n })\n}\n\nexport function registerSsrRoute(app: Hono, {renderModule, manifest, loaderTimeout}: ServerOptions) {\n app.get('*', async (c) => {\n try {\n const {html, statusCode, headers} = await renderModule.render(c.req.url, c.req.raw, {manifest, loaderTimeout})\n const res = c.html(`<!DOCTYPE html>${html}`, statusCode)\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n res.headers.set(key, value)\n }\n return res\n } catch (e) {\n console.error(e)\n return c.text('Internal Server Error', 500)\n }\n })\n}", "import pc from 'picocolors'\nimport {networkInterfaces} from 'node:os'\nimport {createRequire} from 'node:module'\n\nfunction getNetworkUrl(port: number): string | null {\n const nets = networkInterfaces()\n for (const interfaces of Object.values(nets)) {\n for (const net of interfaces ?? []) {\n if (net.family === 'IPv4' && !net.internal) {\n return `http://${net.address}:${port}/`\n }\n }\n }\n return null\n}\n\nexport function printDevBanner(port: number) {\n const req = createRequire(import.meta.url)\n const version = req('../../package.json').version\n const networkUrl = getNetworkUrl(port)\n\n console.log()\n console.log(` ${pc.bold(pc.yellow('devix'))} ${pc.dim(`v${version}`)}`)\n console.log()\n console.log(` ${pc.green('\u279C')} ${pc.bold('Local:')} ${pc.cyan(`http://localhost:${port}/`)}`)\n if (networkUrl) {\n console.log(` ${pc.green('\u279C')} ${pc.bold('Network:')} ${pc.cyan(networkUrl)}`)\n } else {\n console.log(` ${pc.green('\u279C')} ${pc.bold('Network:')} ${pc.dim('use --host to expose')}`)\n }\n console.log()\n}", "import type {ViteDevServer} from 'vite'\n\nexport async function collectCss(vite: ViteDevServer): Promise<string[]> {\n const cssUrls = new Set<string>()\n\n for (const [, mod] of vite.moduleGraph.idToModuleMap) {\n if (!mod.id) continue\n if (mod.id.endsWith('.css') || mod.id.includes('.css?')) {\n cssUrls.add(mod.url)\n }\n }\n\n return [...cssUrls]\n}", "export function parseDuration(value: number | string): number {\n if (typeof value === 'number') return value\n const match = value.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(ms|s|m|h)?$/)\n if (!match) throw new Error(`[devix] Invalid duration: \"${value}\". Use a number (ms) or a string like \"5s\", \"2m\", \"500ms\".`)\n const n = parseFloat(match[1])\n switch (match[2]) {\n case 'h': return n * 3_600_000\n case 'm': return n * 60_000\n case 's': return n * 1_000\n case 'ms':\n default: return n\n }\n}\n", "import {loadEnv} from 'vite'\n\nexport function loadDotenv(mode: string) {\n const env = loadEnv(mode, process.cwd(), '')\n for (const [key, value] of Object.entries(env)) {\n if (process.env[key] === undefined) {\n process.env[key] = value\n }\n }\n}\n", "import {createServer} from 'node:http'\nimport {createServer as createViteServer} from 'vite'\nimport {getRequestListener} from '@hono/node-server'\nimport {Hono} from 'hono'\nimport type {DevixConfig} from '../config'\nimport {devix} from '../vite'\nimport {registerApiRoutes} from '../server/routes'\nimport {printDevBanner} from \"../utils/banner\";\nimport {collectCss} from \"../server/collect-css\";\nimport {parseDuration} from \"../utils/duration\";\nimport {loadDotenv} from \"../utils/env\";\n\nloadDotenv('development')\n\nconst VIRTUAL_RENDER = 'virtual:devix/render'\nconst VIRTUAL_API = 'virtual:devix/api'\n\nconst config: DevixConfig = (await import(`${process.cwd()}/devix.config.ts`)).default\nconst port = Number(process.env.PORT) || config.port || 3000\nconst host = typeof config.host === 'string' ? config.host : config.host ? '0.0.0.0' : 'localhost'\n\nconst vite = await createViteServer({\n ...devix(config),\n configFile: false,\n appType: 'custom',\n server: {middlewareMode: true},\n})\n\nconst renderModule = {\n render: async (...args: any[]) => (await vite.ssrLoadModule(VIRTUAL_RENDER)).render(...args),\n runLoader: async (...args: any[]) => (await vite.ssrLoadModule(VIRTUAL_RENDER)).runLoader(...args),\n}\n\nconst apiModule = {\n handleApiRequest: async (...args: any[]) => (await vite.ssrLoadModule(VIRTUAL_API)).handleApiRequest(...args),\n}\n\nconst app = new Hono()\n\nregisterApiRoutes(app, {renderModule, apiModule})\n\napp.get('*', async (c) => {\n try {\n const {html, statusCode, headers} = await renderModule.render(c.req.url, c.req.raw, {loaderTimeout: parseDuration(config.loaderTimeout ?? 10_000)})\n\n const cssUrls = await collectCss(vite)\n const cssLinks = cssUrls.map(url => `<link rel=\"stylesheet\" href=\"${url}\">`).join('\\n')\n\n const htmlWithCss = cssLinks ? html.replace('</head>', `${cssLinks}\\n</head>`) : html\n const transformed = await vite.transformIndexHtml(c.req.url, `<!DOCTYPE html>${htmlWithCss}`)\n\n const res = c.html(transformed, statusCode)\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n res.headers.set(key, value)\n }\n return res\n } catch (e) {\n vite.ssrFixStacktrace(e as Error)\n console.error(e)\n return c.text('Internal Server Error', 500)\n }\n})\n\nconst honoHandler = getRequestListener(app.fetch)\n\ncreateServer(async (req, res) => {\n await new Promise<void>(resolve => vite.middlewares(req, res, resolve))\n if (!res.writableEnded) await honoHandler(req, res)\n}).listen(port, host, () => {\n printDevBanner(port)\n})\n\nexport {}", "import {writeFileSync} from 'node:fs'\nimport {resolve} from 'node:path'\nimport {build} from 'vite'\nimport type {DevixConfig} from '../config'\nimport {devix} from '../vite'\nimport {parseDuration} from '../utils/duration'\n\nconst config: DevixConfig = (await import(`${process.cwd()}/devix.config.ts`)).default\nconst baseConfig = devix(config)\n\nawait build({\n ...baseConfig,\n configFile: false,\n build: {\n outDir: 'dist/client',\n manifest: true,\n rolldownOptions: {\n input: 'virtual:devix/entry-client',\n },\n },\n})\n\nawait build({\n ...baseConfig,\n configFile: false,\n build: {\n ssr: true,\n outDir: 'dist/server',\n rolldownOptions: {\n input: {\n render: 'virtual:devix/render',\n api: 'virtual:devix/api',\n },\n },\n },\n})\n\nconst runtimeConfig = {\n port: config.port ?? 3000,\n host: config.host ?? false,\n loaderTimeout: parseDuration(config.loaderTimeout ?? 10_000),\n output: config.output ?? 'server',\n}\n\nwriteFileSync(\n resolve(process.cwd(), 'dist/devix.config.json'),\n JSON.stringify(runtimeConfig, null, 2),\n 'utf-8'\n)\n\n\nexport {}", "import {readFileSync, mkdirSync, writeFileSync} from 'node:fs'\nimport {resolve, join} from 'node:path'\nimport type {Manifest} from 'vite'\nimport type {DevixConfig} from '../config'\n\nconst userConfig: DevixConfig = (await import(`${process.cwd()}/devix.config.ts`)).default\nif (userConfig.output !== 'static') {\n console.warn('[devix] Tip: set output: \"static\" in devix.config.ts to skip the SSR server at runtime.')\n}\n\nawait import('./build.js')\n\nconst t = Date.now()\nconst renderModule = await import(resolve(process.cwd(), 'dist/server/render.js') + `?t=${t}`)\n\nconst manifest: Manifest = JSON.parse(\n readFileSync(resolve(process.cwd(), 'dist/client/.vite/manifest.json'), 'utf-8')\n)\n\nconst urls: string[] = await renderModule.getStaticRoutes()\n\nconsole.log(`[devix] Generating ${urls.length} static page${urls.length === 1 ? '' : 's'}...`)\n\nfor (const url of urls) {\n const fullUrl = `http://localhost${url}`\n const {html, statusCode} = await renderModule.render(fullUrl, new Request(fullUrl), {manifest})\n\n if (statusCode !== 200) {\n console.warn(`[devix] Skipping ${url} \u2014 status ${statusCode}`)\n continue\n }\n\n const outPath = url === '/'\n ? join(process.cwd(), 'dist/client/index.html')\n : join(process.cwd(), 'dist/client', url, 'index.html')\n\n mkdirSync(join(outPath, '..'), {recursive: true})\n writeFileSync(outPath, `<!DOCTYPE html>${html}`, 'utf-8')\n console.log(` \u2713 ${url}`)\n}\n\nconsole.log('[devix] Generation complete.')\n\nexport {}\n", "import {readFileSync} from 'node:fs'\nimport {serve} from '@hono/node-server'\nimport {serveStatic} from '@hono/node-server/serve-static'\nimport {Hono} from 'hono'\nimport {resolve} from 'node:path'\nimport type {Manifest} from 'vite'\nimport {registerApiRoutes, registerSsrRoute} from '../server/routes'\nimport {loadDotenv} from '../utils/env'\n\nloadDotenv('production')\n\nlet renderModule: any\nlet apiModule: any\nlet manifest: Manifest\nlet runtimeConfig: { port: number, host: string | boolean, loaderTimeout: number, output: 'server' | 'static' }\n\ntry {\n runtimeConfig = JSON.parse(readFileSync(resolve(process.cwd(), 'dist/devix.config.json'), 'utf-8'))\n if (runtimeConfig.output !== 'static') {\n renderModule = await import(resolve(process.cwd(), 'dist/server/render.js'))\n apiModule = await import(resolve(process.cwd(), 'dist/server/api.js'))\n }\n manifest = JSON.parse(readFileSync(resolve(process.cwd(), 'dist/client/.vite/manifest.json'), 'utf-8'))\n} catch {\n console.error('[devix] Build not found. Run \"devix build\" first.')\n process.exit(1)\n}\n\nconst port = Number(process.env.PORT) || runtimeConfig!.port || 3000\nconst host = typeof runtimeConfig!.host === 'string'\n ? runtimeConfig!.host\n : runtimeConfig!.host ? '0.0.0.0' : (process.env.HOST || '0.0.0.0')\n\nconst app = new Hono()\n\napp.use('/*', serveStatic({\n root: './dist/client',\n onFound: (_path, c) => {\n c.header('Cache-Control', _path.includes('/assets/')\n ? 'public, immutable, max-age=31536000'\n : 'no-cache')\n }\n}))\n\nif (runtimeConfig!.output === 'static') {\n console.log('[devix] Static mode \u2014 serving pre-generated files from dist/client')\n} else {\n registerApiRoutes(app, {renderModule, apiModule, manifest})\n registerSsrRoute(app, {renderModule, apiModule, manifest, loaderTimeout: runtimeConfig!.loaderTimeout})\n}\n\nserve({fetch: app.fetch, port, hostname: host}, (info) => console.log(`http://${info.address}:${info.port}`))\n\nexport {}", "#!/usr/bin/env node\nimport {readFileSync} from 'node:fs'\nimport {join, dirname} from 'node:path'\nimport {fileURLToPath} from 'node:url'\n\nconst command = process.argv[2]\n\nswitch (command) {\n case 'dev':\n await import(\"./dev.js\")\n break\n case \"build\":\n await import(\"./build.js\")\n break\n case \"generate\":\n await import(\"./generate.js\")\n break\n case \"start\":\n await import(\"./start.js\")\n break\n case '--version':\n case '-v': {\n const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../../package.json'), 'utf-8'))\n console.log(pkg.version)\n break\n }\n case '--help':\n case '-h':\n console.log(`\ndevix \u2014 a lightweight SSR framework\n\nUsage:\n devix dev Start development server\n devix build Build for production\n devix generate Build and generate static HTML (SSG)\n devix start Start production server\n\nOptions:\n -v, --version Show version\n -h, --help Show this help\n\nOutput modes (set in devix.config.ts):\n output: \"server\" SSR mode \u2014 devix start handles requests dynamically (default)\n output: \"static\" SSG mode \u2014 devix generate pre-renders all pages; devix start serves static files only\n `.trim())\n break\n default:\n console.error(`Unknown command: ${command}`)\n console.error('Usage: devix <dev|build|generate|start>')\n process.exit(1)\n}\n\nexport {}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["generateEntryClient", "cssUrls", "u", "init_entry_client", "__esmMin", "generateClientRoutes", "pagesDir", "matcherPath", "init_client_routes", "__esmMin", "generateRender", "pagesDir", "renderPath", "init_render", "__esmMin", "generateApi", "apiPath", "appDir", "init_api", "__esmMin", "routePattern", "rel", "init_patterns", "__esmMin", "invalidatePagesCache", "cache", "init_pages_router", "__esmMin", "init_patterns", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "invalidateApiCache", "cache", "init_api_router", "__esmMin", "init_patterns", "generateContext", "init_context", "__esmMin", "stripComments", "content", "extractHttpMethods", "found", "match", "METHOD_EXPORT_RE", "init_extract_methods", "__esmMin", "filePathToIdentifier", "filePath", "apiDir", "buildRouteEntry", "methods", "keyToRoutePattern", "generateRoutesDts", "entries", "imports", "e", "importPath", "routeLines", "m", "init_routes_dts", "__esmMin", "init_api_router", "readFileSync", "readdirSync", "statSync", "join", "relative", "walkDir", "dir", "root", "entries", "name", "full", "scanApiFiles", "appDir", "projectRoot", "apiDir", "files", "f", "filePath", "content", "methods", "extractHttpMethods", "buildRouteEntry", "init_scan_api", "__esmMin", "init_extract_methods", "init_routes_dts", "mkdirSync", "readFileSync", "writeFileSync", "existsSync", "join", "writeRoutesDts", "content", "projectRoot", "devixDir", "outPath", "init_write_routes_dts", "__esmMin", "mergeConfig", "react", "fileURLToPath", "dirname", "resolve", "devix", "config", "appDir", "pagesDir", "cssUrls", "u", "renderPath", "__dirname", "apiPath", "matcherPath", "virtualPlugin", "id", "VIRTUAL_ENTRY_CLIENT", "VIRTUAL_CLIENT_ROUTES", "VIRTUAL_RENDER", "VIRTUAL_API", "VIRTUAL_CONTEXT", "generateEntryClient", "generateClientRoutes", "generateRender", "generateApi", "generateContext", "root", "entries", "scanApiFiles", "writeRoutesDts", "generateRoutesDts", "server", "regenerateDts", "file", "invalidatePagesCache", "invalidateApiCache", "base", "init_vite", "__esmMin", "init_entry_client", "init_client_routes", "init_render", "init_api", "init_pages_router", "init_api_router", "init_context", "init_scan_api", "init_routes_dts", "init_write_routes_dts", "registerApiRoutes", "app", "apiModule", "renderModule", "loaderTimeout", "c", "e", "pathname", "search", "url", "data", "registerSsrRoute", "manifest", "html", "statusCode", "headers", "res", "key", "value", "init_routes", "__esmMin", "pc", "networkInterfaces", "createRequire", "getNetworkUrl", "port", "nets", "interfaces", "net", "printDevBanner", "version", "networkUrl", "init_banner", "__esmMin", "collectCss", "vite", "cssUrls", "mod", "init_collect_css", "__esmMin", "parseDuration", "value", "match", "n", "init_duration", "__esmMin", "loadEnv", "loadDotenv", "mode", "env", "key", "value", "init_env", "__esmMin", "dev_exports", "createServer", "createViteServer", "getRequestListener", "Hono", "VIRTUAL_RENDER", "VIRTUAL_API", "config", "port", "host", "vite", "renderModule", "apiModule", "app", "honoHandler", "init_dev", "__esmMin", "init_vite", "init_routes", "init_banner", "init_collect_css", "init_duration", "init_env", "loadDotenv", "devix", "args", "registerApiRoutes", "c", "html", "statusCode", "headers", "parseDuration", "cssLinks", "collectCss", "url", "htmlWithCss", "transformed", "res", "key", "value", "e", "req", "resolve", "printDevBanner", "build_exports", "writeFileSync", "resolve", "build", "config", "baseConfig", "runtimeConfig", "init_build", "__esmMin", "init_vite", "init_duration", "devix", "parseDuration", "generate_exports", "readFileSync", "mkdirSync", "writeFileSync", "resolve", "join", "userConfig", "t", "renderModule", "manifest", "urls", "init_generate", "__esmMin", "url", "fullUrl", "html", "statusCode", "outPath", "start_exports", "readFileSync", "serve", "serveStatic", "Hono", "resolve", "renderModule", "apiModule", "manifest", "runtimeConfig", "port", "host", "app", "init_start", "__esmMin", "init_routes", "init_env", "loadDotenv", "_path", "c", "registerApiRoutes", "registerSsrRoute", "info", "readFileSync", "join", "dirname", "fileURLToPath", "command", "pkg"]
|
|
7
7
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DevixHandler } from './create-handler';
|
|
1
2
|
export declare class RouteContext {
|
|
2
3
|
readonly params: Record<string, string>;
|
|
3
4
|
private _state;
|
|
@@ -10,12 +11,14 @@ export type RouteHandler = (ctx: RouteContext, req: Request) => Promise<RouteRes
|
|
|
10
11
|
export interface MiddlewareModule {
|
|
11
12
|
middleware: (ctx: RouteContext, req: Request) => Promise<Response | null> | Response | null;
|
|
12
13
|
}
|
|
14
|
+
type AnyHandler = RouteHandler | DevixHandler<any, any>;
|
|
13
15
|
export interface RouteModule {
|
|
14
|
-
GET?:
|
|
15
|
-
POST?:
|
|
16
|
-
PUT?:
|
|
17
|
-
PATCH?:
|
|
18
|
-
DELETE?:
|
|
19
|
-
HEAD?:
|
|
20
|
-
OPTIONS?:
|
|
16
|
+
GET?: AnyHandler;
|
|
17
|
+
POST?: AnyHandler;
|
|
18
|
+
PUT?: AnyHandler;
|
|
19
|
+
PATCH?: AnyHandler;
|
|
20
|
+
DELETE?: AnyHandler;
|
|
21
|
+
HEAD?: AnyHandler;
|
|
22
|
+
OPTIONS?: AnyHandler;
|
|
21
23
|
}
|
|
24
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var n=class{params;_state=new Map;constructor(e={}){this.params=e}set(e,t){this._state.set(e,t)}get(e){return this._state.get(e)}};export{n as RouteContext};
|
|
2
2
|
//# sourceMappingURL=api-context.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/runtime/api-context.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type {DevixHandler} from './create-handler'\n\nexport class RouteContext {\n readonly params: Record<string, string>\n private _state = new Map<string, unknown>()\n\n constructor(params: Record<string, string> = {}) {\n this.params = params\n }\n\n set<T>(key: string, value: T): void {\n this._state.set(key, value)\n }\n\n get<T>(key: string): T | undefined {\n return this._state.get(key) as T\n }\n}\n\nexport type RouteResult = Response | Record<string, unknown> | unknown[] | null | void\n\nexport type RouteHandler = (ctx: RouteContext, req: Request) => Promise<RouteResult> | RouteResult\n\nexport interface MiddlewareModule {\n middleware: (ctx: RouteContext, req: Request) => Promise<Response | null> | Response | null\n}\n\ntype AnyHandler = RouteHandler | DevixHandler<any, any>\n\nexport interface RouteModule {\n GET?: AnyHandler\n POST?: AnyHandler\n PUT?: AnyHandler\n PATCH?: AnyHandler\n DELETE?: AnyHandler\n HEAD?: AnyHandler\n OPTIONS?: AnyHandler\n}\n"],
|
|
5
|
+
"mappings": "AAEO,IAAMA,EAAN,KAAmB,CACb,OACD,OAAS,IAAI,IAErB,YAAYC,EAAiC,CAAC,EAAG,CAC7C,KAAK,OAASA,CAClB,CAEA,IAAOC,EAAaC,EAAgB,CAChC,KAAK,OAAO,IAAID,EAAKC,CAAK,CAC9B,CAEA,IAAOD,EAA4B,CAC/B,OAAO,KAAK,OAAO,IAAIA,CAAG,CAC9B,CACJ",
|
|
6
6
|
"names": ["RouteContext", "params", "key", "value"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RouteResult } from './api-context';
|
|
2
|
+
export declare const HANDLER_BRAND: "__devix_handler__";
|
|
3
|
+
export interface DevixHandler<TBody = undefined, TReturn = RouteResult> {
|
|
4
|
+
readonly [HANDLER_BRAND]: true;
|
|
5
|
+
readonly fn: (...args: any[]) => any;
|
|
6
|
+
readonly __body?: TBody;
|
|
7
|
+
readonly __return?: TReturn;
|
|
8
|
+
}
|
|
9
|
+
export declare function createHandler<TReturn extends RouteResult = RouteResult>(fn: () => Promise<TReturn> | TReturn): DevixHandler<undefined, TReturn>;
|
|
10
|
+
export declare function createHandler<TBody, TReturn extends RouteResult = RouteResult>(fn: (body: TBody) => Promise<TReturn> | TReturn): DevixHandler<TBody, TReturn>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/runtime/create-handler.ts"],
|
|
4
|
+
"sourcesContent": ["import type {RouteResult} from './api-context'\n\nexport const HANDLER_BRAND = '__devix_handler__' as const\n\nexport interface DevixHandler<TBody = undefined, TReturn = RouteResult> {\n readonly [HANDLER_BRAND]: true\n readonly fn: (...args: any[]) => any\n readonly __body?: TBody\n readonly __return?: TReturn\n}\n\nexport function createHandler<TReturn extends RouteResult = RouteResult>(\n fn: () => Promise<TReturn> | TReturn,\n): DevixHandler<undefined, TReturn>\n\nexport function createHandler<TBody, TReturn extends RouteResult = RouteResult>(\n fn: (body: TBody) => Promise<TReturn> | TReturn,\n): DevixHandler<TBody, TReturn>\n\nexport function createHandler(fn: (...args: any[]) => any): DevixHandler<any, any> {\n return {[HANDLER_BRAND]: true, fn}\n}\n"],
|
|
5
|
+
"mappings": "AAEO,IAAMA,EAAgB,oBAiBtB,SAASC,EAAcC,EAAqD,CAC/E,MAAO,CAAC,CAACF,CAAa,EAAG,GAAM,GAAAE,CAAE,CACrC",
|
|
6
|
+
"names": ["HANDLER_BRAND", "createHandler", "fn"]
|
|
7
|
+
}
|
package/dist/runtime/fetch.d.ts
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
export interface ApiRoutes {
|
|
2
2
|
}
|
|
3
3
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
4
|
-
|
|
4
|
+
type ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`;
|
|
5
|
+
type RouteData<M extends HttpMethod, P extends string> = ApiKey<M, P> extends keyof ApiRoutes ? ApiRoutes[ApiKey<M, P>] : unknown;
|
|
6
|
+
type ExtractBody<D> = D extends {
|
|
7
|
+
__body: infer B;
|
|
8
|
+
} ? B : never;
|
|
9
|
+
type ExtractResponse<D> = D extends {
|
|
10
|
+
__response: infer R;
|
|
11
|
+
} ? R : D;
|
|
12
|
+
type InferBody<M extends HttpMethod, P extends string> = ExtractBody<RouteData<M, P>>;
|
|
13
|
+
type InferResult<M extends HttpMethod, P extends string> = ExtractResponse<RouteData<M, P>>;
|
|
14
|
+
type BodyOption<M extends HttpMethod, P extends string> = [
|
|
15
|
+
InferBody<M, P>
|
|
16
|
+
] extends [never] ? unknown : InferBody<M, P>;
|
|
17
|
+
export interface FetchOptions<M extends HttpMethod = 'GET', P extends string = string> {
|
|
5
18
|
method?: M;
|
|
6
|
-
body?:
|
|
19
|
+
body?: BodyOption<M, P>;
|
|
7
20
|
headers?: HeadersInit;
|
|
8
21
|
signal?: AbortSignal;
|
|
9
22
|
}
|
|
10
|
-
type ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`;
|
|
11
|
-
type InferResult<M extends HttpMethod, P extends string> = ApiKey<M, P> extends keyof ApiRoutes ? ApiRoutes[ApiKey<M, P>] : unknown;
|
|
12
23
|
export declare class FetchError extends Error {
|
|
13
24
|
readonly status: number;
|
|
14
25
|
readonly statusText: string;
|
|
15
26
|
readonly response: Response;
|
|
16
27
|
constructor(status: number, statusText: string, response: Response);
|
|
17
28
|
}
|
|
18
|
-
export declare function $fetch<P extends string, M extends HttpMethod = 'GET'>(path: P, options?: FetchOptions<M>): Promise<InferResult<M, P>>;
|
|
29
|
+
export declare function $fetch<P extends string, M extends HttpMethod = 'GET'>(path: P, options?: FetchOptions<M, P>): Promise<InferResult<M, P>>;
|
|
19
30
|
export {};
|
package/dist/runtime/fetch.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var r=class extends Error{constructor(s,n,o){super(`HTTP ${s}: ${n}`);this.status=s;this.statusText=n;this.response=o;this.name="FetchError"}};async function p(
|
|
1
|
+
var r=class extends Error{constructor(s,n,o){super(`HTTP ${s}: ${n}`);this.status=s;this.statusText=n;this.response=o;this.name="FetchError"}};async function p(d,t){let s=t?.method??"GET",n=new Headers(t?.headers),o;t?.body!==void 0&&(o=JSON.stringify(t.body),n.has("Content-Type")||n.set("Content-Type","application/json"));let e=await fetch(d,{method:s,headers:n,body:o,signal:t?.signal});if(!e.ok)throw new r(e.status,e.statusText,e);return(e.headers.get("Content-Type")??"").includes("application/json")?e.json():e.text()}export{p as $fetch,r as FetchError};
|
|
2
2
|
//# sourceMappingURL=fetch.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/runtime/fetch.ts"],
|
|
4
|
-
"sourcesContent": ["export interface ApiRoutes {}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["export interface ApiRoutes {}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\ntype ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`\n\ntype RouteData<M extends HttpMethod, P extends string> =\n ApiKey<M, P> extends keyof ApiRoutes ? ApiRoutes[ApiKey<M, P>] : unknown\n\ntype ExtractBody<D> = D extends {__body: infer B} ? B : never\ntype ExtractResponse<D> = D extends {__response: infer R} ? R : D\n\ntype InferBody<M extends HttpMethod, P extends string> = ExtractBody<RouteData<M, P>>\ntype InferResult<M extends HttpMethod, P extends string> = ExtractResponse<RouteData<M, P>>\n\ntype BodyOption<M extends HttpMethod, P extends string> =\n [InferBody<M, P>] extends [never] ? unknown : InferBody<M, P>\n\nexport interface FetchOptions<M extends HttpMethod = 'GET', P extends string = string> {\n method?: M\n body?: BodyOption<M, P>\n headers?: HeadersInit\n signal?: AbortSignal\n}\n\nexport class FetchError extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly response: Response,\n ) {\n super(`HTTP ${status}: ${statusText}`)\n this.name = 'FetchError'\n }\n}\n\nexport async function $fetch<\n P extends string,\n M extends HttpMethod = 'GET',\n>(path: P, options?: FetchOptions<M, P>): Promise<InferResult<M, P>> {\n const method = (options?.method ?? 'GET') as string\n const headers = new Headers(options?.headers)\n\n let body: BodyInit | undefined\n if (options?.body !== undefined) {\n body = JSON.stringify(options.body)\n if (!headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n }\n\n const response = await fetch(path, {method, headers, body, signal: options?.signal})\n\n if (!response.ok) {\n throw new FetchError(response.status, response.statusText, response)\n }\n\n const contentType = response.headers.get('Content-Type') ?? ''\n if (contentType.includes('application/json')) {\n return response.json() as Promise<InferResult<M, P>>\n }\n\n return response.text() as unknown as Promise<InferResult<M, P>>\n}\n"],
|
|
5
|
+
"mappings": "AAyBO,IAAMA,EAAN,cAAyB,KAAM,CAClC,YACoBC,EACAC,EACAC,EAClB,CACE,MAAM,QAAQF,CAAM,KAAKC,CAAU,EAAE,EAJrB,YAAAD,EACA,gBAAAC,EACA,cAAAC,EAGhB,KAAK,KAAO,YAChB,CACJ,EAEA,eAAsBC,EAGpBC,EAASC,EAA0D,CACjE,IAAMC,EAAUD,GAAS,QAAU,MAC7BE,EAAU,IAAI,QAAQF,GAAS,OAAO,EAExCG,EACAH,GAAS,OAAS,SAClBG,EAAO,KAAK,UAAUH,EAAQ,IAAI,EAC7BE,EAAQ,IAAI,cAAc,GAC3BA,EAAQ,IAAI,eAAgB,kBAAkB,GAItD,IAAML,EAAW,MAAM,MAAME,EAAM,CAAC,OAAAE,EAAQ,QAAAC,EAAS,KAAAC,EAAM,OAAQH,GAAS,MAAM,CAAC,EAEnF,GAAI,CAACH,EAAS,GACV,MAAM,IAAIH,EAAWG,EAAS,OAAQA,EAAS,WAAYA,CAAQ,EAIvE,OADoBA,EAAS,QAAQ,IAAI,cAAc,GAAK,IAC5C,SAAS,kBAAkB,EAChCA,EAAS,KAAK,EAGlBA,EAAS,KAAK,CACzB",
|
|
6
6
|
"names": ["FetchError", "status", "statusText", "response", "$fetch", "path", "options", "method", "headers", "body"]
|
|
7
7
|
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -9,3 +9,6 @@ export { json, text, redirect } from '../utils/response';
|
|
|
9
9
|
export type { JsonResponse } from '../utils/response';
|
|
10
10
|
export { $fetch, FetchError } from './fetch';
|
|
11
11
|
export type { ApiRoutes, FetchOptions } from './fetch';
|
|
12
|
+
export { createHandler } from './create-handler';
|
|
13
|
+
export type { DevixHandler } from './create-handler';
|
|
14
|
+
export { useRequest, useCtx } from '../server/handler-store';
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useCallback as
|
|
1
|
+
import{useCallback as V,useContext as M,useEffect as z,useRef as Q,useState as B}from"react";import{RouterContext as _}from"virtual:devix/context";import{getDefaultErrorPage as X,loadErrorPage as Y,matchClientRoute as Z}from"virtual:devix/client-routes";import{Fragment as J,jsx as T}from"react/jsx-runtime";function G(e,t){let r=[];e.title&&r.push({tag:"title",children:e.title}),e.description&&r.push({tag:"meta",name:"description",content:e.description}),e.keywords?.length&&r.push({tag:"meta",name:"keywords",content:e.keywords.join(", ")});let o=e.og?.title??e.title;o&&r.push({tag:"meta",property:"og:title",content:o});let a=e.og?.description??e.description;a&&r.push({tag:"meta",property:"og:description",content:a}),e.og?.image&&r.push({tag:"meta",property:"og:image",content:e.og.image}),e.og?.type&&r.push({tag:"meta",property:"og:type",content:e.og.type}),e.og?.url&&r.push({tag:"meta",property:"og:url",content:e.og.url});let s=e.twitter?.title??e.title;s&&r.push({tag:"meta",name:"twitter:title",content:s});let g=e.twitter?.description??e.description;if(g&&r.push({tag:"meta",name:"twitter:description",content:g}),e.twitter?.card&&r.push({tag:"meta",name:"twitter:card",content:e.twitter.card}),e.twitter?.image&&r.push({tag:"meta",name:"twitter:image",content:e.twitter.image}),e.twitter?.creator&&r.push({tag:"meta",name:"twitter:creator",content:e.twitter.creator}),e.canonical&&r.push({tag:"link",rel:"canonical",href:e.canonical}),e.robots&&r.push({tag:"meta",name:"robots",content:e.robots}),e.alternates)for(let[l,p]of Object.entries(e.alternates))r.push({tag:"link",rel:"alternate",href:p,hrefLang:l});if(t){let l=[];t.width!==void 0&&l.push(`width=${t.width}`),t.initialScale!==void 0&&l.push(`initial-scale=${t.initialScale}`),t.maximumScale!==void 0&&l.push(`maximum-scale=${t.maximumScale}`),t.userScalable!==void 0&&l.push(`user-scalable=${t.userScalable?"yes":"no"}`),l.length&&r.push({tag:"meta",name:"viewport",content:l.join(", ")}),t.themeColor&&r.push({tag:"meta",name:"theme-color",content:t.themeColor})}return r}function A(e,t){let r=G(e,t);return T(J,{children:r.map((o,a)=>o.tag==="title"?T("title",{children:o.children},a):o.tag==="link"?T("link",{rel:o.rel,href:o.href,hrefLang:o.hrefLang},a):T("meta",{name:o.name,property:o.property,content:o.content},a))})}import{createContext as v}from"react";var y=globalThis;y.__devix_RouterContext__??=v(null);var be=y.__devix_RouterContext__;y.__devix_PageMetaContext__??=v(null);y.__devix_RouteDataContext__??=v(null);var N=y.__devix_PageMetaContext__,R=y.__devix_RouteDataContext__;import{Component as W}from"react";import{jsx as $}from"react/jsx-runtime";var E=class extends W{state={error:null};static getDerivedStateFromError(t){return t instanceof b?{error:{statusCode:t.statusCode,message:t.message}}:{error:{statusCode:500,message:t instanceof Error?t.message:"Unknown error"}}}render(){return this.state.error&&this.props.ErrorPage?$(this.props.ErrorPage,{...this.state.error}):this.state.error?$("h1",{children:this.state.error.statusCode}):this.props.children}},b=class extends Error{statusCode;constructor(t,r){super(r),this.statusCode=t}};import{jsx as c,jsxs as ae}from"react/jsx-runtime";function ee(){return M(_)}function te(){let e=M(_);if(!e)throw new Error("useNavigate must be used within a RouterProvider");return e.navigate}function re(){let e=M(R);if(!e)throw new Error("useParams must be used within a route or layout");return e.params}function oe(){let e=M(R);if(!e)throw new Error("useLoaderData must be used within a route or layout");return e.loaderData}function ne({initialData:e,initialParams:t,initialPage:r,initialLayouts:o=[],initialLayoutsData:a=[],initialMeta:s,initialViewport:g,initialError:l,initialErrorPage:p,clientEntry:x}){let[n,H]=B({pathname:window.location.pathname,params:t,loaderData:e,layoutsData:a,Page:r,layouts:o,metadata:s??null,viewport:g,pendingError:l,ErrorPage:p}),P=Q(null),[q,L]=B(!1),w=V(async(u,i)=>{let f=u.split("?")[0],d=Z(f);if(!d){let m=await Y()??X();H(U=>({...U,pathname:f,pendingError:{statusCode:404,message:"Not found"},ErrorPage:m??void 0}));return}let[S,...K]=await Promise.all([d.load(),...d.loadLayouts.map(m=>m())]);if(i.signal.aborted||!S.default)return;let C=await fetch(`/_data${u}`,{headers:{Accept:"application/json"},signal:i.signal});if(i.signal.aborted)return;if(!C.ok){if(C.status===404){window.location.href=u;return}console.error(`/_data${u} returned ${C.status}`);return}let h=await C.json();window.scrollTo(0,0),H({pathname:f,params:h.params??{},loaderData:h.loaderData,layoutsData:(h.layouts??[]).map(m=>m.loaderData),Page:S.default,layouts:K.map(m=>m.default),metadata:h.metadata??null,viewport:h.viewport})},[]),F=V(async u=>{P.current?.abort();let i=new AbortController;P.current=i,L(!0);try{window.history.pushState(null,"",u),await w(u,i)}finally{i.signal.aborted||L(!1)}},[w]);z(()=>{let u=()=>{P.current?.abort();let i=new AbortController;P.current=i;let f=window.location.pathname+window.location.search;w(f,i).catch(d=>{d.name!=="AbortError"&&console.error("[router] popstate error:",d)})};return window.addEventListener("popstate",u),()=>window.removeEventListener("popstate",u)},[w]);let k;if(n.pendingError)k=n.ErrorPage?c(n.ErrorPage,{...n.pendingError}):c("h1",{children:n.pendingError.statusCode});else{let u=c(R,{value:{loaderData:n.loaderData,params:n.params},children:c(n.Page,{data:n.loaderData,params:n.params,url:n.pathname})});for(let i=n.layouts.length-1;i>=0;i--){let f=n.layouts[i],d=n.layoutsData[i];u=c(R,{value:{loaderData:d,params:n.params},children:c(f,{data:d,params:n.params,children:u})})}k=c(E,{ErrorPage:n.ErrorPage,children:u},n.pathname)}return ae(N,{value:{metadata:n.metadata,viewport:n.viewport,clientEntry:x},children:[n.metadata&&A(n.metadata,n.viewport),c(_,{value:{...n,isNavigating:q,navigate:F},children:k})]})}import{useCallback as se,useContext as ie}from"react";import{matchClientRoute as ue}from"virtual:devix/client-routes";import{RouterContext as pe}from"virtual:devix/context";import{jsx as de}from"react/jsx-runtime";function O(e){if(e.startsWith("/")||e.startsWith("http"))return e;let t=window.location.pathname.endsWith("/")?window.location.href:window.location.href+"/",r=new URL(e,t).pathname;return r.length>1?r.replace(/\/$/,""):r}function le({href:e,prefetch:t=!1,viewTransition:r=!1,children:o,...a}){let s=ie(pe),g=se(()=>{if(!t)return;let p=O(e),x=p.split("?")[0],n=ue(x);n&&(n.load().catch(()=>{}),fetch(`/_data${p}`,{headers:{Accept:"application/json"}}).catch(()=>{}))},[e,t]);return de("a",{href:e,onClick:p=>{if(s&&!p.ctrlKey&&!p.metaKey&&!p.shiftKey&&p.button===0){p.preventDefault();let x=O(e);r&&typeof document.startViewTransition=="function"?document.startViewTransition(()=>s.navigate(x)):s.navigate(x)}},onMouseEnter:g,...a,children:o})}function ce(e,t){let r=e.headers.get("cookie");if(r)for(let o of r.split(";")){let[a,...s]=o.trim().split("=");if(a.trim()===t)return decodeURIComponent(s.join("="))}}function I(e,t,r,o={}){let a=`${t}=${encodeURIComponent(r)}; Path=${o.path??"/"}`;o.domain&&(a+=`; Domain=${o.domain}`),o.maxAge!==void 0&&(a+=`; Max-Age=${o.maxAge}`),o.expires&&(a+=`; Expires=${o.expires.toUTCString()}`),o.httpOnly&&(a+="; HttpOnly"),o.secure&&(a+="; Secure"),o.sameSite&&(a+=`; SameSite=${o.sameSite}`),e.append("Set-Cookie",a)}function ge(e,t,r={}){I(e,t,"",{...r,maxAge:0,expires:new Date(0)})}var fe=(e,t=200)=>Response.json(e,{status:t}),me=(e,t=200)=>new Response(e,{status:t,headers:{"Content-Type":"text/plain; charset=utf-8"}}),xe=(e,t=302)=>new Response(null,{status:t,headers:{Location:e}});var D=class extends Error{constructor(r,o,a){super(`HTTP ${r}: ${o}`);this.status=r;this.statusText=o;this.response=a;this.name="FetchError"}};async function ye(e,t){let r=t?.method??"GET",o=new Headers(t?.headers),a;t?.body!==void 0&&(a=JSON.stringify(t.body),o.has("Content-Type")||o.set("Content-Type","application/json"));let s=await fetch(e,{method:r,headers:o,body:a,signal:t?.signal});if(!s.ok)throw new D(s.status,s.statusText,s);return(s.headers.get("Content-Type")??"").includes("application/json")?s.json():s.text()}var he="__devix_handler__";function Re(e){return{[he]:!0,fn:e}}import{AsyncLocalStorage as Pe}from"node:async_hooks";var we=new Pe;function j(e){let t=we.getStore();if(!t)throw new Error(`[devix] ${e}() called outside of a request handler`);return t}function Ce(){return j("useRequest").request}function Te(){return j("useCtx").ctx}export{ye as $fetch,D as FetchError,le as Link,ne as RouterProvider,Re as createHandler,ge as deleteCookie,ce as getCookie,fe as json,xe as redirect,I as setCookie,me as text,Te as useCtx,oe as useLoaderData,te as useNavigate,re as useParams,Ce as useRequest,ee as useRouter};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|