@devlusoft/devix 0.4.1-beta.12 → 0.4.1-beta.14
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 +63 -35
- package/dist/cli/build.js.map +4 -4
- package/dist/cli/dev-server.js +51 -23
- package/dist/cli/dev-server.js.map +4 -4
- package/dist/cli/generate.js +63 -35
- package/dist/cli/generate.js.map +4 -4
- package/dist/cli/index.js +45 -17
- 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/client-router.js +1 -1
- package/dist/runtime/client-router.js.map +3 -3
- package/dist/runtime/context.d.ts +1 -0
- package/dist/runtime/context.js.map +2 -2
- package/dist/runtime/fetch.d.ts +4 -35
- package/dist/runtime/fetch.js +1 -1
- package/dist/runtime/fetch.js.map +3 -3
- package/dist/runtime/index.d.ts +32 -4
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/index.js.map +4 -4
- package/dist/runtime/link.d.ts +3 -2
- package/dist/runtime/link.js +1 -1
- package/dist/runtime/link.js.map +4 -4
- 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/api-router.d.ts +0 -1
- package/dist/server/api-router.js +1 -1
- package/dist/server/api-router.js.map +3 -3
- package/dist/server/api.js +1 -1
- package/dist/server/api.js.map +3 -3
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +3 -3
- package/dist/server/pages-router.d.ts +0 -1
- package/dist/server/pages-router.js +1 -1
- package/dist/server/pages-router.js.map +3 -3
- package/dist/server/render.d.ts +15 -0
- package/dist/server/render.js +1 -1
- package/dist/server/render.js.map +3 -3
- package/dist/server/routes.js +1 -1
- package/dist/server/routes.js.map +3 -3
- package/dist/server/types.d.ts +4 -2
- package/dist/utils/banner.js +1 -1
- package/dist/utils/response.d.ts +13 -2
- package/dist/utils/response.js +1 -1
- package/dist/utils/response.js.map +3 -3
- package/dist/vite/codegen/entry-client.js +14 -1
- package/dist/vite/codegen/entry-client.js.map +2 -2
- package/dist/vite/codegen/page-types.d.ts +5 -0
- package/dist/vite/codegen/page-types.js +14 -0
- package/dist/vite/codegen/page-types.js.map +7 -0
- package/dist/vite/codegen/routes-dts.js +13 -10
- 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 +65 -37
- package/dist/vite/index.js.map +4 -4
- package/package.json +2 -2
|
@@ -19,7 +19,20 @@ if (!window.__DEVIX__) {
|
|
|
19
19
|
|
|
20
20
|
const matched = matchClientRoute(window.location.pathname)
|
|
21
21
|
|
|
22
|
-
if (
|
|
22
|
+
if (window.__LOADER_ERROR__) {
|
|
23
|
+
const {statusCode, message, data} = window.__LOADER_ERROR__
|
|
24
|
+
const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()
|
|
25
|
+
createRoot(root).render(
|
|
26
|
+
React.createElement(RouterProvider, {
|
|
27
|
+
clientEntry,
|
|
28
|
+
initialData: null,
|
|
29
|
+
initialParams: {},
|
|
30
|
+
initialPage: () => null,
|
|
31
|
+
initialError: {statusCode, message, data},
|
|
32
|
+
initialErrorPage: ErrorPage,
|
|
33
|
+
})
|
|
34
|
+
)
|
|
35
|
+
} else if (matched) {
|
|
23
36
|
const [pageMod, ...layoutMods] = await Promise.all([
|
|
24
37
|
matched.load(),
|
|
25
38
|
...matched.loadLayouts.map(l => l()),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/vite/codegen/entry-client.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\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}"],
|
|
5
|
-
"mappings": "AAIO,SAASA,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,
|
|
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 (window.__LOADER_ERROR__) {\n const {statusCode, message, data} = window.__LOADER_ERROR__\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 initialError: {statusCode, message, data},\n initialErrorPage: ErrorPage,\n })\n )\n } else 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}"],
|
|
5
|
+
"mappings": "AAIO,SAASA,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA4EZ",
|
|
6
6
|
"names": ["generateEntryClient", "cssUrls", "u"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function hasLoaderExport(code: string, filePath: string): boolean;
|
|
2
|
+
export declare function generatePageTypesDts(importPath: string, withLoader: boolean): string;
|
|
3
|
+
export declare function writePageTypes(pageRelPath: string, root: string): void;
|
|
4
|
+
export declare function deletePageTypes(pageRelPath: string, root: string): void;
|
|
5
|
+
export declare function scanAndWritePageTypes(appDir: string, root: string): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import{existsSync as d,mkdirSync as y,readdirSync as x,readFileSync as p,rmSync as m,statSync as P,writeFileSync as v}from"node:fs";import{join as s,relative as f}from"node:path";import{parseSync as D}from"oxc-parser";function l(r,t){let n=[];for(let e of x(r)){let o=s(r,e);P(o).isDirectory()?n.push(...l(o,t)):/\.(ts|tsx)$/.test(e)&&e!=="layout.tsx"&&e!=="error.tsx"&&n.push(f(t,o).replace(/\\/g,"/"))}return n}function h(r,t){let n=D(t,r,{sourceType:"module"});for(let e of n.program.body){if(e.type!=="ExportNamedDeclaration")continue;let o=e.declaration;if(o?.type==="FunctionDeclaration"&&o.id?.name==="loader")return!0;if(o?.type==="VariableDeclaration"){for(let i of o.declarations)if(i.id.type==="Identifier"&&i.id.name==="loader")return!0}for(let i of e.specifiers??[])if(i.exported.type==="Identifier"&&i.exported.name==="loader")return!0}return!1}function S(r,t){return t?`// auto-generado por devix \u2014 no editar
|
|
2
|
+
import type { loader } from "${r}"
|
|
3
|
+
import type { Redirect } from "@devlusoft/devix"
|
|
4
|
+
|
|
5
|
+
export type PageData = Exclude<
|
|
6
|
+
Awaited<ReturnType<NonNullable<typeof loader>>>,
|
|
7
|
+
Redirect | void | undefined
|
|
8
|
+
>
|
|
9
|
+
export type PageParams = NonNullable<Parameters<typeof loader>[0]>["params"]
|
|
10
|
+
`:`// auto-generado por devix - no editar
|
|
11
|
+
export type PageData = undefined
|
|
12
|
+
export type PageParams = Record<string, string>
|
|
13
|
+
`}function b(r,t){let n=s(t,r),e=p(n,"utf-8"),o=h(e,n),i=s(t,".devix","pages",r.replace(/\.(tsx?|jsx?)$/,"")),a=s(i,"$types.d.ts"),u=n.replace(/\.(tsx?|jsx?)$/,""),g=f(i,u).replace(/\\/g,"/"),c=S(g,o);d(a)&&p(a,"utf-8")===c||(y(i,{recursive:!0}),v(a,c,"utf-8"))}function w(r,t){let n=s(t,".devix","pages",r.replace(/\.(tsx?|jsx?)$/,"")),e=s(n,"$types.d.ts");d(e)&&m(e)}function j(r,t){let n=s(t,r,"pages"),e;try{e=l(n,t)}catch{return}for(let o of e)try{b(o,t)}catch{}}export{w as deletePageTypes,S as generatePageTypesDts,h as hasLoaderExport,j as scanAndWritePageTypes,b as writePageTypes};
|
|
14
|
+
//# sourceMappingURL=page-types.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/vite/codegen/page-types.ts"],
|
|
4
|
+
"sourcesContent": ["import {existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync} from \"node:fs\";\nimport {join, relative} from \"node:path\";\nimport {parseSync} from \"oxc-parser\";\n\nfunction walkPages(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(...walkPages(full, root))\n } else if (/\\.(ts|tsx)$/.test(name) && name !== 'layout.tsx' && name !== 'error.tsx') {\n entries.push(relative(root, full).replace(/\\\\/g, '/'))\n }\n }\n return entries\n}\n\nexport function hasLoaderExport(code: string, filePath: string): boolean {\n const ast = parseSync(filePath, code, {sourceType: 'module'})\n for (const node of ast.program.body) {\n if (node.type !== 'ExportNamedDeclaration') continue\n const decl = node.declaration\n if (decl?.type === 'FunctionDeclaration' && decl.id?.name === 'loader') return true\n if (decl?.type === 'VariableDeclaration') {\n for (const d of decl.declarations) {\n if (d.id.type === 'Identifier' && d.id.name === 'loader') return true\n }\n }\n for (const spec of (node.specifiers ?? [])) {\n if (spec.exported.type === 'Identifier' && spec.exported.name === 'loader') return true\n }\n }\n return false\n}\n\nexport function generatePageTypesDts(importPath: string, withLoader: boolean): string {\n if (!withLoader) {\n return '// auto-generado por devix - no editar\\nexport type PageData = undefined\\nexport type PageParams = Record<string, string>\\n'\n }\n return `// auto-generado por devix \u2014 no editar\\nimport type { loader } from \"${importPath}\"\\nimport type { Redirect } from \"@devlusoft/devix\"\\n\\nexport type PageData = Exclude<\\n Awaited<ReturnType<NonNullable<typeof loader>>>,\\n Redirect | void | undefined\\n>\\nexport type PageParams = NonNullable<Parameters<typeof loader>[0]>[\"params\"]\\n`\n}\n\nexport function writePageTypes(pageRelPath: string, root: string): void {\n const fullPath = join(root, pageRelPath)\n const code = readFileSync(fullPath, 'utf-8')\n const withLoader = hasLoaderExport(code, fullPath)\n\n const typesDir = join(root, '.devix', 'pages', pageRelPath.replace(/\\.(tsx?|jsx?)$/, ''))\n const outPath = join(typesDir, '$types.d.ts')\n\n const pageAbsNoExt = fullPath.replace(/\\.(tsx?|jsx?)$/, '')\n const importPath = relative(typesDir, pageAbsNoExt).replace(/\\\\/g, '/')\n\n const content = generatePageTypesDts(importPath, withLoader)\n\n if (existsSync(outPath) && readFileSync(outPath, 'utf-8') === content) return\n\n mkdirSync(typesDir, {recursive: true})\n writeFileSync(outPath, content, 'utf-8')\n}\n\nexport function deletePageTypes(pageRelPath: string, root: string): void {\n const typesDir = join(root, '.devix', 'pages', pageRelPath.replace(/\\.(tsx?|jsx?)$/, ''))\n const outPath = join(typesDir, '$types.d.ts')\n if (existsSync(outPath)) rmSync(outPath)\n}\n\nexport function scanAndWritePageTypes(appDir: string, root: string): void {\n const pagesDir = join(root, appDir, 'pages')\n let files: string[]\n try {\n files = walkPages(pagesDir, root)\n } catch {\n return\n }\n for (const file of files) {\n try {\n writePageTypes(file, root)\n } catch {\n /* ignorar archivos no procesables */\n }\n }\n}"],
|
|
5
|
+
"mappings": "AAAA,OAAQ,cAAAA,EAAY,aAAAC,EAAW,eAAAC,EAAa,gBAAAC,EAAc,UAAAC,EAAQ,YAAAC,EAAU,iBAAAC,MAAoB,UAChG,OAAQ,QAAAC,EAAM,YAAAC,MAAe,YAC7B,OAAQ,aAAAC,MAAgB,aAExB,SAASC,EAAUC,EAAaC,EAAwB,CACpD,IAAMC,EAAoB,CAAC,EAC3B,QAAWC,KAAQZ,EAAYS,CAAG,EAAG,CACjC,IAAMI,EAAOR,EAAKI,EAAKG,CAAI,EACvBT,EAASU,CAAI,EAAE,YAAY,EAC3BF,EAAQ,KAAK,GAAGH,EAAUK,EAAMH,CAAI,CAAC,EAC9B,cAAc,KAAKE,CAAI,GAAKA,IAAS,cAAgBA,IAAS,aACrED,EAAQ,KAAKL,EAASI,EAAMG,CAAI,EAAE,QAAQ,MAAO,GAAG,CAAC,CAE7D,CACA,OAAOF,CACX,CAEO,SAASG,EAAgBC,EAAcC,EAA2B,CACrE,IAAMC,EAAMV,EAAUS,EAAUD,EAAM,CAAC,WAAY,QAAQ,CAAC,EAC5D,QAAWG,KAAQD,EAAI,QAAQ,KAAM,CACjC,GAAIC,EAAK,OAAS,yBAA0B,SAC5C,IAAMC,EAAOD,EAAK,YAClB,GAAIC,GAAM,OAAS,uBAAyBA,EAAK,IAAI,OAAS,SAAU,MAAO,GAC/E,GAAIA,GAAM,OAAS,uBACf,QAAWC,KAAKD,EAAK,aACjB,GAAIC,EAAE,GAAG,OAAS,cAAgBA,EAAE,GAAG,OAAS,SAAU,MAAO,GAGzE,QAAWC,KAASH,EAAK,YAAc,CAAC,EACpC,GAAIG,EAAK,SAAS,OAAS,cAAgBA,EAAK,SAAS,OAAS,SAAU,MAAO,EAE3F,CACA,MAAO,EACX,CAEO,SAASC,EAAqBC,EAAoBC,EAA6B,CAClF,OAAKA,EAGE;AAAA,+BAAwED,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAF9E;AAAA;AAAA;AAAA,CAGf,CAEO,SAASE,EAAeC,EAAqBhB,EAAoB,CACpE,IAAMiB,EAAWtB,EAAKK,EAAMgB,CAAW,EACjCX,EAAOd,EAAa0B,EAAU,OAAO,EACrCH,EAAaV,EAAgBC,EAAMY,CAAQ,EAE3CC,EAAWvB,EAAKK,EAAM,SAAU,QAASgB,EAAY,QAAQ,iBAAkB,EAAE,CAAC,EAClFG,EAAUxB,EAAKuB,EAAU,aAAa,EAEtCE,EAAeH,EAAS,QAAQ,iBAAkB,EAAE,EACpDJ,EAAajB,EAASsB,EAAUE,CAAY,EAAE,QAAQ,MAAO,GAAG,EAEhEC,EAAUT,EAAqBC,EAAYC,CAAU,EAEvD1B,EAAW+B,CAAO,GAAK5B,EAAa4B,EAAS,OAAO,IAAME,IAE9DhC,EAAU6B,EAAU,CAAC,UAAW,EAAI,CAAC,EACrCxB,EAAcyB,EAASE,EAAS,OAAO,EAC3C,CAEO,SAASC,EAAgBN,EAAqBhB,EAAoB,CACrE,IAAMkB,EAAWvB,EAAKK,EAAM,SAAU,QAASgB,EAAY,QAAQ,iBAAkB,EAAE,CAAC,EAClFG,EAAUxB,EAAKuB,EAAU,aAAa,EACxC9B,EAAW+B,CAAO,GAAG3B,EAAO2B,CAAO,CAC3C,CAEO,SAASI,EAAsBC,EAAgBxB,EAAoB,CACtE,IAAMyB,EAAW9B,EAAKK,EAAMwB,EAAQ,OAAO,EACvCE,EACJ,GAAI,CACAA,EAAQ5B,EAAU2B,EAAUzB,CAAI,CACpC,MAAQ,CACJ,MACJ,CACA,QAAW2B,KAAQD,EACf,GAAI,CACAX,EAAeY,EAAM3B,CAAI,CAC7B,MAAQ,CAER,CAER",
|
|
6
|
+
"names": ["existsSync", "mkdirSync", "readdirSync", "readFileSync", "rmSync", "statSync", "writeFileSync", "join", "relative", "parseSync", "walkPages", "dir", "root", "entries", "name", "full", "hasLoaderExport", "code", "filePath", "ast", "node", "decl", "d", "spec", "generatePageTypesDts", "importPath", "withLoader", "writePageTypes", "pageRelPath", "fullPath", "typesDir", "outPath", "pageAbsNoExt", "content", "deletePageTypes", "scanAndWritePageTypes", "appDir", "pagesDir", "files", "file"]
|
|
7
|
+
}
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
function
|
|
1
|
+
function i(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function a(e,t){let n=e.slice(t.length+1).replace(/\\/g,"/"),o=i(n);return o==="/"?"/api":`/api/${o}`.replace("/api//","/api/")}function p(e,t){return"_api_"+e.slice(`${t}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function g(e,t,n){return{filePath:e,urlPattern:a(e,t),identifier:p(e,t),methods:n}}function f(e,t){if(e.length===0)return`// auto-generado por devix \u2014 no editar
|
|
2
|
+
export {}
|
|
2
3
|
declare module '@devlusoft/devix' {
|
|
3
4
|
interface ApiRoutes {}
|
|
4
5
|
}
|
|
5
|
-
`;let n=e.map(r=>{let
|
|
6
|
-
`),o=e.flatMap(r=>r.methods.map(
|
|
6
|
+
`;let n=e.map(r=>{let s="../"+r.filePath.replace(/\.(ts|tsx)$/,"");return`import type * as ${r.identifier} from '${s}'`}).join(`
|
|
7
|
+
`),o=e.flatMap(r=>r.methods.map(s=>` '${s} ${r.urlPattern}': InferRoute<(typeof ${r.identifier})['${s}']>`)).join(`
|
|
7
8
|
`);return`// auto-generado por devix \u2014 no editar
|
|
8
9
|
${n}
|
|
9
10
|
|
|
10
|
-
type JsonResponse<T> = Response & { readonly __body: T }
|
|
11
|
-
type
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
type JsonResponse<T, S extends number = number> = Response & { readonly __body: T; readonly __status: S }
|
|
12
|
+
type Is2xx<S extends number> = [number] extends [S] ? boolean : S extends 200 | 201 | 202 | 203 | 204 | 205 | 206 ? true : false
|
|
13
|
+
type UnwrapSuccessJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends false ? never : U : never
|
|
14
|
+
type UnwrapErrorJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends true ? never : U : never
|
|
15
|
+
type InferFnSuccess<T> = T extends (...args: any[]) => any ? UnwrapSuccessJson<Awaited<ReturnType<T>>> : never
|
|
16
|
+
type InferFnErrors<T> = T extends (...args: any[]) => any ? UnwrapErrorJson<Awaited<ReturnType<T>>> : never
|
|
15
17
|
type InferRoute<T> =
|
|
16
18
|
T extends { readonly __return?: infer TReturn; readonly __body?: infer TBody }
|
|
17
19
|
? {
|
|
18
20
|
__body: [TBody] extends [undefined] ? never : Exclude<TBody, undefined>
|
|
19
|
-
__response:
|
|
21
|
+
__response: InferFnSuccess<() => TReturn>
|
|
22
|
+
__errors: InferFnErrors<() => TReturn>
|
|
20
23
|
}
|
|
21
|
-
:
|
|
24
|
+
: InferFnSuccess<T>
|
|
22
25
|
|
|
23
26
|
declare module '@devlusoft/devix' {
|
|
24
27
|
interface ApiRoutes {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/utils/patterns.ts", "../../../src/server/api-router.ts", "../../../src/vite/codegen/routes-dts.ts"],
|
|
4
|
-
"sourcesContent": ["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 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\
|
|
5
|
-
"mappings": "AAAO,SAASA,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYO,SAASC,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,CCbO,SAASE,EAAqBC,EAAkBC,EAAwB,CAC3E,MAAO,QAAUD,EACZ,MAAM,GAAGC,CAAM,IAAI,MAAM,EACzB,QAAQ,cAAe,EAAE,EACzB,QAAQ,gBAAiB,GAAG,CACrC,CAEO,SAASC,EAAgBF,EAAkBC,EAAgBE,EAAmC,CACjG,MAAO,CACH,SAAAH,EACA,WAAYI,EAAkBJ,EAAUC,CAAM,EAC9C,WAAYF,EAAqBC,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["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 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\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\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 return {routes, middlewares}\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", "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\\nexport {}\\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, S extends number = number> = Response & { readonly __body: T; readonly __status: S }\ntype Is2xx<S extends number> = [number] extends [S] ? boolean : S extends 200 | 201 | 202 | 203 | 204 | 205 | 206 ? true : false\ntype UnwrapSuccessJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends false ? never : U : never\ntype UnwrapErrorJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends true ? never : U : never\ntype InferFnSuccess<T> = T extends (...args: any[]) => any ? UnwrapSuccessJson<Awaited<ReturnType<T>>> : never\ntype InferFnErrors<T> = T extends (...args: any[]) => any ? UnwrapErrorJson<Awaited<ReturnType<T>>> : 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: InferFnSuccess<() => TReturn>\n __errors: InferFnErrors<() => TReturn>\n }\n : InferFnSuccess<T>\n\ndeclare module '@devlusoft/devix' {\n interface ApiRoutes {\n${routeLines}\n }\n}\n`\n}\n"],
|
|
5
|
+
"mappings": "AAAO,SAASA,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYO,SAASC,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,CCbO,SAASE,EAAqBC,EAAkBC,EAAwB,CAC3E,MAAO,QAAUD,EACZ,MAAM,GAAGC,CAAM,IAAI,MAAM,EACzB,QAAQ,cAAe,EAAE,EACzB,QAAQ,gBAAiB,GAAG,CACrC,CAEO,SAASC,EAAgBF,EAAkBC,EAAgBE,EAAmC,CACjG,MAAO,CACH,SAAAH,EACA,WAAYI,EAAkBJ,EAAUC,CAAM,EAC9C,WAAYF,EAAqBC,EAAUC,CAAM,EACjD,QAAAE,CACJ,CACJ,CAEO,SAASE,EAAkBC,EAAuBL,EAAwB,CAC7E,GAAIK,EAAQ,SAAW,EACnB,MAAO;AAAA;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBPG,CAAU;AAAA;AAAA;AAAA,CAIZ",
|
|
6
6
|
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "filePathToIdentifier", "filePath", "apiDir", "buildRouteEntry", "methods", "keyToRoutePattern", "generateRoutesDts", "entries", "imports", "e", "importPath", "routeLines", "m"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readFileSync as m,readdirSync as
|
|
1
|
+
import{readFileSync as m,readdirSync as h,statSync as y}from"node:fs";import{join as o,relative as T}from"node:path";var f=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g;function g(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function a(e){let t=new Set;for(let r of g(e).matchAll(f))t.add(r[1]);return[...t]}function p(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function u(e,t){let r=e.slice(t.length+1).replace(/\\/g,"/"),s=p(r);return s==="/"?"/api":`/api/${s}`.replace("/api//","/api/")}function x(e,t){return"_api_"+e.slice(`${t}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function c(e,t,r){return{filePath:e,urlPattern:u(e,t),identifier:x(e,t),methods:r}}function d(e,t){let r=[];for(let s of h(e)){let n=o(e,s);y(n).isDirectory()?r.push(...d(n,t)):/\.(ts|tsx)$/.test(s)&&r.push(T(t,n).replace(/\\/g,"/"))}return r}function I(e,t){let r=o(t,e,"api"),s;try{s=d(r,t)}catch{return[]}return s.filter(n=>!n.endsWith("middleware.ts")&&!n.endsWith("middleware.tsx")).flatMap(n=>{try{let l=m(o(t,n),"utf-8"),i=a(l);return i.length===0?[]:[c(n,`${e}/api`,i)]}catch{return[]}})}export{I as scanApiFiles};
|
|
2
2
|
//# sourceMappingURL=scan-api.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/vite/codegen/scan-api.ts", "../../../src/vite/codegen/extract-methods.ts", "../../../src/utils/patterns.ts", "../../../src/server/api-router.ts", "../../../src/vite/codegen/routes-dts.ts"],
|
|
4
|
-
"sourcesContent": ["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", "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 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\
|
|
4
|
+
"sourcesContent": ["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", "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 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\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\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 return {routes, middlewares}\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", "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\\nexport {}\\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, S extends number = number> = Response & { readonly __body: T; readonly __status: S }\ntype Is2xx<S extends number> = [number] extends [S] ? boolean : S extends 200 | 201 | 202 | 203 | 204 | 205 | 206 ? true : false\ntype UnwrapSuccessJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends false ? never : U : never\ntype UnwrapErrorJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends true ? never : U : never\ntype InferFnSuccess<T> = T extends (...args: any[]) => any ? UnwrapSuccessJson<Awaited<ReturnType<T>>> : never\ntype InferFnErrors<T> = T extends (...args: any[]) => any ? UnwrapErrorJson<Awaited<ReturnType<T>>> : 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: InferFnSuccess<() => TReturn>\n __errors: InferFnErrors<() => TReturn>\n }\n : InferFnSuccess<T>\n\ndeclare module '@devlusoft/devix' {\n interface ApiRoutes {\n${routeLines}\n }\n}\n`\n}\n"],
|
|
5
5
|
"mappings": "AAAA,OAAQ,gBAAAA,EAAc,eAAAC,EAAa,YAAAC,MAAe,UAClD,OAAQ,QAAAC,EAAM,YAAAC,MAAe,YCE7B,IAAMC,EAAmB,6FAEzB,SAASC,EAAcC,EAAyB,CAC5C,OAAOA,EACF,QAAQ,oBAAqB,EAAE,EAC/B,QAAQ,YAAa,EAAE,CAChC,CAEO,SAASC,EAAmBD,EAA+B,CAC9D,IAAME,EAAQ,IAAI,IAClB,QAAWC,KAASJ,EAAcC,CAAO,EAAE,SAASF,CAAgB,EAChEI,EAAM,IAAIC,EAAM,CAAC,CAAe,EAEpC,MAAO,CAAC,GAAGD,CAAK,CACpB,CCjBO,SAASE,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYO,SAASC,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,CCbO,SAASE,EAAqBC,EAAkBC,EAAwB,CAC3E,MAAO,QAAUD,EACZ,MAAM,GAAGC,CAAM,IAAI,MAAM,EACzB,QAAQ,cAAe,EAAE,EACzB,QAAQ,gBAAiB,GAAG,CACrC,CAEO,SAASC,EAAgBF,EAAkBC,EAAgBE,EAAmC,CACjG,MAAO,CACH,SAAAH,EACA,WAAYI,EAAkBJ,EAAUC,CAAM,EAC9C,WAAYF,EAAqBC,EAAUC,CAAM,EACjD,QAAAE,CACJ,CACJ,CJlBA,SAASE,EAAQC,EAAaC,EAAwB,CAClD,IAAMC,EAAoB,CAAC,EAC3B,QAAWC,KAAQC,EAAYJ,CAAG,EAAG,CACjC,IAAMK,EAAOC,EAAKN,EAAKG,CAAI,EACvBI,EAASF,CAAI,EAAE,YAAY,EAC3BH,EAAQ,KAAK,GAAGH,EAAQM,EAAMJ,CAAI,CAAC,EAC5B,cAAc,KAAKE,CAAI,GAC9BD,EAAQ,KAAKM,EAASP,EAAMI,CAAI,EAAE,QAAQ,MAAO,GAAG,CAAC,CAE7D,CACA,OAAOH,CACX,CAEO,SAASO,EAAaC,EAAgBC,EAAmC,CAC5E,IAAMC,EAASN,EAAKK,EAAaD,EAAQ,KAAK,EAE1CG,EACJ,GAAI,CACAA,EAAQd,EAAQa,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,EAAUC,EAAaX,EAAKK,EAAaI,CAAQ,EAAG,OAAO,EAC3DG,EAAUC,EAAmBH,CAAO,EAC1C,OAAIE,EAAQ,SAAW,EAAU,CAAC,EAC3B,CAACE,EAAgBL,EAAU,GAAGL,CAAM,OAAQQ,CAAO,CAAC,CAC/D,MAAQ,CACJ,MAAO,CAAC,CACZ,CACJ,CAAC,CACT",
|
|
6
6
|
"names": ["readFileSync", "readdirSync", "statSync", "join", "relative", "METHOD_EXPORT_RE", "stripComments", "content", "extractHttpMethods", "found", "match", "routePattern", "rel", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "filePathToIdentifier", "filePath", "apiDir", "buildRouteEntry", "methods", "keyToRoutePattern", "walkDir", "dir", "root", "entries", "name", "readdirSync", "full", "join", "statSync", "relative", "scanApiFiles", "appDir", "projectRoot", "apiDir", "files", "f", "filePath", "content", "readFileSync", "methods", "extractHttpMethods", "buildRouteEntry"]
|
|
7
7
|
}
|
package/dist/vite/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{mergeConfig as
|
|
2
|
-
${
|
|
1
|
+
import{mergeConfig as Te}from"vite";import Se from"@vitejs/plugin-react";import{fileURLToPath as we}from"node:url";import{dirname as $e,relative as De,resolve as u}from"node:path";import{createRequire as Ae}from"node:module";function L({cssUrls:e}){return`
|
|
2
|
+
${e.map(r=>`import '${r}'`).join(`
|
|
3
3
|
`)}
|
|
4
4
|
import "@vitejs/plugin-react/preamble"
|
|
5
5
|
import React from "react"
|
|
@@ -19,7 +19,20 @@ if (!window.__DEVIX__) {
|
|
|
19
19
|
|
|
20
20
|
const matched = matchClientRoute(window.location.pathname)
|
|
21
21
|
|
|
22
|
-
if (
|
|
22
|
+
if (window.__LOADER_ERROR__) {
|
|
23
|
+
const {statusCode, message, data} = window.__LOADER_ERROR__
|
|
24
|
+
const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()
|
|
25
|
+
createRoot(root).render(
|
|
26
|
+
React.createElement(RouterProvider, {
|
|
27
|
+
clientEntry,
|
|
28
|
+
initialData: null,
|
|
29
|
+
initialParams: {},
|
|
30
|
+
initialPage: () => null,
|
|
31
|
+
initialError: {statusCode, message, data},
|
|
32
|
+
initialErrorPage: ErrorPage,
|
|
33
|
+
})
|
|
34
|
+
)
|
|
35
|
+
} else if (matched) {
|
|
23
36
|
const [pageMod, ...layoutMods] = await Promise.all([
|
|
24
37
|
matched.load(),
|
|
25
38
|
...matched.loadLayouts.map(l => l()),
|
|
@@ -62,12 +75,12 @@ if (!window.__DEVIX__) {
|
|
|
62
75
|
)
|
|
63
76
|
}
|
|
64
77
|
}
|
|
65
|
-
`}function
|
|
78
|
+
`}function j({pagesDir:e,matcherPath:t}){return`
|
|
66
79
|
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('/${
|
|
80
|
+
import { createMatcher } from '${t}'
|
|
81
|
+
const pageFiles = import.meta.glob(['/${e}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
82
|
+
const layoutFiles = import.meta.glob('/${e}/**/layout.tsx')
|
|
83
|
+
const errorFiles = import.meta.glob('/${e}/**/error.tsx')
|
|
71
84
|
|
|
72
85
|
export const matchClientRoute = createMatcher(pageFiles, layoutFiles)
|
|
73
86
|
|
|
@@ -90,16 +103,16 @@ export function getDefaultErrorPage() {
|
|
|
90
103
|
)
|
|
91
104
|
}
|
|
92
105
|
}
|
|
93
|
-
`}function
|
|
94
|
-
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${
|
|
106
|
+
`}function U({pagesDir:e,renderPath:t}){return`
|
|
107
|
+
import { render as _render, runLoader as _runLoader, getStaticRoutes as _getStaticRoutes } from '${t}'
|
|
95
108
|
|
|
96
|
-
const _pages = import.meta.glob(['/${
|
|
97
|
-
const _layouts = import.meta.glob('/${
|
|
109
|
+
const _pages = import.meta.glob(['/${e}/**/*.tsx', '!**/error.tsx', '!**/layout.tsx'])
|
|
110
|
+
const _layouts = import.meta.glob('/${e}/**/layout.tsx')
|
|
98
111
|
|
|
99
112
|
const _glob = {
|
|
100
113
|
pages: _pages,
|
|
101
114
|
layouts: _layouts,
|
|
102
|
-
pagesDir: '/${
|
|
115
|
+
pagesDir: '/${e}',
|
|
103
116
|
}
|
|
104
117
|
|
|
105
118
|
export function render(url, request, options) {
|
|
@@ -113,59 +126,62 @@ export function runLoader(url, request, options) {
|
|
|
113
126
|
export function getStaticRoutes() {
|
|
114
127
|
return _getStaticRoutes(_glob)
|
|
115
128
|
}
|
|
116
|
-
`}function
|
|
117
|
-
import { handleApiRequest as _handleApiRequest } from '${
|
|
129
|
+
`}function H({apiPath:e,appDir:t}){return`
|
|
130
|
+
import { handleApiRequest as _handleApiRequest } from '${e}'
|
|
118
131
|
|
|
119
|
-
const _routes = import.meta.glob(['/${
|
|
120
|
-
const _middlewares = import.meta.glob('/${
|
|
132
|
+
const _routes = import.meta.glob(['/${t}/api/**/*.ts', '!**/middleware.ts'])
|
|
133
|
+
const _middlewares = import.meta.glob('/${t}/api/**/middleware.ts')
|
|
121
134
|
|
|
122
135
|
const _glob = {
|
|
123
136
|
routes: _routes,
|
|
124
137
|
middlewares: _middlewares,
|
|
125
|
-
apiDir: '/${
|
|
138
|
+
apiDir: '/${t}/api',
|
|
126
139
|
}
|
|
127
140
|
|
|
128
141
|
export function handleApiRequest(url, request) {
|
|
129
142
|
return _handleApiRequest(url, request, _glob)
|
|
130
143
|
}
|
|
131
|
-
`}function
|
|
144
|
+
`}function N(){return`
|
|
132
145
|
export {RouterContext} from '@devlusoft/devix/runtime/context'
|
|
133
|
-
`}import{readFileSync as
|
|
146
|
+
`}import{readFileSync as ce,readdirSync as le,statSync as ue}from"node:fs";import{join as D,relative as pe}from"node:path";var ie=/export\s+(?:const|async\s+function|function)\s+(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\b/g;function se(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"")}function k(e){let t=new Set;for(let r of se(e).matchAll(ie))t.add(r[1]);return[...t]}function V(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function q(e,t){let r=e.slice(t.length+1).replace(/\\/g,"/"),n=V(r);return n==="/"?"/api":`/api/${n}`.replace("/api//","/api/")}function ae(e,t){return"_api_"+e.slice(`${t}/`.length).replace(/\.(ts|tsx)$/,"").replace(/[^a-zA-Z0-9]/g,"_")}function W(e,t,r){return{filePath:e,urlPattern:q(e,t),identifier:ae(e,t),methods:r}}function $(e,t){if(e.length===0)return`// auto-generado por devix \u2014 no editar
|
|
147
|
+
export {}
|
|
134
148
|
declare module '@devlusoft/devix' {
|
|
135
149
|
interface ApiRoutes {}
|
|
136
150
|
}
|
|
137
|
-
`;let
|
|
138
|
-
`),
|
|
151
|
+
`;let r=e.map(o=>{let a="../"+o.filePath.replace(/\.(ts|tsx)$/,"");return`import type * as ${o.identifier} from '${a}'`}).join(`
|
|
152
|
+
`),n=e.flatMap(o=>o.methods.map(a=>` '${a} ${o.urlPattern}': InferRoute<(typeof ${o.identifier})['${a}']>`)).join(`
|
|
139
153
|
`);return`// auto-generado por devix \u2014 no editar
|
|
140
|
-
${
|
|
154
|
+
${r}
|
|
141
155
|
|
|
142
|
-
type JsonResponse<T> = Response & { readonly __body: T }
|
|
143
|
-
type
|
|
144
|
-
type
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
type JsonResponse<T, S extends number = number> = Response & { readonly __body: T; readonly __status: S }
|
|
157
|
+
type Is2xx<S extends number> = [number] extends [S] ? boolean : S extends 200 | 201 | 202 | 203 | 204 | 205 | 206 ? true : false
|
|
158
|
+
type UnwrapSuccessJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends false ? never : U : never
|
|
159
|
+
type UnwrapErrorJson<T> = T extends JsonResponse<infer U, infer S> ? Is2xx<S> extends true ? never : U : never
|
|
160
|
+
type InferFnSuccess<T> = T extends (...args: any[]) => any ? UnwrapSuccessJson<Awaited<ReturnType<T>>> : never
|
|
161
|
+
type InferFnErrors<T> = T extends (...args: any[]) => any ? UnwrapErrorJson<Awaited<ReturnType<T>>> : never
|
|
147
162
|
type InferRoute<T> =
|
|
148
163
|
T extends { readonly __return?: infer TReturn; readonly __body?: infer TBody }
|
|
149
164
|
? {
|
|
150
165
|
__body: [TBody] extends [undefined] ? never : Exclude<TBody, undefined>
|
|
151
|
-
__response:
|
|
166
|
+
__response: InferFnSuccess<() => TReturn>
|
|
167
|
+
__errors: InferFnErrors<() => TReturn>
|
|
152
168
|
}
|
|
153
|
-
:
|
|
169
|
+
: InferFnSuccess<T>
|
|
154
170
|
|
|
155
171
|
declare module '@devlusoft/devix' {
|
|
156
172
|
interface ApiRoutes {
|
|
157
|
-
${
|
|
173
|
+
${n}
|
|
158
174
|
}
|
|
159
175
|
}
|
|
160
|
-
`}function
|
|
176
|
+
`}function B(e,t){let r=[];for(let n of le(e)){let o=D(e,n);ue(o).isDirectory()?r.push(...B(o,t)):/\.(ts|tsx)$/.test(n)&&r.push(pe(t,o).replace(/\\/g,"/"))}return r}function A(e,t){let r=D(t,e,"api"),n;try{n=B(r,t)}catch{return[]}return n.filter(o=>!o.endsWith("middleware.ts")&&!o.endsWith("middleware.tsx")).flatMap(o=>{try{let a=ce(D(t,o),"utf-8"),m=k(a);return m.length===0?[]:[W(o,`${e}/api`,m)]}catch{return[]}})}import{mkdirSync as de,readFileSync as me,writeFileSync as fe,existsSync as ge}from"node:fs";import{join as J}from"node:path";function b(e,t){let r=J(t,".devix"),n=J(r,"routes.d.ts");return de(r,{recursive:!0}),ge(n)&&me(n,"utf-8")===e?!1:(fe(n,e,"utf-8"),!0)}import{parseSync as be}from"oxc-parser";function G({routesPath:e,envPath:t,honoServerPath:r,honoServerStaticPath:n,honoPath:o}){return`
|
|
161
177
|
import { readFileSync } from 'node:fs'
|
|
162
|
-
import { serve } from '${
|
|
163
|
-
import { serveStatic } from '${
|
|
178
|
+
import { serve } from '${r}'
|
|
179
|
+
import { serveStatic } from '${n}'
|
|
164
180
|
import { Hono } from '${o}'
|
|
165
181
|
import { resolve, join, dirname } from 'node:path'
|
|
166
182
|
import { pathToFileURL } from 'node:url'
|
|
167
|
-
import { registerApiRoutes, registerSsrRoute } from '${
|
|
168
|
-
import { loadDotenv } from '${
|
|
183
|
+
import { registerApiRoutes, registerSsrRoute } from '${e}'
|
|
184
|
+
import { loadDotenv } from '${t}'
|
|
169
185
|
|
|
170
186
|
loadDotenv('production')
|
|
171
187
|
|
|
@@ -228,5 +244,17 @@ import { readFileSync } from 'node:fs'
|
|
|
228
244
|
|
|
229
245
|
process.on('SIGTERM', () => server.close())
|
|
230
246
|
process.on('SIGINT', () => server.close())
|
|
231
|
-
`}
|
|
247
|
+
`}import{existsSync as Y,mkdirSync as he,readdirSync as xe,readFileSync as X,rmSync as ye,statSync as Re,writeFileSync as ve}from"node:fs";import{join as f,relative as z}from"node:path";import{parseSync as _e}from"oxc-parser";function Z(e,t){let r=[];for(let n of xe(e)){let o=f(e,n);Re(o).isDirectory()?r.push(...Z(o,t)):/\.(ts|tsx)$/.test(n)&&n!=="layout.tsx"&&n!=="error.tsx"&&r.push(z(t,o).replace(/\\/g,"/"))}return r}function Ee(e,t){let r=_e(t,e,{sourceType:"module"});for(let n of r.program.body){if(n.type!=="ExportNamedDeclaration")continue;let o=n.declaration;if(o?.type==="FunctionDeclaration"&&o.id?.name==="loader")return!0;if(o?.type==="VariableDeclaration"){for(let a of o.declarations)if(a.id.type==="Identifier"&&a.id.name==="loader")return!0}for(let a of n.specifiers??[])if(a.exported.type==="Identifier"&&a.exported.name==="loader")return!0}return!1}function Pe(e,t){return t?`// auto-generado por devix \u2014 no editar
|
|
248
|
+
import type { loader } from "${e}"
|
|
249
|
+
import type { Redirect } from "@devlusoft/devix"
|
|
250
|
+
|
|
251
|
+
export type PageData = Exclude<
|
|
252
|
+
Awaited<ReturnType<NonNullable<typeof loader>>>,
|
|
253
|
+
Redirect | void | undefined
|
|
254
|
+
>
|
|
255
|
+
export type PageParams = NonNullable<Parameters<typeof loader>[0]>["params"]
|
|
256
|
+
`:`// auto-generado por devix - no editar
|
|
257
|
+
export type PageData = undefined
|
|
258
|
+
export type PageParams = Record<string, string>
|
|
259
|
+
`}function P(e,t){let r=f(t,e),n=X(r,"utf-8"),o=Ee(n,r),a=f(t,".devix","pages",e.replace(/\.(tsx?|jsx?)$/,"")),m=f(a,"$types.d.ts"),T=r.replace(/\.(tsx?|jsx?)$/,""),S=z(a,T).replace(/\\/g,"/"),g=Pe(S,o);Y(m)&&X(m,"utf-8")===g||(he(a,{recursive:!0}),ve(m,g,"utf-8"))}function K(e,t){let r=f(t,".devix","pages",e.replace(/\.(tsx?|jsx?)$/,"")),n=f(r,"$types.d.ts");Y(n)&&ye(n)}function C(e,t){let r=f(t,e,"pages"),n;try{n=Z(r,t)}catch{return}for(let o of n)try{P(o,t)}catch{}}var R=$e(we(import.meta.url)),I="virtual:devix/entry-client",M="virtual:devix/client-routes",v="virtual:devix/render",_="virtual:devix/api",O="virtual:devix/context",F="virtual:devix/server-entry",Q=new Set(["loader","guard","generateStaticParams","headers"]);function Rt(e){let t=e.appDir??"app",r=`${t}/pages`,n=(e.css??[]).map(i=>i.startsWith("/")?i:`/${i.replace(/^\.\//,"")}`),o=u(R,"../server/render.js").replace(/\\/g,"/"),a=u(R,"../server/api.js").replace(/\\/g,"/"),m=u(R,"../runtime/client-router.js").replace(/\\/g,"/"),T=u(R,"../server/routes.js").replace(/\\/g,"/"),S=u(R,"../utils/env.js").replace(/\\/g,"/"),g=Ae(import.meta.url),ee=g.resolve("@hono/node-server").replace(/\\/g,"/"),te=g.resolve("@hono/node-server/serve-static").replace(/\\/g,"/"),re=g.resolve("hono").replace(/\\/g,"/"),ne={name:"devix",enforce:"pre",resolveId(i){if(i===I)return`\0${I}`;if(i===M)return`\0${M}`;if(i===v)return`\0${v}`;if(i===_)return`\0${_}`;if(i===O)return`\0${O}`;if(i===F)return`\0${F}`},load(i){if(i===`\0${I}`)return L({cssUrls:n});if(i===`\0${M}`)return j({pagesDir:r,matcherPath:m});if(i===`\0${v}`)return U({pagesDir:r,renderPath:o});if(i===`\0${_}`)return H({apiPath:a,appDir:t});if(i===`\0${O}`)return N();if(i===`\0${F}`)return G({routesPath:T,envPath:S,honoServerPath:ee,honoServerStaticPath:te,honoPath:re})},transform(i,c,h){if(h?.ssr)return;let x=u(process.cwd(),r);if(!c.startsWith(x))return;let y=be(c,i,{sourceType:"module"}),p=[];for(let l of y.program.body){if(l.type!=="ExportNamedDeclaration"||!l.declaration)continue;let d=l.declaration;if(d.type==="FunctionDeclaration"&&d.id&&Q.has(d.id.name)&&p.push({start:l.start,end:l.end,name:d.id.name}),d.type==="VariableDeclaration"){let E=new Set;for(let w of d.declarations)w.id.type==="Identifier"&&Q.has(w.id.name)&&(E.has(l.start)||(E.add(l.start),p.push({start:l.start,end:l.end,name:w.id.name})))}}if(p.length===0)return;p.sort((l,d)=>d.start-l.start);let s=i;for(let{start:l,end:d,name:E}of p)s=s.slice(0,l)+`export const ${E} = undefined`+s.slice(d);return{code:s,map:null}},buildStart(){let i=process.cwd(),c=A(t,i);b($(c,`${t}/api`),i),C(t,i)},configureServer(i){let c=process.cwd();C(t,c);let h=()=>{let s=A(t,c);b($(s,`${t}/api`),c)},x=s=>s.startsWith(u(c,r))&&!s.endsWith("layout.tsx")&&!s.endsWith("error.tsx"),y=s=>De(c,s).replace(/\\/g,"/"),p=s=>{let l=i.moduleGraph.getModuleById(`\0${s}`);l&&i.moduleGraph.invalidateModule(l)};i.watcher.add(u(c,"devix.config.ts")),i.watcher.on("change",s=>{s===u(c,"devix.config.ts")&&(console.log("[devix] Config changed, restarting..."),process.exit(75))}),i.watcher.on("add",s=>{s.startsWith(u(c,r))&&p(v),x(s)&&P(y(s),c),s.includes(`${t}/api`)&&(p(_),h())}),i.watcher.on("unlink",s=>{s.startsWith(u(c,r))&&p(v),x(s)&&K(y(s),c),s.includes(`${t}/api`)&&(p(_),h())}),i.watcher.on("change",s=>{x(s)&&P(y(s),c),s.includes(`${t}/api`)&&!s.endsWith("middleware.ts")&&h()})}},oe={plugins:[Se(),ne],publicDir:u(process.cwd(),e.publicDir??"public"),ssr:{noExternal:["@devlusoft/devix"]},...e.envPrefix?{envPrefix:e.envPrefix}:{}};return Te(oe,e.vite??{})}export{Rt as devix};
|
|
232
260
|
//# sourceMappingURL=index.js.map
|