@bobtail.software/b-ssr 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,6 +59,71 @@ await fastify.listen({ port: 3000 });
59
59
  console.log('Server running on http://localhost:3000');
60
60
  ```
61
61
 
62
+ ### Multi-entry SSR (opcional)
63
+
64
+ Puedes definir múltiples entry points de SSR y escogerlos por ruta o con un resolver.
65
+
66
+ ```typescript
67
+ await fastify.register(bSsrPlugin, {
68
+ root: process.cwd(),
69
+ entries: [
70
+ {
71
+ name: 'app',
72
+ match: '/app',
73
+ devEntryFile: '/src/entry-app-server.tsx',
74
+ prodEntryFile: './dist/app/server/entry-server.mjs',
75
+ },
76
+ {
77
+ name: 'admin',
78
+ match: /^\\/admin/,
79
+ devEntryFile: '/src/entry-admin-server.tsx',
80
+ prodEntryFile: './dist/admin/server/entry-server.mjs',
81
+ },
82
+ {
83
+ name: 'fallback',
84
+ devEntryFile: '/src/entry-server.tsx',
85
+ prodEntryFile: './dist/server/entry-server.mjs',
86
+ },
87
+ ],
88
+ // Solo se sirve un clientDistDir por defecto.
89
+ // Si necesitas varios, registra static manualmente.
90
+ clientDistDir: './dist/client',
91
+ });
92
+ ```
93
+
94
+ Selección de entry (orden de prioridad):
95
+
96
+ 1. `entry` en `addRenderRoute` (override explícito)
97
+ 2. `resolveEntry(req)` en opciones del plugin
98
+ 3. `entries[].match` (string, RegExp, o función)
99
+ 4. Fallback sin `match`
100
+ 5. `devEntryFile` / `prodEntryFile` (single-entry legacy)
101
+
102
+ Resolver global:
103
+
104
+ ```typescript
105
+ const entries = [
106
+ {
107
+ name: 'app',
108
+ devEntryFile: '/src/entry-app-server.tsx',
109
+ prodEntryFile: './dist/app/server/entry-server.mjs',
110
+ },
111
+ {
112
+ name: 'admin',
113
+ devEntryFile: '/src/entry-admin-server.tsx',
114
+ prodEntryFile: './dist/admin/server/entry-server.mjs',
115
+ },
116
+ ];
117
+
118
+ await fastify.register(bSsrPlugin, {
119
+ root: process.cwd(),
120
+ entries,
121
+ resolveEntry: (req) => (req.headers['x-entry'] === 'admin' ? entries[1] : null),
122
+ });
123
+ ```
124
+
125
+ Si `entries` no existe, el comportamiento es el mismo que antes (single-entry).
126
+
62
127
  ### 2. Configuración de Vite (`vite.config.ts`)
63
128
 
64
129
  Necesitas el plugin `rpcGeneratorPlugin` para habilitar la magia de los tipos y la separación cliente/servidor.
@@ -342,6 +407,14 @@ fastify.addRenderRoute('/*', {
342
407
  });
343
408
  ```
344
409
 
410
+ Puedes forzar un entry específico por ruta usando `entry` (aplica también a sub-rutas por el wildcard):
411
+
412
+ ```typescript
413
+ fastify.addRenderRoute('/admin', { entry: 'admin' });
414
+ ```
415
+
416
+ `entry` debe coincidir con `entries[].name`.
417
+
345
418
  ---
346
419
 
347
420
  ## 📂 Estructura de Archivos Recomendada
@@ -392,13 +465,12 @@ pnpm test:coverage
392
465
 
393
466
  ### Cobertura de Tests
394
467
 
395
- - **70/70 tests passing (100% de tests ejecutados)**
396
- - **4 tests en skip** - Limitaciones conocidas del generador de tipos
468
+ La suite cubre unit tests e integration tests. Algunos tests están en `skip` por limitaciones conocidas del generador de tipos.
397
469
 
398
- **Distribución:**
470
+ **Distribución (general):**
399
471
 
400
- - Unit Tests: 27 tests (vite-rpc-plugin, standalone type generator, virtual modules, firewall)
401
- - Integration Tests: 43 tests (zod-validation, error-handling, ssr-hydration, rpc-client)
472
+ - Unit Tests: vite-rpc-plugin, type generator standalone, virtual modules, firewall
473
+ - Integration Tests: zod-validation, error-handling, ssr-hydration, rpc-client
402
474
 
403
475
  ## 🔒 Seguridad
404
476
 
@@ -1 +1 @@
1
- "use strict";var D=Object.create;var R=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var I=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var P=(t,r)=>{for(var a in r)R(t,a,{get:r[a],enumerable:!0})},T=(t,r,a,l)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of b(r))!G.call(t,o)&&o!==a&&R(t,o,{get:()=>r[o],enumerable:!(l=O(r,o))||l.enumerable});return t};var S=(t,r,a)=>(a=t!=null?D(I(t)):{},T(r||!t||!t.__esModule?R(a,"default",{value:t,enumerable:!0}):a,t)),k=t=>T(R({},"__esModule",{value:!0}),t);var H={};P(H,{default:()=>_});module.exports=k(H);var $=require("@fastify/multipart"),w=S(require("fastify-plugin"),1),v=S(require("path"),1);async function E(t=24678){let r=await import("net");return new Promise((a,l)=>{let o=r.createServer();o.listen(t,"127.0.0.1",()=>{let e=o.address(),n=typeof e=="object"&&e!==null?e.port:t;o.close(()=>a(n))}),o.on("error",e=>{e.code==="EADDRINUSE"?o.close(()=>a(E(t+1))):l(e)})})}function g(t){if(t)return t}var A=async(t,r)=>{if(t.body&&typeof t.body=="object"){let a=t.body,l={};for(let o of Object.keys(a)){let e=a[o];e&&typeof e=="object"?e.type==="field"?l[o]=e.value:e.type==="file"&&(l[o]={filename:e.filename,mimetype:e.mimetype,encoding:e.encoding,fieldname:e.fieldname,file:e.file}):l[o]=e}t.body=l}},C=async(t,r)=>{let a=e=>{if(r.errorHandler){let n=r.errorHandler(e);if(n)return n}return{message:"Internal Server Error",statusCode:500}};if(t.hasDecorator("viteInitDone")&&t.viteInitDone)return;if(!t.hasDecorator("multipartErrors"))try{let e=await import("@fastify/multipart");await t.register(e.default)}catch(e){if(e.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw e}let l=process.env.NODE_ENV==="production";if(l){if(r.clientDistDir)try{let e=await import("@fastify/static"),n=v.default.resolve(r.root,r.clientDistDir);await t.register(e.default,{root:n,wildcard:!1}),console.log(`\u{1F4C2} [Fastify-SSR] Serving static assets from: ${n}`)}catch(e){console.error("\u274C [Fastify-SSR] Error registering @fastify/static. Did you install it?",e)}}else{if(!t.hasDecorator("use"))try{let c=await import("@fastify/middie");await t.register(c.default,{hook:"onRequest"})}catch(c){if(c.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw c}let e=await import("vite"),n=r.viteConfig||{},f;n.server?.hmr&&typeof n.server.hmr=="object"&&"port"in n.server.hmr?f=n.server.hmr.port:f=r.hmrPort??await E();let u=await e.createServer({root:r.root,appType:"custom",...n,server:{hmr:{port:f},...n.server,middlewareMode:!0}});t.use(u.middlewares),t.hasDecorator("viteServer")||t.decorate("viteServer",u),console.log("\u{1F680} [Fastify-SSR] Vite Dev Server Ready")}t.decorate("viteInitDone",!0);let o=async(e,n,f)=>{try{let u=e.raw.url,c=r.getGlobalSettings?await r.getGlobalSettings(e):void 0;if(v.default.extname(u)!==""){n.status(404).send(`File not found: ${u}`);return}let s="";!l&&t.viteServer&&(s=await t.viteServer.transformIndexHtml(u,"<html><head></head><body></body></html>"),s=s.substring(s.indexOf("<head>")+6,s.indexOf("</head>"))),s=(c?`<script>window.__GLOBAL_SETTINGS__ = ${JSON.stringify(c)}</script>`:"")+s;let m=l?await import(v.default.resolve(r.root,r.prodEntryFile)):await t.viteServer.ssrLoadModule(r.devEntryFile),i=m.render||m.default;if(typeof i!="function")throw new Error(`Entry file ${r.devEntryFile} must export a 'render' function.`);await i({req:e,reply:n,head:s,data:f,globalSettings:c})}catch(u){t.viteServer?.ssrFixStacktrace(u),console.error("[SSR Error]:",u),n.sent||n.status(500).send("Internal Server Error")}};t.decorate("addRpcRoute",function(e,n){let{handler:f,schema:u,...c}=n,s=`/rpc${e}`,p=g(u),m={...c,schema:p};n?.schema?.consumes?.includes("multipart/form-data")&&(m.preValidation=A),this.route({method:"POST",url:s,...m,handler:async(h,d)=>{try{let y=await f.call(this,h,d);return d.sent?void 0:y}catch(y){if(console.error(`[RPC Error] ${s}:`,y),!d.sent){let{statusCode:F,message:x}=a(y);d.status(F).send({error:{message:x}})}}}})}),t.decorate("addRenderRoute",function(e,n){let{handler:f,schema:u,...c}=n||{},s=g(u),p=async(m,i,h)=>{try{let d=await f?.call(this,m,i);return h?d:o(m,i,d)}catch(d){if(console.error(`[Render Error] ${e}:`,d),!i.sent){let{statusCode:y,message:F}=a(d);if(h)i.status(y).send({error:{message:F}});else return o(m,i,{ssrError:{statusCode:500,message:"Internal Error"}})}}};if(this.route({method:"GET",url:e,schema:s,...c,handler:(m,i)=>p(m,i,!1)}),e!=="*"&&e!=="/*"){this.route({method:"GET",url:`/loader${e}`,schema:s,...c,handler:(h,d)=>p(h,d,!0)});let m=e.endsWith("/")?"*":"/*",i=`${e}${m}`;this.route({method:"GET",url:i,schema:s,...c,handler:(h,d)=>p(h,d,!1)})}}),t.decorate("addLoaderRoute",function(e,n){let{handler:f,schema:u,...c}=n,s=`/api${e}`,p=g(u);this.route({method:"GET",url:s,schema:p,...c,handler:async(m,i)=>{try{let h=await f.call(this,m,i);return i.sent?void 0:h}catch(h){if(console.error(`[Loader API Error] ${s}:`,h),!i.sent){let{statusCode:d,message:y}=a(h);i.status(d).send({error:{message:y}})}}}})})},_=(0,w.default)(C,{name:"fastify-b-ssr"});
1
+ "use strict";var b=Object.create;var v=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var G=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var k=(e,r)=>{for(var n in r)v(e,n,{get:r[n],enumerable:!0})},w=(e,r,n,f)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of I(r))!P.call(e,o)&&o!==n&&v(e,o,{get:()=>r[o],enumerable:!(f=O(r,o))||f.enumerable});return e};var R=(e,r,n)=>(n=e!=null?b(G(e)):{},w(r||!e||!e.__esModule?v(n,"default",{value:e,enumerable:!0}):n,e)),q=e=>w(v({},"__esModule",{value:!0}),e);var Z={};k(Z,{default:()=>H});module.exports=q(Z);var N=require("@fastify/multipart"),T=R(require("fastify-plugin"),1),E=R(require("path"),1);async function D(e=24678){let r=await import("net");return new Promise((n,f)=>{let o=r.createServer();o.listen(e,"127.0.0.1",()=>{let t=o.address(),s=typeof t=="object"&&t!==null?t.port:e;o.close(()=>n(s))}),o.on("error",t=>{t.code==="EADDRINUSE"?o.close(()=>n(D(e+1))):f(t)})})}function F(e){if(e)return e}function x(e){let r=e.raw?.url||e.url||"",n=r.indexOf("?");return n===-1?r:r.slice(0,n)}function A(e,r,n){return e.match?typeof e.match=="string"?n.startsWith(e.match):e.match instanceof RegExp?e.match.test(n):e.match(r):!1}function C(e,r){if(r.resolveEntry){let t=r.resolveEntry(e);if(t)return t}let n=r.entries||[];if(n.length===0)return;let f=x(e),o;for(let t of n){if(!t.match){o||(o=t);continue}if(A(t,e,f))return t}return o}function _(e,r){if(!(!r.entries||r.entries.length===0))return r.entries.find(n=>n.name===e)}var $=async(e,r)=>{if(e.body&&typeof e.body=="object"){let n=e.body,f={};for(let o of Object.keys(n)){let t=n[o];t&&typeof t=="object"?t.type==="field"?f[o]=t.value:t.type==="file"&&(f[o]={filename:t.filename,mimetype:t.mimetype,encoding:t.encoding,fieldname:t.fieldname,file:t.file}):f[o]=t}e.body=f}},M=async(e,r)=>{let n=t=>{if(r.errorHandler){let s=r.errorHandler(t);if(s)return s}return{message:"Internal Server Error",statusCode:500}};if(e.hasDecorator("viteInitDone")&&e.viteInitDone)return;if(!e.hasDecorator("multipartErrors"))try{let t=await import("@fastify/multipart");await e.register(t.default)}catch(t){if(t.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw t}let f=process.env.NODE_ENV==="production";if(f){let t=new Set;r.clientDistDir&&t.add(r.clientDistDir);for(let d of r.entries||[])d.clientDistDir&&t.add(d.clientDistDir);t.size>1&&console.warn("\u26A0\uFE0F [Fastify-SSR] Multiple clientDistDir detected. Only the first will be served. Register additional static dirs manually if needed.");let[s]=t;if(s)try{let d=await import("@fastify/static"),h=E.default.resolve(r.root,s);await e.register(d.default,{root:h,wildcard:!1}),console.log(`\u{1F4C2} [Fastify-SSR] Serving static assets from: ${h}`)}catch(d){console.error("\u274C [Fastify-SSR] Error registering @fastify/static. Did you install it?",d)}}else{if(!e.hasDecorator("use"))try{let u=await import("@fastify/middie");await e.register(u.default,{hook:"onRequest"})}catch(u){if(u.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw u}let t=await import("vite"),s=r.viteConfig||{},d;s.server?.hmr&&typeof s.server.hmr=="object"&&"port"in s.server.hmr?d=s.server.hmr.port:d=r.hmrPort??await D();let h=await t.createServer({root:r.root,appType:"custom",...s,server:{hmr:{port:d},...s.server,middlewareMode:!0}});e.use(h.middlewares),e.hasDecorator("viteServer")||e.decorate("viteServer",h),console.log("\u{1F680} [Fastify-SSR] Vite Dev Server Ready")}e.decorate("viteInitDone",!0);let o=async(t,s,d,h)=>{try{let u=t.raw.url,y=r.getGlobalSettings?await r.getGlobalSettings(t):void 0;if(E.default.extname(u)!==""){s.status(404).send(`File not found: ${u}`);return}let m="";!f&&e.viteServer&&(m=await e.viteServer.transformIndexHtml(u,"<html><head></head><body></body></html>"),m=m.substring(m.indexOf("<head>")+6,m.indexOf("</head>"))),m=(y?`<script>window.__GLOBAL_SETTINGS__ = ${JSON.stringify(y)}</script>`:"")+m;let a;if(h){if(a=_(h,r),!a)throw new Error(`Entry "${h}" not found. Make sure entries[] includes a matching name.`)}else a=C(t,r);let i=a?.devEntryFile??r.devEntryFile,l=a?.prodEntryFile??r.prodEntryFile;if(!i||!l)throw new Error(`No SSR entry resolved for request "${x(t)}". Provide devEntryFile/prodEntryFile or configure entries/resolveEntry.`);let c=f?await import(E.default.resolve(r.root,l)):await e.viteServer.ssrLoadModule(i),p=c.render||c.default;if(typeof p!="function")throw new Error(`Entry file ${f?l:i} must export a 'render' function.`);await p({req:t,reply:s,head:m,data:d,globalSettings:y})}catch(u){e.viteServer?.ssrFixStacktrace(u),console.error("[SSR Error]:",u),s.sent||s.status(500).send("Internal Server Error")}};e.decorate("addRpcRoute",function(t,s){let{handler:d,schema:h,...u}=s,y=`/rpc${t}`,m=F(h),S={...u,schema:m};s?.schema?.consumes?.includes("multipart/form-data")&&(S.preValidation=$),this.route({method:"POST",url:y,...S,handler:async(i,l)=>{try{let c=await d.call(this,i,l);return l.sent?void 0:c}catch(c){if(console.error(`[RPC Error] ${y}:`,c),!l.sent){let{statusCode:p,message:g}=n(c);l.status(p).send({error:{message:g}})}}}})}),e.decorate("addRenderRoute",function(t,s){let{handler:d,schema:h,entry:u,...y}=s||{},m=F(h),S=async(a,i,l)=>{try{let c=await d?.call(this,a,i);return l?c:o(a,i,c,u)}catch(c){if(console.error(`[Render Error] ${t}:`,c),!i.sent){let{statusCode:p,message:g}=n(c);if(l)i.status(p).send({error:{message:g}});else return o(a,i,{ssrError:{statusCode:500,message:"Internal Error"}})}}};if(this.route({method:"GET",url:t,schema:m,...y,handler:(a,i)=>S(a,i,!1)}),t!=="*"&&t!=="/*"){this.route({method:"GET",url:`/loader${t}`,schema:m,...y,handler:(l,c)=>S(l,c,!0)});let a=t.endsWith("/")?"*":"/*",i=`${t}${a}`;this.route({method:"GET",url:i,schema:m,...y,handler:(l,c)=>S(l,c,!1)})}}),e.decorate("addLoaderRoute",function(t,s){let{handler:d,schema:h,...u}=s,y=`/api${t}`,m=F(h);this.route({method:"GET",url:y,schema:m,...u,handler:async(S,a)=>{try{let i=await d.call(this,S,a);return a.sent?void 0:i}catch(i){if(console.error(`[Loader API Error] ${y}:`,i),!a.sent){let{statusCode:l,message:c}=n(i);a.status(l).send({error:{message:c}})}}}})})},H=(0,T.default)(M,{name:"fastify-b-ssr"});
@@ -13,6 +13,11 @@ type AddRpcRouteOptions<TRpcSchema extends FastifySchema> = BaseRouteOptions<Rou
13
13
  type AddRenderRouteOptions<TSchema extends FastifySchema, TRpcSchema extends FastifySchema> = BaseRouteOptions<RouteGenericForSchema<TSchema>> & {
14
14
  handler?: (this: FastifyInstance, req: FastifyRequest<RouteGenericForSchema<TSchema>>, reply: FastifyReply<RouteGenericForSchema<TSchema>>) => Promise<unknown> | unknown;
15
15
  prefix?: string;
16
+ /**
17
+ * Nombre del entry point a usar para esta ruta (y sus sub-rutas).
18
+ * Debe coincidir con `entries[].name` en las opciones del plugin.
19
+ */
20
+ entry?: string;
16
21
  };
17
22
  type AddLoaderRouteOptions<TSchema extends FastifySchema> = BaseRouteOptions<RouteGenericForSchema<TSchema>> & {
18
23
  handler: (this: FastifyInstance, req: FastifyRequest<RouteGenericForSchema<TSchema>>, reply: FastifyReply<RouteGenericForSchema<TSchema>>) => Promise<unknown> | unknown;
@@ -25,18 +30,39 @@ interface RouteGenericForSchema<TSchema extends FastifySchema> extends RouteGene
25
30
  Params: InferZod<TSchema['params']>;
26
31
  Headers: InferZod<TSchema['headers']>;
27
32
  }
33
+ type SsrEntryMatch = string | RegExp | ((req: FastifyRequest) => boolean);
34
+ interface SsrEntry {
35
+ /** Nombre opcional para debugging */
36
+ name?: string;
37
+ /**
38
+ * Regla para escoger el entry. Si no se provee, actúa como fallback
39
+ * cuando ningún match coincide.
40
+ */
41
+ match?: SsrEntryMatch;
42
+ /** Ruta al archivo de entrada SSR en desarrollo (ej: '/src/entry-ssr-server.tsx') */
43
+ devEntryFile: string;
44
+ /** Ruta relativa al archivo compilado del servidor SSR en producción (ej: './dist-react/server/entry-server.mjs') */
45
+ prodEntryFile: string;
46
+ /** Ruta relativa a la carpeta de salida del cliente en producción */
47
+ clientDistDir?: string;
48
+ }
49
+ type SsrEntryResolver = (req: FastifyRequest) => SsrEntry | null | undefined;
28
50
  interface FastifyReactSsrOptions {
29
51
  /** Raíz del proyecto (donde está vite.config.ts). Generalmente `process.cwd()` o `__dirname` */
30
52
  root: string;
31
53
  /** Ruta al archivo de entrada SSR en desarrollo (ej: '/src/entry-ssr-server.tsx') */
32
- devEntryFile: string;
54
+ devEntryFile?: string;
33
55
  /** Ruta relativa al archivo compilado del servidor SSR en producción (ej: './dist-react/server/entry-server.mjs') */
34
- prodEntryFile: string;
56
+ prodEntryFile?: string;
35
57
  /**
36
58
  * Ruta relativa a la carpeta de salida del cliente en producción (ej: './dist-react/client').
37
59
  * Requerido para servir assets (CSS, JS) en producción.
38
60
  */
39
61
  clientDistDir?: string;
62
+ /** Múltiples entry points para SSR */
63
+ entries?: SsrEntry[];
64
+ /** Resolver custom para elegir entry point en base al request */
65
+ resolveEntry?: SsrEntryResolver;
40
66
  /** Configuración extra para Vite (opcional) */
41
67
  viteConfig?: InlineConfig;
42
68
  /** Manejador de errores personalizado */
@@ -62,4 +88,4 @@ declare module 'fastify' {
62
88
  }
63
89
  declare const _default: FastifyPluginAsyncZod<FastifyReactSsrOptions>;
64
90
 
65
- export { type AddLoaderRouteOptions, type AddRenderRouteOptions, type AddRpcRouteOptions, type BaseRouteOptions, type FastifyReactSsrOptions, type RouteGenericForSchema, _default as default };
91
+ export { type AddLoaderRouteOptions, type AddRenderRouteOptions, type AddRpcRouteOptions, type BaseRouteOptions, type FastifyReactSsrOptions, type RouteGenericForSchema, type SsrEntry, type SsrEntryMatch, type SsrEntryResolver, _default as default };
@@ -13,6 +13,11 @@ type AddRpcRouteOptions<TRpcSchema extends FastifySchema> = BaseRouteOptions<Rou
13
13
  type AddRenderRouteOptions<TSchema extends FastifySchema, TRpcSchema extends FastifySchema> = BaseRouteOptions<RouteGenericForSchema<TSchema>> & {
14
14
  handler?: (this: FastifyInstance, req: FastifyRequest<RouteGenericForSchema<TSchema>>, reply: FastifyReply<RouteGenericForSchema<TSchema>>) => Promise<unknown> | unknown;
15
15
  prefix?: string;
16
+ /**
17
+ * Nombre del entry point a usar para esta ruta (y sus sub-rutas).
18
+ * Debe coincidir con `entries[].name` en las opciones del plugin.
19
+ */
20
+ entry?: string;
16
21
  };
17
22
  type AddLoaderRouteOptions<TSchema extends FastifySchema> = BaseRouteOptions<RouteGenericForSchema<TSchema>> & {
18
23
  handler: (this: FastifyInstance, req: FastifyRequest<RouteGenericForSchema<TSchema>>, reply: FastifyReply<RouteGenericForSchema<TSchema>>) => Promise<unknown> | unknown;
@@ -25,18 +30,39 @@ interface RouteGenericForSchema<TSchema extends FastifySchema> extends RouteGene
25
30
  Params: InferZod<TSchema['params']>;
26
31
  Headers: InferZod<TSchema['headers']>;
27
32
  }
33
+ type SsrEntryMatch = string | RegExp | ((req: FastifyRequest) => boolean);
34
+ interface SsrEntry {
35
+ /** Nombre opcional para debugging */
36
+ name?: string;
37
+ /**
38
+ * Regla para escoger el entry. Si no se provee, actúa como fallback
39
+ * cuando ningún match coincide.
40
+ */
41
+ match?: SsrEntryMatch;
42
+ /** Ruta al archivo de entrada SSR en desarrollo (ej: '/src/entry-ssr-server.tsx') */
43
+ devEntryFile: string;
44
+ /** Ruta relativa al archivo compilado del servidor SSR en producción (ej: './dist-react/server/entry-server.mjs') */
45
+ prodEntryFile: string;
46
+ /** Ruta relativa a la carpeta de salida del cliente en producción */
47
+ clientDistDir?: string;
48
+ }
49
+ type SsrEntryResolver = (req: FastifyRequest) => SsrEntry | null | undefined;
28
50
  interface FastifyReactSsrOptions {
29
51
  /** Raíz del proyecto (donde está vite.config.ts). Generalmente `process.cwd()` o `__dirname` */
30
52
  root: string;
31
53
  /** Ruta al archivo de entrada SSR en desarrollo (ej: '/src/entry-ssr-server.tsx') */
32
- devEntryFile: string;
54
+ devEntryFile?: string;
33
55
  /** Ruta relativa al archivo compilado del servidor SSR en producción (ej: './dist-react/server/entry-server.mjs') */
34
- prodEntryFile: string;
56
+ prodEntryFile?: string;
35
57
  /**
36
58
  * Ruta relativa a la carpeta de salida del cliente en producción (ej: './dist-react/client').
37
59
  * Requerido para servir assets (CSS, JS) en producción.
38
60
  */
39
61
  clientDistDir?: string;
62
+ /** Múltiples entry points para SSR */
63
+ entries?: SsrEntry[];
64
+ /** Resolver custom para elegir entry point en base al request */
65
+ resolveEntry?: SsrEntryResolver;
40
66
  /** Configuración extra para Vite (opcional) */
41
67
  viteConfig?: InlineConfig;
42
68
  /** Manejador de errores personalizado */
@@ -62,4 +88,4 @@ declare module 'fastify' {
62
88
  }
63
89
  declare const _default: FastifyPluginAsyncZod<FastifyReactSsrOptions>;
64
90
 
65
- export { type AddLoaderRouteOptions, type AddRenderRouteOptions, type AddRpcRouteOptions, type BaseRouteOptions, type FastifyReactSsrOptions, type RouteGenericForSchema, _default as default };
91
+ export { type AddLoaderRouteOptions, type AddRenderRouteOptions, type AddRpcRouteOptions, type BaseRouteOptions, type FastifyReactSsrOptions, type RouteGenericForSchema, type SsrEntry, type SsrEntryMatch, type SsrEntryResolver, _default as default };
@@ -1 +1 @@
1
- import"@fastify/multipart";import T from"fastify-plugin";import R from"path";async function F(t=24678){let a=await import("net");return new Promise((f,h)=>{let u=a.createServer();u.listen(t,"127.0.0.1",()=>{let e=u.address(),r=typeof e=="object"&&e!==null?e.port:t;u.close(()=>f(r))}),u.on("error",e=>{e.code==="EADDRINUSE"?u.close(()=>f(F(t+1))):h(e)})})}function v(t){if(t)return t}var w=async(t,a)=>{if(t.body&&typeof t.body=="object"){let f=t.body,h={};for(let u of Object.keys(f)){let e=f[u];e&&typeof e=="object"?e.type==="field"?h[u]=e.value:e.type==="file"&&(h[u]={filename:e.filename,mimetype:e.mimetype,encoding:e.encoding,fieldname:e.fieldname,file:e.file}):h[u]=e}t.body=h}},E=async(t,a)=>{let f=e=>{if(a.errorHandler){let r=a.errorHandler(e);if(r)return r}return{message:"Internal Server Error",statusCode:500}};if(t.hasDecorator("viteInitDone")&&t.viteInitDone)return;if(!t.hasDecorator("multipartErrors"))try{let e=await import("@fastify/multipart");await t.register(e.default)}catch(e){if(e.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw e}let h=process.env.NODE_ENV==="production";if(h){if(a.clientDistDir)try{let e=await import("@fastify/static"),r=R.resolve(a.root,a.clientDistDir);await t.register(e.default,{root:r,wildcard:!1}),console.log(`\u{1F4C2} [Fastify-SSR] Serving static assets from: ${r}`)}catch(e){console.error("\u274C [Fastify-SSR] Error registering @fastify/static. Did you install it?",e)}}else{if(!t.hasDecorator("use"))try{let s=await import("@fastify/middie");await t.register(s.default,{hook:"onRequest"})}catch(s){if(s.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw s}let e=await import("vite"),r=a.viteConfig||{},l;r.server?.hmr&&typeof r.server.hmr=="object"&&"port"in r.server.hmr?l=r.server.hmr.port:l=a.hmrPort??await F();let c=await e.createServer({root:a.root,appType:"custom",...r,server:{hmr:{port:l},...r.server,middlewareMode:!0}});t.use(c.middlewares),t.hasDecorator("viteServer")||t.decorate("viteServer",c),console.log("\u{1F680} [Fastify-SSR] Vite Dev Server Ready")}t.decorate("viteInitDone",!0);let u=async(e,r,l)=>{try{let c=e.raw.url,s=a.getGlobalSettings?await a.getGlobalSettings(e):void 0;if(R.extname(c)!==""){r.status(404).send(`File not found: ${c}`);return}let n="";!h&&t.viteServer&&(n=await t.viteServer.transformIndexHtml(c,"<html><head></head><body></body></html>"),n=n.substring(n.indexOf("<head>")+6,n.indexOf("</head>"))),n=(s?`<script>window.__GLOBAL_SETTINGS__ = ${JSON.stringify(s)}</script>`:"")+n;let d=h?await import(R.resolve(a.root,a.prodEntryFile)):await t.viteServer.ssrLoadModule(a.devEntryFile),o=d.render||d.default;if(typeof o!="function")throw new Error(`Entry file ${a.devEntryFile} must export a 'render' function.`);await o({req:e,reply:r,head:n,data:l,globalSettings:s})}catch(c){t.viteServer?.ssrFixStacktrace(c),console.error("[SSR Error]:",c),r.sent||r.status(500).send("Internal Server Error")}};t.decorate("addRpcRoute",function(e,r){let{handler:l,schema:c,...s}=r,n=`/rpc${e}`,p=v(c),d={...s,schema:p};r?.schema?.consumes?.includes("multipart/form-data")&&(d.preValidation=w),this.route({method:"POST",url:n,...d,handler:async(m,i)=>{try{let y=await l.call(this,m,i);return i.sent?void 0:y}catch(y){if(console.error(`[RPC Error] ${n}:`,y),!i.sent){let{statusCode:S,message:g}=f(y);i.status(S).send({error:{message:g}})}}}})}),t.decorate("addRenderRoute",function(e,r){let{handler:l,schema:c,...s}=r||{},n=v(c),p=async(d,o,m)=>{try{let i=await l?.call(this,d,o);return m?i:u(d,o,i)}catch(i){if(console.error(`[Render Error] ${e}:`,i),!o.sent){let{statusCode:y,message:S}=f(i);if(m)o.status(y).send({error:{message:S}});else return u(d,o,{ssrError:{statusCode:500,message:"Internal Error"}})}}};if(this.route({method:"GET",url:e,schema:n,...s,handler:(d,o)=>p(d,o,!1)}),e!=="*"&&e!=="/*"){this.route({method:"GET",url:`/loader${e}`,schema:n,...s,handler:(m,i)=>p(m,i,!0)});let d=e.endsWith("/")?"*":"/*",o=`${e}${d}`;this.route({method:"GET",url:o,schema:n,...s,handler:(m,i)=>p(m,i,!1)})}}),t.decorate("addLoaderRoute",function(e,r){let{handler:l,schema:c,...s}=r,n=`/api${e}`,p=v(c);this.route({method:"GET",url:n,schema:p,...s,handler:async(d,o)=>{try{let m=await l.call(this,d,o);return o.sent?void 0:m}catch(m){if(console.error(`[Loader API Error] ${n}:`,m),!o.sent){let{statusCode:i,message:y}=f(m);o.status(i).send({error:{message:y}})}}}})})},b=T(E,{name:"fastify-b-ssr"});export{b as default};
1
+ import"@fastify/multipart";import w from"fastify-plugin";import v from"path";async function g(t=24678){let r=await import("net");return new Promise((s,h)=>{let d=r.createServer();d.listen(t,"127.0.0.1",()=>{let e=d.address(),n=typeof e=="object"&&e!==null?e.port:t;d.close(()=>s(n))}),d.on("error",e=>{e.code==="EADDRINUSE"?d.close(()=>s(g(t+1))):h(e)})})}function E(t){if(t)return t}function F(t){let r=t.raw?.url||t.url||"",s=r.indexOf("?");return s===-1?r:r.slice(0,s)}function T(t,r,s){return t.match?typeof t.match=="string"?s.startsWith(t.match):t.match instanceof RegExp?t.match.test(s):t.match(r):!1}function D(t,r){if(r.resolveEntry){let e=r.resolveEntry(t);if(e)return e}let s=r.entries||[];if(s.length===0)return;let h=F(t),d;for(let e of s){if(!e.match){d||(d=e);continue}if(T(e,t,h))return e}return d}function x(t,r){if(!(!r.entries||r.entries.length===0))return r.entries.find(s=>s.name===t)}var b=async(t,r)=>{if(t.body&&typeof t.body=="object"){let s=t.body,h={};for(let d of Object.keys(s)){let e=s[d];e&&typeof e=="object"?e.type==="field"?h[d]=e.value:e.type==="file"&&(h[d]={filename:e.filename,mimetype:e.mimetype,encoding:e.encoding,fieldname:e.fieldname,file:e.file}):h[d]=e}t.body=h}},O=async(t,r)=>{let s=e=>{if(r.errorHandler){let n=r.errorHandler(e);if(n)return n}return{message:"Internal Server Error",statusCode:500}};if(t.hasDecorator("viteInitDone")&&t.viteInitDone)return;if(!t.hasDecorator("multipartErrors"))try{let e=await import("@fastify/multipart");await t.register(e.default)}catch(e){if(e.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw e}let h=process.env.NODE_ENV==="production";if(h){let e=new Set;r.clientDistDir&&e.add(r.clientDistDir);for(let c of r.entries||[])c.clientDistDir&&e.add(c.clientDistDir);e.size>1&&console.warn("\u26A0\uFE0F [Fastify-SSR] Multiple clientDistDir detected. Only the first will be served. Register additional static dirs manually if needed.");let[n]=e;if(n)try{let c=await import("@fastify/static"),m=v.resolve(r.root,n);await t.register(c.default,{root:m,wildcard:!1}),console.log(`\u{1F4C2} [Fastify-SSR] Serving static assets from: ${m}`)}catch(c){console.error("\u274C [Fastify-SSR] Error registering @fastify/static. Did you install it?",c)}}else{if(!t.hasDecorator("use"))try{let u=await import("@fastify/middie");await t.register(u.default,{hook:"onRequest"})}catch(u){if(u.code!=="FST_ERR_DEC_ALREADY_PRESENT")throw u}let e=await import("vite"),n=r.viteConfig||{},c;n.server?.hmr&&typeof n.server.hmr=="object"&&"port"in n.server.hmr?c=n.server.hmr.port:c=r.hmrPort??await g();let m=await e.createServer({root:r.root,appType:"custom",...n,server:{hmr:{port:c},...n.server,middlewareMode:!0}});t.use(m.middlewares),t.hasDecorator("viteServer")||t.decorate("viteServer",m),console.log("\u{1F680} [Fastify-SSR] Vite Dev Server Ready")}t.decorate("viteInitDone",!0);let d=async(e,n,c,m)=>{try{let u=e.raw.url,y=r.getGlobalSettings?await r.getGlobalSettings(e):void 0;if(v.extname(u)!==""){n.status(404).send(`File not found: ${u}`);return}let f="";!h&&t.viteServer&&(f=await t.viteServer.transformIndexHtml(u,"<html><head></head><body></body></html>"),f=f.substring(f.indexOf("<head>")+6,f.indexOf("</head>"))),f=(y?`<script>window.__GLOBAL_SETTINGS__ = ${JSON.stringify(y)}</script>`:"")+f;let i;if(m){if(i=x(m,r),!i)throw new Error(`Entry "${m}" not found. Make sure entries[] includes a matching name.`)}else i=D(e,r);let o=i?.devEntryFile??r.devEntryFile,l=i?.prodEntryFile??r.prodEntryFile;if(!o||!l)throw new Error(`No SSR entry resolved for request "${F(e)}". Provide devEntryFile/prodEntryFile or configure entries/resolveEntry.`);let a=h?await import(v.resolve(r.root,l)):await t.viteServer.ssrLoadModule(o),R=a.render||a.default;if(typeof R!="function")throw new Error(`Entry file ${h?l:o} must export a 'render' function.`);await R({req:e,reply:n,head:f,data:c,globalSettings:y})}catch(u){t.viteServer?.ssrFixStacktrace(u),console.error("[SSR Error]:",u),n.sent||n.status(500).send("Internal Server Error")}};t.decorate("addRpcRoute",function(e,n){let{handler:c,schema:m,...u}=n,y=`/rpc${e}`,f=E(m),S={...u,schema:f};n?.schema?.consumes?.includes("multipart/form-data")&&(S.preValidation=b),this.route({method:"POST",url:y,...S,handler:async(o,l)=>{try{let a=await c.call(this,o,l);return l.sent?void 0:a}catch(a){if(console.error(`[RPC Error] ${y}:`,a),!l.sent){let{statusCode:R,message:p}=s(a);l.status(R).send({error:{message:p}})}}}})}),t.decorate("addRenderRoute",function(e,n){let{handler:c,schema:m,entry:u,...y}=n||{},f=E(m),S=async(i,o,l)=>{try{let a=await c?.call(this,i,o);return l?a:d(i,o,a,u)}catch(a){if(console.error(`[Render Error] ${e}:`,a),!o.sent){let{statusCode:R,message:p}=s(a);if(l)o.status(R).send({error:{message:p}});else return d(i,o,{ssrError:{statusCode:500,message:"Internal Error"}})}}};if(this.route({method:"GET",url:e,schema:f,...y,handler:(i,o)=>S(i,o,!1)}),e!=="*"&&e!=="/*"){this.route({method:"GET",url:`/loader${e}`,schema:f,...y,handler:(l,a)=>S(l,a,!0)});let i=e.endsWith("/")?"*":"/*",o=`${e}${i}`;this.route({method:"GET",url:o,schema:f,...y,handler:(l,a)=>S(l,a,!1)})}}),t.decorate("addLoaderRoute",function(e,n){let{handler:c,schema:m,...u}=n,y=`/api${e}`,f=E(m);this.route({method:"GET",url:y,schema:f,...u,handler:async(S,i)=>{try{let o=await c.call(this,S,i);return i.sent?void 0:o}catch(o){if(console.error(`[Loader API Error] ${y}:`,o),!i.sent){let{statusCode:l,message:a}=s(o);i.status(l).send({error:{message:a}})}}}})})},k=w(O,{name:"fastify-b-ssr"});export{k as default};
@@ -1,9 +1,9 @@
1
- "use strict";var ge=Object.create;var W=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty;var de=(e,t)=>{for(var r in t)W(e,r,{get:t[r],enumerable:!0})},Y=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of fe(t))!ye.call(e,s)&&s!==r&&W(e,s,{get:()=>t[s],enumerable:!(n=ue(t,s))||n.enumerable});return e};var Z=(e,t,r)=>(r=e!=null?ge(me(e)):{},Y(t||!e||!e.__esModule?W(r,"default",{value:e,enumerable:!0}):r,e)),Te=e=>Y(W({},"__esModule",{value:!0}),e);var we={};de(we,{generateRpcTypes:()=>Se});module.exports=Te(we);var H=Z(require("fast-glob"),1),N=require("fs/promises"),w=Z(require("path"),1),A=require("ts-morph");var U=require("fs/promises"),P=Z(require("path"),1),V=require("prettier"),p=require("ts-morph");function he(e){let t=e.replace(/[^a-zA-Z0-9]+(.)?/g,(r,n)=>n?n.toUpperCase():"");return t.charAt(0).toLowerCase()+t.slice(1)}function B(e,t,r){let n=P.default.basename(r,P.default.extname(r))||"Index",s=t.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),g=`${e} ${s} ${n}`;return he(g)}function xe(e){let t=/'[^']+'/g,r=/`[^`]+`/g,n=[],s,g=/'[^']+'/g;for(;(s=g.exec(e))!==null;)n.push({start:s.index,end:s.index+s[0].length,value:s[0]});let o=/`[^`]+`/g;for(;(s=o.exec(e))!==null;)n.push({start:s.index,end:s.index+s[0].length,value:s[0]});if(n.length>1){let a=[...n].sort((m,F)=>{let f=m.value.replace(/['`]/g,""),i=F.value.replace(/['`]/g,"");return f.localeCompare(i)}),c="",T=0;for(let m=0;m<n.length;m++)c+=e.slice(T,n[m].start),c+=a[m].value,T=n[m].end;return c+=e.slice(T),c}return e}function be(e){let t=e.match(/^\{([\s\S]*)\}$/);if(!t)return e;let r=t[1];if(!r.includes(":"))return e;let n=r.split(/[;,]/).map(o=>o.trim()).filter(o=>o),s=[];for(let o of n){let a=o.indexOf(":");if(a===-1)continue;let c=o.slice(0,a).trim(),T=o.slice(a+1).trim();s.push({name:c,value:T})}return s.length<=1?e:(s.sort((o,a)=>o.name.localeCompare(a.name)),`{ ${s.map(o=>`${o.name}: ${o.value}`).join("; ")} }`)}function G(e){let t=xe(e);return t=be(t),t}async function ee(e,t){try{if(await(0,U.readFile)(e,"utf-8")===t)return!1}catch{}let r=t;try{let n=await(0,V.resolveConfig)(e)||{};r=await(0,V.format)(t,{...n,parser:"typescript",filepath:e})}catch{}try{if(await(0,U.readFile)(e,"utf-8")===r)return!1}catch{}return await(0,U.writeFile)(e,r),!0}function j(e,t,r,n,s,g){function o(i){return i.replace(/import\(['"](.*?)['"]\)/g,(l,u)=>{if(!P.default.isAbsolute(u))return l;let d=u;if(!P.default.extname(d)){let E=s.getSourceFile(x=>x.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===u);E&&(d=E.getFilePath())}let h=P.default.relative(P.default.dirname(n),d).replace(/\\/g,"/");return h.startsWith(".")||(h="./"+h),`import("${h}")`})}if(e.getSymbol()?.getName()==="Promise"){let i=e.getAwaitedType();if(i)return`Promise<${j(i,t,r,n,s,g)}>`}let a=e.getAliasSymbol()??e.getSymbol();if(a?.getName()==="__object")return G(o(e.getText(t,p.ts.TypeFormatFlags.NoTruncation|p.ts.TypeFormatFlags.UseFullyQualifiedType)));if(e.isObject()&&!a){let i=(l,u=0)=>{if(!(u>5)){if(l.isArray()){let d=l.getArrayElementType();d&&i(d,u);return}if(l.isObject()&&!l.getSymbol()&&!l.getAliasSymbol()){for(let d of l.getApparentProperties()){let h=d.getValueDeclaration();h&&i(d.getTypeAtLocation(h),u+1)}return}j(l,t,r,n,s,g)}};return i(e),G(o(e.getText(t,p.ts.TypeFormatFlags.NoTruncation|p.ts.TypeFormatFlags.UseFullyQualifiedType)))}if(!a)return G(o(e.getText(t,p.ts.TypeFormatFlags.NoTruncation)));let c=a.getDeclarations()[0];if(!c)return a.getName();if(p.Node.isImportSpecifier(c)||p.Node.isImportClause(c)){let i=c.getFirstAncestorByKind(p.SyntaxKind.ImportDeclaration);if(i){let l=i.getModuleSpecifierValue(),u=a.getName();return g.has(l)||g.set(l,new Set),g.get(l)?.add(u),u}}let T=c.getSourceFile();if(T.getFilePath()===r.getFilePath())return a.getName();if(T.isInNodeModules())return G(o(e.getText(t,p.ts.TypeFormatFlags.NoTruncation)));let m=P.default.relative(P.default.dirname(n),T.getFilePath()).replace(/\\/g,"/"),F=m.startsWith(".")?m:`./${m}`,f=a.getName();return g.has(F)||g.set(F,new Set),g.get(F)?.add(f),f}function te(e,t,r,n,s){let g;if(p.Node.isFunctionLikeDeclaration(e)||p.Node.isArrowFunction(e)){let o=e.getDescendantsOfKind(p.SyntaxKind.ReturnStatement);for(let a of o){let c=a.getExpression();if(c?.isKind(p.SyntaxKind.SatisfiesExpression)){g=c.getTypeNode()?.getType();break}}}if(g)return j(g,e,t,r,n,s);{let o=e.getType().getCallSignatures();if(o.length>0){let a=o[0]?.getReturnType();return j(a,e,t,r,n,s)}}return"unknown"}function ne(e,t,r,n,s){let g="unknown",o="unknown",a="unknown",c=!1;if(!e||!p.Node.isObjectLiteralExpression(e))return{paramsType:g,queryType:o,bodyType:a,isMultipart:c};let T=e.getProperty("schema");if(T?.isKind(p.SyntaxKind.PropertyAssignment)){let m=T.getInitializer();if(m?.isKind(p.SyntaxKind.Identifier)){let f=m.getSymbol()?.getValueDeclaration();if(f){let i=f.getFirstDescendantByKind(p.SyntaxKind.ObjectLiteralExpression);i&&(m=i)}}if(m&&p.Node.isObjectLiteralExpression(m)){let F=m.getProperty("consumes");if(F?.isKind(p.SyntaxKind.PropertyAssignment)){let i=F.getInitializer();p.Node.isArrayLiteralExpression(i)&&(c=i.getElements().some(l=>l.isKind(p.SyntaxKind.StringLiteral)&&l.getLiteralValue()==="multipart/form-data"))}let f=i=>{let l=m.getProperty(i);if(l?.isKind(p.SyntaxKind.PropertyAssignment)){let u=l.getInitializer();if(u){let d=u.getType(),h=d.getApparentType(),E=h.getProperty("_output");if(E)return j(E.getTypeAtLocation(u).getApparentType(),u,t,r,n,s);let x=d.getSymbol(),v=d.getAliasSymbol(),b=x?.getName(),I=v?.getName();if(b&&b!=="__type"&&b!=="object"||I&&I!=="__type"&&I!=="object")return j(d,u,t,r,n,s);let C=h.getProperties();if(C.length>0){let _=[];for(let D of C){let k=D.getTypeAtLocation(u);_.push(`${D.getName()}: ${k.getText(u)}`)}return`{ ${_.join("; ")} }`}return j(d,u,t,r,n,s)}}return"unknown"};if(g=f("params"),o=f("querystring"),a=f("body"),c){let i="{ file: File }";a=a!=="unknown"&&a.trim().startsWith("{")?`(${a} & ${i})`:i}}}return{paramsType:g,queryType:o,bodyType:a,isMultipart:c}}function Fe(e){let t=[];return e.paramsType!=="unknown"&&t.push(`params: ${e.paramsType}`),e.queryType!=="unknown"&&t.push(`query: ${e.queryType}`),e.bodyType!=="unknown"&&t.push(`body: ${e.bodyType}`),t.push("signal?: AbortSignal"),t}function re(e){let t=Fe(e),r="";return t.length>0&&(r=`args: { ${t.join("; ")} }`),r||(r="args: { signal?: AbortSignal }"),`export declare const ${e.name}: (${r}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${e.returnType};`}async function Se(e={}){let{routerPattern:t="src-ts/routers/**/*.mts",tsConfigFilePath:r="tsconfig.json",routerBaseDir:n="src-ts/routers",clean:s=!1}=e,g=[],o=[],a=[];try{let c=new A.Project({tsConfigFilePath:r,skipAddingFilesFromTsConfig:!1}),T=w.default.resolve(process.cwd(),n||".");async function m(f){try{let i=c.addSourceFileAtPath(f);await i.refreshFromFileSystem();let l=i.getDescendantsOfKind(A.SyntaxKind.CallExpression),u=l.filter(y=>y.getExpression().getText().endsWith(".addRpcRoute")),d=l.filter(y=>y.getExpression().getText().endsWith(".addRenderRoute")),h=l.filter(y=>y.getExpression().getText().endsWith(".addLoaderRoute")),E=w.default.extname(f),x=f.substring(0,f.length-E.length)+".universal.d.ts";if(u.length===0&&d.length===0&&h.length===0){if(s)try{await(0,N.unlink)(x),o.push(x)}catch{}return!1}let v=[],b=new Map;b.has("fastify")||b.set("fastify",new Set),b.get("fastify")?.add("FastifyRequest"),b.get("fastify")?.add("FastifyReply");let C=w.default.relative(T,w.default.dirname(f)).split(w.default.sep).join("/"),_=C==="."||!C?"":C.startsWith("/")?C:"/"+C,D=(y,S)=>{let[q,z]=y.getArguments();if(!q?.isKind(A.SyntaxKind.StringLiteral))return;let R=q.getLiteralValue(),L="unknown",$=_,{paramsType:ae,queryType:ce,bodyType:le,isMultipart:pe}=ne(z,i,x,c,b);if(z?.isKind(A.SyntaxKind.ObjectLiteralExpression)){let J=z.getProperty("prefix");if(J?.isKind(A.SyntaxKind.PropertyAssignment)){let M=J.getInitializer();M?.isKind(A.SyntaxKind.StringLiteral)&&($=M.getLiteralValue())}let X=z.getProperty("handler");if(X?.isKind(A.SyntaxKind.PropertyAssignment)){let M=X.getInitializer();M&&(L=te(M,i,x,c,b),L.startsWith("Promise<")||(L=`Promise<${L}>`))}}let K="",O="";S==="rpc"?(K=w.default.join($,"rpc",R).replace(/\\/g,"/"),O=B("action",$,R)):S==="loader"?(K=w.default.join($,"loader",R).replace(/\\/g,"/"),O=B("loader",$,R)):S==="api"&&(K=w.default.join($,"api",R).replace(/\\/g,"/"),O=B("get",$,R)),O&&v.push({type:S,name:O,returnType:L,url:R,rpcUrl:K,loaderUrl:K,paramsType:ae,queryType:ce,bodyType:le,isMultipart:pe})};if(u.forEach(y=>D(y,"rpc")),d.forEach(y=>D(y,"loader")),h.forEach(y=>D(y,"api")),v.length===0){if(s)try{await(0,N.unlink)(x),o.push(x)}catch{}return!1}let k=[],se=[...b.entries()].sort((y,S)=>y[0].localeCompare(S[0]));for(let[y,S]of se)k.push(`import type { ${[...S].sort().join(", ")} } from "${y}";`);let ie=[...v].sort((y,S)=>y.name.localeCompare(S.name)),Q=[];ie.forEach(y=>{Q.push(re(y))});let oe=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
1
+ "use strict";var be=Object.create;var G=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Ce=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Pe=(e,t)=>{for(var r in t)G(e,r,{get:t[r],enumerable:!0})},se=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of we(t))!Se.call(e,s)&&s!==r&&G(e,s,{get:()=>t[s],enumerable:!(n=Fe(t,s))||n.enumerable});return e};var X=(e,t,r)=>(r=e!=null?be(Ce(e)):{},se(t||!e||!e.__esModule?G(r,"default",{value:e,enumerable:!0}):r,e)),Ee=e=>se(G({},"__esModule",{value:!0}),e);var Ne={};Pe(Ne,{generateRpcTypes:()=>$e});module.exports=Ee(Ne);var te=X(require("fast-glob"),1),E=require("fs/promises"),P=X(require("path"),1),j=require("ts-morph");var v=require("fs/promises"),S=X(require("path"),1),q=require("prettier"),g=require("ts-morph"),ie=require("crypto");function Ae(e){let t=e.replace(/[^a-zA-Z0-9]+(.)?/g,(r,n)=>n?n.toUpperCase():"");return t.charAt(0).toLowerCase()+t.slice(1)}function J(e,t,r){let n=S.default.basename(r,S.default.extname(r))||"Index",s=t.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),p=`${e} ${s} ${n}`;return Ae(p)}function Re(e){let t=/'[^']+'/g,r=/`[^`]+`/g,n=[],s,p=/'[^']+'/g;for(;(s=p.exec(e))!==null;)n.push({start:s.index,end:s.index+s[0].length,value:s[0]});let o=/`[^`]+`/g;for(;(s=o.exec(e))!==null;)n.push({start:s.index,end:s.index+s[0].length,value:s[0]});if(n.length>1){let a=[...n].sort((u,w)=>{let F=u.value.replace(/['`]/g,""),l=w.value.replace(/['`]/g,"");return F.localeCompare(l)}),m="",f=0;for(let u=0;u<n.length;u++)m+=e.slice(f,n[u].start),m+=a[u].value,f=n[u].end;return m+=e.slice(f),m}return e}function ve(e){let t=e.match(/^\{([\s\S]*)\}$/);if(!t)return e;let r=t[1];if(!r.includes(":"))return e;let n=r.split(/[;,]/).map(o=>o.trim()).filter(o=>o),s=[];for(let o of n){let a=o.indexOf(":");if(a===-1)continue;let m=o.slice(0,a).trim(),f=o.slice(a+1).trim();s.push({name:m,value:f})}return s.length<=1?e:(s.sort((o,a)=>o.name.localeCompare(a.name)),`{ ${s.map(o=>`${o.name}: ${o.value}`).join("; ")} }`)}function Z(e){let t=Re(e);return t=ve(t),t}async function ee(e,t){try{if(await(0,v.readFile)(e,"utf-8")===t)return!1}catch{}let r=t;try{let n=await(0,q.resolveConfig)(e)||{};r=await(0,q.format)(t,{...n,parser:"typescript",filepath:e})}catch{}try{if(await(0,v.readFile)(e,"utf-8")===r)return!1}catch{}return await(0,v.writeFile)(e,r),!0}function oe(e){return(0,ie.createHash)("sha1").update(e).digest("hex")}var Y="v1",ae=S.default.join(process.cwd(),"node_modules",".cache","b-ssr"),ce=S.default.join(ae,"rpc-cache.json");async function le(){try{let e=await(0,v.readFile)(ce,"utf-8"),t=JSON.parse(e);return t.version!==Y?{version:Y,files:{}}:t}catch{return{version:Y,files:{}}}}async function pe(e){try{await(0,v.mkdir)(ae,{recursive:!0}),await(0,v.writeFile)(ce,JSON.stringify(e,null,2))}catch(t){console.error("\u26A0\uFE0F [B-SSR] Failed to save persistent cache:",t)}}function L(e,t,r,n,s,p){function o(l){return l.replace(/import\(['"](.*?)['"]\)/g,(y,i)=>{if(!S.default.isAbsolute(i))return y;let c=i;if(!S.default.extname(c)){let C=s.getSourceFile(N=>N.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===i);C&&(c=C.getFilePath())}let d=S.default.relative(S.default.dirname(n),c).replace(/\\/g,"/");return d.startsWith(".")||(d="./"+d),`import("${d}")`})}if(e.getSymbol()?.getName()==="Promise"){let l=e.getAwaitedType();if(l)return`Promise<${L(l,t,r,n,s,p)}>`}let a=e.getAliasSymbol()??e.getSymbol();if(a?.getName()==="__object")return Z(o(e.getText(t,g.ts.TypeFormatFlags.NoTruncation|g.ts.TypeFormatFlags.UseFullyQualifiedType)));if(e.isObject()&&!a){let l=(y,i=0)=>{if(!(i>5)){if(y.isArray()){let c=y.getArrayElementType();c&&l(c,i);return}if(y.isObject()&&!y.getSymbol()&&!y.getAliasSymbol()){for(let c of y.getApparentProperties()){let d=c.getValueDeclaration();d&&l(c.getTypeAtLocation(d),i+1)}return}L(y,t,r,n,s,p)}};return l(e),Z(o(e.getText(t,g.ts.TypeFormatFlags.NoTruncation|g.ts.TypeFormatFlags.UseFullyQualifiedType)))}if(!a)return Z(o(e.getText(t,g.ts.TypeFormatFlags.NoTruncation)));let m=a.getDeclarations()[0];if(!m)return a.getName();if(g.Node.isImportSpecifier(m)||g.Node.isImportClause(m)){let l=m.getFirstAncestorByKind(g.SyntaxKind.ImportDeclaration);if(l){let y=l.getModuleSpecifierValue(),i=a.getName();return p.has(y)||p.set(y,new Set),p.get(y)?.add(i),i}}let f=m.getSourceFile();if(f.getFilePath()===r.getFilePath())return a.getName();if(f.isInNodeModules())return Z(o(e.getText(t,g.ts.TypeFormatFlags.NoTruncation)));let u=S.default.relative(S.default.dirname(n),f.getFilePath()).replace(/\\/g,"/"),w=u.startsWith(".")?u:`./${u}`,F=a.getName();return p.has(w)||p.set(w,new Set),p.get(w)?.add(F),F}function ge(e,t,r,n,s){let p;if(g.Node.isFunctionLikeDeclaration(e)||g.Node.isArrowFunction(e)){let o=e.getDescendantsOfKind(g.SyntaxKind.ReturnStatement);for(let a of o){let m=a.getExpression();if(m?.isKind(g.SyntaxKind.SatisfiesExpression)){p=m.getTypeNode()?.getType();break}}}if(p)return L(p,e,t,r,n,s);{let o=e.getType().getCallSignatures();if(o.length>0){let a=o[0]?.getReturnType();return L(a,e,t,r,n,s)}}return"unknown"}function ue(e,t,r,n,s){let p="unknown",o="unknown",a="unknown",m=!1;if(!e||!g.Node.isObjectLiteralExpression(e))return{paramsType:p,queryType:o,bodyType:a,isMultipart:m};let f=e.getProperty("schema");if(f?.isKind(g.SyntaxKind.PropertyAssignment)){let u=f.getInitializer();if(u?.isKind(g.SyntaxKind.Identifier)){let F=u.getSymbol()?.getValueDeclaration();if(F){let l=F.getFirstDescendantByKind(g.SyntaxKind.ObjectLiteralExpression);l&&(u=l)}}if(u&&g.Node.isObjectLiteralExpression(u)){let w=u.getProperty("consumes");if(w?.isKind(g.SyntaxKind.PropertyAssignment)){let l=w.getInitializer();g.Node.isArrayLiteralExpression(l)&&(m=l.getElements().some(y=>y.isKind(g.SyntaxKind.StringLiteral)&&y.getLiteralValue()==="multipart/form-data"))}let F=l=>{let y=u.getProperty(l);if(y?.isKind(g.SyntaxKind.PropertyAssignment)){let i=y.getInitializer();if(i){let c=i.getType(),d=c.getApparentType(),C=d.getProperty("_output");if(C)return L(C.getTypeAtLocation(i).getApparentType(),i,t,r,n,s);let N=c.getSymbol(),h=c.getAliasSymbol(),T=N?.getName(),b=h?.getName();if(T&&T!=="__type"&&T!=="object"||b&&b!=="__type"&&b!=="object")return L(c,i,t,r,n,s);let O=d.getProperties();if(O.length>0){let I=[];for(let K of O){let W=K.getTypeAtLocation(i);I.push(`${K.getName()}: ${W.getText(i)}`)}return`{ ${I.join("; ")} }`}return L(c,i,t,r,n,s)}}return"unknown"};if(p=F("params"),o=F("querystring"),a=F("body"),m){let l="{ file: File }";a=a!=="unknown"&&a.trim().startsWith("{")?`(${a} & ${l})`:l}}}return{paramsType:p,queryType:o,bodyType:a,isMultipart:m}}function je(e){let t=[];return e.paramsType!=="unknown"&&t.push(`params: ${e.paramsType}`),e.queryType!=="unknown"&&t.push(`query: ${e.queryType}`),e.bodyType!=="unknown"&&t.push(`body: ${e.bodyType}`),t.push("signal?: AbortSignal"),t}function fe(e){let t=je(e),r="";return t.length>0&&(r=`args: { ${t.join("; ")} }`),r||(r="args: { signal?: AbortSignal }"),`export declare const ${e.name}: (${r}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${e.returnType};`}async function $e(e={}){let{routerPattern:t="src-ts/routers/**/*.mts",tsConfigFilePath:r="tsconfig.json",routerBaseDir:n="src-ts/routers",clean:s=!1}=e,p=[],o=[],a=[];try{let l=function(i,c){let d=[],C=[...c.entries()].sort((T,b)=>T[0].localeCompare(b[0]));for(let[T,b]of C)d.push(`import type { ${[...b].sort().join(", ")} } from "${T}";`);let N=[...i].sort((T,b)=>T.name.localeCompare(b.name)),h=[];return N.forEach(T=>{h.push(fe(T))}),`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
2
2
  /* eslint-disable */
3
3
 
4
- `+(k.length>0?k.join(`
4
+ `+(d.length>0?d.join(`
5
5
  `)+`
6
6
 
7
- `:"")+Q.join(`
7
+ `:"")+h.join(`
8
8
 
9
- `);return(await ee(x,oe)||await(0,N.access)(x).then(()=>!0).catch(()=>!1))&&g.push(x),!0}catch(i){return a.push(`Error processing ${f}: ${i instanceof Error?i.message:String(i)}`),!1}}let F=await(0,H.default)(t,{absolute:!0});if(await Promise.all(F.map(f=>m(f))),c.resolveSourceFileDependencies(),s){let f=await(0,H.default)(w.default.join(n,"**/*.universal.d.ts"),{absolute:!0});for(let i of f){let l=i.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await(0,N.access)(l).then(()=>!0).catch(()=>!1))try{await(0,N.unlink)(i),o.push(i)}catch{}}}}catch(c){a.push(`Fatal error: ${c instanceof Error?c.message:String(c)}`)}return{generated:g,cleaned:o,errors:a}}0&&(module.exports={generateRpcTypes});
9
+ `)};var m=l;let f=await le(),u=new j.Project({tsConfigFilePath:r,skipAddingFilesFromTsConfig:!0}),w=P.default.resolve(process.cwd(),n||".");async function F(i){try{let c=P.default.resolve(i),d=await(0,E.readFile)(i,"utf-8"),C=oe(d),N=P.default.extname(i),h=i.substring(0,i.length-N.length)+".universal.d.ts",T=f.files[c];if(T&&T.hash===C){let x=T.fnInfo,A=new Map;T.imports.forEach(([R,D])=>{A.set(R,new Set(D))});let B=l(x,A);return(await ee(h,B)||await(0,E.access)(h).then(()=>!0).catch(()=>!1))&&p.push(h),!0}let b=u.addSourceFileAtPath(i);await b.refreshFromFileSystem();let O=b.getDescendantsOfKind(j.SyntaxKind.CallExpression),I=O.filter(x=>x.getExpression().getText().endsWith(".addRpcRoute")),K=O.filter(x=>x.getExpression().getText().endsWith(".addRenderRoute")),W=O.filter(x=>x.getExpression().getText().endsWith(".addLoaderRoute"));if(I.length===0&&K.length===0&&W.length===0){if(delete f.files[c],s)try{await(0,E.unlink)(h),o.push(h)}catch{}return!1}let V=[],$=new Map;$.has("fastify")||$.set("fastify",new Set),$.get("fastify")?.add("FastifyRequest"),$.get("fastify")?.add("FastifyReply");let M=P.default.relative(w,P.default.dirname(i)).split(P.default.sep).join("/"),me=M==="."||!M?"":M.startsWith("/")?M:"/"+M,Q=(x,A)=>{let[B,_]=x.getArguments();if(!B?.isKind(j.SyntaxKind.StringLiteral))return;let R=B.getLiteralValue(),D="unknown",k=me,{paramsType:de,queryType:he,bodyType:Te,isMultipart:xe}=ue(_,b,h,u,$);if(_?.isKind(j.SyntaxKind.ObjectLiteralExpression)){let ne=_.getProperty("prefix");if(ne?.isKind(j.SyntaxKind.PropertyAssignment)){let H=ne.getInitializer();H?.isKind(j.SyntaxKind.StringLiteral)&&(k=H.getLiteralValue())}let re=_.getProperty("handler");if(re?.isKind(j.SyntaxKind.PropertyAssignment)){let H=re.getInitializer();H&&(D=ge(H,b,h,u,$),D.startsWith("Promise<")||(D=`Promise<${D}>`))}}let U="",z="";A==="rpc"?(U=P.default.join(k,"rpc",R).replace(/\\/g,"/"),z=J("action",k,R)):A==="loader"?(U=P.default.join(k,"loader",R).replace(/\\/g,"/"),z=J("loader",k,R)):A==="api"&&(U=P.default.join(k,"api",R).replace(/\\/g,"/"),z=J("get",k,R)),z&&V.push({type:A,name:z,returnType:D,url:R,rpcUrl:U,loaderUrl:U,paramsType:de,queryType:he,bodyType:Te,isMultipart:xe})};if(I.forEach(x=>Q(x,"rpc")),K.forEach(x=>Q(x,"loader")),W.forEach(x=>Q(x,"api")),V.length===0){if(delete f.files[c],s)try{await(0,E.unlink)(h),o.push(h)}catch{}return!1}let ye=l(V,$);return(await ee(h,ye)||await(0,E.access)(h).then(()=>!0).catch(()=>!1))&&p.push(h),f.files[c]={hash:C,fnInfo:V,imports:Array.from($.entries()).map(([x,A])=>[x,Array.from(A)])},!0}catch(c){return a.push(`Error processing ${i}: ${c instanceof Error?c.message:String(c)}`),!1}}let y=await(0,te.default)(t,{absolute:!0});if(await Promise.all(y.map(i=>F(i))),u.resolveSourceFileDependencies(),await pe(f),s){let i=await(0,te.default)(P.default.join(n,"**/*.universal.d.ts"),{absolute:!0});for(let c of i){let d=c.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await(0,E.access)(d).then(()=>!0).catch(()=>!1))try{await(0,E.unlink)(c),o.push(c)}catch{}}}}catch(f){a.push(`Fatal error: ${f instanceof Error?f.message:String(f)}`)}return{generated:p,cleaned:o,errors:a}}0&&(module.exports={generateRpcTypes});
@@ -1,9 +1,9 @@
1
- import te from"fast-glob";import{access as ne,unlink as V}from"fs/promises";import w from"path";import{Project as Te,SyntaxKind as k}from"ts-morph";import{writeFile as pe,readFile as q}from"fs/promises";import A from"path";import{format as ge,resolveConfig as ue}from"prettier";import{Node as $,SyntaxKind as S,ts as D}from"ts-morph";function fe(e){let t=e.replace(/[^a-zA-Z0-9]+(.)?/g,(a,n)=>n?n.toUpperCase():"");return t.charAt(0).toLowerCase()+t.slice(1)}function G(e,t,a){let n=A.basename(a,A.extname(a))||"Index",i=t.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),p=`${e} ${i} ${n}`;return fe(p)}function me(e){let t=/'[^']+'/g,a=/`[^`]+`/g,n=[],i,p=/'[^']+'/g;for(;(i=p.exec(e))!==null;)n.push({start:i.index,end:i.index+i[0].length,value:i[0]});let s=/`[^`]+`/g;for(;(i=s.exec(e))!==null;)n.push({start:i.index,end:i.index+i[0].length,value:i[0]});if(n.length>1){let o=[...n].sort((f,b)=>{let u=f.value.replace(/['`]/g,""),r=b.value.replace(/['`]/g,"");return u.localeCompare(r)}),c="",d=0;for(let f=0;f<n.length;f++)c+=e.slice(d,n[f].start),c+=o[f].value,d=n[f].end;return c+=e.slice(d),c}return e}function ye(e){let t=e.match(/^\{([\s\S]*)\}$/);if(!t)return e;let a=t[1];if(!a.includes(":"))return e;let n=a.split(/[;,]/).map(s=>s.trim()).filter(s=>s),i=[];for(let s of n){let o=s.indexOf(":");if(o===-1)continue;let c=s.slice(0,o).trim(),d=s.slice(o+1).trim();i.push({name:c,value:d})}return i.length<=1?e:(i.sort((s,o)=>s.name.localeCompare(o.name)),`{ ${i.map(s=>`${s.name}: ${s.value}`).join("; ")} }`)}function W(e){let t=me(e);return t=ye(t),t}async function J(e,t){try{if(await q(e,"utf-8")===t)return!1}catch{}let a=t;try{let n=await ue(e)||{};a=await ge(t,{...n,parser:"typescript",filepath:e})}catch{}try{if(await q(e,"utf-8")===a)return!1}catch{}return await pe(e,a),!0}function j(e,t,a,n,i,p){function s(r){return r.replace(/import\(['"](.*?)['"]\)/g,(l,g)=>{if(!A.isAbsolute(g))return l;let y=g;if(!A.extname(y)){let C=i.getSourceFile(h=>h.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===g);C&&(y=C.getFilePath())}let T=A.relative(A.dirname(n),y).replace(/\\/g,"/");return T.startsWith(".")||(T="./"+T),`import("${T}")`})}if(e.getSymbol()?.getName()==="Promise"){let r=e.getAwaitedType();if(r)return`Promise<${j(r,t,a,n,i,p)}>`}let o=e.getAliasSymbol()??e.getSymbol();if(o?.getName()==="__object")return W(s(e.getText(t,D.TypeFormatFlags.NoTruncation|D.TypeFormatFlags.UseFullyQualifiedType)));if(e.isObject()&&!o){let r=(l,g=0)=>{if(!(g>5)){if(l.isArray()){let y=l.getArrayElementType();y&&r(y,g);return}if(l.isObject()&&!l.getSymbol()&&!l.getAliasSymbol()){for(let y of l.getApparentProperties()){let T=y.getValueDeclaration();T&&r(y.getTypeAtLocation(T),g+1)}return}j(l,t,a,n,i,p)}};return r(e),W(s(e.getText(t,D.TypeFormatFlags.NoTruncation|D.TypeFormatFlags.UseFullyQualifiedType)))}if(!o)return W(s(e.getText(t,D.TypeFormatFlags.NoTruncation)));let c=o.getDeclarations()[0];if(!c)return o.getName();if($.isImportSpecifier(c)||$.isImportClause(c)){let r=c.getFirstAncestorByKind(S.ImportDeclaration);if(r){let l=r.getModuleSpecifierValue(),g=o.getName();return p.has(l)||p.set(l,new Set),p.get(l)?.add(g),g}}let d=c.getSourceFile();if(d.getFilePath()===a.getFilePath())return o.getName();if(d.isInNodeModules())return W(s(e.getText(t,D.TypeFormatFlags.NoTruncation)));let f=A.relative(A.dirname(n),d.getFilePath()).replace(/\\/g,"/"),b=f.startsWith(".")?f:`./${f}`,u=o.getName();return p.has(b)||p.set(b,new Set),p.get(b)?.add(u),u}function X(e,t,a,n,i){let p;if($.isFunctionLikeDeclaration(e)||$.isArrowFunction(e)){let s=e.getDescendantsOfKind(S.ReturnStatement);for(let o of s){let c=o.getExpression();if(c?.isKind(S.SatisfiesExpression)){p=c.getTypeNode()?.getType();break}}}if(p)return j(p,e,t,a,n,i);{let s=e.getType().getCallSignatures();if(s.length>0){let o=s[0]?.getReturnType();return j(o,e,t,a,n,i)}}return"unknown"}function Y(e,t,a,n,i){let p="unknown",s="unknown",o="unknown",c=!1;if(!e||!$.isObjectLiteralExpression(e))return{paramsType:p,queryType:s,bodyType:o,isMultipart:c};let d=e.getProperty("schema");if(d?.isKind(S.PropertyAssignment)){let f=d.getInitializer();if(f?.isKind(S.Identifier)){let u=f.getSymbol()?.getValueDeclaration();if(u){let r=u.getFirstDescendantByKind(S.ObjectLiteralExpression);r&&(f=r)}}if(f&&$.isObjectLiteralExpression(f)){let b=f.getProperty("consumes");if(b?.isKind(S.PropertyAssignment)){let r=b.getInitializer();$.isArrayLiteralExpression(r)&&(c=r.getElements().some(l=>l.isKind(S.StringLiteral)&&l.getLiteralValue()==="multipart/form-data"))}let u=r=>{let l=f.getProperty(r);if(l?.isKind(S.PropertyAssignment)){let g=l.getInitializer();if(g){let y=g.getType(),T=y.getApparentType(),C=T.getProperty("_output");if(C)return j(C.getTypeAtLocation(g).getApparentType(),g,t,a,n,i);let h=y.getSymbol(),N=y.getAliasSymbol(),x=h?.getName(),I=N?.getName();if(x&&x!=="__type"&&x!=="object"||I&&I!=="__type"&&I!=="object")return j(y,g,t,a,n,i);let P=T.getProperties();if(P.length>0){let _=[];for(let v of P){let L=v.getTypeAtLocation(g);_.push(`${v.getName()}: ${L.getText(g)}`)}return`{ ${_.join("; ")} }`}return j(y,g,t,a,n,i)}}return"unknown"};if(p=u("params"),s=u("querystring"),o=u("body"),c){let r="{ file: File }";o=o!=="unknown"&&o.trim().startsWith("{")?`(${o} & ${r})`:r}}}return{paramsType:p,queryType:s,bodyType:o,isMultipart:c}}function de(e){let t=[];return e.paramsType!=="unknown"&&t.push(`params: ${e.paramsType}`),e.queryType!=="unknown"&&t.push(`query: ${e.queryType}`),e.bodyType!=="unknown"&&t.push(`body: ${e.bodyType}`),t.push("signal?: AbortSignal"),t}function ee(e){let t=de(e),a="";return t.length>0&&(a=`args: { ${t.join("; ")} }`),a||(a="args: { signal?: AbortSignal }"),`export declare const ${e.name}: (${a}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${e.returnType};`}async function ke(e={}){let{routerPattern:t="src-ts/routers/**/*.mts",tsConfigFilePath:a="tsconfig.json",routerBaseDir:n="src-ts/routers",clean:i=!1}=e,p=[],s=[],o=[];try{let c=new Te({tsConfigFilePath:a,skipAddingFilesFromTsConfig:!1}),d=w.resolve(process.cwd(),n||".");async function f(u){try{let r=c.addSourceFileAtPath(u);await r.refreshFromFileSystem();let l=r.getDescendantsOfKind(k.CallExpression),g=l.filter(m=>m.getExpression().getText().endsWith(".addRpcRoute")),y=l.filter(m=>m.getExpression().getText().endsWith(".addRenderRoute")),T=l.filter(m=>m.getExpression().getText().endsWith(".addLoaderRoute")),C=w.extname(u),h=u.substring(0,u.length-C.length)+".universal.d.ts";if(g.length===0&&y.length===0&&T.length===0){if(i)try{await V(h),s.push(h)}catch{}return!1}let N=[],x=new Map;x.has("fastify")||x.set("fastify",new Set),x.get("fastify")?.add("FastifyRequest"),x.get("fastify")?.add("FastifyReply");let P=w.relative(d,w.dirname(u)).split(w.sep).join("/"),_=P==="."||!P?"":P.startsWith("/")?P:"/"+P,v=(m,F)=>{let[Z,z]=m.getArguments();if(!Z?.isKind(k.StringLiteral))return;let E=Z.getLiteralValue(),K="unknown",R=_,{paramsType:oe,queryType:ae,bodyType:ce,isMultipart:le}=Y(z,r,h,c,x);if(z?.isKind(k.ObjectLiteralExpression)){let H=z.getProperty("prefix");if(H?.isKind(k.PropertyAssignment)){let U=H.getInitializer();U?.isKind(k.StringLiteral)&&(R=U.getLiteralValue())}let Q=z.getProperty("handler");if(Q?.isKind(k.PropertyAssignment)){let U=Q.getInitializer();U&&(K=X(U,r,h,c,x),K.startsWith("Promise<")||(K=`Promise<${K}>`))}}let O="",M="";F==="rpc"?(O=w.join(R,"rpc",E).replace(/\\/g,"/"),M=G("action",R,E)):F==="loader"?(O=w.join(R,"loader",E).replace(/\\/g,"/"),M=G("loader",R,E)):F==="api"&&(O=w.join(R,"api",E).replace(/\\/g,"/"),M=G("get",R,E)),M&&N.push({type:F,name:M,returnType:K,url:E,rpcUrl:O,loaderUrl:O,paramsType:oe,queryType:ae,bodyType:ce,isMultipart:le})};if(g.forEach(m=>v(m,"rpc")),y.forEach(m=>v(m,"loader")),T.forEach(m=>v(m,"api")),N.length===0){if(i)try{await V(h),s.push(h)}catch{}return!1}let L=[],re=[...x.entries()].sort((m,F)=>m[0].localeCompare(F[0]));for(let[m,F]of re)L.push(`import type { ${[...F].sort().join(", ")} } from "${m}";`);let se=[...N].sort((m,F)=>m.name.localeCompare(F.name)),B=[];se.forEach(m=>{B.push(ee(m))});let ie=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
1
+ import ue from"fast-glob";import{access as Y,unlink as ee,readFile as Ae}from"fs/promises";import S from"path";import{Project as Re,SyntaxKind as O}from"ts-morph";import{writeFile as re,readFile as Q,mkdir as xe}from"fs/promises";import C from"path";import{format as be,resolveConfig as Fe}from"prettier";import{Node as N,SyntaxKind as A,ts as L}from"ts-morph";import{createHash as we}from"crypto";function Ce(e){let t=e.replace(/[^a-zA-Z0-9]+(.)?/g,(c,n)=>n?n.toUpperCase():"");return t.charAt(0).toLowerCase()+t.slice(1)}function Z(e,t,c){let n=C.basename(c,C.extname(c))||"Index",i=t.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),p=`${e} ${i} ${n}`;return Ce(p)}function Se(e){let t=/'[^']+'/g,c=/`[^`]+`/g,n=[],i,p=/'[^']+'/g;for(;(i=p.exec(e))!==null;)n.push({start:i.index,end:i.index+i[0].length,value:i[0]});let s=/`[^`]+`/g;for(;(i=s.exec(e))!==null;)n.push({start:i.index,end:i.index+i[0].length,value:i[0]});if(n.length>1){let o=[...n].sort((g,F)=>{let b=g.value.replace(/['`]/g,""),l=F.value.replace(/['`]/g,"");return b.localeCompare(l)}),f="",u=0;for(let g=0;g<n.length;g++)f+=e.slice(u,n[g].start),f+=o[g].value,u=n[g].end;return f+=e.slice(u),f}return e}function Pe(e){let t=e.match(/^\{([\s\S]*)\}$/);if(!t)return e;let c=t[1];if(!c.includes(":"))return e;let n=c.split(/[;,]/).map(s=>s.trim()).filter(s=>s),i=[];for(let s of n){let o=s.indexOf(":");if(o===-1)continue;let f=s.slice(0,o).trim(),u=s.slice(o+1).trim();i.push({name:f,value:u})}return i.length<=1?e:(i.sort((s,o)=>s.name.localeCompare(o.name)),`{ ${i.map(s=>`${s.name}: ${s.value}`).join("; ")} }`)}function G(e){let t=Se(e);return t=Pe(t),t}async function X(e,t){try{if(await Q(e,"utf-8")===t)return!1}catch{}let c=t;try{let n=await Fe(e)||{};c=await be(t,{...n,parser:"typescript",filepath:e})}catch{}try{if(await Q(e,"utf-8")===c)return!1}catch{}return await re(e,c),!0}function se(e){return we("sha1").update(e).digest("hex")}var J="v1",ie=C.join(process.cwd(),"node_modules",".cache","b-ssr"),oe=C.join(ie,"rpc-cache.json");async function ae(){try{let e=await Q(oe,"utf-8"),t=JSON.parse(e);return t.version!==J?{version:J,files:{}}:t}catch{return{version:J,files:{}}}}async function ce(e){try{await xe(ie,{recursive:!0}),await re(oe,JSON.stringify(e,null,2))}catch(t){console.error("\u26A0\uFE0F [B-SSR] Failed to save persistent cache:",t)}}function D(e,t,c,n,i,p){function s(l){return l.replace(/import\(['"](.*?)['"]\)/g,(m,r)=>{if(!C.isAbsolute(r))return m;let a=r;if(!C.extname(a)){let w=i.getSourceFile(v=>v.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===r);w&&(a=w.getFilePath())}let y=C.relative(C.dirname(n),a).replace(/\\/g,"/");return y.startsWith(".")||(y="./"+y),`import("${y}")`})}if(e.getSymbol()?.getName()==="Promise"){let l=e.getAwaitedType();if(l)return`Promise<${D(l,t,c,n,i,p)}>`}let o=e.getAliasSymbol()??e.getSymbol();if(o?.getName()==="__object")return G(s(e.getText(t,L.TypeFormatFlags.NoTruncation|L.TypeFormatFlags.UseFullyQualifiedType)));if(e.isObject()&&!o){let l=(m,r=0)=>{if(!(r>5)){if(m.isArray()){let a=m.getArrayElementType();a&&l(a,r);return}if(m.isObject()&&!m.getSymbol()&&!m.getAliasSymbol()){for(let a of m.getApparentProperties()){let y=a.getValueDeclaration();y&&l(a.getTypeAtLocation(y),r+1)}return}D(m,t,c,n,i,p)}};return l(e),G(s(e.getText(t,L.TypeFormatFlags.NoTruncation|L.TypeFormatFlags.UseFullyQualifiedType)))}if(!o)return G(s(e.getText(t,L.TypeFormatFlags.NoTruncation)));let f=o.getDeclarations()[0];if(!f)return o.getName();if(N.isImportSpecifier(f)||N.isImportClause(f)){let l=f.getFirstAncestorByKind(A.ImportDeclaration);if(l){let m=l.getModuleSpecifierValue(),r=o.getName();return p.has(m)||p.set(m,new Set),p.get(m)?.add(r),r}}let u=f.getSourceFile();if(u.getFilePath()===c.getFilePath())return o.getName();if(u.isInNodeModules())return G(s(e.getText(t,L.TypeFormatFlags.NoTruncation)));let g=C.relative(C.dirname(n),u.getFilePath()).replace(/\\/g,"/"),F=g.startsWith(".")?g:`./${g}`,b=o.getName();return p.has(F)||p.set(F,new Set),p.get(F)?.add(b),b}function le(e,t,c,n,i){let p;if(N.isFunctionLikeDeclaration(e)||N.isArrowFunction(e)){let s=e.getDescendantsOfKind(A.ReturnStatement);for(let o of s){let f=o.getExpression();if(f?.isKind(A.SatisfiesExpression)){p=f.getTypeNode()?.getType();break}}}if(p)return D(p,e,t,c,n,i);{let s=e.getType().getCallSignatures();if(s.length>0){let o=s[0]?.getReturnType();return D(o,e,t,c,n,i)}}return"unknown"}function pe(e,t,c,n,i){let p="unknown",s="unknown",o="unknown",f=!1;if(!e||!N.isObjectLiteralExpression(e))return{paramsType:p,queryType:s,bodyType:o,isMultipart:f};let u=e.getProperty("schema");if(u?.isKind(A.PropertyAssignment)){let g=u.getInitializer();if(g?.isKind(A.Identifier)){let b=g.getSymbol()?.getValueDeclaration();if(b){let l=b.getFirstDescendantByKind(A.ObjectLiteralExpression);l&&(g=l)}}if(g&&N.isObjectLiteralExpression(g)){let F=g.getProperty("consumes");if(F?.isKind(A.PropertyAssignment)){let l=F.getInitializer();N.isArrayLiteralExpression(l)&&(f=l.getElements().some(m=>m.isKind(A.StringLiteral)&&m.getLiteralValue()==="multipart/form-data"))}let b=l=>{let m=g.getProperty(l);if(m?.isKind(A.PropertyAssignment)){let r=m.getInitializer();if(r){let a=r.getType(),y=a.getApparentType(),w=y.getProperty("_output");if(w)return D(w.getTypeAtLocation(r).getApparentType(),r,t,c,n,i);let v=a.getSymbol(),d=a.getAliasSymbol(),h=v?.getName(),x=d?.getName();if(h&&h!=="__type"&&h!=="object"||x&&x!=="__type"&&x!=="object")return D(a,r,t,c,n,i);let k=y.getProperties();if(k.length>0){let I=[];for(let K of k){let W=K.getTypeAtLocation(r);I.push(`${K.getName()}: ${W.getText(r)}`)}return`{ ${I.join("; ")} }`}return D(a,r,t,c,n,i)}}return"unknown"};if(p=b("params"),s=b("querystring"),o=b("body"),f){let l="{ file: File }";o=o!=="unknown"&&o.trim().startsWith("{")?`(${o} & ${l})`:l}}}return{paramsType:p,queryType:s,bodyType:o,isMultipart:f}}function Ee(e){let t=[];return e.paramsType!=="unknown"&&t.push(`params: ${e.paramsType}`),e.queryType!=="unknown"&&t.push(`query: ${e.queryType}`),e.bodyType!=="unknown"&&t.push(`body: ${e.bodyType}`),t.push("signal?: AbortSignal"),t}function ge(e){let t=Ee(e),c="";return t.length>0&&(c=`args: { ${t.join("; ")} }`),c||(c="args: { signal?: AbortSignal }"),`export declare const ${e.name}: (${c}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${e.returnType};`}async function Ze(e={}){let{routerPattern:t="src-ts/routers/**/*.mts",tsConfigFilePath:c="tsconfig.json",routerBaseDir:n="src-ts/routers",clean:i=!1}=e,p=[],s=[],o=[];try{let l=function(r,a){let y=[],w=[...a.entries()].sort((h,x)=>h[0].localeCompare(x[0]));for(let[h,x]of w)y.push(`import type { ${[...x].sort().join(", ")} } from "${h}";`);let v=[...r].sort((h,x)=>h.name.localeCompare(x.name)),d=[];return v.forEach(h=>{d.push(ge(h))}),`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
2
2
  /* eslint-disable */
3
3
 
4
- `+(L.length>0?L.join(`
4
+ `+(y.length>0?y.join(`
5
5
  `)+`
6
6
 
7
- `:"")+B.join(`
7
+ `:"")+d.join(`
8
8
 
9
- `);return(await J(h,ie)||await ne(h).then(()=>!0).catch(()=>!1))&&p.push(h),!0}catch(r){return o.push(`Error processing ${u}: ${r instanceof Error?r.message:String(r)}`),!1}}let b=await te(t,{absolute:!0});if(await Promise.all(b.map(u=>f(u))),c.resolveSourceFileDependencies(),i){let u=await te(w.join(n,"**/*.universal.d.ts"),{absolute:!0});for(let r of u){let l=r.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await ne(l).then(()=>!0).catch(()=>!1))try{await V(r),s.push(r)}catch{}}}}catch(c){o.push(`Fatal error: ${c instanceof Error?c.message:String(c)}`)}return{generated:p,cleaned:s,errors:o}}export{ke as generateRpcTypes};
9
+ `)};var f=l;let u=await ae(),g=new Re({tsConfigFilePath:c,skipAddingFilesFromTsConfig:!0}),F=S.resolve(process.cwd(),n||".");async function b(r){try{let a=S.resolve(r),y=await Ae(r,"utf-8"),w=se(y),v=S.extname(r),d=r.substring(0,r.length-v.length)+".universal.d.ts",h=u.files[a];if(h&&h.hash===w){let T=h.fnInfo,P=new Map;h.imports.forEach(([E,j])=>{P.set(E,new Set(j))});let B=l(T,P);return(await X(d,B)||await Y(d).then(()=>!0).catch(()=>!1))&&p.push(d),!0}let x=g.addSourceFileAtPath(r);await x.refreshFromFileSystem();let k=x.getDescendantsOfKind(O.CallExpression),I=k.filter(T=>T.getExpression().getText().endsWith(".addRpcRoute")),K=k.filter(T=>T.getExpression().getText().endsWith(".addRenderRoute")),W=k.filter(T=>T.getExpression().getText().endsWith(".addLoaderRoute"));if(I.length===0&&K.length===0&&W.length===0){if(delete u.files[a],i)try{await ee(d),s.push(d)}catch{}return!1}let V=[],R=new Map;R.has("fastify")||R.set("fastify",new Set),R.get("fastify")?.add("FastifyRequest"),R.get("fastify")?.add("FastifyReply");let M=S.relative(F,S.dirname(r)).split(S.sep).join("/"),fe=M==="."||!M?"":M.startsWith("/")?M:"/"+M,q=(T,P)=>{let[B,_]=T.getArguments();if(!B?.isKind(O.StringLiteral))return;let E=B.getLiteralValue(),j="unknown",$=fe,{paramsType:ye,queryType:de,bodyType:he,isMultipart:Te}=pe(_,x,d,g,R);if(_?.isKind(O.ObjectLiteralExpression)){let te=_.getProperty("prefix");if(te?.isKind(O.PropertyAssignment)){let H=te.getInitializer();H?.isKind(O.StringLiteral)&&($=H.getLiteralValue())}let ne=_.getProperty("handler");if(ne?.isKind(O.PropertyAssignment)){let H=ne.getInitializer();H&&(j=le(H,x,d,g,R),j.startsWith("Promise<")||(j=`Promise<${j}>`))}}let U="",z="";P==="rpc"?(U=S.join($,"rpc",E).replace(/\\/g,"/"),z=Z("action",$,E)):P==="loader"?(U=S.join($,"loader",E).replace(/\\/g,"/"),z=Z("loader",$,E)):P==="api"&&(U=S.join($,"api",E).replace(/\\/g,"/"),z=Z("get",$,E)),z&&V.push({type:P,name:z,returnType:j,url:E,rpcUrl:U,loaderUrl:U,paramsType:ye,queryType:de,bodyType:he,isMultipart:Te})};if(I.forEach(T=>q(T,"rpc")),K.forEach(T=>q(T,"loader")),W.forEach(T=>q(T,"api")),V.length===0){if(delete u.files[a],i)try{await ee(d),s.push(d)}catch{}return!1}let me=l(V,R);return(await X(d,me)||await Y(d).then(()=>!0).catch(()=>!1))&&p.push(d),u.files[a]={hash:w,fnInfo:V,imports:Array.from(R.entries()).map(([T,P])=>[T,Array.from(P)])},!0}catch(a){return o.push(`Error processing ${r}: ${a instanceof Error?a.message:String(a)}`),!1}}let m=await ue(t,{absolute:!0});if(await Promise.all(m.map(r=>b(r))),g.resolveSourceFileDependencies(),await ce(u),i){let r=await ue(S.join(n,"**/*.universal.d.ts"),{absolute:!0});for(let a of r){let y=a.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await Y(y).then(()=>!0).catch(()=>!1))try{await ee(a),s.push(a)}catch{}}}}catch(u){o.push(`Fatal error: ${u instanceof Error?u.message:String(u)}`)}return{generated:p,cleaned:s,errors:o}}export{Ze as generateRpcTypes};
@@ -1,45 +1,45 @@
1
- "use strict";var Fe=Object.create;var ce=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var Ee=Object.getPrototypeOf,ve=Object.prototype.hasOwnProperty;var Ae=(e,n)=>{for(var l in n)ce(e,l,{get:n[l],enumerable:!0})},we=(e,n,l,a)=>{if(n&&typeof n=="object"||typeof n=="function")for(let i of Ce(n))!ve.call(e,i)&&i!==l&&ce(e,i,{get:()=>n[i],enumerable:!(a=Pe(n,i))||a.enumerable});return e};var re=(e,n,l)=>(l=e!=null?Fe(Ee(e)):{},we(n||!e||!e.__esModule?ce(l,"default",{value:e,enumerable:!0}):l,e)),$e=e=>we(ce({},"__esModule",{value:!0}),e);var ke={};Ae(ke,{generateRpcTypes:()=>Re,rpcGeneratorPlugin:()=>Le});module.exports=$e(ke);var Se=re(require("fast-glob"),1),se=require("fs/promises"),P=re(require("path"),1),q=require("ts-morph");var ne=require("fs/promises"),L=re(require("path"),1),pe=require("prettier"),h=require("ts-morph");function je(e){let n=e.replace(/[^a-zA-Z0-9]+(.)?/g,(l,a)=>a?a.toUpperCase():"");return n.charAt(0).toLowerCase()+n.slice(1)}function N(e,n,l){let a=L.default.basename(l,L.default.extname(l))||"Index",i=n.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),d=`${e} ${i} ${a}`;return je(d)}function Oe(e){let n=/'[^']+'/g,l=/`[^`]+`/g,a=[],i,d=/'[^']+'/g;for(;(i=d.exec(e))!==null;)a.push({start:i.index,end:i.index+i[0].length,value:i[0]});let p=/`[^`]+`/g;for(;(i=p.exec(e))!==null;)a.push({start:i.index,end:i.index+i[0].length,value:i[0]});if(a.length>1){let u=[...a].sort((b,E)=>{let x=b.value.replace(/['`]/g,""),t=E.value.replace(/['`]/g,"");return x.localeCompare(t)}),g="",S=0;for(let b=0;b<a.length;b++)g+=e.slice(S,a[b].start),g+=u[b].value,S=a[b].end;return g+=e.slice(S),g}return e}function Me(e){let n=e.match(/^\{([\s\S]*)\}$/);if(!n)return e;let l=n[1];if(!l.includes(":"))return e;let a=l.split(/[;,]/).map(p=>p.trim()).filter(p=>p),i=[];for(let p of a){let u=p.indexOf(":");if(u===-1)continue;let g=p.slice(0,u).trim(),S=p.slice(u+1).trim();i.push({name:g,value:S})}return i.length<=1?e:(i.sort((p,u)=>p.name.localeCompare(u.name)),`{ ${i.map(p=>`${p.name}: ${p.value}`).join("; ")} }`)}function le(e){let n=Oe(e);return n=Me(n),n}async function ue(e,n){try{if(await(0,ne.readFile)(e,"utf-8")===n)return!1}catch{}let l=n;try{let a=await(0,pe.resolveConfig)(e)||{};l=await(0,pe.format)(n,{...a,parser:"typescript",filepath:e})}catch{}try{if(await(0,ne.readFile)(e,"utf-8")===l)return!1}catch{}return await(0,ne.writeFile)(e,l),!0}function z(e,n,l,a,i,d){function p(t){return t.replace(/import\(['"](.*?)['"]\)/g,(s,r)=>{if(!L.default.isAbsolute(r))return s;let o=r;if(!L.default.extname(o)){let f=i.getSourceFile(w=>w.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===r);f&&(o=f.getFilePath())}let m=L.default.relative(L.default.dirname(a),o).replace(/\\/g,"/");return m.startsWith(".")||(m="./"+m),`import("${m}")`})}if(e.getSymbol()?.getName()==="Promise"){let t=e.getAwaitedType();if(t)return`Promise<${z(t,n,l,a,i,d)}>`}let u=e.getAliasSymbol()??e.getSymbol();if(u?.getName()==="__object")return le(p(e.getText(n,h.ts.TypeFormatFlags.NoTruncation|h.ts.TypeFormatFlags.UseFullyQualifiedType)));if(e.isObject()&&!u){let t=(s,r=0)=>{if(!(r>5)){if(s.isArray()){let o=s.getArrayElementType();o&&t(o,r);return}if(s.isObject()&&!s.getSymbol()&&!s.getAliasSymbol()){for(let o of s.getApparentProperties()){let m=o.getValueDeclaration();m&&t(o.getTypeAtLocation(m),r+1)}return}z(s,n,l,a,i,d)}};return t(e),le(p(e.getText(n,h.ts.TypeFormatFlags.NoTruncation|h.ts.TypeFormatFlags.UseFullyQualifiedType)))}if(!u)return le(p(e.getText(n,h.ts.TypeFormatFlags.NoTruncation)));let g=u.getDeclarations()[0];if(!g)return u.getName();if(h.Node.isImportSpecifier(g)||h.Node.isImportClause(g)){let t=g.getFirstAncestorByKind(h.SyntaxKind.ImportDeclaration);if(t){let s=t.getModuleSpecifierValue(),r=u.getName();return d.has(s)||d.set(s,new Set),d.get(s)?.add(r),r}}let S=g.getSourceFile();if(S.getFilePath()===l.getFilePath())return u.getName();if(S.isInNodeModules())return le(p(e.getText(n,h.ts.TypeFormatFlags.NoTruncation)));let b=L.default.relative(L.default.dirname(a),S.getFilePath()).replace(/\\/g,"/"),E=b.startsWith(".")?b:`./${b}`,x=u.getName();return d.has(E)||d.set(E,new Set),d.get(E)?.add(x),x}function ge(e,n,l,a,i){let d;if(h.Node.isFunctionLikeDeclaration(e)||h.Node.isArrowFunction(e)){let p=e.getDescendantsOfKind(h.SyntaxKind.ReturnStatement);for(let u of p){let g=u.getExpression();if(g?.isKind(h.SyntaxKind.SatisfiesExpression)){d=g.getTypeNode()?.getType();break}}}if(d)return z(d,e,n,l,a,i);{let p=e.getType().getCallSignatures();if(p.length>0){let u=p[0]?.getReturnType();return z(u,e,n,l,a,i)}}return"unknown"}function fe(e,n,l,a,i){let d="unknown",p="unknown",u="unknown",g=!1;if(!e||!h.Node.isObjectLiteralExpression(e))return{paramsType:d,queryType:p,bodyType:u,isMultipart:g};let S=e.getProperty("schema");if(S?.isKind(h.SyntaxKind.PropertyAssignment)){let b=S.getInitializer();if(b?.isKind(h.SyntaxKind.Identifier)){let x=b.getSymbol()?.getValueDeclaration();if(x){let t=x.getFirstDescendantByKind(h.SyntaxKind.ObjectLiteralExpression);t&&(b=t)}}if(b&&h.Node.isObjectLiteralExpression(b)){let E=b.getProperty("consumes");if(E?.isKind(h.SyntaxKind.PropertyAssignment)){let t=E.getInitializer();h.Node.isArrayLiteralExpression(t)&&(g=t.getElements().some(s=>s.isKind(h.SyntaxKind.StringLiteral)&&s.getLiteralValue()==="multipart/form-data"))}let x=t=>{let s=b.getProperty(t);if(s?.isKind(h.SyntaxKind.PropertyAssignment)){let r=s.getInitializer();if(r){let o=r.getType(),m=o.getApparentType(),f=m.getProperty("_output");if(f)return z(f.getTypeAtLocation(r).getApparentType(),r,n,l,a,i);let w=o.getSymbol(),R=o.getAliasSymbol(),y=w?.getName(),$=R?.getName();if(y&&y!=="__type"&&y!=="object"||$&&$!=="__type"&&$!=="object")return z(o,r,n,l,a,i);let C=m.getProperties();if(C.length>0){let Z=[];for(let j of C){let U=j.getTypeAtLocation(r);Z.push(`${j.getName()}: ${U.getText(r)}`)}return`{ ${Z.join("; ")} }`}return z(o,r,n,l,a,i)}}return"unknown"};if(d=x("params"),p=x("querystring"),u=x("body"),g){let t="{ file: File }";u=u!=="unknown"&&u.trim().startsWith("{")?`(${u} & ${t})`:t}}}return{paramsType:d,queryType:p,bodyType:u,isMultipart:g}}function De(e){let n=[];return e.paramsType!=="unknown"&&n.push(`params: ${e.paramsType}`),e.queryType!=="unknown"&&n.push(`query: ${e.queryType}`),e.bodyType!=="unknown"&&n.push(`body: ${e.bodyType}`),n.push("signal?: AbortSignal"),n}function de(e){let n=De(e),l="";return n.length>0&&(l=`args: { ${n.join("; ")} }`),l||(l="args: { signal?: AbortSignal }"),`export declare const ${e.name}: (${l}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${e.returnType};`}var xe=require("perf_hooks");var he=re(require("fast-glob"),1),V=require("fs/promises"),O=re(require("path"),1),k=require("ts-morph");async function Re(e={}){let{routerPattern:n="src-ts/routers/**/*.mts",tsConfigFilePath:l="tsconfig.json",routerBaseDir:a="src-ts/routers",clean:i=!1}=e,d=[],p=[],u=[];try{let g=new k.Project({tsConfigFilePath:l,skipAddingFilesFromTsConfig:!1}),S=O.default.resolve(process.cwd(),a||".");async function b(x){try{let t=g.addSourceFileAtPath(x);await t.refreshFromFileSystem();let s=t.getDescendantsOfKind(k.SyntaxKind.CallExpression),r=s.filter(T=>T.getExpression().getText().endsWith(".addRpcRoute")),o=s.filter(T=>T.getExpression().getText().endsWith(".addRenderRoute")),m=s.filter(T=>T.getExpression().getText().endsWith(".addLoaderRoute")),f=O.default.extname(x),w=x.substring(0,x.length-f.length)+".universal.d.ts";if(r.length===0&&o.length===0&&m.length===0){if(i)try{await(0,V.unlink)(w),p.push(w)}catch{}return!1}let R=[],y=new Map;y.has("fastify")||y.set("fastify",new Set),y.get("fastify")?.add("FastifyRequest"),y.get("fastify")?.add("FastifyReply");let C=O.default.relative(S,O.default.dirname(x)).split(O.default.sep).join("/"),Z=C==="."||!C?"":C.startsWith("/")?C:"/"+C,j=(T,v)=>{let[Y,G]=T.getArguments();if(!Y?.isKind(k.SyntaxKind.StringLiteral))return;let M=Y.getLiteralValue(),c="unknown",F=Z,{paramsType:_,queryType:I,bodyType:D,isMultipart:K}=fe(G,t,w,g,y);if(G?.isKind(k.SyntaxKind.ObjectLiteralExpression)){let ie=G.getProperty("prefix");if(ie?.isKind(k.SyntaxKind.PropertyAssignment)){let B=ie.getInitializer();B?.isKind(k.SyntaxKind.StringLiteral)&&(F=B.getLiteralValue())}let ae=G.getProperty("handler");if(ae?.isKind(k.SyntaxKind.PropertyAssignment)){let B=ae.getInitializer();B&&(c=ge(B,t,w,g,y),c.startsWith("Promise<")||(c=`Promise<${c}>`))}}let A="",W="";v==="rpc"?(A=O.default.join(F,"rpc",M).replace(/\\/g,"/"),W=N("action",F,M)):v==="loader"?(A=O.default.join(F,"loader",M).replace(/\\/g,"/"),W=N("loader",F,M)):v==="api"&&(A=O.default.join(F,"api",M).replace(/\\/g,"/"),W=N("get",F,M)),W&&R.push({type:v,name:W,returnType:c,url:M,rpcUrl:A,loaderUrl:A,paramsType:_,queryType:I,bodyType:D,isMultipart:K})};if(r.forEach(T=>j(T,"rpc")),o.forEach(T=>j(T,"loader")),m.forEach(T=>j(T,"api")),R.length===0){if(i)try{await(0,V.unlink)(w),p.push(w)}catch{}return!1}let U=[],Q=[...y.entries()].sort((T,v)=>T[0].localeCompare(v[0]));for(let[T,v]of Q)U.push(`import type { ${[...v].sort().join(", ")} } from "${T}";`);let X=[...R].sort((T,v)=>T.name.localeCompare(v.name)),oe=[];X.forEach(T=>{oe.push(de(T))});let me=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
1
+ "use strict";var je=Object.create;var ue=Object.defineProperty;var Me=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var Ie=Object.getPrototypeOf,De=Object.prototype.hasOwnProperty;var Le=(e,r)=>{for(var p in r)ue(e,p,{get:r[p],enumerable:!0})},Fe=(e,r,p,c)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of Oe(r))!De.call(e,a)&&a!==p&&ue(e,a,{get:()=>r[a],enumerable:!(c=Me(r,a))||c.enumerable});return e};var pe=(e,r,p)=>(p=e!=null?je(Ie(e)):{},Fe(r||!e||!e.__esModule?ue(p,"default",{value:e,enumerable:!0}):p,e)),ke=e=>Fe(ue({},"__esModule",{value:!0}),e);var Be={};Le(Be,{generateRpcTypes:()=>Ae,rpcGeneratorPlugin:()=>We});module.exports=ke(Be);var $e=pe(require("fast-glob"),1),ee=require("fs/promises"),E=pe(require("path"),1),H=require("ts-morph");var B=require("fs/promises"),k=pe(require("path"),1),fe=require("prettier"),T=require("ts-morph"),Pe=require("crypto");function Ne(e){let r=e.replace(/[^a-zA-Z0-9]+(.)?/g,(p,c)=>c?c.toUpperCase():"");return r.charAt(0).toLowerCase()+r.slice(1)}function Z(e,r,p){let c=k.default.basename(p,k.default.extname(p))||"Index",a=r.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),m=`${e} ${a} ${c}`;return Ne(m)}function qe(e){let r=/'[^']+'/g,p=/`[^`]+`/g,c=[],a,m=/'[^']+'/g;for(;(a=m.exec(e))!==null;)c.push({start:a.index,end:a.index+a[0].length,value:a[0]});let u=/`[^`]+`/g;for(;(a=u.exec(e))!==null;)c.push({start:a.index,end:a.index+a[0].length,value:a[0]});if(c.length>1){let d=[...c].sort((x,$)=>{let v=x.value.replace(/['`]/g,""),h=$.value.replace(/['`]/g,"");return v.localeCompare(h)}),b="",y=0;for(let x=0;x<c.length;x++)b+=e.slice(y,c[x].start),b+=d[x].value,y=c[x].end;return b+=e.slice(y),b}return e}function Ue(e){let r=e.match(/^\{([\s\S]*)\}$/);if(!r)return e;let p=r[1];if(!p.includes(":"))return e;let c=p.split(/[;,]/).map(u=>u.trim()).filter(u=>u),a=[];for(let u of c){let d=u.indexOf(":");if(d===-1)continue;let b=u.slice(0,d).trim(),y=u.slice(d+1).trim();a.push({name:b,value:y})}return a.length<=1?e:(a.sort((u,d)=>u.name.localeCompare(d.name)),`{ ${a.map(u=>`${u.name}: ${u.value}`).join("; ")} }`)}function ge(e){let r=qe(e);return r=Ue(r),r}async function ne(e,r){try{if(await(0,B.readFile)(e,"utf-8")===r)return!1}catch{}let p=r;try{let c=await(0,fe.resolveConfig)(e)||{};p=await(0,fe.format)(r,{...c,parser:"typescript",filepath:e})}catch{}try{if(await(0,B.readFile)(e,"utf-8")===p)return!1}catch{}return await(0,B.writeFile)(e,p),!0}function de(e){return(0,Pe.createHash)("sha1").update(e).digest("hex")}var we="v1",Ee=k.default.join(process.cwd(),"node_modules",".cache","b-ssr"),ve=k.default.join(Ee,"rpc-cache.json");async function me(){try{let e=await(0,B.readFile)(ve,"utf-8"),r=JSON.parse(e);return r.version!==we?{version:we,files:{}}:r}catch{return{version:we,files:{}}}}async function he(e){try{await(0,B.mkdir)(Ee,{recursive:!0}),await(0,B.writeFile)(ve,JSON.stringify(e,null,2))}catch(r){console.error("\u26A0\uFE0F [B-SSR] Failed to save persistent cache:",r)}}function Y(e,r,p,c,a,m){function u(h){return h.replace(/import\(['"](.*?)['"]\)/g,(C,f)=>{if(!k.default.isAbsolute(f))return C;let t=f;if(!k.default.extname(t)){let s=a.getSourceFile(l=>l.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===f);s&&(t=s.getFilePath())}let n=k.default.relative(k.default.dirname(c),t).replace(/\\/g,"/");return n.startsWith(".")||(n="./"+n),`import("${n}")`})}if(e.getSymbol()?.getName()==="Promise"){let h=e.getAwaitedType();if(h)return`Promise<${Y(h,r,p,c,a,m)}>`}let d=e.getAliasSymbol()??e.getSymbol();if(d?.getName()==="__object")return ge(u(e.getText(r,T.ts.TypeFormatFlags.NoTruncation|T.ts.TypeFormatFlags.UseFullyQualifiedType)));if(e.isObject()&&!d){let h=(C,f=0)=>{if(!(f>5)){if(C.isArray()){let t=C.getArrayElementType();t&&h(t,f);return}if(C.isObject()&&!C.getSymbol()&&!C.getAliasSymbol()){for(let t of C.getApparentProperties()){let n=t.getValueDeclaration();n&&h(t.getTypeAtLocation(n),f+1)}return}Y(C,r,p,c,a,m)}};return h(e),ge(u(e.getText(r,T.ts.TypeFormatFlags.NoTruncation|T.ts.TypeFormatFlags.UseFullyQualifiedType)))}if(!d)return ge(u(e.getText(r,T.ts.TypeFormatFlags.NoTruncation)));let b=d.getDeclarations()[0];if(!b)return d.getName();if(T.Node.isImportSpecifier(b)||T.Node.isImportClause(b)){let h=b.getFirstAncestorByKind(T.SyntaxKind.ImportDeclaration);if(h){let C=h.getModuleSpecifierValue(),f=d.getName();return m.has(C)||m.set(C,new Set),m.get(C)?.add(f),f}}let y=b.getSourceFile();if(y.getFilePath()===p.getFilePath())return d.getName();if(y.isInNodeModules())return ge(u(e.getText(r,T.ts.TypeFormatFlags.NoTruncation)));let x=k.default.relative(k.default.dirname(c),y.getFilePath()).replace(/\\/g,"/"),$=x.startsWith(".")?x:`./${x}`,v=d.getName();return m.has($)||m.set($,new Set),m.get($)?.add(v),v}function ye(e,r,p,c,a){let m;if(T.Node.isFunctionLikeDeclaration(e)||T.Node.isArrowFunction(e)){let u=e.getDescendantsOfKind(T.SyntaxKind.ReturnStatement);for(let d of u){let b=d.getExpression();if(b?.isKind(T.SyntaxKind.SatisfiesExpression)){m=b.getTypeNode()?.getType();break}}}if(m)return Y(m,e,r,p,c,a);{let u=e.getType().getCallSignatures();if(u.length>0){let d=u[0]?.getReturnType();return Y(d,e,r,p,c,a)}}return"unknown"}function xe(e,r,p,c,a){let m="unknown",u="unknown",d="unknown",b=!1;if(!e||!T.Node.isObjectLiteralExpression(e))return{paramsType:m,queryType:u,bodyType:d,isMultipart:b};let y=e.getProperty("schema");if(y?.isKind(T.SyntaxKind.PropertyAssignment)){let x=y.getInitializer();if(x?.isKind(T.SyntaxKind.Identifier)){let v=x.getSymbol()?.getValueDeclaration();if(v){let h=v.getFirstDescendantByKind(T.SyntaxKind.ObjectLiteralExpression);h&&(x=h)}}if(x&&T.Node.isObjectLiteralExpression(x)){let $=x.getProperty("consumes");if($?.isKind(T.SyntaxKind.PropertyAssignment)){let h=$.getInitializer();T.Node.isArrayLiteralExpression(h)&&(b=h.getElements().some(C=>C.isKind(T.SyntaxKind.StringLiteral)&&C.getLiteralValue()==="multipart/form-data"))}let v=h=>{let C=x.getProperty(h);if(C?.isKind(T.SyntaxKind.PropertyAssignment)){let f=C.getInitializer();if(f){let t=f.getType(),n=t.getApparentType(),s=n.getProperty("_output");if(s)return Y(s.getTypeAtLocation(f).getApparentType(),f,r,p,c,a);let l=t.getSymbol(),g=t.getAliasSymbol(),o=l?.getName(),i=g?.getName();if(o&&o!=="__type"&&o!=="object"||i&&i!=="__type"&&i!=="object")return Y(t,f,r,p,c,a);let w=n.getProperties();if(w.length>0){let S=[];for(let j of w){let te=j.getTypeAtLocation(f);S.push(`${j.getName()}: ${te.getText(f)}`)}return`{ ${S.join("; ")} }`}return Y(t,f,r,p,c,a)}}return"unknown"};if(m=v("params"),u=v("querystring"),d=v("body"),b){let h="{ file: File }";d=d!=="unknown"&&d.trim().startsWith("{")?`(${d} & ${h})`:h}}}return{paramsType:m,queryType:u,bodyType:d,isMultipart:b}}function Ke(e){let r=[];return e.paramsType!=="unknown"&&r.push(`params: ${e.paramsType}`),e.queryType!=="unknown"&&r.push(`query: ${e.queryType}`),e.bodyType!=="unknown"&&r.push(`body: ${e.bodyType}`),r.push("signal?: AbortSignal"),r}function be(e){let r=Ke(e),p="";return r.length>0&&(p=`args: { ${r.join("; ")} }`),p||(p="args: { signal?: AbortSignal }"),`export declare const ${e.name}: (${p}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${e.returnType};`}var Ce=require("perf_hooks");var Te=pe(require("fast-glob"),1),U=require("fs/promises"),N=pe(require("path"),1),_=require("ts-morph");async function Ae(e={}){let{routerPattern:r="src-ts/routers/**/*.mts",tsConfigFilePath:p="tsconfig.json",routerBaseDir:c="src-ts/routers",clean:a=!1}=e,m=[],u=[],d=[];try{let h=function(f,t){let n=[],s=[...t.entries()].sort((o,i)=>o[0].localeCompare(i[0]));for(let[o,i]of s)n.push(`import type { ${[...i].sort().join(", ")} } from "${o}";`);let l=[...f].sort((o,i)=>o.name.localeCompare(i.name)),g=[];return l.forEach(o=>{g.push(be(o))}),`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
2
2
  /* eslint-disable */
3
3
 
4
- `+(U.length>0?U.join(`
4
+ `+(n.length>0?n.join(`
5
5
  `)+`
6
6
 
7
- `:"")+oe.join(`
7
+ `:"")+g.join(`
8
8
 
9
- `);return(await ue(w,me)||await(0,V.access)(w).then(()=>!0).catch(()=>!1))&&d.push(w),!0}catch(t){return u.push(`Error processing ${x}: ${t instanceof Error?t.message:String(t)}`),!1}}let E=await(0,he.default)(n,{absolute:!0});if(await Promise.all(E.map(x=>b(x))),g.resolveSourceFileDependencies(),i){let x=await(0,he.default)(O.default.join(a,"**/*.universal.d.ts"),{absolute:!0});for(let t of x){let s=t.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await(0,V.access)(s).then(()=>!0).catch(()=>!1))try{await(0,V.unlink)(t),p.push(t)}catch{}}}}catch(g){u.push(`Fatal error: ${g instanceof Error?g.message:String(g)}`)}return{generated:d,cleaned:p,errors:u}}var H="virtual:b-ssr-rpc-universal:";function Le(e={}){let{routerPattern:n="src-ts/routers/**/*.mts",tsConfigFilePath:l="tsconfig.json",routerBaseDir:a="src-ts/routers"}=e,i=new Map,d=new Set,p=new q.Project({tsConfigFilePath:l,skipAddingFilesFromTsConfig:!1}),u=P.default.resolve(process.cwd(),a||"."),g=!1;async function S(t){try{let s=p.addSourceFileAtPath(t);await s.refreshFromFileSystem(),g||p.resolveSourceFileDependencies();let r=s.getDescendantsOfKind(q.SyntaxKind.CallExpression),o=r.filter(c=>c.getExpression().getText().endsWith(".addRpcRoute")),m=r.filter(c=>c.getExpression().getText().endsWith(".addRenderRoute")),f=r.filter(c=>c.getExpression().getText().endsWith(".addLoaderRoute")),w=P.default.extname(t),R=t.substring(0,t.length-w.length)+".universal.d.ts",y=P.default.resolve(t);if(o.length===0&&m.length===0&&f.length===0){i.delete(y),d.delete(y),R!==t&&await(0,se.unlink)(R).catch(()=>{});return}d.add(y);let $=[],C=new Map;C.has("fastify")||C.set("fastify",new Set),C.get("fastify")?.add("FastifyRequest"),C.get("fastify")?.add("FastifyReply");let j=P.default.relative(u,P.default.dirname(t)).split(P.default.sep).join("/"),U=j==="."||!j?"":j.startsWith("/")?j:"/"+j,Q=(c,F)=>{let[_,I]=c.getArguments();if(!_?.isKind(q.SyntaxKind.StringLiteral))return;let D=_.getLiteralValue(),K="unknown",A=U,{paramsType:W,queryType:ie,bodyType:ae,isMultipart:B}=fe(I,s,R,p,C);if(I?.isKind(q.SyntaxKind.ObjectLiteralExpression)){let be=I.getProperty("prefix");if(be?.isKind(q.SyntaxKind.PropertyAssignment)){let te=be.getInitializer();te?.isKind(q.SyntaxKind.StringLiteral)&&(A=te.getLiteralValue())}let Te=I.getProperty("handler");if(Te?.isKind(q.SyntaxKind.PropertyAssignment)){let te=Te.getInitializer();te&&(K=ge(te,s,R,p,C),K.startsWith("Promise<")||(K=`Promise<${K}>`))}}let J="",ee="";F==="rpc"?(J=P.default.join(A,"rpc",D).replace(/\\/g,"/"),ee=N("action",A,D)):F==="loader"?(J=P.default.join(A,"loader",D).replace(/\\/g,"/"),ee=N("loader",A,D)):F==="api"&&(J=P.default.join(A,"api",D).replace(/\\/g,"/"),ee=N("get",A,D)),ee&&$.push({type:F,name:ee,returnType:K,url:D,rpcUrl:J,loaderUrl:J,paramsType:W,queryType:ie,bodyType:ae,isMultipart:B})};o.forEach(c=>Q(c,"rpc")),m.forEach(c=>Q(c,"loader")),f.forEach(c=>Q(c,"api"));let X=[],oe=[...C.entries()].sort((c,F)=>c[0].localeCompare(F[0]));for(let[c,F]of oe)X.push(`import type { ${[...F].sort().join(", ")} } from "${c}";`);let me=[...$].sort((c,F)=>c.name.localeCompare(F.name)),ye=[];me.forEach(c=>{ye.push(de(c))});let T=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
9
+ `)};var b=h;let y=await me(),x=new _.Project({tsConfigFilePath:p,skipAddingFilesFromTsConfig:!0}),$=N.default.resolve(process.cwd(),c||".");async function v(f){try{let t=N.default.resolve(f),n=await(0,U.readFile)(f,"utf-8"),s=de(n),l=N.default.extname(f),g=f.substring(0,f.length-l.length)+".universal.d.ts",o=y.files[t];if(o&&o.hash===s){let F=o.fnInfo,D=new Map;o.imports.forEach(([M,O])=>{D.set(M,new Set(O))});let R=h(F,D);return(await ne(g,R)||await(0,U.access)(g).then(()=>!0).catch(()=>!1))&&m.push(g),!0}let i=x.addSourceFileAtPath(f);await i.refreshFromFileSystem();let w=i.getDescendantsOfKind(_.SyntaxKind.CallExpression),S=w.filter(F=>F.getExpression().getText().endsWith(".addRpcRoute")),j=w.filter(F=>F.getExpression().getText().endsWith(".addRenderRoute")),te=w.filter(F=>F.getExpression().getText().endsWith(".addLoaderRoute"));if(S.length===0&&j.length===0&&te.length===0){if(delete y.files[t],a)try{await(0,U.unlink)(g),u.push(g)}catch{}return!1}let q=[],I=new Map;I.has("fastify")||I.set("fastify",new Set),I.get("fastify")?.add("FastifyRequest"),I.get("fastify")?.add("FastifyReply");let re=N.default.relative($,N.default.dirname(f)).split(N.default.sep).join("/"),J=re==="."||!re?"":re.startsWith("/")?re:"/"+re,oe=(F,D)=>{let[R,A]=F.getArguments();if(!R?.isKind(_.SyntaxKind.StringLiteral))return;let M=R.getLiteralValue(),O="unknown",P=J,{paramsType:W,queryType:L,bodyType:ae,isMultipart:ce}=xe(A,i,g,x,I);if(A?.isKind(_.SyntaxKind.ObjectLiteralExpression)){let V=A.getProperty("prefix");if(V?.isKind(_.SyntaxKind.PropertyAssignment)){let G=V.getInitializer();G?.isKind(_.SyntaxKind.StringLiteral)&&(P=G.getLiteralValue())}let z=A.getProperty("handler");if(z?.isKind(_.SyntaxKind.PropertyAssignment)){let G=z.getInitializer();G&&(O=ye(G,i,g,x,I),O.startsWith("Promise<")||(O=`Promise<${O}>`))}}let Q="",X="";D==="rpc"?(Q=N.default.join(P,"rpc",M).replace(/\\/g,"/"),X=Z("action",P,M)):D==="loader"?(Q=N.default.join(P,"loader",M).replace(/\\/g,"/"),X=Z("loader",P,M)):D==="api"&&(Q=N.default.join(P,"api",M).replace(/\\/g,"/"),X=Z("get",P,M)),X&&q.push({type:D,name:X,returnType:O,url:M,rpcUrl:Q,loaderUrl:Q,paramsType:W,queryType:L,bodyType:ae,isMultipart:ce})};if(S.forEach(F=>oe(F,"rpc")),j.forEach(F=>oe(F,"loader")),te.forEach(F=>oe(F,"api")),q.length===0){if(delete y.files[t],a)try{await(0,U.unlink)(g),u.push(g)}catch{}return!1}let ie=h(q,I);return(await ne(g,ie)||await(0,U.access)(g).then(()=>!0).catch(()=>!1))&&m.push(g),y.files[t]={hash:s,fnInfo:q,imports:Array.from(I.entries()).map(([F,D])=>[F,Array.from(D)])},!0}catch(t){return d.push(`Error processing ${f}: ${t instanceof Error?t.message:String(t)}`),!1}}let C=await(0,Te.default)(r,{absolute:!0});if(await Promise.all(C.map(f=>v(f))),x.resolveSourceFileDependencies(),await he(y),a){let f=await(0,Te.default)(N.default.join(c,"**/*.universal.d.ts"),{absolute:!0});for(let t of f){let n=t.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await(0,U.access)(n).then(()=>!0).catch(()=>!1))try{await(0,U.unlink)(t),u.push(t)}catch{}}}}catch(y){d.push(`Fatal error: ${y instanceof Error?y.message:String(y)}`)}return{generated:m,cleaned:u,errors:d}}var se="virtual:b-ssr-rpc-universal:";function We(e={}){let{routerPattern:r="src-ts/routers/**/*.mts",tsConfigFilePath:p="tsconfig.json",routerBaseDir:c="src-ts/routers"}=e,a=new Map,m=new Set,u=new H.Project({tsConfigFilePath:p,skipAddingFilesFromTsConfig:!0}),d=E.default.resolve(process.cwd(),c||"."),b=!1,y={version:"v1",files:{}};async function x(t){try{let n=E.default.resolve(t),s=await(0,ee.readFile)(t,"utf-8"),l=de(s),g=y.files[n];if(g&&g.hash===l){let R=g.fnInfo,A=new Map;g.imports.forEach(([ae,ce])=>{A.set(ae,new Set(ce))}),m.add(n);let{client:M,server:O}=v(R,t);a.set(n,{client:M,server:O});let P=E.default.extname(t),W=t.substring(0,t.length-P.length)+".universal.d.ts",L=$(R,A);await ne(W,L);return}let o=u.addSourceFileAtPath(t);await o.refreshFromFileSystem(),b||u.resolveSourceFileDependencies();let i=o.getDescendantsOfKind(H.SyntaxKind.CallExpression),w=i.filter(R=>R.getExpression().getText().endsWith(".addRpcRoute")),S=i.filter(R=>R.getExpression().getText().endsWith(".addRenderRoute")),j=i.filter(R=>R.getExpression().getText().endsWith(".addLoaderRoute")),te=E.default.extname(t),q=t.substring(0,t.length-te.length)+".universal.d.ts";if(w.length===0&&S.length===0&&j.length===0){a.delete(n),m.delete(n),delete y.files[n],q!==t&&await(0,ee.unlink)(q).catch(()=>{});return}m.add(n);let I=[],K=new Map;K.has("fastify")||K.set("fastify",new Set),K.get("fastify")?.add("FastifyRequest"),K.get("fastify")?.add("FastifyReply");let J=E.default.relative(d,E.default.dirname(t)).split(E.default.sep).join("/"),oe=J==="."||!J?"":J.startsWith("/")?J:"/"+J,ie=(R,A)=>{let[M,O]=R.getArguments();if(!M?.isKind(H.SyntaxKind.StringLiteral))return;let P=M.getLiteralValue(),W="unknown",L=oe,{paramsType:ae,queryType:ce,bodyType:Q,isMultipart:X}=xe(O,o,q,u,K);if(O?.isKind(H.SyntaxKind.ObjectLiteralExpression)){let G=O.getProperty("prefix");if(G?.isKind(H.SyntaxKind.PropertyAssignment)){let le=G.getInitializer();le?.isKind(H.SyntaxKind.StringLiteral)&&(L=le.getLiteralValue())}let Se=O.getProperty("handler");if(Se?.isKind(H.SyntaxKind.PropertyAssignment)){let le=Se.getInitializer();le&&(W=ye(le,o,q,u,K),W.startsWith("Promise<")||(W=`Promise<${W}>`))}}let V="",z="";A==="rpc"?(V=E.default.join(L,"rpc",P).replace(/\\/g,"/"),z=Z("action",L,P)):A==="loader"?(V=E.default.join(L,"loader",P).replace(/\\/g,"/"),z=Z("loader",L,P)):A==="api"&&(V=E.default.join(L,"api",P).replace(/\\/g,"/"),z=Z("get",L,P)),z&&I.push({type:A,name:z,returnType:W,url:P,rpcUrl:V,loaderUrl:V,paramsType:ae,queryType:ce,bodyType:Q,isMultipart:X})};w.forEach(R=>ie(R,"rpc")),S.forEach(R=>ie(R,"loader")),j.forEach(R=>ie(R,"api"));let Re=$(I,K);await ne(q,Re);let{client:F,server:D}=v(I,t);a.set(n,{client:F,server:D}),y.files[n]={hash:l,fnInfo:I,imports:Array.from(K.entries()).map(([R,A])=>[R,Array.from(A)])}}catch(n){console.error(`[rpc-generator] Error al procesar ${t}:`,{error:n})}}function $(t,n){let s=[],l=[...n.entries()].sort((i,w)=>i[0].localeCompare(w[0]));for(let[i,w]of l)s.push(`import type { ${[...w].sort().join(", ")} } from "${i}";`);let g=[...t].sort((i,w)=>i.name.localeCompare(w.name)),o=[];return g.forEach(i=>{o.push(be(i))}),`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
10
10
  /* eslint-disable */
11
11
 
12
- `+(X.length>0?X.join(`
12
+ `+(s.length>0?s.join(`
13
13
  `)+`
14
14
 
15
- `:"")+ye.join(`
15
+ `:"")+o.join(`
16
16
 
17
- `);await ue(R,T);let v=[],Y=[];$.forEach(c=>{let _=c.type==="rpc"?"POST":"GET",I=c.type==="loader"?c.loaderUrl:c.rpcUrl;Y.push({name:c.name,rpcUrl:I,method:_,isMultipart:!!c.isMultipart}),v.push({name:c.name,url:c.url,type:c.type,requiresArgs:!0})});let G=`
18
- import { createClientRpc } from '@bobtail.software/b-ssr/client';
19
-
20
- if (import.meta.env.DEV) {
21
- console.debug('\u{1F6E1}\uFE0F [B-SSR Security] Loaded SAFE Client-Stub for: ${P.default.basename(t)}');
22
- }
17
+ `)}function v(t,n){let s=[],l=[];t.forEach(i=>{let S=i.type==="rpc"?"POST":"GET",j=i.type==="loader"?i.loaderUrl:i.rpcUrl;l.push({name:i.name,rpcUrl:j,method:S,isMultipart:!!i.isMultipart}),s.push({name:i.name,url:i.url,type:i.type,requiresArgs:!0})});let g=`
18
+ import { createClientRpc } from '@bobtail.software/b-ssr/client';
19
+
20
+ if (import.meta.env.DEV) {
21
+ console.debug('\u{1F6E1}\uFE0F [B-SSR Security] Loaded SAFE Client-Stub for: ${E.default.basename(n)}');
22
+ }
23
23
 
24
- ${Y.map(c=>`
25
- export const ${c.name} = createClientRpc({
26
- url: '${c.rpcUrl}',
27
- method: '${c.method}',
28
- isMultipart: ${c.isMultipart}
29
- });
30
- `).join(`
24
+ ${l.map(i=>`
25
+ export const ${i.name} = createClientRpc({
26
+ url: '${i.rpcUrl}',
27
+ method: '${i.method}',
28
+ isMultipart: ${i.isMultipart}
29
+ });
30
+ `).join(`
31
31
  `)}
32
- `,M=E(v,t);i.set(P.default.resolve(t),{client:G,server:M})}catch(s){console.error(`[rpc-generator] Error al procesar ${t}:`,{error:s})}}let b=(t,s,r)=>{if(s.includes("node_modules")||s.startsWith(H))return null;if(r?.ssr===!0&&/\.[cm]?[jt]sx?$/.test(s)){let o=/\brequire\s*\(/.test(t),m=/\bmodule\.exports\b/.test(t),f=/\bexports\./.test(t);if(o||m||f)return"import { createRequire } from 'module';"+`
32
+ `,o=C(s,n);return{client:g,server:o}}let h=(t,n,s)=>{if(n.includes("node_modules")||n.startsWith(se))return null;if(s?.ssr===!0&&/\.[cm]?[jt]sx?$/.test(n)){let l=/\brequire\s*\(/.test(t),g=/\bmodule\.exports\b/.test(t),o=/\bexports\./.test(t);if(l||g||o)return"import { createRequire } from 'module';"+`
33
33
  const require = createRequire(import.meta.url);
34
34
  const module = { exports: {} };
35
35
  const exports = module.exports;
36
36
  `+t+`
37
- export default module.exports;`}return null};function E(t,s){if(t.length===0)return"";let r=process.cwd(),o=P.default.relative(r,s).replace(/\\/g,"/");return`
37
+ export default module.exports;`}return null};function C(t,n){if(t.length===0)return"";let s=process.cwd(),l=E.default.relative(s,n).replace(/\\/g,"/");return`
38
38
  import path from 'path';
39
39
  import { pathToFileURL } from 'url';
40
40
 
41
41
  if (typeof window !== 'undefined' && typeof document !== 'undefined') {
42
- throw new Error('\u{1F6A8} [B-SSR SECURITY ALERT] Server-side code leaked to browser: ${`./${o}`}');
42
+ throw new Error('\u{1F6A8} [B-SSR SECURITY ALERT] Server-side code leaked to browser: ${`./${l}`}');
43
43
  }
44
44
 
45
45
  let initPromise;
@@ -53,7 +53,7 @@ export default module.exports;`}return null};function E(t,s){if(t.length===0)ret
53
53
  renderOptionsMap = new Map();
54
54
  loaderApiOptionsMap = new Map();
55
55
  const projectRoot = process.cwd();
56
- const absolutePath = path.resolve(projectRoot, '${o}');
56
+ const absolutePath = path.resolve(projectRoot, '${l}');
57
57
  const serverModuleUrl = pathToFileURL(absolutePath).href;
58
58
 
59
59
  if (typeof globalThis.require === 'undefined') {
@@ -101,46 +101,46 @@ export default module.exports;`}return null};function E(t,s){if(t.length===0)ret
101
101
  return initPromise;
102
102
  }
103
103
 
104
- ${t.map(f=>{let w=[];f.requiresArgs&&w.push("args"),w.push("ssrContext");let R=f.requiresArgs?"args":"{}",y="";return f.type==="rpc"?y=`
104
+ ${t.map(o=>{let i=[];o.requiresArgs&&i.push("args"),i.push("ssrContext");let w=o.requiresArgs?"args":"{}",S="";return o.type==="rpc"?S=`
105
105
  if (fn.isMultipart) throw new Error('RPC multipart no soportado en SSR.');
106
106
  await getOptionsMaps();
107
- const options = rpcOptionsMap.get('${f.url}');
108
- if (!options?.handler) throw new Error('Handler no encontrado para RPC: ${f.name}');
109
- const augmentedReq = Object.assign(Object.create(ssrContext.req), ${R});
107
+ const options = rpcOptionsMap.get('${o.url}');
108
+ if (!options?.handler) throw new Error('Handler no encontrado para RPC: ${o.name}');
109
+ const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
110
110
  return await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply);
111
- `:f.type==="api"?y=`
111
+ `:o.type==="api"?S=`
112
112
  await getOptionsMaps();
113
- const options = loaderApiOptionsMap.get('${f.url}');
113
+ const options = loaderApiOptionsMap.get('${o.url}');
114
114
  if (!options?.handler) {
115
- console.error('\u26A0\uFE0F [B-SSR Warning] Handler API no encontrado:', '${f.name}', 'URL:', '${f.url}');
115
+ console.error('\u26A0\uFE0F [B-SSR Warning] Handler API no encontrado:', '${o.name}', 'URL:', '${o.url}');
116
116
  return null;
117
117
  }
118
- const augmentedReq = Object.assign(Object.create(ssrContext.req), ${R});
118
+ const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
119
119
  return await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply);
120
- `:y=`
120
+ `:S=`
121
121
  await getOptionsMaps();
122
- const options = renderOptionsMap.get('${f.url}');
122
+ const options = renderOptionsMap.get('${o.url}');
123
123
  if (!options) return {};
124
- const augmentedReq = Object.assign(Object.create(ssrContext.req), ${R});
124
+ const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
125
125
  let customData = {};
126
126
  try {
127
127
  if (options.handler) {
128
128
  customData = (await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply)) || {};
129
129
  }
130
130
  } catch (handlerErr) {
131
- console.error('\u274C [B-SSR Handler Error] ${f.name}:', handlerErr);
131
+ console.error('\u274C [B-SSR Handler Error] ${o.name}:', handlerErr);
132
132
  return {};
133
133
  }
134
134
  if (ssrContext.reply.sent) return;
135
135
  return { ...customData };
136
- `,`export const ${f.name} = async (${w.join(", ")}) => {
136
+ `,`export const ${o.name} = async (${i.join(", ")}) => {
137
137
  try {
138
- if (!ssrContext?.req) throw new Error('ssrContext requerido en ${f.name} (SSR)');
139
- ${y}
138
+ if (!ssrContext?.req) throw new Error('ssrContext requerido en ${o.name} (SSR)');
139
+ ${S}
140
140
  } catch (error) {
141
- console.error('\u274C [B-SSR Error] ${f.name}:', error);
141
+ console.error('\u274C [B-SSR Error] ${o.name}:', error);
142
142
  throw error;
143
143
  }
144
144
  };`}).join(`
145
145
  `)}
146
- `}async function x(){g=!0;let t=xe.performance.now(),s=await(0,Se.default)(n,{absolute:!0});await Promise.all(s.map(o=>S(o))),p.resolveSourceFileDependencies();let r=xe.performance.now();console.log(`\u{1F680} [B-SSR] RPC Generation completed in ${Math.round(r-t)}ms (${s.length} files)`),g=!1}return{name:"b-ssr-vite-plugin-rpc-universal-generator",enforce:"pre",async buildStart(){await x()},configureServer(t){let s=r=>r.endsWith(".mts")||r.endsWith(".ts");t.watcher.on("add",r=>s(r)&&S(r)),t.watcher.on("change",r=>s(r)&&S(r)),t.watcher.on("unlink",r=>{if(s(r)){let o=P.default.resolve(r);i.delete(o),d.delete(o);let m=P.default.extname(r),f=r.substring(0,r.length-m.length)+".universal.d.ts";(0,se.unlink)(f).catch(()=>{})}})},async resolveId(t,s,r){if(t.startsWith(H))return null;if(t.includes(".universal")){let o=t.split("?")[0],m=o;if(o.endsWith(".universal"))m=o;else if(o.endsWith(".universal.ts"))m=o.slice(0,-3);else if(o.endsWith(".universal.mts"))m=o.slice(0,-4);else if(o.endsWith(".universal.js"))m=o.slice(0,-3);else return null;let f=[".mts",".ts"];for(let w of f){let R=m.slice(0,-10)+w,y=await this.resolve(R,s,{skipSelf:!0});if(y){let $=r?.ssr?"?mode=ssr":"?mode=client";return H+y.id+$}try{await(0,se.access)(R);let $=r?.ssr?"?mode=ssr":"?mode=client";return H+R+$}catch{}}}return null},async load(t,s){if(t.startsWith(H)){let r=t.slice(H.length).split("?")[0],o=i.get(r);return o||(await S(r),o=i.get(r)),o?s?.ssr===!0?o.server:o.client:null}if(s?.ssr!==!0){let r=P.default.resolve(t);if(d.has(r))return`throw new Error("\u{1F6A8} [B-SSR FIREWALL] BLOCKED: Backend File imported in Client: ${P.default.basename(t)}");`}return null},transform:b}}0&&(module.exports={generateRpcTypes,rpcGeneratorPlugin});
146
+ `}async function f(){b=!0;let t=Ce.performance.now();y=await me();let n=await(0,$e.default)(r,{absolute:!0});await Promise.all(n.map(l=>x(l))),u.resolveSourceFileDependencies(),await he(y);let s=Ce.performance.now();console.log(`\u{1F680} [B-SSR] RPC Generation completed in ${Math.round(s-t)}ms (${n.length} files)`),b=!1}return{name:"b-ssr-vite-plugin-rpc-universal-generator",enforce:"pre",async buildStart(){await f()},configureServer(t){let n=s=>s.endsWith(".mts")||s.endsWith(".ts");t.watcher.on("add",s=>n(s)&&x(s)),t.watcher.on("change",s=>n(s)&&x(s)),t.watcher.on("unlink",s=>{if(n(s)){let l=E.default.resolve(s);a.delete(l),m.delete(l),delete y.files[l];let g=E.default.extname(s),o=s.substring(0,s.length-g.length)+".universal.d.ts";(0,ee.unlink)(o).catch(()=>{})}})},async resolveId(t,n,s){if(t.startsWith(se))return null;if(t.includes(".universal")){let l=t.split("?")[0],g=l;if(l.endsWith(".universal"))g=l;else if(l.endsWith(".universal.ts"))g=l.slice(0,-3);else if(l.endsWith(".universal.mts"))g=l.slice(0,-4);else if(l.endsWith(".universal.js"))g=l.slice(0,-3);else return null;let o=[".mts",".ts"];for(let i of o){let w=g.slice(0,-10)+i,S=await this.resolve(w,n,{skipSelf:!0});if(S){let j=s?.ssr?"?mode=ssr":"?mode=client";return se+S.id+j}try{await(0,ee.access)(w);let j=s?.ssr?"?mode=ssr":"?mode=client";return se+w+j}catch{}}}return null},async load(t,n){if(t.startsWith(se)){let s=t.slice(se.length).split("?")[0],l=a.get(s);return l||(await x(s),l=a.get(s)),l?n?.ssr===!0?l.server:l.client:null}if(n?.ssr!==!0){let s=E.default.resolve(t);if(m.has(s))return`throw new Error("\u{1F6A8} [B-SSR FIREWALL] BLOCKED: Backend File imported in Client: ${E.default.basename(t)}");`}return null},transform:h}}0&&(module.exports={generateRpcTypes,rpcGeneratorPlugin});
@@ -1,45 +1,45 @@
1
- import $e from"fast-glob";import{access as je,unlink as be}from"fs/promises";import P from"path";import{Project as Oe,SyntaxKind as H}from"ts-morph";import{writeFile as we,readFile as ye}from"fs/promises";import k from"path";import{format as Re,resolveConfig as Se}from"prettier";import{Node as W,SyntaxKind as M,ts as G}from"ts-morph";function Fe(t){let o=t.replace(/[^a-zA-Z0-9]+(.)?/g,(g,a)=>a?a.toUpperCase():"");return o.charAt(0).toLowerCase()+o.slice(1)}function q(t,o,g){let a=k.basename(g,k.extname(g))||"Index",l=o.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),d=`${t} ${l} ${a}`;return Fe(d)}function Pe(t){let o=/'[^']+'/g,g=/`[^`]+`/g,a=[],l,d=/'[^']+'/g;for(;(l=d.exec(t))!==null;)a.push({start:l.index,end:l.index+l[0].length,value:l[0]});let c=/`[^`]+`/g;for(;(l=c.exec(t))!==null;)a.push({start:l.index,end:l.index+l[0].length,value:l[0]});if(a.length>1){let p=[...a].sort((x,C)=>{let h=x.value.replace(/['`]/g,""),e=C.value.replace(/['`]/g,"");return h.localeCompare(e)}),u="",R=0;for(let x=0;x<a.length;x++)u+=t.slice(R,a[x].start),u+=p[x].value,R=a[x].end;return u+=t.slice(R),u}return t}function Ce(t){let o=t.match(/^\{([\s\S]*)\}$/);if(!o)return t;let g=o[1];if(!g.includes(":"))return t;let a=g.split(/[;,]/).map(c=>c.trim()).filter(c=>c),l=[];for(let c of a){let p=c.indexOf(":");if(p===-1)continue;let u=c.slice(0,p).trim(),R=c.slice(p+1).trim();l.push({name:u,value:R})}return l.length<=1?t:(l.sort((c,p)=>c.name.localeCompare(p.name)),`{ ${l.map(c=>`${c.name}: ${c.value}`).join("; ")} }`)}function ie(t){let o=Pe(t);return o=Ce(o),o}async function ae(t,o){try{if(await ye(t,"utf-8")===o)return!1}catch{}let g=o;try{let a=await Se(t)||{};g=await Re(o,{...a,parser:"typescript",filepath:t})}catch{}try{if(await ye(t,"utf-8")===g)return!1}catch{}return await we(t,g),!0}function B(t,o,g,a,l,d){function c(e){return e.replace(/import\(['"](.*?)['"]\)/g,(n,r)=>{if(!k.isAbsolute(r))return n;let s=r;if(!k.extname(s)){let f=l.getSourceFile(T=>T.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===r);f&&(s=f.getFilePath())}let m=k.relative(k.dirname(a),s).replace(/\\/g,"/");return m.startsWith(".")||(m="./"+m),`import("${m}")`})}if(t.getSymbol()?.getName()==="Promise"){let e=t.getAwaitedType();if(e)return`Promise<${B(e,o,g,a,l,d)}>`}let p=t.getAliasSymbol()??t.getSymbol();if(p?.getName()==="__object")return ie(c(t.getText(o,G.TypeFormatFlags.NoTruncation|G.TypeFormatFlags.UseFullyQualifiedType)));if(t.isObject()&&!p){let e=(n,r=0)=>{if(!(r>5)){if(n.isArray()){let s=n.getArrayElementType();s&&e(s,r);return}if(n.isObject()&&!n.getSymbol()&&!n.getAliasSymbol()){for(let s of n.getApparentProperties()){let m=s.getValueDeclaration();m&&e(s.getTypeAtLocation(m),r+1)}return}B(n,o,g,a,l,d)}};return e(t),ie(c(t.getText(o,G.TypeFormatFlags.NoTruncation|G.TypeFormatFlags.UseFullyQualifiedType)))}if(!p)return ie(c(t.getText(o,G.TypeFormatFlags.NoTruncation)));let u=p.getDeclarations()[0];if(!u)return p.getName();if(W.isImportSpecifier(u)||W.isImportClause(u)){let e=u.getFirstAncestorByKind(M.ImportDeclaration);if(e){let n=e.getModuleSpecifierValue(),r=p.getName();return d.has(n)||d.set(n,new Set),d.get(n)?.add(r),r}}let R=u.getSourceFile();if(R.getFilePath()===g.getFilePath())return p.getName();if(R.isInNodeModules())return ie(c(t.getText(o,G.TypeFormatFlags.NoTruncation)));let x=k.relative(k.dirname(a),R.getFilePath()).replace(/\\/g,"/"),C=x.startsWith(".")?x:`./${x}`,h=p.getName();return d.has(C)||d.set(C,new Set),d.get(C)?.add(h),h}function ce(t,o,g,a,l){let d;if(W.isFunctionLikeDeclaration(t)||W.isArrowFunction(t)){let c=t.getDescendantsOfKind(M.ReturnStatement);for(let p of c){let u=p.getExpression();if(u?.isKind(M.SatisfiesExpression)){d=u.getTypeNode()?.getType();break}}}if(d)return B(d,t,o,g,a,l);{let c=t.getType().getCallSignatures();if(c.length>0){let p=c[0]?.getReturnType();return B(p,t,o,g,a,l)}}return"unknown"}function le(t,o,g,a,l){let d="unknown",c="unknown",p="unknown",u=!1;if(!t||!W.isObjectLiteralExpression(t))return{paramsType:d,queryType:c,bodyType:p,isMultipart:u};let R=t.getProperty("schema");if(R?.isKind(M.PropertyAssignment)){let x=R.getInitializer();if(x?.isKind(M.Identifier)){let h=x.getSymbol()?.getValueDeclaration();if(h){let e=h.getFirstDescendantByKind(M.ObjectLiteralExpression);e&&(x=e)}}if(x&&W.isObjectLiteralExpression(x)){let C=x.getProperty("consumes");if(C?.isKind(M.PropertyAssignment)){let e=C.getInitializer();W.isArrayLiteralExpression(e)&&(u=e.getElements().some(n=>n.isKind(M.StringLiteral)&&n.getLiteralValue()==="multipart/form-data"))}let h=e=>{let n=x.getProperty(e);if(n?.isKind(M.PropertyAssignment)){let r=n.getInitializer();if(r){let s=r.getType(),m=s.getApparentType(),f=m.getProperty("_output");if(f)return B(f.getTypeAtLocation(r).getApparentType(),r,o,g,a,l);let T=s.getSymbol(),w=s.getAliasSymbol(),y=T?.getName(),A=w?.getName();if(y&&y!=="__type"&&y!=="object"||A&&A!=="__type"&&A!=="object")return B(s,r,o,g,a,l);let F=m.getProperties();if(F.length>0){let Q=[];for(let $ of F){let I=$.getTypeAtLocation(r);Q.push(`${$.getName()}: ${I.getText(r)}`)}return`{ ${Q.join("; ")} }`}return B(s,r,o,g,a,l)}}return"unknown"};if(d=h("params"),c=h("querystring"),p=h("body"),u){let e="{ file: File }";p=p!=="unknown"&&p.trim().startsWith("{")?`(${p} & ${e})`:e}}}return{paramsType:d,queryType:c,bodyType:p,isMultipart:u}}function Ee(t){let o=[];return t.paramsType!=="unknown"&&o.push(`params: ${t.paramsType}`),t.queryType!=="unknown"&&o.push(`query: ${t.queryType}`),t.bodyType!=="unknown"&&o.push(`body: ${t.bodyType}`),o.push("signal?: AbortSignal"),o}function pe(t){let o=Ee(t),g="";return o.length>0&&(g=`args: { ${o.join("; ")} }`),g||(g="args: { signal?: AbortSignal }"),`export declare const ${t.name}: (${g}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${t.returnType};`}import{performance as Te}from"perf_hooks";import he from"fast-glob";import{access as xe,unlink as fe}from"fs/promises";import D from"path";import{Project as ve,SyntaxKind as _}from"ts-morph";async function Ae(t={}){let{routerPattern:o="src-ts/routers/**/*.mts",tsConfigFilePath:g="tsconfig.json",routerBaseDir:a="src-ts/routers",clean:l=!1}=t,d=[],c=[],p=[];try{let u=new ve({tsConfigFilePath:g,skipAddingFilesFromTsConfig:!1}),R=D.resolve(process.cwd(),a||".");async function x(h){try{let e=u.addSourceFileAtPath(h);await e.refreshFromFileSystem();let n=e.getDescendantsOfKind(_.CallExpression),r=n.filter(b=>b.getExpression().getText().endsWith(".addRpcRoute")),s=n.filter(b=>b.getExpression().getText().endsWith(".addRenderRoute")),m=n.filter(b=>b.getExpression().getText().endsWith(".addLoaderRoute")),f=D.extname(h),T=h.substring(0,h.length-f.length)+".universal.d.ts";if(r.length===0&&s.length===0&&m.length===0){if(l)try{await fe(T),c.push(T)}catch{}return!1}let w=[],y=new Map;y.has("fastify")||y.set("fastify",new Set),y.get("fastify")?.add("FastifyRequest"),y.get("fastify")?.add("FastifyReply");let F=D.relative(R,D.dirname(h)).split(D.sep).join("/"),Q=F==="."||!F?"":F.startsWith("/")?F:"/"+F,$=(b,E)=>{let[J,z]=b.getArguments();if(!J?.isKind(_.StringLiteral))return;let j=J.getLiteralValue(),i="unknown",S=Q,{paramsType:V,queryType:L,bodyType:O,isMultipart:N}=le(z,e,T,u,y);if(z?.isKind(_.ObjectLiteralExpression)){let se=z.getProperty("prefix");if(se?.isKind(_.PropertyAssignment)){let K=se.getInitializer();K?.isKind(_.StringLiteral)&&(S=K.getLiteralValue())}let oe=z.getProperty("handler");if(oe?.isKind(_.PropertyAssignment)){let K=oe.getInitializer();K&&(i=ce(K,e,T,u,y),i.startsWith("Promise<")||(i=`Promise<${i}>`))}}let v="",U="";E==="rpc"?(v=D.join(S,"rpc",j).replace(/\\/g,"/"),U=q("action",S,j)):E==="loader"?(v=D.join(S,"loader",j).replace(/\\/g,"/"),U=q("loader",S,j)):E==="api"&&(v=D.join(S,"api",j).replace(/\\/g,"/"),U=q("get",S,j)),U&&w.push({type:E,name:U,returnType:i,url:j,rpcUrl:v,loaderUrl:v,paramsType:V,queryType:L,bodyType:O,isMultipart:N})};if(r.forEach(b=>$(b,"rpc")),s.forEach(b=>$(b,"loader")),m.forEach(b=>$(b,"api")),w.length===0){if(l)try{await fe(T),c.push(T)}catch{}return!1}let I=[],X=[...y.entries()].sort((b,E)=>b[0].localeCompare(E[0]));for(let[b,E]of X)I.push(`import type { ${[...E].sort().join(", ")} } from "${b}";`);let Y=[...w].sort((b,E)=>b.name.localeCompare(E.name)),ne=[];Y.forEach(b=>{ne.push(pe(b))});let ue=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
1
+ import qe from"fast-glob";import{access as Ue,unlink as Pe,readFile as Ke}from"fs/promises";import E from"path";import{Project as We,SyntaxKind as re}from"ts-morph";import{writeFile as Ce,readFile as ye,mkdir as ve}from"fs/promises";import k from"path";import{format as Ae,resolveConfig as $e}from"prettier";import{Node as Z,SyntaxKind as K,ts as Y}from"ts-morph";import{createHash as je}from"crypto";function Me(t){let s=t.replace(/[^a-zA-Z0-9]+(.)?/g,(d,c)=>c?c.toUpperCase():"");return s.charAt(0).toLowerCase()+s.slice(1)}function H(t,s,d){let c=k.basename(d,k.extname(d))||"Index",l=s.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),m=`${t} ${l} ${c}`;return Me(m)}function Oe(t){let s=/'[^']+'/g,d=/`[^`]+`/g,c=[],l,m=/'[^']+'/g;for(;(l=m.exec(t))!==null;)c.push({start:l.index,end:l.index+l[0].length,value:l[0]});let p=/`[^`]+`/g;for(;(l=p.exec(t))!==null;)c.push({start:l.index,end:l.index+l[0].length,value:l[0]});if(c.length>1){let f=[...c].sort((x,A)=>{let P=x.value.replace(/['`]/g,""),h=A.value.replace(/['`]/g,"");return P.localeCompare(h)}),b="",y=0;for(let x=0;x<c.length;x++)b+=t.slice(y,c[x].start),b+=f[x].value,y=c[x].end;return b+=t.slice(y),b}return t}function Ie(t){let s=t.match(/^\{([\s\S]*)\}$/);if(!s)return t;let d=s[1];if(!d.includes(":"))return t;let c=d.split(/[;,]/).map(p=>p.trim()).filter(p=>p),l=[];for(let p of c){let f=p.indexOf(":");if(f===-1)continue;let b=p.slice(0,f).trim(),y=p.slice(f+1).trim();l.push({name:b,value:y})}return l.length<=1?t:(l.sort((p,f)=>p.name.localeCompare(f.name)),`{ ${l.map(p=>`${p.name}: ${p.value}`).join("; ")} }`)}function le(t){let s=Oe(t);return s=Ie(s),s}async function ee(t,s){try{if(await ye(t,"utf-8")===s)return!1}catch{}let d=s;try{let c=await $e(t)||{};d=await Ae(s,{...c,parser:"typescript",filepath:t})}catch{}try{if(await ye(t,"utf-8")===d)return!1}catch{}return await Ce(t,d),!0}function pe(t){return je("sha1").update(t).digest("hex")}var he="v1",Re=k.join(process.cwd(),"node_modules",".cache","b-ssr"),Se=k.join(Re,"rpc-cache.json");async function ue(){try{let t=await ye(Se,"utf-8"),s=JSON.parse(t);return s.version!==he?{version:he,files:{}}:s}catch{return{version:he,files:{}}}}async function ge(t){try{await ve(Re,{recursive:!0}),await Ce(Se,JSON.stringify(t,null,2))}catch(s){console.error("\u26A0\uFE0F [B-SSR] Failed to save persistent cache:",s)}}function J(t,s,d,c,l,m){function p(h){return h.replace(/import\(['"](.*?)['"]\)/g,(T,g)=>{if(!k.isAbsolute(g))return T;let e=g;if(!k.extname(e)){let n=l.getSourceFile(a=>a.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===g);n&&(e=n.getFilePath())}let r=k.relative(k.dirname(c),e).replace(/\\/g,"/");return r.startsWith(".")||(r="./"+r),`import("${r}")`})}if(t.getSymbol()?.getName()==="Promise"){let h=t.getAwaitedType();if(h)return`Promise<${J(h,s,d,c,l,m)}>`}let f=t.getAliasSymbol()??t.getSymbol();if(f?.getName()==="__object")return le(p(t.getText(s,Y.TypeFormatFlags.NoTruncation|Y.TypeFormatFlags.UseFullyQualifiedType)));if(t.isObject()&&!f){let h=(T,g=0)=>{if(!(g>5)){if(T.isArray()){let e=T.getArrayElementType();e&&h(e,g);return}if(T.isObject()&&!T.getSymbol()&&!T.getAliasSymbol()){for(let e of T.getApparentProperties()){let r=e.getValueDeclaration();r&&h(e.getTypeAtLocation(r),g+1)}return}J(T,s,d,c,l,m)}};return h(t),le(p(t.getText(s,Y.TypeFormatFlags.NoTruncation|Y.TypeFormatFlags.UseFullyQualifiedType)))}if(!f)return le(p(t.getText(s,Y.TypeFormatFlags.NoTruncation)));let b=f.getDeclarations()[0];if(!b)return f.getName();if(Z.isImportSpecifier(b)||Z.isImportClause(b)){let h=b.getFirstAncestorByKind(K.ImportDeclaration);if(h){let T=h.getModuleSpecifierValue(),g=f.getName();return m.has(T)||m.set(T,new Set),m.get(T)?.add(g),g}}let y=b.getSourceFile();if(y.getFilePath()===d.getFilePath())return f.getName();if(y.isInNodeModules())return le(p(t.getText(s,Y.TypeFormatFlags.NoTruncation)));let x=k.relative(k.dirname(c),y.getFilePath()).replace(/\\/g,"/"),A=x.startsWith(".")?x:`./${x}`,P=f.getName();return m.has(A)||m.set(A,new Set),m.get(A)?.add(P),P}function fe(t,s,d,c,l){let m;if(Z.isFunctionLikeDeclaration(t)||Z.isArrowFunction(t)){let p=t.getDescendantsOfKind(K.ReturnStatement);for(let f of p){let b=f.getExpression();if(b?.isKind(K.SatisfiesExpression)){m=b.getTypeNode()?.getType();break}}}if(m)return J(m,t,s,d,c,l);{let p=t.getType().getCallSignatures();if(p.length>0){let f=p[0]?.getReturnType();return J(f,t,s,d,c,l)}}return"unknown"}function de(t,s,d,c,l){let m="unknown",p="unknown",f="unknown",b=!1;if(!t||!Z.isObjectLiteralExpression(t))return{paramsType:m,queryType:p,bodyType:f,isMultipart:b};let y=t.getProperty("schema");if(y?.isKind(K.PropertyAssignment)){let x=y.getInitializer();if(x?.isKind(K.Identifier)){let P=x.getSymbol()?.getValueDeclaration();if(P){let h=P.getFirstDescendantByKind(K.ObjectLiteralExpression);h&&(x=h)}}if(x&&Z.isObjectLiteralExpression(x)){let A=x.getProperty("consumes");if(A?.isKind(K.PropertyAssignment)){let h=A.getInitializer();Z.isArrayLiteralExpression(h)&&(b=h.getElements().some(T=>T.isKind(K.StringLiteral)&&T.getLiteralValue()==="multipart/form-data"))}let P=h=>{let T=x.getProperty(h);if(T?.isKind(K.PropertyAssignment)){let g=T.getInitializer();if(g){let e=g.getType(),r=e.getApparentType(),n=r.getProperty("_output");if(n)return J(n.getTypeAtLocation(g).getApparentType(),g,s,d,c,l);let a=e.getSymbol(),u=e.getAliasSymbol(),o=a?.getName(),i=u?.getName();if(o&&o!=="__type"&&o!=="object"||i&&i!=="__type"&&i!=="object")return J(e,g,s,d,c,l);let w=r.getProperties();if(w.length>0){let R=[];for(let $ of w){let Q=$.getTypeAtLocation(g);R.push(`${$.getName()}: ${Q.getText(g)}`)}return`{ ${R.join("; ")} }`}return J(e,g,s,d,c,l)}}return"unknown"};if(m=P("params"),p=P("querystring"),f=P("body"),b){let h="{ file: File }";f=f!=="unknown"&&f.trim().startsWith("{")?`(${f} & ${h})`:h}}}return{paramsType:m,queryType:p,bodyType:f,isMultipart:b}}function De(t){let s=[];return t.paramsType!=="unknown"&&s.push(`params: ${t.paramsType}`),t.queryType!=="unknown"&&s.push(`query: ${t.queryType}`),t.bodyType!=="unknown"&&s.push(`body: ${t.bodyType}`),s.push("signal?: AbortSignal"),s}function me(t){let s=De(t),d="";return s.length>0&&(d=`args: { ${s.join("; ")} }`),d||(d="args: { signal?: AbortSignal }"),`export declare const ${t.name}: (${d}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${t.returnType};`}import{performance as Ee}from"perf_hooks";import Fe from"fast-glob";import{access as xe,unlink as be,readFile as Le}from"fs/promises";import N from"path";import{Project as ke,SyntaxKind as te}from"ts-morph";async function Ne(t={}){let{routerPattern:s="src-ts/routers/**/*.mts",tsConfigFilePath:d="tsconfig.json",routerBaseDir:c="src-ts/routers",clean:l=!1}=t,m=[],p=[],f=[];try{let h=function(g,e){let r=[],n=[...e.entries()].sort((o,i)=>o[0].localeCompare(i[0]));for(let[o,i]of n)r.push(`import type { ${[...i].sort().join(", ")} } from "${o}";`);let a=[...g].sort((o,i)=>o.name.localeCompare(i.name)),u=[];return a.forEach(o=>{u.push(me(o))}),`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
2
2
  /* eslint-disable */
3
3
 
4
- `+(I.length>0?I.join(`
4
+ `+(r.length>0?r.join(`
5
5
  `)+`
6
6
 
7
- `:"")+ne.join(`
7
+ `:"")+u.join(`
8
8
 
9
- `);return(await ae(T,ue)||await xe(T).then(()=>!0).catch(()=>!1))&&d.push(T),!0}catch(e){return p.push(`Error processing ${h}: ${e instanceof Error?e.message:String(e)}`),!1}}let C=await he(o,{absolute:!0});if(await Promise.all(C.map(h=>x(h))),u.resolveSourceFileDependencies(),l){let h=await he(D.join(a,"**/*.universal.d.ts"),{absolute:!0});for(let e of h){let n=e.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await xe(n).then(()=>!0).catch(()=>!1))try{await fe(e),c.push(e)}catch{}}}}catch(u){p.push(`Fatal error: ${u instanceof Error?u.message:String(u)}`)}return{generated:d,cleaned:c,errors:p}}var Z="virtual:b-ssr-rpc-universal:";function rt(t={}){let{routerPattern:o="src-ts/routers/**/*.mts",tsConfigFilePath:g="tsconfig.json",routerBaseDir:a="src-ts/routers"}=t,l=new Map,d=new Set,c=new Oe({tsConfigFilePath:g,skipAddingFilesFromTsConfig:!1}),p=P.resolve(process.cwd(),a||"."),u=!1;async function R(e){try{let n=c.addSourceFileAtPath(e);await n.refreshFromFileSystem(),u||c.resolveSourceFileDependencies();let r=n.getDescendantsOfKind(H.CallExpression),s=r.filter(i=>i.getExpression().getText().endsWith(".addRpcRoute")),m=r.filter(i=>i.getExpression().getText().endsWith(".addRenderRoute")),f=r.filter(i=>i.getExpression().getText().endsWith(".addLoaderRoute")),T=P.extname(e),w=e.substring(0,e.length-T.length)+".universal.d.ts",y=P.resolve(e);if(s.length===0&&m.length===0&&f.length===0){l.delete(y),d.delete(y),w!==e&&await be(w).catch(()=>{});return}d.add(y);let A=[],F=new Map;F.has("fastify")||F.set("fastify",new Set),F.get("fastify")?.add("FastifyRequest"),F.get("fastify")?.add("FastifyReply");let $=P.relative(p,P.dirname(e)).split(P.sep).join("/"),I=$==="."||!$?"":$.startsWith("/")?$:"/"+$,X=(i,S)=>{let[V,L]=i.getArguments();if(!V?.isKind(H.StringLiteral))return;let O=V.getLiteralValue(),N="unknown",v=I,{paramsType:U,queryType:se,bodyType:oe,isMultipart:K}=le(L,n,w,c,F);if(L?.isKind(H.ObjectLiteralExpression)){let de=L.getProperty("prefix");if(de?.isKind(H.PropertyAssignment)){let re=de.getInitializer();re?.isKind(H.StringLiteral)&&(v=re.getLiteralValue())}let me=L.getProperty("handler");if(me?.isKind(H.PropertyAssignment)){let re=me.getInitializer();re&&(N=ce(re,n,w,c,F),N.startsWith("Promise<")||(N=`Promise<${N}>`))}}let ee="",te="";S==="rpc"?(ee=P.join(v,"rpc",O).replace(/\\/g,"/"),te=q("action",v,O)):S==="loader"?(ee=P.join(v,"loader",O).replace(/\\/g,"/"),te=q("loader",v,O)):S==="api"&&(ee=P.join(v,"api",O).replace(/\\/g,"/"),te=q("get",v,O)),te&&A.push({type:S,name:te,returnType:N,url:O,rpcUrl:ee,loaderUrl:ee,paramsType:U,queryType:se,bodyType:oe,isMultipart:K})};s.forEach(i=>X(i,"rpc")),m.forEach(i=>X(i,"loader")),f.forEach(i=>X(i,"api"));let Y=[],ne=[...F.entries()].sort((i,S)=>i[0].localeCompare(S[0]));for(let[i,S]of ne)Y.push(`import type { ${[...S].sort().join(", ")} } from "${i}";`);let ue=[...A].sort((i,S)=>i.name.localeCompare(S.name)),ge=[];ue.forEach(i=>{ge.push(pe(i))});let b=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
9
+ `)};var b=h;let y=await ue(),x=new ke({tsConfigFilePath:d,skipAddingFilesFromTsConfig:!0}),A=N.resolve(process.cwd(),c||".");async function P(g){try{let e=N.resolve(g),r=await Le(g,"utf-8"),n=pe(r),a=N.extname(g),u=g.substring(0,g.length-a.length)+".universal.d.ts",o=y.files[e];if(o&&o.hash===n){let S=o.fnInfo,I=new Map;o.imports.forEach(([j,M])=>{I.set(j,new Set(M))});let C=h(S,I);return(await ee(u,C)||await xe(u).then(()=>!0).catch(()=>!1))&&m.push(u),!0}let i=x.addSourceFileAtPath(g);await i.refreshFromFileSystem();let w=i.getDescendantsOfKind(te.CallExpression),R=w.filter(S=>S.getExpression().getText().endsWith(".addRpcRoute")),$=w.filter(S=>S.getExpression().getText().endsWith(".addRenderRoute")),Q=w.filter(S=>S.getExpression().getText().endsWith(".addLoaderRoute"));if(R.length===0&&$.length===0&&Q.length===0){if(delete y.files[e],l)try{await be(u),p.push(u)}catch{}return!1}let L=[],O=new Map;O.has("fastify")||O.set("fastify",new Set),O.get("fastify")?.add("FastifyRequest"),O.get("fastify")?.add("FastifyReply");let X=N.relative(A,N.dirname(g)).split(N.sep).join("/"),V=X==="."||!X?"":X.startsWith("/")?X:"/"+X,se=(S,I)=>{let[C,v]=S.getArguments();if(!C?.isKind(te.StringLiteral))return;let j=C.getLiteralValue(),M="unknown",F=V,{paramsType:U,queryType:D,bodyType:ie,isMultipart:ae}=de(v,i,u,x,O);if(v?.isKind(te.ObjectLiteralExpression)){let W=v.getProperty("prefix");if(W?.isKind(te.PropertyAssignment)){let _=W.getInitializer();_?.isKind(te.StringLiteral)&&(F=_.getLiteralValue())}let B=v.getProperty("handler");if(B?.isKind(te.PropertyAssignment)){let _=B.getInitializer();_&&(M=fe(_,i,u,x,O),M.startsWith("Promise<")||(M=`Promise<${M}>`))}}let z="",G="";I==="rpc"?(z=N.join(F,"rpc",j).replace(/\\/g,"/"),G=H("action",F,j)):I==="loader"?(z=N.join(F,"loader",j).replace(/\\/g,"/"),G=H("loader",F,j)):I==="api"&&(z=N.join(F,"api",j).replace(/\\/g,"/"),G=H("get",F,j)),G&&L.push({type:I,name:G,returnType:M,url:j,rpcUrl:z,loaderUrl:z,paramsType:U,queryType:D,bodyType:ie,isMultipart:ae})};if(R.forEach(S=>se(S,"rpc")),$.forEach(S=>se(S,"loader")),Q.forEach(S=>se(S,"api")),L.length===0){if(delete y.files[e],l)try{await be(u),p.push(u)}catch{}return!1}let oe=h(L,O);return(await ee(u,oe)||await xe(u).then(()=>!0).catch(()=>!1))&&m.push(u),y.files[e]={hash:n,fnInfo:L,imports:Array.from(O.entries()).map(([S,I])=>[S,Array.from(I)])},!0}catch(e){return f.push(`Error processing ${g}: ${e instanceof Error?e.message:String(e)}`),!1}}let T=await Fe(s,{absolute:!0});if(await Promise.all(T.map(g=>P(g))),x.resolveSourceFileDependencies(),await ge(y),l){let g=await Fe(N.join(c,"**/*.universal.d.ts"),{absolute:!0});for(let e of g){let r=e.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await xe(r).then(()=>!0).catch(()=>!1))try{await be(e),p.push(e)}catch{}}}}catch(y){f.push(`Fatal error: ${y instanceof Error?y.message:String(y)}`)}return{generated:m,cleaned:p,errors:f}}var ne="virtual:b-ssr-rpc-universal:";function mt(t={}){let{routerPattern:s="src-ts/routers/**/*.mts",tsConfigFilePath:d="tsconfig.json",routerBaseDir:c="src-ts/routers"}=t,l=new Map,m=new Set,p=new We({tsConfigFilePath:d,skipAddingFilesFromTsConfig:!0}),f=E.resolve(process.cwd(),c||"."),b=!1,y={version:"v1",files:{}};async function x(e){try{let r=E.resolve(e),n=await Ke(e,"utf-8"),a=pe(n),u=y.files[r];if(u&&u.hash===a){let C=u.fnInfo,v=new Map;u.imports.forEach(([ie,ae])=>{v.set(ie,new Set(ae))}),m.add(r);let{client:j,server:M}=P(C,e);l.set(r,{client:j,server:M});let F=E.extname(e),U=e.substring(0,e.length-F.length)+".universal.d.ts",D=A(C,v);await ee(U,D);return}let o=p.addSourceFileAtPath(e);await o.refreshFromFileSystem(),b||p.resolveSourceFileDependencies();let i=o.getDescendantsOfKind(re.CallExpression),w=i.filter(C=>C.getExpression().getText().endsWith(".addRpcRoute")),R=i.filter(C=>C.getExpression().getText().endsWith(".addRenderRoute")),$=i.filter(C=>C.getExpression().getText().endsWith(".addLoaderRoute")),Q=E.extname(e),L=e.substring(0,e.length-Q.length)+".universal.d.ts";if(w.length===0&&R.length===0&&$.length===0){l.delete(r),m.delete(r),delete y.files[r],L!==e&&await Pe(L).catch(()=>{});return}m.add(r);let O=[],q=new Map;q.has("fastify")||q.set("fastify",new Set),q.get("fastify")?.add("FastifyRequest"),q.get("fastify")?.add("FastifyReply");let V=E.relative(f,E.dirname(e)).split(E.sep).join("/"),se=V==="."||!V?"":V.startsWith("/")?V:"/"+V,oe=(C,v)=>{let[j,M]=C.getArguments();if(!j?.isKind(re.StringLiteral))return;let F=j.getLiteralValue(),U="unknown",D=se,{paramsType:ie,queryType:ae,bodyType:z,isMultipart:G}=de(M,o,L,p,q);if(M?.isKind(re.ObjectLiteralExpression)){let _=M.getProperty("prefix");if(_?.isKind(re.PropertyAssignment)){let ce=_.getInitializer();ce?.isKind(re.StringLiteral)&&(D=ce.getLiteralValue())}let Te=M.getProperty("handler");if(Te?.isKind(re.PropertyAssignment)){let ce=Te.getInitializer();ce&&(U=fe(ce,o,L,p,q),U.startsWith("Promise<")||(U=`Promise<${U}>`))}}let W="",B="";v==="rpc"?(W=E.join(D,"rpc",F).replace(/\\/g,"/"),B=H("action",D,F)):v==="loader"?(W=E.join(D,"loader",F).replace(/\\/g,"/"),B=H("loader",D,F)):v==="api"&&(W=E.join(D,"api",F).replace(/\\/g,"/"),B=H("get",D,F)),B&&O.push({type:v,name:B,returnType:U,url:F,rpcUrl:W,loaderUrl:W,paramsType:ie,queryType:ae,bodyType:z,isMultipart:G})};w.forEach(C=>oe(C,"rpc")),R.forEach(C=>oe(C,"loader")),$.forEach(C=>oe(C,"api"));let we=A(O,q);await ee(L,we);let{client:S,server:I}=P(O,e);l.set(r,{client:S,server:I}),y.files[r]={hash:a,fnInfo:O,imports:Array.from(q.entries()).map(([C,v])=>[C,Array.from(v)])}}catch(r){console.error(`[rpc-generator] Error al procesar ${e}:`,{error:r})}}function A(e,r){let n=[],a=[...r.entries()].sort((i,w)=>i[0].localeCompare(w[0]));for(let[i,w]of a)n.push(`import type { ${[...w].sort().join(", ")} } from "${i}";`);let u=[...e].sort((i,w)=>i.name.localeCompare(w.name)),o=[];return u.forEach(i=>{o.push(me(i))}),`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
10
10
  /* eslint-disable */
11
11
 
12
- `+(Y.length>0?Y.join(`
12
+ `+(n.length>0?n.join(`
13
13
  `)+`
14
14
 
15
- `:"")+ge.join(`
15
+ `:"")+o.join(`
16
16
 
17
- `);await ae(w,b);let E=[],J=[];A.forEach(i=>{let V=i.type==="rpc"?"POST":"GET",L=i.type==="loader"?i.loaderUrl:i.rpcUrl;J.push({name:i.name,rpcUrl:L,method:V,isMultipart:!!i.isMultipart}),E.push({name:i.name,url:i.url,type:i.type,requiresArgs:!0})});let z=`
18
- import { createClientRpc } from '@bobtail.software/b-ssr/client';
19
-
20
- if (import.meta.env.DEV) {
21
- console.debug('\u{1F6E1}\uFE0F [B-SSR Security] Loaded SAFE Client-Stub for: ${P.basename(e)}');
22
- }
17
+ `)}function P(e,r){let n=[],a=[];e.forEach(i=>{let R=i.type==="rpc"?"POST":"GET",$=i.type==="loader"?i.loaderUrl:i.rpcUrl;a.push({name:i.name,rpcUrl:$,method:R,isMultipart:!!i.isMultipart}),n.push({name:i.name,url:i.url,type:i.type,requiresArgs:!0})});let u=`
18
+ import { createClientRpc } from '@bobtail.software/b-ssr/client';
19
+
20
+ if (import.meta.env.DEV) {
21
+ console.debug('\u{1F6E1}\uFE0F [B-SSR Security] Loaded SAFE Client-Stub for: ${E.basename(r)}');
22
+ }
23
23
 
24
- ${J.map(i=>`
25
- export const ${i.name} = createClientRpc({
26
- url: '${i.rpcUrl}',
27
- method: '${i.method}',
28
- isMultipart: ${i.isMultipart}
29
- });
30
- `).join(`
24
+ ${a.map(i=>`
25
+ export const ${i.name} = createClientRpc({
26
+ url: '${i.rpcUrl}',
27
+ method: '${i.method}',
28
+ isMultipart: ${i.isMultipart}
29
+ });
30
+ `).join(`
31
31
  `)}
32
- `,j=C(E,e);l.set(P.resolve(e),{client:z,server:j})}catch(n){console.error(`[rpc-generator] Error al procesar ${e}:`,{error:n})}}let x=(e,n,r)=>{if(n.includes("node_modules")||n.startsWith(Z))return null;if(r?.ssr===!0&&/\.[cm]?[jt]sx?$/.test(n)){let s=/\brequire\s*\(/.test(e),m=/\bmodule\.exports\b/.test(e),f=/\bexports\./.test(e);if(s||m||f)return"import { createRequire } from 'module';"+`
32
+ `,o=T(n,r);return{client:u,server:o}}let h=(e,r,n)=>{if(r.includes("node_modules")||r.startsWith(ne))return null;if(n?.ssr===!0&&/\.[cm]?[jt]sx?$/.test(r)){let a=/\brequire\s*\(/.test(e),u=/\bmodule\.exports\b/.test(e),o=/\bexports\./.test(e);if(a||u||o)return"import { createRequire } from 'module';"+`
33
33
  const require = createRequire(import.meta.url);
34
34
  const module = { exports: {} };
35
35
  const exports = module.exports;
36
36
  `+e+`
37
- export default module.exports;`}return null};function C(e,n){if(e.length===0)return"";let r=process.cwd(),s=P.relative(r,n).replace(/\\/g,"/");return`
37
+ export default module.exports;`}return null};function T(e,r){if(e.length===0)return"";let n=process.cwd(),a=E.relative(n,r).replace(/\\/g,"/");return`
38
38
  import path from 'path';
39
39
  import { pathToFileURL } from 'url';
40
40
 
41
41
  if (typeof window !== 'undefined' && typeof document !== 'undefined') {
42
- throw new Error('\u{1F6A8} [B-SSR SECURITY ALERT] Server-side code leaked to browser: ${`./${s}`}');
42
+ throw new Error('\u{1F6A8} [B-SSR SECURITY ALERT] Server-side code leaked to browser: ${`./${a}`}');
43
43
  }
44
44
 
45
45
  let initPromise;
@@ -53,7 +53,7 @@ export default module.exports;`}return null};function C(e,n){if(e.length===0)ret
53
53
  renderOptionsMap = new Map();
54
54
  loaderApiOptionsMap = new Map();
55
55
  const projectRoot = process.cwd();
56
- const absolutePath = path.resolve(projectRoot, '${s}');
56
+ const absolutePath = path.resolve(projectRoot, '${a}');
57
57
  const serverModuleUrl = pathToFileURL(absolutePath).href;
58
58
 
59
59
  if (typeof globalThis.require === 'undefined') {
@@ -101,25 +101,25 @@ export default module.exports;`}return null};function C(e,n){if(e.length===0)ret
101
101
  return initPromise;
102
102
  }
103
103
 
104
- ${e.map(f=>{let T=[];f.requiresArgs&&T.push("args"),T.push("ssrContext");let w=f.requiresArgs?"args":"{}",y="";return f.type==="rpc"?y=`
104
+ ${e.map(o=>{let i=[];o.requiresArgs&&i.push("args"),i.push("ssrContext");let w=o.requiresArgs?"args":"{}",R="";return o.type==="rpc"?R=`
105
105
  if (fn.isMultipart) throw new Error('RPC multipart no soportado en SSR.');
106
106
  await getOptionsMaps();
107
- const options = rpcOptionsMap.get('${f.url}');
108
- if (!options?.handler) throw new Error('Handler no encontrado para RPC: ${f.name}');
107
+ const options = rpcOptionsMap.get('${o.url}');
108
+ if (!options?.handler) throw new Error('Handler no encontrado para RPC: ${o.name}');
109
109
  const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
110
110
  return await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply);
111
- `:f.type==="api"?y=`
111
+ `:o.type==="api"?R=`
112
112
  await getOptionsMaps();
113
- const options = loaderApiOptionsMap.get('${f.url}');
113
+ const options = loaderApiOptionsMap.get('${o.url}');
114
114
  if (!options?.handler) {
115
- console.error('\u26A0\uFE0F [B-SSR Warning] Handler API no encontrado:', '${f.name}', 'URL:', '${f.url}');
115
+ console.error('\u26A0\uFE0F [B-SSR Warning] Handler API no encontrado:', '${o.name}', 'URL:', '${o.url}');
116
116
  return null;
117
117
  }
118
118
  const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
119
119
  return await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply);
120
- `:y=`
120
+ `:R=`
121
121
  await getOptionsMaps();
122
- const options = renderOptionsMap.get('${f.url}');
122
+ const options = renderOptionsMap.get('${o.url}');
123
123
  if (!options) return {};
124
124
  const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
125
125
  let customData = {};
@@ -128,19 +128,19 @@ export default module.exports;`}return null};function C(e,n){if(e.length===0)ret
128
128
  customData = (await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply)) || {};
129
129
  }
130
130
  } catch (handlerErr) {
131
- console.error('\u274C [B-SSR Handler Error] ${f.name}:', handlerErr);
131
+ console.error('\u274C [B-SSR Handler Error] ${o.name}:', handlerErr);
132
132
  return {};
133
133
  }
134
134
  if (ssrContext.reply.sent) return;
135
135
  return { ...customData };
136
- `,`export const ${f.name} = async (${T.join(", ")}) => {
136
+ `,`export const ${o.name} = async (${i.join(", ")}) => {
137
137
  try {
138
- if (!ssrContext?.req) throw new Error('ssrContext requerido en ${f.name} (SSR)');
139
- ${y}
138
+ if (!ssrContext?.req) throw new Error('ssrContext requerido en ${o.name} (SSR)');
139
+ ${R}
140
140
  } catch (error) {
141
- console.error('\u274C [B-SSR Error] ${f.name}:', error);
141
+ console.error('\u274C [B-SSR Error] ${o.name}:', error);
142
142
  throw error;
143
143
  }
144
144
  };`}).join(`
145
145
  `)}
146
- `}async function h(){u=!0;let e=Te.now(),n=await $e(o,{absolute:!0});await Promise.all(n.map(s=>R(s))),c.resolveSourceFileDependencies();let r=Te.now();console.log(`\u{1F680} [B-SSR] RPC Generation completed in ${Math.round(r-e)}ms (${n.length} files)`),u=!1}return{name:"b-ssr-vite-plugin-rpc-universal-generator",enforce:"pre",async buildStart(){await h()},configureServer(e){let n=r=>r.endsWith(".mts")||r.endsWith(".ts");e.watcher.on("add",r=>n(r)&&R(r)),e.watcher.on("change",r=>n(r)&&R(r)),e.watcher.on("unlink",r=>{if(n(r)){let s=P.resolve(r);l.delete(s),d.delete(s);let m=P.extname(r),f=r.substring(0,r.length-m.length)+".universal.d.ts";be(f).catch(()=>{})}})},async resolveId(e,n,r){if(e.startsWith(Z))return null;if(e.includes(".universal")){let s=e.split("?")[0],m=s;if(s.endsWith(".universal"))m=s;else if(s.endsWith(".universal.ts"))m=s.slice(0,-3);else if(s.endsWith(".universal.mts"))m=s.slice(0,-4);else if(s.endsWith(".universal.js"))m=s.slice(0,-3);else return null;let f=[".mts",".ts"];for(let T of f){let w=m.slice(0,-10)+T,y=await this.resolve(w,n,{skipSelf:!0});if(y){let A=r?.ssr?"?mode=ssr":"?mode=client";return Z+y.id+A}try{await je(w);let A=r?.ssr?"?mode=ssr":"?mode=client";return Z+w+A}catch{}}}return null},async load(e,n){if(e.startsWith(Z)){let r=e.slice(Z.length).split("?")[0],s=l.get(r);return s||(await R(r),s=l.get(r)),s?n?.ssr===!0?s.server:s.client:null}if(n?.ssr!==!0){let r=P.resolve(e);if(d.has(r))return`throw new Error("\u{1F6A8} [B-SSR FIREWALL] BLOCKED: Backend File imported in Client: ${P.basename(e)}");`}return null},transform:x}}export{Ae as generateRpcTypes,rt as rpcGeneratorPlugin};
146
+ `}async function g(){b=!0;let e=Ee.now();y=await ue();let r=await qe(s,{absolute:!0});await Promise.all(r.map(a=>x(a))),p.resolveSourceFileDependencies(),await ge(y);let n=Ee.now();console.log(`\u{1F680} [B-SSR] RPC Generation completed in ${Math.round(n-e)}ms (${r.length} files)`),b=!1}return{name:"b-ssr-vite-plugin-rpc-universal-generator",enforce:"pre",async buildStart(){await g()},configureServer(e){let r=n=>n.endsWith(".mts")||n.endsWith(".ts");e.watcher.on("add",n=>r(n)&&x(n)),e.watcher.on("change",n=>r(n)&&x(n)),e.watcher.on("unlink",n=>{if(r(n)){let a=E.resolve(n);l.delete(a),m.delete(a),delete y.files[a];let u=E.extname(n),o=n.substring(0,n.length-u.length)+".universal.d.ts";Pe(o).catch(()=>{})}})},async resolveId(e,r,n){if(e.startsWith(ne))return null;if(e.includes(".universal")){let a=e.split("?")[0],u=a;if(a.endsWith(".universal"))u=a;else if(a.endsWith(".universal.ts"))u=a.slice(0,-3);else if(a.endsWith(".universal.mts"))u=a.slice(0,-4);else if(a.endsWith(".universal.js"))u=a.slice(0,-3);else return null;let o=[".mts",".ts"];for(let i of o){let w=u.slice(0,-10)+i,R=await this.resolve(w,r,{skipSelf:!0});if(R){let $=n?.ssr?"?mode=ssr":"?mode=client";return ne+R.id+$}try{await Ue(w);let $=n?.ssr?"?mode=ssr":"?mode=client";return ne+w+$}catch{}}}return null},async load(e,r){if(e.startsWith(ne)){let n=e.slice(ne.length).split("?")[0],a=l.get(n);return a||(await x(n),a=l.get(n)),a?r?.ssr===!0?a.server:a.client:null}if(r?.ssr!==!0){let n=E.resolve(e);if(m.has(n))return`throw new Error("\u{1F6A8} [B-SSR FIREWALL] BLOCKED: Backend File imported in Client: ${E.basename(e)}");`}return null},transform:h}}export{Ne as generateRpcTypes,mt as rpcGeneratorPlugin};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobtail.software/b-ssr",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Fastify + Vite SSR Plugin wrapper with RPC",
5
5
  "author": "Victor Moreno <info@bobtail.software> (https://bobtail.software)",
6
6
  "license": "GPL-3.0",