@devlusoft/devix 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- function p(e){let r={statusCode:e.statusCode,message:e.message};return e.code!==void 0&&(r.code=e.code),e.data!==void 0&&(r.data=e.data),r}function m(e,r){return g(r).test(e)}function f(e,r){if(!r||r.length===0)return!1;for(let t of r)if(m(e,t))return!0;return!1}function g(e){let r="",t=0;for(;t<e.length;){let n=e[t];if(n==="*"&&e[t+1]==="*")r+=".*",t+=2;else if(n==="*")r+="[^/]*",t+=1;else if(n===":"){for(t+=1;t<e.length&&/[a-zA-Z0-9_]/.test(e[t]);)t+=1;r+="[^/]+"}else".+?^$()|[]{}\\".includes(n)?(r+="\\"+n,t+=1):(r+=n,t+=1)}return new RegExp(`^${r}$`)}var y="/_devix/server";function l(e,r,t){let n=p({statusCode:e,message:r,code:t});return new Response(JSON.stringify(n),{status:e,headers:{"Content-Type":"application/json"}})}function x(e){if(!e.startsWith(y+"/"))return null;let r=e.slice(y.length+1),t=r.indexOf("/");return t===-1?{namespace:r,path:"/"}:{namespace:r.slice(0,t),path:r.slice(t)}}async function h(e,r){let t=new URL(e.url),n=x(t.pathname);if(!n)return l(404,"Not found","PROXY_NOT_FOUND");let i=r?.[n.namespace];if(!i)return l(404,`Backend "${n.namespace}" not configured`,"BACKEND_NOT_FOUND");if(!f(n.path,i.allowedPaths))return l(403,"Path not allowed","PATH_NOT_ALLOWED");if(f(n.path,i.deniedPaths))return l(403,"Path denied","PATH_DENIED");let o=new URL(n.path+t.search,i.url),a=new Headers;if(i.prepare){let s={request:e,headers:a,url:o};try{let c=await i.prepare(s);if(c instanceof Response)return c}catch(c){return console.error(`[devix] server.${n.namespace}.prepare error:`,c),l(500,"Proxy prepare failed","PREPARE_ERROR")}}if(!a.has("Accept")){let s=e.headers.get("Accept");s&&a.set("Accept",s)}let u=e.headers.get("Content-Type");u&&!a.has("Content-Type")&&a.set("Content-Type",u);let d=null;e.method!=="GET"&&e.method!=="HEAD"&&(d=await e.arrayBuffer(),d.byteLength===0&&(d=null));try{let s=await fetch(o,{method:e.method,headers:a,body:d,redirect:"manual"});return new Response(s.body,{status:s.status,statusText:s.statusText,headers:b(s.headers)})}catch(s){return console.error(`[devix] server.${n.namespace} fetch error:`,s),l(502,"Bad Gateway","BACKEND_UNREACHABLE")}}var E=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailers","transfer-encoding","upgrade"]);function b(e){let r=new Headers;return e.forEach((t,n)=>{E.has(n.toLowerCase())||r.set(n,t)}),r}function A(e,{apiModule:r,renderModule:t,loaderTimeout:n,server:i}){i&&e.all("/_devix/server/*",async o=>{try{return await h(o.req.raw,i)}catch(a){return console.error("[devix] proxy fatal error:",a),o.json({statusCode:500,message:"Internal Server Error"},500)}}),e.all("/api/*",async o=>{try{return await r.handleApiRequest(o.req.url,o.req.raw,i)}catch(a){return console.error(a),o.json({statusCode:500,message:"Internal Server Error"},500)}}),e.get("/_data/*",async o=>{try{let{pathname:a,search:u}=new URL(o.req.url,"http://localhost"),d=a.replace(/^\/_data/,"")+u,s=await t.runLoader(d,o.req.raw,{loaderTimeout:n,server:i});if(s.error)return o.json({statusCode:500,message:"Internal Server Error"},500);if("loaderError"in s){let c=p(s.loaderError);return o.json(c,c.statusCode)}return o.json(s)}catch(a){return console.error(a),o.json({statusCode:500,message:"Internal Server Error"},500)}})}function v(e,{renderModule:r,manifest:t,loaderTimeout:n,server:i}){e.get("*",async o=>{try{let{html:a,statusCode:u,headers:d}=await r.render(o.req.url,o.req.raw,{manifest:t,loaderTimeout:n,server:i}),s=o.html(`<!DOCTYPE html>${a}`,u);for(let[c,R]of Object.entries(d))s.headers.set(c,R);return s}catch(a){return console.error(a),o.text("Internal Server Error",500)}})}export{A as registerApiRoutes,v as registerSsrRoute};
1
+ function p(e){let r={statusCode:e.statusCode,message:e.message};return e.code!==void 0&&(r.code=e.code),e.data!==void 0&&(r.data=e.data),r}function m(e,r){return g(r).test(e)}function f(e,r){if(!r||r.length===0)return!1;for(let t of r)if(m(e,t))return!0;return!1}function g(e){let r="",t=0;for(;t<e.length;){let n=e[t];if(n==="*"&&e[t+1]==="*")r+=".*",t+=2;else if(n==="*")r+="[^/]*",t+=1;else if(n===":"){for(t+=1;t<e.length&&/[a-zA-Z0-9_]/.test(e[t]);)t+=1;r+="[^/]+"}else".+?^$()|[]{}\\".includes(n)?(r+="\\"+n,t+=1):(r+=n,t+=1)}return new RegExp(`^${r}$`)}var y="/_devix/server";function l(e,r,t){let n=p({statusCode:e,message:r,code:t});return new Response(JSON.stringify(n),{status:e,headers:{"Content-Type":"application/json"}})}function x(e){if(!e.startsWith(y+"/"))return null;let r=e.slice(y.length+1),t=r.indexOf("/");return t===-1?{namespace:r,path:"/"}:{namespace:r.slice(0,t),path:r.slice(t)}}async function h(e,r){let t=new URL(e.url),n=x(t.pathname);if(!n)return l(404,"Not found","PROXY_NOT_FOUND");let i=r?.[n.namespace];if(!i)return l(404,`Backend "${n.namespace}" not configured`,"BACKEND_NOT_FOUND");if(!f(n.path,i.allowedPaths))return l(403,"Path not allowed","PATH_NOT_ALLOWED");if(f(n.path,i.deniedPaths))return l(403,"Path denied","PATH_DENIED");let o=new URL(n.path+t.search,i.url),a=new Headers;if(i.prepare){let s={request:e,headers:a,url:o};try{let c=await i.prepare(s);if(c instanceof Response)return c}catch(c){return console.error(`[devix] server.${n.namespace}.prepare error:`,c),l(500,"Proxy prepare failed","PREPARE_ERROR")}}if(!a.has("Accept")){let s=e.headers.get("Accept");s&&a.set("Accept",s)}let u=e.headers.get("Content-Type");u&&!a.has("Content-Type")&&a.set("Content-Type",u);let d=null;e.method!=="GET"&&e.method!=="HEAD"&&(d=await e.arrayBuffer(),d.byteLength===0&&(d=null));try{let s=await fetch(o,{method:e.method,headers:a,body:d,redirect:"manual"});return new Response(s.body,{status:s.status,statusText:s.statusText,headers:C(s.headers)})}catch(s){return console.error(`[devix] server.${n.namespace} fetch error:`,s),l(502,"Bad Gateway","BACKEND_UNREACHABLE")}}var E=new Set(["connection","keep-alive","proxy-authenticate","proxy-authorization","te","trailers","transfer-encoding","upgrade"]);function C(e){let r=new Headers;return e.forEach((t,n)=>{E.has(n.toLowerCase())||r.set(n,t)}),r}function A(e,{apiModule:r,renderModule:t,loaderTimeout:n,server:i}){i&&e.all("/_devix/server/*",async o=>{try{return await h(o.req.raw,i)}catch(a){return console.error("[devix] proxy fatal error:",a),o.json({statusCode:500,message:"Internal Server Error"},500)}}),e.all("/api/*",async o=>{try{return await r.handleApiRequest(o.req.url,o.req.raw,i)}catch(a){return console.error(a),o.json({statusCode:500,message:"Internal Server Error"},500)}}),e.get("/_data/*",async o=>{try{let{pathname:a,search:u}=new URL(o.req.url,"http://localhost"),d=a.replace(/^\/_data/,"")+u,s=await t.runLoader(d,o.req.raw,{loaderTimeout:n,server:i});if(s.error)return o.json({statusCode:500,message:"Internal Server Error"},500);if("loaderError"in s){let c=p(s.loaderError);return o.json(c,c.statusCode)}return o.json(s)}catch(a){return console.error(a),o.json({statusCode:500,message:"Internal Server Error"},500)}})}function v(e,{renderModule:r,manifest:t,loaderTimeout:n,server:i}){e.get("*",async o=>{try{let{html:a,statusCode:u,headers:d}=await r.render(o.req.url,o.req.raw,{manifest:t,loaderTimeout:n,server:i}),s=o.html(`<!DOCTYPE html>${a}`,u);for(let[c,R]of Object.entries(d))s.headers.set(c,R);return s}catch(a){return console.error(a),o.text("Internal Server Error",500)}})}export{A as registerApiRoutes,v as registerSsrRoute};
2
2
  //# sourceMappingURL=routes.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/response.ts", "../../src/utils/glob.ts", "../../src/server/server-proxy.ts", "../../src/server/routes.ts"],
4
- "sourcesContent": ["export type JsonResponse<T = unknown, S extends number = number> = Response & {\n readonly __body: T\n readonly __status: S\n}\n\nexport function json<const T>(data: T): JsonResponse<T, 200>\nexport function json<const T, const S extends number>(data: T, status: S): JsonResponse<T, S>\nexport function json<const T>(data: T, status: number = 200): JsonResponse<T, any> {\n return new Response(JSON.stringify(data), {\n status,\n headers: {'Content-Type': 'application/json'},\n }) as JsonResponse<T, any>\n}\n\nexport const text = (body: string, status = 200): Response =>\n new Response(body, {status, headers: {'Content-Type': 'text/plain; charset=utf-8'}})\n\nconst REDIRECT_BRAND = Symbol.for('devix.redirect')\n\nexport interface RedirectOptions {\n status?: number\n replace?: boolean\n}\n\nexport interface Redirect {\n readonly [REDIRECT_BRAND]: true\n readonly url: string\n readonly status: number\n readonly replace: boolean\n}\n\nexport function redirect(url: string, statusOrOptions?: number | RedirectOptions): Redirect {\n const status = typeof statusOrOptions === 'number' ? statusOrOptions : (statusOrOptions?.status ?? 302)\n const replace = typeof statusOrOptions === 'object' ? (statusOrOptions?.replace ?? false) : false\n return {[REDIRECT_BRAND]: true, url, status, replace} as Redirect\n}\n\nexport function isRedirect(value: unknown): value is Redirect {\n return typeof value === 'object' && value !== null && REDIRECT_BRAND in value\n}\n\nconst ERROR_BRAND = Symbol.for('devix.loaderError')\n\nexport interface RouteError {\n readonly [ERROR_BRAND]: true\n readonly statusCode: number\n readonly message: string\n readonly code?: string\n readonly data?: unknown\n}\n\nexport interface ErrorOptions {\n code?: string\n data?: unknown\n}\n\n/**\n * Crea un error tipado que funciona en loaders, guards y handlers API.\n *\n * En loaders/guards: ret\u00F3rnalo (no lo lances) y el sistema renderiza `error.tsx`.\n * En handlers API: ret\u00F3rnalo y el sistema serializa el shape `ErrorBody` como JSON\n * con el statusCode correcto.\n *\n * ```ts\n * return error(404, 'Post no encontrado', { code: 'POST_NOT_FOUND' })\n * ```\n */\nexport function error(statusCode: number, message: string, options?: ErrorOptions): RouteError {\n return {\n [ERROR_BRAND]: true,\n statusCode,\n message,\n code: options?.code,\n data: options?.data,\n } as RouteError\n}\n\nexport function isLoaderError(value: unknown): value is RouteError {\n return typeof value === 'object' && value !== null && ERROR_BRAND in value\n}\n\n/**\n * Shape p\u00FAblico del body de un error API. Todos los errores emitidos por `error()`\n * o `DevixError` se serializan a este shape. `FetchError.body` del cliente lo recibe.\n */\nexport interface ErrorBody {\n statusCode: number\n message: string\n code?: string\n data?: unknown\n}\n\nexport function errorToBody(err: { statusCode: number; message: string; code?: string; data?: unknown }): ErrorBody {\n const body: ErrorBody = { statusCode: err.statusCode, message: err.message }\n if (err.code !== undefined) body.code = err.code\n if (err.data !== undefined) body.data = err.data\n return body\n}\n", "/**\n * Match simple de path contra un glob estilo `'/v1/**'`, `'/v1/users/*'`, `'/v1/users/:id'`.\n *\n * Reglas:\n * - `**` matchea cualquier subpath (incluye `/`).\n * - `*` matchea un \u00FAnico segmento (sin `/`).\n * - `:param` matchea un \u00FAnico segmento.\n * - Cualquier otro caracter es literal.\n */\nexport function matchPathGlob(path: string, pattern: string): boolean {\n const regex = globToRegex(pattern)\n return regex.test(path)\n}\n\nexport function matchesAnyGlob(path: string, patterns: readonly string[] | undefined): boolean {\n if (!patterns || patterns.length === 0) return false\n for (const pattern of patterns) {\n if (matchPathGlob(path, pattern)) return true\n }\n return false\n}\n\nfunction globToRegex(pattern: string): RegExp {\n let regex = ''\n let i = 0\n while (i < pattern.length) {\n const c = pattern[i]\n if (c === '*' && pattern[i + 1] === '*') {\n regex += '.*'\n i += 2\n } else if (c === '*') {\n regex += '[^/]*'\n i += 1\n } else if (c === ':') {\n i += 1\n while (i < pattern.length && /[a-zA-Z0-9_]/.test(pattern[i])) i += 1\n regex += '[^/]+'\n } else if ('.+?^$()|[]{}\\\\'.includes(c)) {\n regex += '\\\\' + c\n i += 1\n } else {\n regex += c\n i += 1\n }\n }\n return new RegExp(`^${regex}$`)\n}\n", "import type {ServerBackendConfig, PrepareContext} from '../config'\nimport {matchesAnyGlob} from '../utils/glob'\nimport {errorToBody} from '../utils/response'\n\nconst PROXY_PREFIX = '/_devix/server'\n\nfunction jsonError(statusCode: number, message: string, code?: string): Response {\n const body = errorToBody({statusCode, message, code})\n return new Response(JSON.stringify(body), {\n status: statusCode,\n headers: {'Content-Type': 'application/json'},\n })\n}\n\n/**\n * Parsea `/_devix/server/<namespace>/<path>` \u2192 `{namespace, path}`.\n * Retorna null si el path no es un request al proxy.\n */\nexport function parseProxyPath(pathname: string): {namespace: string; path: string} | null {\n if (!pathname.startsWith(PROXY_PREFIX + '/')) return null\n const rest = pathname.slice(PROXY_PREFIX.length + 1)\n const slash = rest.indexOf('/')\n if (slash === -1) {\n return {namespace: rest, path: '/'}\n }\n return {namespace: rest.slice(0, slash), path: rest.slice(slash)}\n}\n\n/**\n * Maneja un request entrante al proxy interno. Aplica allowlist/denylist,\n * ejecuta `prepare`, y reenv\u00EDa al backend configurado.\n */\nexport async function handleProxyRequest(\n request: Request,\n config: Record<string, ServerBackendConfig> | undefined,\n): Promise<Response> {\n const url = new URL(request.url)\n const parsed = parseProxyPath(url.pathname)\n if (!parsed) {\n return jsonError(404, 'Not found', 'PROXY_NOT_FOUND')\n }\n\n const backend = config?.[parsed.namespace]\n if (!backend) {\n return jsonError(404, `Backend \"${parsed.namespace}\" not configured`, 'BACKEND_NOT_FOUND')\n }\n\n if (!matchesAnyGlob(parsed.path, backend.allowedPaths)) {\n return jsonError(403, 'Path not allowed', 'PATH_NOT_ALLOWED')\n }\n if (matchesAnyGlob(parsed.path, backend.deniedPaths)) {\n return jsonError(403, 'Path denied', 'PATH_DENIED')\n }\n\n const targetUrl = new URL(parsed.path + url.search, backend.url)\n const headers = new Headers()\n\n if (backend.prepare) {\n const ctx: PrepareContext = {request, headers, url: targetUrl}\n try {\n const result = await backend.prepare(ctx)\n if (result instanceof Response) return result\n } catch (err) {\n console.error(`[devix] server.${parsed.namespace}.prepare error:`, err)\n return jsonError(500, 'Proxy prepare failed', 'PREPARE_ERROR')\n }\n }\n\n if (!headers.has('Accept')) {\n const accept = request.headers.get('Accept')\n if (accept) headers.set('Accept', accept)\n }\n const ct = request.headers.get('Content-Type')\n if (ct && !headers.has('Content-Type')) headers.set('Content-Type', ct)\n\n let body: BodyInit | null = null\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n body = await request.arrayBuffer()\n if ((body as ArrayBuffer).byteLength === 0) body = null\n }\n\n try {\n const backendRes = await fetch(targetUrl, {\n method: request.method,\n headers,\n body,\n redirect: 'manual',\n })\n return new Response(backendRes.body, {\n status: backendRes.status,\n statusText: backendRes.statusText,\n headers: filterHopByHop(backendRes.headers),\n })\n } catch (err) {\n console.error(`[devix] server.${parsed.namespace} fetch error:`, err)\n return jsonError(502, 'Bad Gateway', 'BACKEND_UNREACHABLE')\n }\n}\n\nconst HOP_BY_HOP = new Set([\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailers', 'transfer-encoding', 'upgrade',\n])\n\nfunction filterHopByHop(src: Headers): Headers {\n const dst = new Headers()\n src.forEach((value, key) => {\n if (!HOP_BY_HOP.has(key.toLowerCase())) dst.set(key, value)\n })\n return dst\n}\n\nexport const PROXY_PATH_PREFIX = PROXY_PREFIX\n", "import type {Hono} from 'hono'\nimport type {ContentfulStatusCode} from 'hono/utils/http-status'\nimport type {Manifest} from 'vite'\nimport {errorToBody} from \"../utils/response\"\nimport type {ServerBackendConfig} from \"../config\"\nimport {handleProxyRequest} from \"./server-proxy\"\n\ninterface ServerOptions {\n renderModule: any\n apiModule: any\n manifest?: Manifest\n loaderTimeout?: number\n server?: Record<string, ServerBackendConfig>\n}\n\nexport function registerApiRoutes(app: Hono, {apiModule, renderModule, loaderTimeout, server}: ServerOptions) {\n if (server) {\n app.all('/_devix/server/*', async (c) => {\n try {\n return await handleProxyRequest(c.req.raw, server)\n } catch (e) {\n console.error('[devix] proxy fatal error:', e)\n return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n }\n })\n }\n\n app.all('/api/*', async (c) => {\n try {\n return await apiModule.handleApiRequest(c.req.url, c.req.raw, server)\n } catch (e) {\n console.error(e)\n return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n }\n })\n\n app.get('/_data/*', async (c) => {\n try {\n const {pathname, search} = new URL(c.req.url, 'http://localhost')\n const url = pathname.replace(/^\\/_data/, '') + search\n\n const data = await renderModule.runLoader(url, c.req.raw, {loaderTimeout, server})\n if (data.error) return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n if ('loaderError' in data) {\n const body = errorToBody(data.loaderError)\n return c.json(body, body.statusCode as ContentfulStatusCode)\n }\n return c.json(data)\n } catch (e) {\n console.error(e)\n return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n }\n })\n}\n\nexport function registerSsrRoute(app: Hono, {renderModule, manifest, loaderTimeout, server}: ServerOptions) {\n app.get('*', async (c) => {\n try {\n const {html, statusCode, headers} = await renderModule.render(c.req.url, c.req.raw, {manifest, loaderTimeout, server})\n const res = c.html(`<!DOCTYPE html>${html}`, statusCode)\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n res.headers.set(key, value)\n }\n return res\n } catch (e) {\n console.error(e)\n return c.text('Internal Server Error', 500)\n }\n })\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export type JsonResponse<T = unknown, S extends number = number> = Response & {\n readonly __body: T\n readonly __status: S\n}\n\nexport function json<const T>(data: T): JsonResponse<T, 200>\nexport function json<const T, const S extends number>(data: T, status: S): JsonResponse<T, S>\nexport function json<const T>(data: T, status: number = 200): JsonResponse<T, any> {\n return new Response(JSON.stringify(data), {\n status,\n headers: {'Content-Type': 'application/json'},\n }) as JsonResponse<T, any>\n}\n\nexport const text = (body: string, status = 200): Response =>\n new Response(body, {status, headers: {'Content-Type': 'text/plain; charset=utf-8'}})\n\nconst REDIRECT_BRAND = Symbol.for('devix.redirect')\n\nexport interface RedirectOptions {\n status?: number\n replace?: boolean\n}\n\nexport interface Redirect {\n readonly [REDIRECT_BRAND]: true\n readonly url: string\n readonly status: number\n readonly replace: boolean\n}\n\nexport function redirect(url: string, statusOrOptions?: number | RedirectOptions): Redirect {\n const status = typeof statusOrOptions === 'number' ? statusOrOptions : (statusOrOptions?.status ?? 302)\n const replace = typeof statusOrOptions === 'object' ? (statusOrOptions?.replace ?? false) : false\n return {[REDIRECT_BRAND]: true, url, status, replace} as Redirect\n}\n\nexport function isRedirect(value: unknown): value is Redirect {\n return typeof value === 'object' && value !== null && REDIRECT_BRAND in value\n}\n\nconst ERROR_BRAND = Symbol.for('devix.loaderError')\n\nexport interface RouteError {\n readonly [ERROR_BRAND]: true\n readonly statusCode: number\n readonly message: string\n readonly code?: string\n readonly data?: unknown\n}\n\nexport interface ErrorOptions {\n code?: string\n data?: unknown\n}\n\n/**\n * Crea un error tipado que funciona en loaders, guards y handlers API.\n *\n * En loaders/guards: ret\u00F3rnalo (no lo lances) y el sistema renderiza `error.tsx`.\n * En handlers API: ret\u00F3rnalo y el sistema serializa el shape `ErrorBody` como JSON\n * con el statusCode correcto.\n *\n * ```ts\n * return error(404, 'Post no encontrado', { code: 'POST_NOT_FOUND' })\n * ```\n */\nexport function error(statusCode: number, message: string, options?: ErrorOptions): RouteError {\n return {\n [ERROR_BRAND]: true,\n statusCode,\n message,\n code: options?.code,\n data: options?.data,\n } as RouteError\n}\n\nexport function isLoaderError(value: unknown): value is RouteError {\n return typeof value === 'object' && value !== null && ERROR_BRAND in value\n}\n\n/**\n * Shape p\u00FAblico del body de un error API. Todos los errores emitidos por `error()`\n * o `DevixError` se serializan a este shape. `FetchError.body` del cliente lo recibe.\n */\nexport interface ErrorBody {\n statusCode: number\n message: string\n code?: string\n data?: unknown\n}\n\nexport function errorToBody(err: { statusCode: number; message: string; code?: string; data?: unknown }): ErrorBody {\n const body: ErrorBody = { statusCode: err.statusCode, message: err.message }\n if (err.code !== undefined) body.code = err.code\n if (err.data !== undefined) body.data = err.data\n return body\n}\n", "/**\n * Match simple de path contra un glob estilo `'/v1/**'`, `'/v1/users/*'`, `'/v1/users/:id'`.\n *\n * Reglas:\n * - `**` matchea cualquier subpath (incluye `/`).\n * - `*` matchea un \u00FAnico segmento (sin `/`).\n * - `:param` matchea un \u00FAnico segmento.\n * - Cualquier otro caracter es literal.\n */\nexport function matchPathGlob(path: string, pattern: string): boolean {\n const regex = globToRegex(pattern)\n return regex.test(path)\n}\n\nexport function matchesAnyGlob(path: string, patterns: readonly string[] | undefined): boolean {\n if (!patterns || patterns.length === 0) return false\n for (const pattern of patterns) {\n if (matchPathGlob(path, pattern)) return true\n }\n return false\n}\n\nfunction globToRegex(pattern: string): RegExp {\n let regex = ''\n let i = 0\n while (i < pattern.length) {\n const c = pattern[i]\n if (c === '*' && pattern[i + 1] === '*') {\n regex += '.*'\n i += 2\n } else if (c === '*') {\n regex += '[^/]*'\n i += 1\n } else if (c === ':') {\n i += 1\n while (i < pattern.length && /[a-zA-Z0-9_]/.test(pattern[i])) i += 1\n regex += '[^/]+'\n } else if ('.+?^$()|[]{}\\\\'.includes(c)) {\n regex += '\\\\' + c\n i += 1\n } else {\n regex += c\n i += 1\n }\n }\n return new RegExp(`^${regex}$`)\n}\n", "import type {ServerBackendConfig, PrepareContext} from '../config'\nimport {matchesAnyGlob} from '../utils/glob'\nimport {errorToBody} from '../utils/response'\n\nconst PROXY_PREFIX = '/_devix/server'\n\nfunction jsonError(statusCode: number, message: string, code?: string): Response {\n const body = errorToBody({statusCode, message, code})\n return new Response(JSON.stringify(body), {\n status: statusCode,\n headers: {'Content-Type': 'application/json'},\n })\n}\n\n/**\n * Parsea `/_devix/server/<namespace>/<path>` \u2192 `{namespace, path}`.\n * Retorna null si el path no es un request al proxy.\n */\nexport function parseProxyPath(pathname: string): {namespace: string; path: string} | null {\n if (!pathname.startsWith(PROXY_PREFIX + '/')) return null\n const rest = pathname.slice(PROXY_PREFIX.length + 1)\n const slash = rest.indexOf('/')\n if (slash === -1) {\n return {namespace: rest, path: '/'}\n }\n return {namespace: rest.slice(0, slash), path: rest.slice(slash)}\n}\n\n/**\n * Maneja un request entrante al proxy interno. Aplica allowlist/denylist,\n * ejecuta `prepare`, y reenv\u00EDa al backend configurado.\n */\nexport async function handleProxyRequest(\n request: Request,\n config: Record<string, ServerBackendConfig> | undefined,\n): Promise<Response> {\n const url = new URL(request.url)\n const parsed = parseProxyPath(url.pathname)\n if (!parsed) {\n return jsonError(404, 'Not found', 'PROXY_NOT_FOUND')\n }\n\n const backend = config?.[parsed.namespace]\n if (!backend) {\n return jsonError(404, `Backend \"${parsed.namespace}\" not configured`, 'BACKEND_NOT_FOUND')\n }\n\n if (!matchesAnyGlob(parsed.path, backend.allowedPaths)) {\n return jsonError(403, 'Path not allowed', 'PATH_NOT_ALLOWED')\n }\n if (matchesAnyGlob(parsed.path, backend.deniedPaths)) {\n return jsonError(403, 'Path denied', 'PATH_DENIED')\n }\n\n const targetUrl = new URL(parsed.path + url.search, backend.url)\n const headers = new Headers()\n\n if (backend.prepare) {\n const ctx: PrepareContext = {request, headers, url: targetUrl}\n try {\n const result = await backend.prepare(ctx)\n if (result instanceof Response) return result\n } catch (err) {\n console.error(`[devix] server.${parsed.namespace}.prepare error:`, err)\n return jsonError(500, 'Proxy prepare failed', 'PREPARE_ERROR')\n }\n }\n\n if (!headers.has('Accept')) {\n const accept = request.headers.get('Accept')\n if (accept) headers.set('Accept', accept)\n }\n const ct = request.headers.get('Content-Type')\n if (ct && !headers.has('Content-Type')) headers.set('Content-Type', ct)\n\n let body: BodyInit | null = null\n if (request.method !== 'GET' && request.method !== 'HEAD') {\n body = await request.arrayBuffer()\n if ((body as ArrayBuffer).byteLength === 0) body = null\n }\n\n try {\n const backendRes = await fetch(targetUrl, {\n method: request.method,\n headers,\n body,\n redirect: 'manual',\n })\n return new Response(backendRes.body, {\n status: backendRes.status,\n statusText: backendRes.statusText,\n headers: filterHopByHop(backendRes.headers),\n })\n } catch (err) {\n console.error(`[devix] server.${parsed.namespace} fetch error:`, err)\n return jsonError(502, 'Bad Gateway', 'BACKEND_UNREACHABLE')\n }\n}\n\nconst HOP_BY_HOP = new Set([\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailers', 'transfer-encoding', 'upgrade',\n])\n\nfunction filterHopByHop(src: Headers): Headers {\n const dst = new Headers()\n src.forEach((value, key) => {\n if (!HOP_BY_HOP.has(key.toLowerCase())) dst.set(key, value)\n })\n return dst\n}\n\nexport const PROXY_PATH_PREFIX = PROXY_PREFIX\n", "import type {Context, Hono} from 'hono'\nimport type {ContentfulStatusCode} from 'hono/utils/http-status'\nimport type {Manifest} from 'vite'\nimport {errorToBody} from \"../utils/response\"\nimport type {ServerBackendConfig} from \"../config\"\nimport {handleProxyRequest} from \"./server-proxy\"\n\ninterface ServerOptions {\n renderModule: any\n apiModule: any\n manifest?: Manifest\n loaderTimeout?: number\n server?: Record<string, ServerBackendConfig>\n}\n\nexport function registerApiRoutes(app: Hono, {apiModule, renderModule, loaderTimeout, server}: ServerOptions) {\n if (server) {\n app.all('/_devix/server/*', async (c: Context) => {\n try {\n return await handleProxyRequest(c.req.raw, server)\n } catch (e) {\n console.error('[devix] proxy fatal error:', e)\n return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n }\n })\n }\n\n app.all('/api/*', async (c: Context) => {\n try {\n return await apiModule.handleApiRequest(c.req.url, c.req.raw, server)\n } catch (e) {\n console.error(e)\n return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n }\n })\n\n app.get('/_data/*', async (c: Context) => {\n try {\n const {pathname, search} = new URL(c.req.url, 'http://localhost')\n const url = pathname.replace(/^\\/_data/, '') + search\n\n const data = await renderModule.runLoader(url, c.req.raw, {loaderTimeout, server})\n if (data.error) return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n if ('loaderError' in data) {\n const body = errorToBody(data.loaderError)\n return c.json(body, body.statusCode as ContentfulStatusCode)\n }\n return c.json(data)\n } catch (e) {\n console.error(e)\n return c.json({statusCode: 500, message: 'Internal Server Error'}, 500)\n }\n })\n}\n\nexport function registerSsrRoute(app: Hono, {renderModule, manifest, loaderTimeout, server}: ServerOptions) {\n app.get('*', async (c: Context) => {\n try {\n const {html, statusCode, headers} = await renderModule.render(c.req.url, c.req.raw, {manifest, loaderTimeout, server})\n const res = c.html(`<!DOCTYPE html>${html}`, statusCode)\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n res.headers.set(key, value)\n }\n return res\n } catch (e) {\n console.error(e)\n return c.text('Internal Server Error', 500)\n }\n })\n}"],
5
+ "mappings": "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",
6
6
  "names": ["errorToBody", "err", "body", "matchPathGlob", "path", "pattern", "globToRegex", "matchesAnyGlob", "patterns", "regex", "i", "c", "PROXY_PREFIX", "jsonError", "statusCode", "message", "code", "body", "errorToBody", "parseProxyPath", "pathname", "rest", "slash", "handleProxyRequest", "request", "config", "url", "parsed", "backend", "matchesAnyGlob", "targetUrl", "headers", "ctx", "result", "err", "accept", "ct", "backendRes", "filterHopByHop", "HOP_BY_HOP", "src", "dst", "value", "key", "registerApiRoutes", "app", "apiModule", "renderModule", "loaderTimeout", "server", "c", "handleProxyRequest", "e", "pathname", "search", "url", "data", "body", "errorToBody", "registerSsrRoute", "manifest", "html", "statusCode", "headers", "res", "key", "value"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import o from"picocolors";import{networkInterfaces as r}from"node:os";function s(e){let l=r();for(let n of Object.values(l))for(let t of n??[])if(t.family==="IPv4"&&!t.internal)return`http://${t.address}:${e}/`;return null}function $(e){let l="0.5.0",n=s(e);console.log(),console.log(` ${o.bold(o.yellow("devix"))} ${o.dim(`v${l}`)}`),console.log(),console.log(` ${o.green("\u279C")} ${o.bold("Local:")} ${o.cyan(`http://localhost:${e}/`)}`),console.log(n?` ${o.green("\u279C")} ${o.bold("Network:")} ${o.cyan(n)}`:` ${o.green("\u279C")} ${o.bold("Network:")} ${o.dim("use --host to expose")}`),console.log()}export{$ as printDevBanner};
1
+ import o from"picocolors";import{networkInterfaces as r}from"node:os";function s(e){let l=r();for(let n of Object.values(l))for(let t of n??[])if(t.family==="IPv4"&&!t.internal)return`http://${t.address}:${e}/`;return null}function $(e){let l="0.5.1",n=s(e);console.log(),console.log(` ${o.bold(o.yellow("devix"))} ${o.dim(`v${l}`)}`),console.log(),console.log(` ${o.green("\u279C")} ${o.bold("Local:")} ${o.cyan(`http://localhost:${e}/`)}`),console.log(n?` ${o.green("\u279C")} ${o.bold("Network:")} ${o.cyan(n)}`:` ${o.green("\u279C")} ${o.bold("Network:")} ${o.dim("use --host to expose")}`),console.log()}export{$ as printDevBanner};
2
2
  //# sourceMappingURL=banner.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devlusoft/devix",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "A lightweight React SSR meta-framework — devix",
6
6
  "author": "devlusoft",