@devlusoft/devix 0.4.1-beta.6 → 0.4.1-beta.8
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 +6 -6
- package/dist/cli/build.js.map +4 -4
- package/dist/cli/dev-server.js +24 -24
- package/dist/cli/dev-server.js.map +4 -4
- package/dist/cli/generate.js +7 -7
- package/dist/cli/generate.js.map +4 -4
- package/dist/cli/index.js +10 -10
- package/dist/cli/index.js.map +4 -4
- package/dist/cli/start.js +1 -1
- package/dist/cli/start.js.map +3 -3
- package/dist/runtime/head.js +1 -1
- package/dist/runtime/head.js.map +3 -3
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/index.js.map +3 -3
- package/dist/runtime/router-provider.js +1 -1
- package/dist/runtime/router-provider.js.map +3 -3
- package/dist/runtime/server-app.js +1 -1
- package/dist/runtime/server-app.js.map +3 -3
- package/dist/server/render.js +1 -1
- package/dist/server/render.js.map +3 -3
- package/dist/types.d.ts +7 -0
- package/dist/utils/banner.js +1 -1
- package/dist/utils/load-config.d.ts +2 -0
- package/dist/utils/load-config.js +2 -0
- package/dist/utils/load-config.js.map +7 -0
- package/package.json +1 -1
package/dist/cli/build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{writeFileSync as
|
|
1
|
+
import{writeFileSync as Et}from"node:fs";import{resolve as wt}from"node:path";import{build as X}from"vite";import{mergeConfig as pt}from"vite";import dt from"@vitejs/plugin-react";import{fileURLToPath as mt}from"node:url";import{dirname as ft,resolve as u}from"node:path";function I({cssUrls:t}){return`
|
|
2
2
|
${t.map(r=>`import '${r}'`).join(`
|
|
3
3
|
`)}
|
|
4
4
|
import "@vitejs/plugin-react/preamble"
|
|
@@ -62,7 +62,7 @@ if (!window.__DEVIX__) {
|
|
|
62
62
|
)
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
`}function
|
|
65
|
+
`}function L({pagesDir:t,matcherPath:e}){return`
|
|
66
66
|
import React from 'react'
|
|
67
67
|
import { createMatcher } from '${e}'
|
|
68
68
|
const pageFiles = import.meta.glob(['/${t}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
@@ -90,7 +90,7 @@ export function getDefaultErrorPage() {
|
|
|
90
90
|
)
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
`}function
|
|
93
|
+
`}function O({pagesDir:t,renderPath:e}){return`
|
|
94
94
|
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${e}'
|
|
95
95
|
|
|
96
96
|
const _pages = import.meta.glob(['/${t}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
@@ -128,9 +128,9 @@ const _glob = {
|
|
|
128
128
|
export function handleApiRequest(url, request) {
|
|
129
129
|
return _handleApiRequest(url, request, _glob)
|
|
130
130
|
}
|
|
131
|
-
`}function R(t){return t.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}var
|
|
131
|
+
`}function R(t){return t.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}var K=null;function v(){K=null}function F(t,e){let r=t.slice(e.length+1).replace(/\\/g,"/"),i=R(r);return i==="/"?"/api":`/api/${i}`.replace("/api//","/api/")}var Q=null;function E(){Q=null}function U(){return`
|
|
132
132
|
export {RouterContext} from '@devlusoft/devix/runtime/context'
|
|
133
|
-
`}import{readFileSync as
|
|
133
|
+
`}import{readFileSync as nt,readdirSync as ot,statSync as it}from"node:fs";import{join as P,relative as at}from"node:path";var tt=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g;function et(t){return t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function k(t){let e=new Set;for(let r of et(t).matchAll(tt))e.add(r[1]);return[...e]}function rt(t,e){return"_api_"+t.slice(`${e}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function H(t,e,r){return{filePath:t,urlPattern:F(t,e),identifier:rt(t,e),methods:r}}function w(t,e){if(t.length===0)return`// auto-generado por devix \u2014 no editar
|
|
134
134
|
declare module '@devlusoft/devix' {
|
|
135
135
|
interface ApiRoutes {}
|
|
136
136
|
}
|
|
@@ -157,5 +157,5 @@ declare module '@devlusoft/devix' {
|
|
|
157
157
|
${i}
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
`}function j(t,e){let r=[];for(let i of
|
|
160
|
+
`}function j(t,e){let r=[];for(let i of ot(t)){let o=P(t,i);it(o).isDirectory()?r.push(...j(o,e)):/\.(ts|tsx)$/.test(i)&&r.push(at(e,o).replace(/\\/g,"/"))}return r}function _(t,e){let r=P(e,t,"api"),i;try{i=j(r,e)}catch{return[]}return i.filter(o=>!o.endsWith("middleware.ts")&&!o.endsWith("middleware.tsx")).flatMap(o=>{try{let p=nt(P(e,o),"utf-8"),g=k(p);return g.length===0?[]:[H(o,`${t}/api`,g)]}catch{return[]}})}import{mkdirSync as st,readFileSync as ct,writeFileSync as lt,existsSync as ut}from"node:fs";import{join as q}from"node:path";function T(t,e){let r=q(e,".devix"),i=q(r,"routes.d.ts");return st(r,{recursive:!0}),ut(i)&&ct(i,"utf-8")===t?!1:(lt(i,t,"utf-8"),!0)}import{parseSync as gt}from"oxc-parser";var $=ft(mt(import.meta.url)),D="virtual:devix/entry-client",A="virtual:devix/client-routes",b="virtual:devix/render",C="virtual:devix/api",S="virtual:devix/context",V=new Set(["loader","guard","generateStaticParams","headers"]);function N(t){let e=t.appDir??"app",r=`${e}/pages`,i=(t.css??[]).map(n=>n.startsWith("/")?n:`/${n.replace(/^\.\//,"")}`),o=u($,"../server/render.js").replace(/\\/g,"/"),p=u($,"../server/api.js").replace(/\\/g,"/"),g=u($,"../runtime/client-router.js").replace(/\\/g,"/"),G={name:"devix",enforce:"pre",resolveId(n){if(n===D)return`\0${D}`;if(n===A)return`\0${A}`;if(n===b)return`\0${b}`;if(n===C)return`\0${C}`;if(n===S)return`\0${S}`},load(n){if(n===`\0${D}`)return I({cssUrls:i});if(n===`\0${A}`)return L({pagesDir:r,matcherPath:g});if(n===`\0${b}`)return O({pagesDir:r,renderPath:o});if(n===`\0${C}`)return M({apiPath:p,appDir:e});if(n===`\0${S}`)return U()},transform(n,c,d){if(d?.ssr)return;let a=u(process.cwd(),r);if(!c.startsWith(a))return;let Z=gt(c,n,{sourceType:"module"}),m=[];for(let s of Z.program.body){if(s.type!=="ExportNamedDeclaration"||!s.declaration)continue;let l=s.declaration;if(l.type==="FunctionDeclaration"&&l.id&&V.has(l.id.name)&&m.push({start:s.start,end:s.end,name:l.id.name}),l.type==="VariableDeclaration"){let x=new Set;for(let y of l.declarations)y.id.type==="Identifier"&&V.has(y.id.name)&&(x.has(s.start)||(x.add(s.start),m.push({start:s.start,end:s.end,name:y.id.name})))}}if(m.length===0)return;m.sort((s,l)=>l.start-s.start);let h=n;for(let{start:s,end:l,name:x}of m)h=h.slice(0,s)+`export const ${x} = undefined`+h.slice(l);return{code:h,map:null}},buildStart(){let n=process.cwd(),c=_(e,n);T(w(c,`${e}/api`),n)},configureServer(n){let c=process.cwd(),d=()=>{let a=_(e,c);T(w(a,`${e}/api`),c)};n.watcher.add(u(c,"devix.config.ts")),n.watcher.on("change",a=>{a===u(c,"devix.config.ts")&&(console.log("[devix] Config changed, restarting..."),process.exit(75))}),n.watcher.on("add",a=>{a.startsWith(u(c,r))&&v(),a.includes(`${e}/api`)&&(E(),d())}),n.watcher.on("unlink",a=>{a.startsWith(u(c,r))&&v(),a.includes(`${e}/api`)&&(E(),d())}),n.watcher.on("change",a=>{a.includes(`${e}/api`)&&!a.endsWith("middleware.ts")&&d()})}},Y={plugins:[dt(),G],publicDir:u(process.cwd(),t.publicDir??"public"),ssr:{noExternal:["@devlusoft/devix"]},...t.envPrefix?{envPrefix:t.envPrefix}:{}};return pt(Y,t.vite??{})}function W(t){if(typeof t=="number")return t;let e=t.trim().match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h)?$/);if(!e)throw new Error(`[devix] Invalid duration: "${t}". Use a number (ms) or a string like "5s", "2m", "500ms".`);let r=parseFloat(e[1]);switch(e[2]){case"h":return r*36e5;case"m":return r*6e4;case"s":return r*1e3;default:return r}}import{build as ht}from"esbuild";import{join as B}from"node:path";import{tmpdir as xt}from"node:os";import{unlinkSync as yt,writeFileSync as Rt}from"node:fs";import{pathToFileURL as vt}from"node:url";async function J(t){let e=await ht({entryPoints:[B(t,"devix.config.ts")],bundle:!0,write:!1,format:"esm",platform:"node",packages:"external"}),r=B(xt(),`devix-config-${Date.now()}.mjs`);Rt(r,e.outputFiles[0].text);try{return(await import(vt(r).href)).default}finally{yt(r)}}var f=await J(process.cwd()),z=N(f);await X({...z,configFile:!1,build:{outDir:"dist/client",manifest:!0,rolldownOptions:{input:"virtual:devix/entry-client"}}});await X({...z,configFile:!1,build:{ssr:!0,outDir:"dist/server",copyPublicDir:!1,rolldownOptions:{input:{render:"virtual:devix/render",api:"virtual:devix/api"}}}});var Pt={port:f.port??3e3,host:f.host??!1,loaderTimeout:W(f.loaderTimeout??1e4),output:f.output??"server"};Et(wt(process.cwd(),"dist/devix.config.json"),JSON.stringify(Pt,null,2),"utf-8");
|
|
161
161
|
//# sourceMappingURL=build.js.map
|
package/dist/cli/build.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/cli/build.ts", "../../src/vite/index.ts", "../../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/scan-api.ts", "../../src/vite/codegen/extract-methods.ts", "../../src/vite/codegen/routes-dts.ts", "../../src/vite/codegen/write-routes-dts.ts", "../../src/utils/duration.ts"],
|
|
4
|
-
"sourcesContent": ["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 copyPublicDir: false,\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 { 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\";\nimport { parseSync } from 'oxc-parser'\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\nconst SERVER_EXPORTS = new Set(['loader', 'guard', 'generateStaticParams', 'headers'])\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\n transform(code, id, options) {\n if (options?.ssr) return\n\n const resolvedPagesDir = resolve(process.cwd(), pagesDir)\n if (!id.startsWith(resolvedPagesDir)) return\n\n const ast = parseSync(id, code, { sourceType: 'module' })\n\n const replacements: { start: number; end: number; name: string }[] = []\n\n for (const node of ast.program.body) {\n if (node.type !== 'ExportNamedDeclaration' || !node.declaration) continue\n\n const decl = node.declaration\n\n if (decl.type === 'FunctionDeclaration' && decl.id && SERVER_EXPORTS.has(decl.id.name)) {\n replacements.push({ start: node.start, end: node.end, name: decl.id.name })\n }\n\n if (decl.type === 'VariableDeclaration') {\n const seen = new Set<number>()\n for (const declarator of decl.declarations) {\n if (declarator.id.type === 'Identifier' && SERVER_EXPORTS.has(declarator.id.name)) {\n if (!seen.has(node.start)) {\n seen.add(node.start)\n replacements.push({ start: node.start, end: node.end, name: declarator.id.name })\n }\n }\n }\n }\n }\n\n if (replacements.length === 0) return\n\n replacements.sort((a, b) => b.start - a.start)\n\n let result = code\n for (const { start, end, name } of replacements) {\n result = result.slice(0, start) + `export const ${name} = undefined` + result.slice(end)\n }\n\n return { code: result, map: null }\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.add(resolve(root, 'devix.config.ts'))\n server.watcher.on('change', (file) => {\n if (file === resolve(root, 'devix.config.ts')) {\n console.log('[devix] Config changed, restarting...')\n process.exit(75)\n }\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 publicDir: resolve(process.cwd(), config.publicDir ?? 'public'),\n ssr: { noExternal: ['@devlusoft/devix'] },\n ...(config.envPrefix ? { envPrefix: config.envPrefix } : {}),\n }\n\n return mergeConfig(base, config.vite ?? {})\n}", "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\n if (window.location.hash) { \n const id = window.location.hash.slice(1) \n const scrollBehavior = getComputedStyle(document.documentElement).scrollBehavior \n requestAnimationFrame(() => { \n document.getElementById(id)?.scrollIntoView({ behavior: scrollBehavior }) \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}", "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", "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>>> | Exclude<Awaited<ReturnType<T>>, JsonResponse<any> | null | void | undefined>\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 {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", "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"],
|
|
5
|
-
"mappings": "AAAA,OAAQ,iBAAAA,OAAoB,UAC5B,OAAQ,WAAAC,OAAc,YACtB,OAAQ,SAAAC,MAAY,OCFpB,OAA6B,eAAAC,OAAmB,OAEhD,OAAOC,OAAW,uBAClB,OAAS,iBAAAC,OAAqB,WAC9B,OAAS,WAAAC,GAAS,WAAAC,MAAe,YCA1B,SAASC,EAAoB,CAAE,QAAAC,CAAQ,EAA+B,CAGzE,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA+DZ,CClEO,SAASC,EAAqB,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,CC9BO,SAASE,EAAe,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,CCzBO,SAASE,EAAY,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,CCtBO,SAASC,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCsBA,IAAIC,EAA4B,KAEzB,SAASC,GAAuB,CACnCD,EAAQ,IACZ,CCdO,SAASE,EAAkBC,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,CAMA,IAAIE,EAA0B,KAEvB,SAASC,GAAqB,CACjCD,EAAQ,IACZ,CCjCO,SAASE,GAA0B,CACtC,MAAO;AAAA;AAAA,CAGX,CCJA,OAAQ,gBAAAC,GAAc,eAAAC,GAAa,YAAAC,OAAe,UAClD,OAAQ,QAAAC,EAAM,YAAAC,OAAe,YCE7B,IAAMC,
|
|
6
|
-
"names": ["writeFileSync", "resolve", "build", "mergeConfig", "react", "fileURLToPath", "dirname", "resolve", "generateEntryClient", "cssUrls", "u", "generateClientRoutes", "pagesDir", "matcherPath", "generateRender", "pagesDir", "renderPath", "generateApi", "apiPath", "appDir", "routePattern", "rel", "cache", "invalidatePagesCache", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "cache", "invalidateApiCache", "generateContext", "readFileSync", "readdirSync", "statSync", "join", "relative", "METHOD_EXPORT_RE", "stripComments", "content", "extractHttpMethods", "found", "match", "filePathToIdentifier", "filePath", "apiDir", "buildRouteEntry", "methods", "keyToRoutePattern", "generateRoutesDts", "entries", "imports", "e", "importPath", "routeLines", "m", "walkDir", "dir", "root", "entries", "name", "readdirSync", "full", "join", "statSync", "relative", "scanApiFiles", "appDir", "projectRoot", "apiDir", "files", "f", "filePath", "content", "readFileSync", "methods", "extractHttpMethods", "buildRouteEntry", "mkdirSync", "readFileSync", "writeFileSync", "existsSync", "join", "writeRoutesDts", "content", "projectRoot", "devixDir", "outPath", "parseSync", "__dirname", "dirname", "fileURLToPath", "VIRTUAL_ENTRY_CLIENT", "VIRTUAL_CLIENT_ROUTES", "VIRTUAL_RENDER", "VIRTUAL_API", "VIRTUAL_CONTEXT", "SERVER_EXPORTS", "devix", "config", "appDir", "pagesDir", "cssUrls", "u", "renderPath", "resolve", "apiPath", "matcherPath", "virtualPlugin", "id", "generateEntryClient", "generateClientRoutes", "generateRender", "generateApi", "generateContext", "code", "options", "resolvedPagesDir", "ast", "replacements", "node", "decl", "seen", "declarator", "b", "result", "start", "end", "name", "root", "entries", "scanApiFiles", "writeRoutesDts", "generateRoutesDts", "server", "regenerateDts", "file", "invalidatePagesCache", "invalidateApiCache", "base", "react", "mergeConfig", "parseDuration", "value", "match", "n", "config", "baseConfig", "devix", "build", "runtimeConfig", "parseDuration", "writeFileSync", "resolve"]
|
|
3
|
+
"sources": ["../../src/cli/build.ts", "../../src/vite/index.ts", "../../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/scan-api.ts", "../../src/vite/codegen/extract-methods.ts", "../../src/vite/codegen/routes-dts.ts", "../../src/vite/codegen/write-routes-dts.ts", "../../src/utils/duration.ts", "../../src/utils/load-config.ts"],
|
|
4
|
+
"sourcesContent": ["import {writeFileSync} from 'node:fs'\nimport {resolve} from 'node:path'\nimport {build} from 'vite'\nimport {devix} from '../vite'\nimport {parseDuration} from '../utils/duration'\nimport {loadConfig} from \"../utils/load-config\";\n\nconst config = await loadConfig(process.cwd())\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 copyPublicDir: false,\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 { 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\";\nimport { parseSync } from 'oxc-parser'\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\nconst SERVER_EXPORTS = new Set(['loader', 'guard', 'generateStaticParams', 'headers'])\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\n transform(code, id, options) {\n if (options?.ssr) return\n\n const resolvedPagesDir = resolve(process.cwd(), pagesDir)\n if (!id.startsWith(resolvedPagesDir)) return\n\n const ast = parseSync(id, code, { sourceType: 'module' })\n\n const replacements: { start: number; end: number; name: string }[] = []\n\n for (const node of ast.program.body) {\n if (node.type !== 'ExportNamedDeclaration' || !node.declaration) continue\n\n const decl = node.declaration\n\n if (decl.type === 'FunctionDeclaration' && decl.id && SERVER_EXPORTS.has(decl.id.name)) {\n replacements.push({ start: node.start, end: node.end, name: decl.id.name })\n }\n\n if (decl.type === 'VariableDeclaration') {\n const seen = new Set<number>()\n for (const declarator of decl.declarations) {\n if (declarator.id.type === 'Identifier' && SERVER_EXPORTS.has(declarator.id.name)) {\n if (!seen.has(node.start)) {\n seen.add(node.start)\n replacements.push({ start: node.start, end: node.end, name: declarator.id.name })\n }\n }\n }\n }\n }\n\n if (replacements.length === 0) return\n\n replacements.sort((a, b) => b.start - a.start)\n\n let result = code\n for (const { start, end, name } of replacements) {\n result = result.slice(0, start) + `export const ${name} = undefined` + result.slice(end)\n }\n\n return { code: result, map: null }\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.add(resolve(root, 'devix.config.ts'))\n server.watcher.on('change', (file) => {\n if (file === resolve(root, 'devix.config.ts')) {\n console.log('[devix] Config changed, restarting...')\n process.exit(75)\n }\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 publicDir: resolve(process.cwd(), config.publicDir ?? 'public'),\n ssr: { noExternal: ['@devlusoft/devix'] },\n ...(config.envPrefix ? { envPrefix: config.envPrefix } : {}),\n }\n\n return mergeConfig(base, config.vite ?? {})\n}", "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\n if (window.location.hash) { \n const id = window.location.hash.slice(1) \n const scrollBehavior = getComputedStyle(document.documentElement).scrollBehavior \n requestAnimationFrame(() => { \n document.getElementById(id)?.scrollIntoView({ behavior: scrollBehavior }) \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}", "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", "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>>> | Exclude<Awaited<ReturnType<T>>, JsonResponse<any> | null | void | undefined>\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 {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", "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 {build} from 'esbuild'\nimport type {DevixConfig} from \"../config\"\nimport {join} from \"node:path\";\nimport {tmpdir} from \"node:os\";\nimport {unlinkSync, writeFileSync} from \"node:fs\";\nimport {pathToFileURL} from \"node:url\";\n\nexport async function loadConfig(cwd: string): Promise<DevixConfig> {\n const result = await build({\n entryPoints: [join(cwd, 'devix.config.ts')],\n bundle: true,\n write: false,\n format: 'esm',\n platform: 'node',\n packages: 'external',\n })\n\n const tmpFile = join(tmpdir(), `devix-config-${Date.now()}.mjs`)\n writeFileSync(tmpFile, result.outputFiles[0].text)\n\n try {\n const mod = await import(pathToFileURL(tmpFile).href)\n return mod.default\n } finally {\n unlinkSync(tmpFile)\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["writeFileSync", "resolve", "build", "mergeConfig", "react", "fileURLToPath", "dirname", "resolve", "generateEntryClient", "cssUrls", "u", "generateClientRoutes", "pagesDir", "matcherPath", "generateRender", "pagesDir", "renderPath", "generateApi", "apiPath", "appDir", "routePattern", "rel", "cache", "invalidatePagesCache", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "cache", "invalidateApiCache", "generateContext", "readFileSync", "readdirSync", "statSync", "join", "relative", "METHOD_EXPORT_RE", "stripComments", "content", "extractHttpMethods", "found", "match", "filePathToIdentifier", "filePath", "apiDir", "buildRouteEntry", "methods", "keyToRoutePattern", "generateRoutesDts", "entries", "imports", "e", "importPath", "routeLines", "m", "walkDir", "dir", "root", "entries", "name", "readdirSync", "full", "join", "statSync", "relative", "scanApiFiles", "appDir", "projectRoot", "apiDir", "files", "f", "filePath", "content", "readFileSync", "methods", "extractHttpMethods", "buildRouteEntry", "mkdirSync", "readFileSync", "writeFileSync", "existsSync", "join", "writeRoutesDts", "content", "projectRoot", "devixDir", "outPath", "parseSync", "__dirname", "dirname", "fileURLToPath", "VIRTUAL_ENTRY_CLIENT", "VIRTUAL_CLIENT_ROUTES", "VIRTUAL_RENDER", "VIRTUAL_API", "VIRTUAL_CONTEXT", "SERVER_EXPORTS", "devix", "config", "appDir", "pagesDir", "cssUrls", "u", "renderPath", "resolve", "apiPath", "matcherPath", "virtualPlugin", "id", "generateEntryClient", "generateClientRoutes", "generateRender", "generateApi", "generateContext", "code", "options", "resolvedPagesDir", "ast", "replacements", "node", "decl", "seen", "declarator", "a", "b", "result", "start", "end", "name", "root", "entries", "scanApiFiles", "writeRoutesDts", "generateRoutesDts", "server", "regenerateDts", "file", "invalidatePagesCache", "invalidateApiCache", "base", "react", "mergeConfig", "parseDuration", "value", "match", "n", "build", "join", "tmpdir", "unlinkSync", "writeFileSync", "pathToFileURL", "loadConfig", "cwd", "result", "tmpFile", "config", "loadConfig", "baseConfig", "devix", "build", "runtimeConfig", "parseDuration", "writeFileSync", "resolve"]
|
|
7
7
|
}
|
package/dist/cli/dev-server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{createServer as
|
|
2
|
-
${
|
|
1
|
+
import{createServer as It}from"node:http";import{createServer as Lt}from"vite";import{getRequestListener as Mt}from"@hono/node-server";import{Hono as Ot}from"hono";import{mergeConfig as Rt}from"vite";import vt from"@vitejs/plugin-react";import{fileURLToPath as wt}from"node:url";import{dirname as Et,resolve as d}from"node:path";function U({cssUrls:t}){return`
|
|
2
|
+
${t.map(r=>`import '${r}'`).join(`
|
|
3
3
|
`)}
|
|
4
4
|
import "@vitejs/plugin-react/preamble"
|
|
5
5
|
import React from "react"
|
|
@@ -62,12 +62,12 @@ if (!window.__DEVIX__) {
|
|
|
62
62
|
)
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
`}function
|
|
65
|
+
`}function F({pagesDir:t,matcherPath:e}){return`
|
|
66
66
|
import React from 'react'
|
|
67
|
-
import { createMatcher } from '${
|
|
68
|
-
const pageFiles = import.meta.glob(['/${
|
|
69
|
-
const layoutFiles = import.meta.glob('/${
|
|
70
|
-
const errorFiles = import.meta.glob('/${
|
|
67
|
+
import { createMatcher } from '${e}'
|
|
68
|
+
const pageFiles = import.meta.glob(['/${t}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
69
|
+
const layoutFiles = import.meta.glob('/${t}/**/layout.tsx')
|
|
70
|
+
const errorFiles = import.meta.glob('/${t}/**/error.tsx')
|
|
71
71
|
|
|
72
72
|
export const matchClientRoute = createMatcher(pageFiles, layoutFiles)
|
|
73
73
|
|
|
@@ -90,16 +90,16 @@ export function getDefaultErrorPage() {
|
|
|
90
90
|
)
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
`}function
|
|
94
|
-
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${
|
|
93
|
+
`}function H({pagesDir:t,renderPath:e}){return`
|
|
94
|
+
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${e}'
|
|
95
95
|
|
|
96
|
-
const _pages = import.meta.glob(['/${
|
|
97
|
-
const _layouts = import.meta.glob('/${
|
|
96
|
+
const _pages = import.meta.glob(['/${t}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
97
|
+
const _layouts = import.meta.glob('/${t}/**/layout.tsx')
|
|
98
98
|
|
|
99
99
|
const _glob = {
|
|
100
100
|
pages: _pages,
|
|
101
101
|
layouts: _layouts,
|
|
102
|
-
pagesDir: '/${
|
|
102
|
+
pagesDir: '/${t}',
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export function render(url, request, options) {
|
|
@@ -113,29 +113,29 @@ export function runLoader(url, request, options) {
|
|
|
113
113
|
export function getStaticRoutes() {
|
|
114
114
|
return _getStaticRoutes(_glob)
|
|
115
115
|
}
|
|
116
|
-
`}function
|
|
117
|
-
import { handleApiRequest as _handleApiRequest } from '${
|
|
116
|
+
`}function q({apiPath:t,appDir:e}){return`
|
|
117
|
+
import { handleApiRequest as _handleApiRequest } from '${t}'
|
|
118
118
|
|
|
119
|
-
const _routes = import.meta.glob(['/${
|
|
120
|
-
const _middlewares = import.meta.glob('/${
|
|
119
|
+
const _routes = import.meta.glob(['/${e}/api/**/*.ts', '!**/middleware.ts'])
|
|
120
|
+
const _middlewares = import.meta.glob('/${e}/api/**/middleware.ts')
|
|
121
121
|
|
|
122
122
|
const _glob = {
|
|
123
123
|
routes: _routes,
|
|
124
124
|
middlewares: _middlewares,
|
|
125
|
-
apiDir: '/${
|
|
125
|
+
apiDir: '/${e}/api',
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
export function handleApiRequest(url, request) {
|
|
129
129
|
return _handleApiRequest(url, request, _glob)
|
|
130
130
|
}
|
|
131
|
-
`}function _(
|
|
131
|
+
`}function _(t){return t.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}var st=null;function P(){st=null}function j(t,e){let r=t.slice(e.length+1).replace(/\\/g,"/"),i=_(r);return i==="/"?"/api":`/api/${i}`.replace("/api//","/api/")}var at=null;function $(){at=null}function V(){return`
|
|
132
132
|
export {RouterContext} from '@devlusoft/devix/runtime/context'
|
|
133
|
-
`}import{readFileSync as
|
|
133
|
+
`}import{readFileSync as pt,readdirSync as dt,statSync as mt}from"node:fs";import{join as D,relative as ft}from"node:path";var ct=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g;function lt(t){return t.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function N(t){let e=new Set;for(let r of lt(t).matchAll(ct))e.add(r[1]);return[...e]}function ut(t,e){return"_api_"+t.slice(`${e}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function W(t,e,r){return{filePath:t,urlPattern:j(t,e),identifier:ut(t,e),methods:r}}function T(t,e){if(t.length===0)return`// auto-generado por devix \u2014 no editar
|
|
134
134
|
declare module '@devlusoft/devix' {
|
|
135
135
|
interface ApiRoutes {}
|
|
136
136
|
}
|
|
137
|
-
`;let r=
|
|
138
|
-
`),i=
|
|
137
|
+
`;let r=t.map(o=>{let s="../"+o.filePath.replace(/\.(ts|tsx)$/,"");return`import type * as ${o.identifier} from '${s}'`}).join(`
|
|
138
|
+
`),i=t.flatMap(o=>o.methods.map(s=>` '${s} ${o.urlPattern}': InferRoute<(typeof ${o.identifier})['${s}']>`)).join(`
|
|
139
139
|
`);return`// auto-generado por devix \u2014 no editar
|
|
140
140
|
${r}
|
|
141
141
|
|
|
@@ -157,7 +157,7 @@ declare module '@devlusoft/devix' {
|
|
|
157
157
|
${i}
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
-
`}function B(e
|
|
161
|
-
`),m=s?
|
|
162
|
-
</head>`):
|
|
160
|
+
`}function B(t,e){let r=[];for(let i of dt(t)){let o=D(t,i);mt(o).isDirectory()?r.push(...B(o,e)):/\.(ts|tsx)$/.test(i)&&r.push(ft(e,o).replace(/\\/g,"/"))}return r}function A(t,e){let r=D(e,t,"api"),i;try{i=B(r,e)}catch{return[]}return i.filter(o=>!o.endsWith("middleware.ts")&&!o.endsWith("middleware.tsx")).flatMap(o=>{try{let s=pt(D(e,o),"utf-8"),m=N(s);return m.length===0?[]:[W(o,`${t}/api`,m)]}catch{return[]}})}import{mkdirSync as gt,readFileSync as ht,writeFileSync as yt,existsSync as xt}from"node:fs";import{join as X}from"node:path";function b(t,e){let r=X(e,".devix"),i=X(r,"routes.d.ts");return gt(r,{recursive:!0}),xt(i)&&ht(i,"utf-8")===t?!1:(yt(i,t,"utf-8"),!0)}import{parseSync as _t}from"oxc-parser";var S=Et(wt(import.meta.url)),C="virtual:devix/entry-client",I="virtual:devix/client-routes",L="virtual:devix/render",M="virtual:devix/api",O="virtual:devix/context",J=new Set(["loader","guard","generateStaticParams","headers"]);function Y(t){let e=t.appDir??"app",r=`${e}/pages`,i=(t.css??[]).map(n=>n.startsWith("/")?n:`/${n.replace(/^\.\//,"")}`),o=d(S,"../server/render.js").replace(/\\/g,"/"),s=d(S,"../server/api.js").replace(/\\/g,"/"),m=d(S,"../runtime/client-router.js").replace(/\\/g,"/"),y={name:"devix",enforce:"pre",resolveId(n){if(n===C)return`\0${C}`;if(n===I)return`\0${I}`;if(n===L)return`\0${L}`;if(n===M)return`\0${M}`;if(n===O)return`\0${O}`},load(n){if(n===`\0${C}`)return U({cssUrls:i});if(n===`\0${I}`)return F({pagesDir:r,matcherPath:m});if(n===`\0${L}`)return H({pagesDir:r,renderPath:o});if(n===`\0${M}`)return q({apiPath:s,appDir:e});if(n===`\0${O}`)return V()},transform(n,c,x){if(x?.ssr)return;let a=d(process.cwd(),r);if(!c.startsWith(a))return;let it=_t(c,n,{sourceType:"module"}),R=[];for(let l of it.program.body){if(l.type!=="ExportNamedDeclaration"||!l.declaration)continue;let p=l.declaration;if(p.type==="FunctionDeclaration"&&p.id&&J.has(p.id.name)&&R.push({start:l.start,end:l.end,name:p.id.name}),p.type==="VariableDeclaration"){let w=new Set;for(let E of p.declarations)E.id.type==="Identifier"&&J.has(E.id.name)&&(w.has(l.start)||(w.add(l.start),R.push({start:l.start,end:l.end,name:E.id.name})))}}if(R.length===0)return;R.sort((l,p)=>p.start-l.start);let v=n;for(let{start:l,end:p,name:w}of R)v=v.slice(0,l)+`export const ${w} = undefined`+v.slice(p);return{code:v,map:null}},buildStart(){let n=process.cwd(),c=A(e,n);b(T(c,`${e}/api`),n)},configureServer(n){let c=process.cwd(),x=()=>{let a=A(e,c);b(T(a,`${e}/api`),c)};n.watcher.add(d(c,"devix.config.ts")),n.watcher.on("change",a=>{a===d(c,"devix.config.ts")&&(console.log("[devix] Config changed, restarting..."),process.exit(75))}),n.watcher.on("add",a=>{a.startsWith(d(c,r))&&P(),a.includes(`${e}/api`)&&($(),x())}),n.watcher.on("unlink",a=>{a.startsWith(d(c,r))&&P(),a.includes(`${e}/api`)&&($(),x())}),n.watcher.on("change",a=>{a.includes(`${e}/api`)&&!a.endsWith("middleware.ts")&&x()})}},f={plugins:[vt(),y],publicDir:d(process.cwd(),t.publicDir??"public"),ssr:{noExternal:["@devlusoft/devix"]},...t.envPrefix?{envPrefix:t.envPrefix}:{}};return Rt(f,t.vite??{})}function G(t,{apiModule:e,renderModule:r,loaderTimeout:i}){t.all("/api/*",async o=>{try{return await e.handleApiRequest(o.req.url,o.req.raw)}catch(s){return console.error(s),o.json({error:"internal error"},500)}}),t.get("/_data/*",async o=>{try{let{pathname:s,search:m}=new URL(o.req.url,"http://localhost"),y=s.replace(/^\/_data/,"")+m,f=await r.runLoader(y,o.req.raw,{loaderTimeout:i});return f.error?o.json({error:"internal error"},500):o.json(f)}catch(s){return console.error(s),o.json({error:"internal error"},500)}})}import u from"picocolors";import{networkInterfaces as Pt}from"node:os";function $t(t){let e=Pt();for(let r of Object.values(e))for(let i of r??[])if(i.family==="IPv4"&&!i.internal)return`http://${i.address}:${t}/`;return null}function z(t){let e="0.4.1-beta.8",r=$t(t);console.log(),console.log(` ${u.bold(u.yellow("devix"))} ${u.dim(`v${e}`)}`),console.log(),console.log(` ${u.green("\u279C")} ${u.bold("Local:")} ${u.cyan(`http://localhost:${t}/`)}`),console.log(r?` ${u.green("\u279C")} ${u.bold("Network:")} ${u.cyan(r)}`:` ${u.green("\u279C")} ${u.bold("Network:")} ${u.dim("use --host to expose")}`),console.log()}async function Z(t){let e=new Set;for(let[,r]of t.moduleGraph.idToModuleMap)r.id&&(r.id.endsWith(".css")||r.id.includes(".css?"))&&r.url.startsWith("/")&&e.add(r.url);return[...e]}function K(t){if(typeof t=="number")return t;let e=t.trim().match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h)?$/);if(!e)throw new Error(`[devix] Invalid duration: "${t}". Use a number (ms) or a string like "5s", "2m", "500ms".`);let r=parseFloat(e[1]);switch(e[2]){case"h":return r*36e5;case"m":return r*6e4;case"s":return r*1e3;default:return r}}import{loadEnv as Tt}from"vite";function Q(t){let e=Tt(t,process.cwd(),"");for(let[r,i]of Object.entries(e))process.env[r]===void 0&&(process.env[r]=i)}import{build as Dt}from"esbuild";import{join as tt}from"node:path";import{tmpdir as At}from"node:os";import{unlinkSync as bt,writeFileSync as St}from"node:fs";import{pathToFileURL as Ct}from"node:url";async function et(t){let e=await Dt({entryPoints:[tt(t,"devix.config.ts")],bundle:!0,write:!1,format:"esm",platform:"node",packages:"external"}),r=tt(At(),`devix-config-${Date.now()}.mjs`);St(r,e.outputFiles[0].text);try{return(await import(Ct(r).href)).default}finally{bt(r)}}Q("development");var rt="virtual:devix/render",kt="virtual:devix/api",h=await et(process.cwd()),nt=Number(process.env.PORT)||h.port||3e3,Ut=typeof h.host=="string"?h.host:h.host?"0.0.0.0":"localhost",g=await Lt({...Y(h),configFile:!1,appType:"custom",server:{middlewareMode:!0}}),ot={render:async(...t)=>(await g.ssrLoadModule(rt)).render(...t),runLoader:async(...t)=>(await g.ssrLoadModule(rt)).runLoader(...t)},Ft={handleApiRequest:async(...t)=>(await g.ssrLoadModule(kt)).handleApiRequest(...t)},k=new Ot;G(k,{renderModule:ot,apiModule:Ft});k.get("*",async t=>{try{let{html:e,statusCode:r,headers:i}=await ot.render(t.req.url,t.req.raw,{loaderTimeout:K(h.loaderTimeout??1e4)}),s=(await Z(g)).map(n=>`<link rel="stylesheet" href="${n}">`).join(`
|
|
161
|
+
`),m=s?e.replace("</head>",`${s}
|
|
162
|
+
</head>`):e,y=await g.transformIndexHtml(t.req.url,`<!DOCTYPE html>${m}`),f=t.html(y,r);for(let[n,c]of Object.entries(i))f.headers.set(n,c);return f}catch(e){return g.ssrFixStacktrace(e),console.error(e),t.text("Internal Server Error",500)}});var Ht=Mt(k.fetch);It(async(t,e)=>{await new Promise(r=>g.middlewares(t,e,r)),e.writableEnded||await Ht(t,e)}).listen(nt,Ut,()=>{z(nt)});
|
|
163
163
|
//# sourceMappingURL=dev-server.js.map
|