@bobtail.software/b-ssr 1.0.64 → 1.0.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,27 @@
1
- import pe from"fast-glob";import{access as ue,unlink as ee,writeFile as ge}from"fs/promises";import o from"path";import{format as de,resolveConfig as me}from"prettier";import{Node as M,Project as fe,SyntaxKind as h,ts as j}from"ts-morph";var L="virtual:b-ssr-rpc-universal:";function ye(T){let x=T.replace(/[^a-zA-Z0-9]+(.)?/g,(k,O)=>O?O.toUpperCase():"");return x.charAt(0).toLowerCase()+x.slice(1)}function G(T,x,k){let O=o.basename(k,o.extname(k))||"Index",C=x.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),q=`${T} ${C} ${O}`;return ye(q)}function Re(T={}){let{routerPattern:x="src-ts/routers/**/*.mts",tsConfigFilePath:k="tsconfig.json",routerBaseDir:O="src-ts/routers"}=T,C=new Map,q=new Set,K=new fe({tsConfigFilePath:k,skipAddingFilesFromTsConfig:!1}),te=o.resolve(process.cwd(),O||".");async function I(t){try{let N=function(e){return e.replace(/import\(['"](.*?)['"]\)/g,(a,n)=>{if(!o.isAbsolute(n))return a;let s=n;if(!o.extname(s)){let y=K.getSourceFile(d=>d.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===n);y&&(s=y.getFilePath())}let l=o.relative(o.dirname(A),s).replace(/\\/g,"/");return l.startsWith(".")||(l="./"+l),`import("${l}")`})},$=function(e,a){if(e.getSymbol()?.getName()==="Promise"){let p=e.getAwaitedType();if(p)return`Promise<${$(p,a)}>`}let n=e.getAliasSymbol()??e.getSymbol();if(n?.getName()==="__object")return N(e.getText(a,j.TypeFormatFlags.NoTruncation|j.TypeFormatFlags.UseFullyQualifiedType));if(e.isObject()&&!n){let p=(g,m=0)=>{if(!(m>5)){if(g.isArray()){let b=g.getArrayElementType();b&&p(b,m);return}if(g.isObject()&&!g.getSymbol()&&!g.getAliasSymbol()){for(let b of g.getApparentProperties()){let E=b.getValueDeclaration();E&&p(b.getTypeAtLocation(E),m+1)}return}$(g,a)}};return p(e),N(e.getText(a,j.TypeFormatFlags.NoTruncation|j.TypeFormatFlags.UseFullyQualifiedType))}if(!n)return N(e.getText(a,j.TypeFormatFlags.NoTruncation));let s=n.getDeclarations()[0];if(!s)return n.getName();if(M.isImportSpecifier(s)||M.isImportClause(s)){let p=s.getFirstAncestorByKind(h.ImportDeclaration);if(p){let g=p.getModuleSpecifierValue(),m=n.getName();return F.has(g)||F.set(g,new Set),F.get(g)?.add(m),m}}let l=s.getSourceFile();if(l.getFilePath()===f.getFilePath())return n.getName();if(l.isInNodeModules())return N(e.getText(a,j.TypeFormatFlags.NoTruncation));let y=o.relative(o.dirname(A),l.getFilePath()).replace(/\\/g,"/"),R=y.startsWith(".")?y:`./${y}`,P=n.getName();return F.has(R)||F.set(R,new Set),F.get(R)?.add(P),P},Z=function(e){let a;if(M.isFunctionLikeDeclaration(e)||M.isArrowFunction(e)){let n=e.getDescendantsOfKind(h.ReturnStatement);for(let s of n){let l=s.getExpression();if(l?.isKind(h.SatisfiesExpression)){a=l.getTypeNode()?.getType();break}}}if(a)return $(a,e);{let n=e.getType().getCallSignatures();if(n.length>0){let s=n[0]?.getReturnType();return $(s,e)}}return"unknown"};var u=N,r=$,c=Z;let f=K.addSourceFileAtPath(t);await f.refreshFromFileSystem(),K.resolveSourceFileDependencies();let i=f.getDescendantsOfKind(h.CallExpression),v=i.filter(e=>e.getExpression().getText().endsWith(".addRpcRoute")),w=i.filter(e=>e.getExpression().getText().endsWith(".addRenderRoute")),S=i.filter(e=>e.getExpression().getText().endsWith(".addLoaderRoute")),D=o.extname(t),A=t.substring(0,t.length-D.length)+".universal.d.ts",B=o.resolve(t);if(v.length===0&&w.length===0&&S.length===0){C.delete(B),q.delete(B),A!==t&&await ee(A).catch(()=>{});return}q.add(B);let V=[],F=new Map;F.has("fastify")||F.set("fastify",new Set),F.get("fastify")?.add("FastifyRequest"),F.get("fastify")?.add("FastifyReply");let ie=e=>{let a="unknown",n="unknown",s="unknown",l=!1;if(!e||!M.isObjectLiteralExpression(e))return{paramsType:a,queryType:n,bodyType:s,isMultipart:l};let y=e.getProperty("schema");if(y?.isKind(h.PropertyAssignment)){let d=y.getInitializer();if(d?.isKind(h.Identifier)){let P=d.getSymbol()?.getValueDeclaration();if(P){let p=P.getFirstDescendantByKind(h.ObjectLiteralExpression);p&&(d=p)}}if(d&&M.isObjectLiteralExpression(d)){let R=d.getProperty("consumes");if(R?.isKind(h.PropertyAssignment)){let p=R.getInitializer();M.isArrayLiteralExpression(p)&&(l=p.getElements().some(g=>g.isKind(h.StringLiteral)&&g.getLiteralValue()==="multipart/form-data"))}let P=p=>{let g=d.getProperty(p);if(g?.isKind(h.PropertyAssignment)){let m=g.getInitializer();if(m){let b=m.getType(),E=b.getProperty("_output");return $(E?E.getTypeAtLocation(m).getApparentType():b,m)}}return"unknown"};if(a=P("params"),n=P("querystring"),s=P("body"),l){let p="{ file: File }";s=s!=="unknown"&&s.trim().startsWith("{")?`(${s} & ${p})`:p}}}return{paramsType:a,queryType:n,bodyType:s,isMultipart:l}},U=o.relative(te,o.dirname(t)).split(o.sep).join("/"),ae=U==="."||!U?"":U.startsWith("/")?U:"/"+U,_=(e,a)=>{let[n,s]=e.getArguments();if(!n?.isKind(h.StringLiteral))return;let l=n.getLiteralValue(),y="unknown",d=ae,{paramsType:R,queryType:P,bodyType:p,isMultipart:g}=ie(s);if(s?.isKind(h.ObjectLiteralExpression)){let E=s.getProperty("prefix");if(E?.isKind(h.PropertyAssignment)){let W=E.getInitializer();W?.isKind(h.StringLiteral)&&(d=W.getLiteralValue())}let J=s.getProperty("handler");if(J?.isKind(h.PropertyAssignment)){let W=J.getInitializer();W&&(y=Z(W),y.startsWith("Promise<")||(y=`Promise<${y}>`))}}let m="",b="";a==="rpc"?(m=o.join(d,"rpc",l).replace(/\\/g,"/"),b=G("action",d,l)):a==="loader"?(m=o.join(d,"loader",l).replace(/\\/g,"/"),b=G("loader",d,l)):a==="api"&&(m=o.join(d,"api",l).replace(/\\/g,"/"),b=G("get",d,l)),b&&V.push({type:a,name:b,returnType:y,url:l,rpcUrl:m,loaderUrl:m,paramsType:R,queryType:P,bodyType:p,isMultipart:g})};v.forEach(e=>_(e,"rpc")),w.forEach(e=>_(e,"loader")),S.forEach(e=>_(e,"api"));let z=[];for(let[e,a]of F.entries())z.push(`import type { ${[...a].sort().join(", ")} } from "${e}";`);let Q=[];V.forEach(e=>{Q.push(se(e))});let H=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
1
+ import Ee from"fast-glob";import{access as Re,unlink as ye,writeFile as Ae}from"fs/promises";import b from"path";import{format as $e,resolveConfig as Ce}from"prettier";import{Node as X,Project as ve,SyntaxKind as C,ts as J}from"ts-morph";import de from"fast-glob";import{access as Te,unlink as ue,writeFile as be}from"fs/promises";import R from"path";import{format as xe,resolveConfig as Pe}from"prettier";import{Node as Q,Project as Fe,SyntaxKind as $,ts as Y}from"ts-morph";function we(S){let w=S.replace(/[^a-zA-Z0-9]+(.)?/g,(k,v)=>v?v.toUpperCase():"");return w.charAt(0).toLowerCase()+w.slice(1)}function ge(S,w,k){let v=R.basename(k,R.extname(k))||"Index",M=w.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),N=`${S} ${M} ${v}`;return we(N)}async function Se(S={}){let{routerPattern:w="src-ts/routers/**/*.mts",tsConfigFilePath:k="tsconfig.json",routerBaseDir:v="src-ts/routers",clean:M=!1}=S,N=[],B=[],te=[];try{let oe=function(o){let s=[];return o.paramsType!=="unknown"&&s.push(`params: ${o.paramsType}`),o.queryType!=="unknown"&&s.push(`query: ${o.queryType}`),o.bodyType!=="unknown"&&s.push(`body: ${o.bodyType}`),s.push("signal?: AbortSignal"),s};var re=oe;let I=new Fe({tsConfigFilePath:k,skipAddingFilesFromTsConfig:!1}),ae=R.resolve(process.cwd(),v||".");async function le(o){try{let K=function(t){return t.replace(/import\(['"](.*?)['"]\)/g,(m,g)=>{if(!R.isAbsolute(g))return m;let d=g;if(!R.extname(d)){let i=I.getSourceFile(r=>r.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===g);i&&(d=i.getFilePath())}let e=R.relative(R.dirname(q),d).replace(/\\/g,"/");return e.startsWith(".")||(e="./"+e),`import("${e}")`})},A=function(t,m){if(t.getSymbol()?.getName()==="Promise"){let l=t.getAwaitedType();if(l)return`Promise<${A(l,m)}>`}let g=t.getAliasSymbol()??t.getSymbol();if(g?.getName()==="__object")return K(t.getText(m,Y.TypeFormatFlags.NoTruncation|Y.TypeFormatFlags.UseFullyQualifiedType));if(t.isObject()&&!g){let l=(c,y=0)=>{if(!(y>5)){if(c.isArray()){let h=c.getArrayElementType();h&&l(h,y);return}if(c.isObject()&&!c.getSymbol()&&!c.getAliasSymbol()){for(let h of c.getApparentProperties()){let f=h.getValueDeclaration();f&&l(h.getTypeAtLocation(f),y+1)}return}A(c,m)}};return l(t),K(t.getText(m,Y.TypeFormatFlags.NoTruncation|Y.TypeFormatFlags.UseFullyQualifiedType))}if(!g)return K(t.getText(m,Y.TypeFormatFlags.NoTruncation));let d=g.getDeclarations()[0];if(!d)return g.getName();if(Q.isImportSpecifier(d)||Q.isImportClause(d)){let l=d.getFirstAncestorByKind($.ImportDeclaration);if(l){let c=l.getModuleSpecifierValue(),y=g.getName();return P.has(c)||P.set(c,new Set),P.get(c)?.add(y),y}}let e=d.getSourceFile();if(e.getFilePath()===u.getFilePath())return g.getName();if(e.isInNodeModules())return K(t.getText(m,Y.TypeFormatFlags.NoTruncation));let i=R.relative(R.dirname(q),e.getFilePath()).replace(/\\/g,"/"),a=i.startsWith(".")?i:`./${i}`,p=g.getName();return P.has(a)||P.set(a,new Set),P.get(a)?.add(p),p},se=function(t){let m;if(Q.isFunctionLikeDeclaration(t)||Q.isArrowFunction(t)){let g=t.getDescendantsOfKind($.ReturnStatement);for(let d of g){let e=d.getExpression();if(e?.isKind($.SatisfiesExpression)){m=e.getTypeNode()?.getType();break}}}if(m)return A(m,t);{let g=t.getType().getCallSignatures();if(g.length>0){let d=g[0]?.getReturnType();return A(d,t)}}return"unknown"};var s=K,T=A,E=se;let u=I.addSourceFileAtPath(o);await u.refreshFromFileSystem(),I.resolveSourceFileDependencies();let D=u.getDescendantsOfKind($.CallExpression),j=D.filter(t=>t.getExpression().getText().endsWith(".addRpcRoute")),O=D.filter(t=>t.getExpression().getText().endsWith(".addRenderRoute")),V=D.filter(t=>t.getExpression().getText().endsWith(".addLoaderRoute")),U=R.extname(o),q=o.substring(0,o.length-U.length)+".universal.d.ts";if(j.length===0&&O.length===0&&V.length===0){if(M)try{await ue(q),B.push(q)}catch{}return!1}let _=[],P=new Map;P.has("fastify")||P.set("fastify",new Set),P.get("fastify")?.add("FastifyRequest"),P.get("fastify")?.add("FastifyReply");let ce=t=>{let m="unknown",g="unknown",d="unknown",e=!1;if(!t||!Q.isObjectLiteralExpression(t))return{paramsType:m,queryType:g,bodyType:d,isMultipart:e};let i=t.getProperty("schema");if(i?.isKind($.PropertyAssignment)){let r=i.getInitializer();if(r?.isKind($.Identifier)){let p=r.getSymbol()?.getValueDeclaration();if(p){let l=p.getFirstDescendantByKind($.ObjectLiteralExpression);l&&(r=l)}}if(r&&Q.isObjectLiteralExpression(r)){let a=r.getProperty("consumes");if(a?.isKind($.PropertyAssignment)){let l=a.getInitializer();Q.isArrayLiteralExpression(l)&&(e=l.getElements().some(c=>c.isKind($.StringLiteral)&&c.getLiteralValue()==="multipart/form-data"))}let p=l=>{let c=r.getProperty(l);if(c?.isKind($.PropertyAssignment)){let y=c.getInitializer();if(y){let h=y.getType(),f=h.getProperty("_output");return A(f?f.getTypeAtLocation(y).getApparentType():h,y)}}return"unknown"};if(m=p("params"),g=p("querystring"),d=p("body"),e){let l="{ file: File }";d=d!=="unknown"&&d.trim().startsWith("{")?`(${d} & ${l})`:l}}}return{paramsType:m,queryType:g,bodyType:d,isMultipart:e}},W=R.relative(ae,R.dirname(o)).split(R.sep).join("/"),pe=W==="."||!W?"":W.startsWith("/")?W:"/"+W,G=(t,m)=>{let[g,d]=t.getArguments();if(!g?.isKind($.StringLiteral))return;let e=g.getLiteralValue(),i="unknown",r=pe,{paramsType:a,queryType:p,bodyType:l,isMultipart:c}=ce(d);if(d?.isKind($.ObjectLiteralExpression)){let f=d.getProperty("prefix");if(f?.isKind($.PropertyAssignment)){let x=f.getInitializer();x?.isKind($.StringLiteral)&&(r=x.getLiteralValue())}let F=d.getProperty("handler");if(F?.isKind($.PropertyAssignment)){let x=F.getInitializer();x&&(i=se(x),i.startsWith("Promise<")||(i=`Promise<${i}>`))}}let y="",h="";m==="rpc"?(y=R.join(r,"rpc",e).replace(/\\/g,"/"),h=ge("action",r,e)):m==="loader"?(y=R.join(r,"loader",e).replace(/\\/g,"/"),h=ge("loader",r,e)):m==="api"&&(y=R.join(r,"api",e).replace(/\\/g,"/"),h=ge("get",r,e)),h&&_.push({type:m,name:h,returnType:i,url:e,rpcUrl:y,loaderUrl:y,paramsType:a,queryType:p,bodyType:l,isMultipart:c})};if(j.forEach(t=>G(t,"rpc")),O.forEach(t=>G(t,"loader")),V.forEach(t=>G(t,"api")),_.length===0){if(M)try{await ue(q),B.push(q)}catch{}return!1}let Z=[];for(let[t,m]of P.entries())Z.push(`import type { ${[...m].sort().join(", ")} } from "${t}";`);let ne=[];_.forEach(t=>{let m=oe(t),g="";m.length>0&&(g=`args: { ${m.join("; ")} }`),g||(g="args: { signal?: AbortSignal }"),ne.push(`export declare const ${t.name}: (${g}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${t.returnType};`)});let H=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
2
2
  /* eslint-disable */
3
3
 
4
- `+(z.length>0?z.join(`
4
+ `+(Z.length>0?Z.join(`
5
5
  `)+`
6
6
 
7
- `:"")+Q.join(`
7
+ `:"")+ne.join(`
8
8
 
9
- `);try{let e=await me(A)||{};H=await de(H,{...e,parser:"typescript",filepath:A})}catch{}await ge(A,H);let X=[],Y=[];V.forEach(e=>{let n=e.type==="rpc"?"POST":"GET",s=e.type==="loader"?e.loaderUrl:e.rpcUrl;Y.push({name:e.name,rpcUrl:s,method:n,isMultipart:!!e.isMultipart}),X.push({name:e.name,url:e.url,type:e.type,requiresArgs:!0})});let le=`
9
+ `);try{let t=await Pe(q)||{};H=await xe(H,{...t,parser:"typescript",filepath:q})}catch{}return await be(q,H),N.push(q),!0}catch(u){return te.push(`Error processing ${o}: ${u instanceof Error?u.message:String(u)}`),!1}}let n=await de(w,{absolute:!0});if(await Promise.all(n.map(o=>le(o))),M){let o=await de(R.join(v,"**/*.universal.d.ts"),{absolute:!0});for(let s of o){let T=s.replace(".universal.d.ts",".mts").replace(".universal.d.ts",".ts");if(!await Te(T).then(()=>!0).catch(()=>!1))try{await ue(s),B.push(s)}catch{}}}}catch(I){te.push(`Fatal error: ${I instanceof Error?I.message:String(I)}`)}return{generated:N,cleaned:B,errors:te}}var ee="virtual:b-ssr-rpc-universal:";function je(S){let w=S.replace(/[^a-zA-Z0-9]+(.)?/g,(k,v)=>v?v.toUpperCase():"");return w.charAt(0).toLowerCase()+w.slice(1)}function fe(S,w,k){let v=b.basename(k,b.extname(k))||"Index",M=w.replace(/:[a-zA-Z0-9_]+/g,"").replace(/\//g," "),N=`${S} ${M} ${v}`;return je(N)}function _e(S={}){let{routerPattern:w="src-ts/routers/**/*.mts",tsConfigFilePath:k="tsconfig.json",routerBaseDir:v="src-ts/routers"}=S,M=new Map,N=new Set,B=new ve({tsConfigFilePath:k,skipAddingFilesFromTsConfig:!1}),te=b.resolve(process.cwd(),v||".");async function re(n){try{let K=function(e){return e.replace(/import\(['"](.*?)['"]\)/g,(i,r)=>{if(!b.isAbsolute(r))return i;let a=r;if(!b.extname(a)){let l=B.getSourceFile(c=>c.getFilePath().replace(/\.(mts|ts|tsx)$/,"")===r);l&&(a=l.getFilePath())}let p=b.relative(b.dirname(U),a).replace(/\\/g,"/");return p.startsWith(".")||(p="./"+p),`import("${p}")`})},A=function(e,i){if(e.getSymbol()?.getName()==="Promise"){let f=e.getAwaitedType();if(f)return`Promise<${A(f,i)}>`}let r=e.getAliasSymbol()??e.getSymbol();if(r?.getName()==="__object")return K(e.getText(i,J.TypeFormatFlags.NoTruncation|J.TypeFormatFlags.UseFullyQualifiedType));if(e.isObject()&&!r){let f=(F,x=0)=>{if(!(x>5)){if(F.isArray()){let L=F.getArrayElementType();L&&f(L,x);return}if(F.isObject()&&!F.getSymbol()&&!F.getAliasSymbol()){for(let L of F.getApparentProperties()){let z=L.getValueDeclaration();z&&f(L.getTypeAtLocation(z),x+1)}return}A(F,i)}};return f(e),K(e.getText(i,J.TypeFormatFlags.NoTruncation|J.TypeFormatFlags.UseFullyQualifiedType))}if(!r)return K(e.getText(i,J.TypeFormatFlags.NoTruncation));let a=r.getDeclarations()[0];if(!a)return r.getName();if(X.isImportSpecifier(a)||X.isImportClause(a)){let f=a.getFirstAncestorByKind(C.ImportDeclaration);if(f){let F=f.getModuleSpecifierValue(),x=r.getName();return P.has(F)||P.set(F,new Set),P.get(F)?.add(x),x}}let p=a.getSourceFile();if(p.getFilePath()===E.getFilePath())return r.getName();if(p.isInNodeModules())return K(e.getText(i,J.TypeFormatFlags.NoTruncation));let l=b.relative(b.dirname(U),p.getFilePath()).replace(/\\/g,"/"),y=l.startsWith(".")?l:`./${l}`,h=r.getName();return P.has(y)||P.set(y,new Set),P.get(y)?.add(h),h},se=function(e){let i;if(X.isFunctionLikeDeclaration(e)||X.isArrowFunction(e)){let r=e.getDescendantsOfKind(C.ReturnStatement);for(let a of r){let p=a.getExpression();if(p?.isKind(C.SatisfiesExpression)){i=p.getTypeNode()?.getType();break}}}if(i)return A(i,e);{let r=e.getType().getCallSignatures();if(r.length>0){let a=r[0]?.getReturnType();return A(a,e)}}return"unknown"};var o=K,s=A,T=se;let E=B.addSourceFileAtPath(n);await E.refreshFromFileSystem(),B.resolveSourceFileDependencies();let u=E.getDescendantsOfKind(C.CallExpression),D=u.filter(e=>e.getExpression().getText().endsWith(".addRpcRoute")),j=u.filter(e=>e.getExpression().getText().endsWith(".addRenderRoute")),O=u.filter(e=>e.getExpression().getText().endsWith(".addLoaderRoute")),V=b.extname(n),U=n.substring(0,n.length-V.length)+".universal.d.ts",q=b.resolve(n);if(D.length===0&&j.length===0&&O.length===0){M.delete(q),N.delete(q),U!==n&&await ye(U).catch(()=>{});return}N.add(q);let _=[],P=new Map;P.has("fastify")||P.set("fastify",new Set),P.get("fastify")?.add("FastifyRequest"),P.get("fastify")?.add("FastifyReply");let ce=e=>{let i="unknown",r="unknown",a="unknown",p=!1;if(!e||!X.isObjectLiteralExpression(e))return{paramsType:i,queryType:r,bodyType:a,isMultipart:p};let l=e.getProperty("schema");if(l?.isKind(C.PropertyAssignment)){let c=l.getInitializer();if(c?.isKind(C.Identifier)){let h=c.getSymbol()?.getValueDeclaration();if(h){let f=h.getFirstDescendantByKind(C.ObjectLiteralExpression);f&&(c=f)}}if(c&&X.isObjectLiteralExpression(c)){let y=c.getProperty("consumes");if(y?.isKind(C.PropertyAssignment)){let f=y.getInitializer();X.isArrayLiteralExpression(f)&&(p=f.getElements().some(F=>F.isKind(C.StringLiteral)&&F.getLiteralValue()==="multipart/form-data"))}let h=f=>{let F=c.getProperty(f);if(F?.isKind(C.PropertyAssignment)){let x=F.getInitializer();if(x){let L=x.getType(),z=L.getProperty("_output");return A(z?z.getTypeAtLocation(x).getApparentType():L,x)}}return"unknown"};if(i=h("params"),r=h("querystring"),a=h("body"),p){let f="{ file: File }";a=a!=="unknown"&&a.trim().startsWith("{")?`(${a} & ${f})`:f}}}return{paramsType:i,queryType:r,bodyType:a,isMultipart:p}},W=b.relative(te,b.dirname(n)).split(b.sep).join("/"),pe=W==="."||!W?"":W.startsWith("/")?W:"/"+W,G=(e,i)=>{let[r,a]=e.getArguments();if(!r?.isKind(C.StringLiteral))return;let p=r.getLiteralValue(),l="unknown",c=pe,{paramsType:y,queryType:h,bodyType:f,isMultipart:F}=ce(a);if(a?.isKind(C.ObjectLiteralExpression)){let z=a.getProperty("prefix");if(z?.isKind(C.PropertyAssignment)){let ie=z.getInitializer();ie?.isKind(C.StringLiteral)&&(c=ie.getLiteralValue())}let me=a.getProperty("handler");if(me?.isKind(C.PropertyAssignment)){let ie=me.getInitializer();ie&&(l=se(ie),l.startsWith("Promise<")||(l=`Promise<${l}>`))}}let x="",L="";i==="rpc"?(x=b.join(c,"rpc",p).replace(/\\/g,"/"),L=fe("action",c,p)):i==="loader"?(x=b.join(c,"loader",p).replace(/\\/g,"/"),L=fe("loader",c,p)):i==="api"&&(x=b.join(c,"api",p).replace(/\\/g,"/"),L=fe("get",c,p)),L&&_.push({type:i,name:L,returnType:l,url:p,rpcUrl:x,loaderUrl:x,paramsType:y,queryType:h,bodyType:f,isMultipart:F})};D.forEach(e=>G(e,"rpc")),j.forEach(e=>G(e,"loader")),O.forEach(e=>G(e,"api"));let Z=[];for(let[e,i]of P.entries())Z.push(`import type { ${[...i].sort().join(", ")} } from "${e}";`);let ne=[];_.forEach(e=>{ne.push(ae(e))});let H=`// AUTO-GENERATED by @bobtail.software/b-ssr. DO NOT EDIT.
10
+ /* eslint-disable */
11
+
12
+ `+(Z.length>0?Z.join(`
13
+ `)+`
14
+
15
+ `:"")+ne.join(`
16
+
17
+ `);try{let e=await Ce(U)||{};H=await $e(H,{...e,parser:"typescript",filepath:U})}catch{}await Ae(U,H);let t=[],m=[];_.forEach(e=>{let r=e.type==="rpc"?"POST":"GET",a=e.type==="loader"?e.loaderUrl:e.rpcUrl;m.push({name:e.name,rpcUrl:a,method:r,isMultipart:!!e.isMultipart}),t.push({name:e.name,url:e.url,type:e.type,requiresArgs:!0})});let g=`
10
18
  import { createClientRpc } from '@bobtail.software/b-ssr/client';
11
19
 
12
20
  if (import.meta.env.DEV) {
13
- console.debug('\u{1F6E1}\uFE0F [B-SSR Security] Loaded SAFE Client-Stub for: ${o.basename(t)}');
21
+ console.debug('\u{1F6E1}\uFE0F [B-SSR Security] Loaded SAFE Client-Stub for: ${b.basename(n)}');
14
22
  }
15
23
 
16
- ${Y.map(e=>`
24
+ ${m.map(e=>`
17
25
  export const ${e.name} = createClientRpc({
18
26
  url: '${e.rpcUrl}',
19
27
  method: '${e.method}',
@@ -21,17 +29,17 @@ import pe from"fast-glob";import{access as ue,unlink as ee,writeFile as ge}from"
21
29
  });
22
30
  `).join(`
23
31
  `)}
24
- `,ce=ne(X,t);C.set(o.resolve(t),{client:le,server:ce})}catch(f){console.error(`[rpc-generator] Error al procesar ${t}:`,{error:f})}}let re=(t,u,r)=>{if(u.includes("node_modules")||u.startsWith(L))return null;if(r?.ssr===!0&&/\.[cm]?[jt]sx?$/.test(u)){let c=/\brequire\s*\(/.test(t),f=/\bmodule\.exports\b/.test(t),i=/\bexports\./.test(t);if(c||f||i)return"import { createRequire } from 'module';"+`
32
+ `,d=le(t,n);M.set(b.resolve(n),{client:g,server:d})}catch(E){console.error(`[rpc-generator] Error al procesar ${n}:`,{error:E})}}let I=(n,o,s)=>{if(o.includes("node_modules")||o.startsWith(ee))return null;if(s?.ssr===!0&&/\.[cm]?[jt]sx?$/.test(o)){let T=/\brequire\s*\(/.test(n),E=/\bmodule\.exports\b/.test(n),u=/\bexports\./.test(n);if(T||E||u)return"import { createRequire } from 'module';"+`
25
33
  const require = createRequire(import.meta.url);
26
34
  const module = { exports: {} };
27
35
  const exports = module.exports;
28
- `+t+`
29
- export default module.exports;`}return null};function se(t){let u=he(t),r="";return u.length>0&&(r=`args: { ${u.join("; ")} }`),r||(r="args: { signal?: AbortSignal }"),`export declare const ${t.name}: (${r}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${t.returnType};`}function ne(t,u){if(t.length===0)return"";let r=o.relative(process.cwd(),u).replace(/\\/g,"/");return`
36
+ `+n+`
37
+ export default module.exports;`}return null};function ae(n){let o=Oe(n),s="";return o.length>0&&(s=`args: { ${o.join("; ")} }`),s||(s="args: { signal?: AbortSignal }"),`export declare const ${n.name}: (${s}, ssrContext?: { req?: FastifyRequest, reply?: FastifyReply }) => ${n.returnType};`}function le(n,o){if(n.length===0)return"";let s=b.relative(process.cwd(),o).replace(/\\/g,"/");return`
30
38
  import path from 'path';
31
39
  import { pathToFileURL } from 'url';
32
40
 
33
41
  if (typeof window !== 'undefined' && typeof document !== 'undefined') {
34
- throw new Error('\u{1F6A8} [B-SSR SECURITY ALERT] Server-side code leaked to browser: ${`./${o.relative(process.cwd(),u).replace(/\\/g,"/")}`}');
42
+ throw new Error('\u{1F6A8} [B-SSR SECURITY ALERT] Server-side code leaked to browser: ${`./${b.relative(process.cwd(),o).replace(/\\/g,"/")}`}');
35
43
  }
36
44
 
37
45
  let initPromise;
@@ -45,7 +53,7 @@ export default module.exports;`}return null};function se(t){let u=he(t),r="";ret
45
53
  renderOptionsMap = new Map();
46
54
  loaderApiOptionsMap = new Map();
47
55
  const projectRoot = process.cwd();
48
- const absolutePath = path.resolve(projectRoot, '${r}');
56
+ const absolutePath = path.resolve(projectRoot, '${s}');
49
57
  const serverModuleUrl = pathToFileURL(absolutePath).href;
50
58
 
51
59
  if (typeof globalThis.require === 'undefined') {
@@ -93,46 +101,46 @@ export default module.exports;`}return null};function se(t){let u=he(t),r="";ret
93
101
  return initPromise;
94
102
  }
95
103
 
96
- ${t.map(i=>{let v=[];i.requiresArgs&&v.push("args"),v.push("ssrContext");let w=i.requiresArgs?"args":"{}",S="";return i.type==="rpc"?S=`
104
+ ${n.map(u=>{let D=[];u.requiresArgs&&D.push("args"),D.push("ssrContext");let j=u.requiresArgs?"args":"{}",O="";return u.type==="rpc"?O=`
97
105
  if (fn.isMultipart) throw new Error('RPC multipart no soportado en SSR.');
98
106
  await getOptionsMaps();
99
- const options = rpcOptionsMap.get('${i.url}');
100
- if (!options?.handler) throw new Error('Handler no encontrado para RPC: ${i.name}');
101
- const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
107
+ const options = rpcOptionsMap.get('${u.url}');
108
+ if (!options?.handler) throw new Error('Handler no encontrado para RPC: ${u.name}');
109
+ const augmentedReq = Object.assign(Object.create(ssrContext.req), ${j});
102
110
  return await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply);
103
- `:i.type==="api"?S=`
111
+ `:u.type==="api"?O=`
104
112
  await getOptionsMaps();
105
- const options = loaderApiOptionsMap.get('${i.url}');
113
+ const options = loaderApiOptionsMap.get('${u.url}');
106
114
  if (!options?.handler) {
107
- console.error('\u26A0\uFE0F [B-SSR Warning] Handler API no encontrado:', '${i.name}', 'URL:', '${i.url}');
115
+ console.error('\u26A0\uFE0F [B-SSR Warning] Handler API no encontrado:', '${u.name}', 'URL:', '${u.url}');
108
116
  return null;
109
117
  }
110
- const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
118
+ const augmentedReq = Object.assign(Object.create(ssrContext.req), ${j});
111
119
  return await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply);
112
- `:S=`
120
+ `:O=`
113
121
  await getOptionsMaps();
114
- const options = renderOptionsMap.get('${i.url}');
122
+ const options = renderOptionsMap.get('${u.url}');
115
123
  if (!options) return {};
116
- const augmentedReq = Object.assign(Object.create(ssrContext.req), ${w});
124
+ const augmentedReq = Object.assign(Object.create(ssrContext.req), ${j});
117
125
  let customData = {};
118
126
  try {
119
127
  if (options.handler) {
120
128
  customData = (await options.handler.call(ssrContext.req.server, augmentedReq, ssrContext.reply)) || {};
121
129
  }
122
130
  } catch (handlerErr) {
123
- console.error('\u274C [B-SSR Handler Error] ${i.name}:', handlerErr);
131
+ console.error('\u274C [B-SSR Handler Error] ${u.name}:', handlerErr);
124
132
  return {};
125
133
  }
126
134
  if (ssrContext.reply.sent) return;
127
135
  return { ...customData };
128
- `,`export const ${i.name} = async (${v.join(", ")}) => {
136
+ `,`export const ${u.name} = async (${D.join(", ")}) => {
129
137
  try {
130
- if (!ssrContext?.req) throw new Error('ssrContext requerido en ${i.name} (SSR)');
131
- ${S}
138
+ if (!ssrContext?.req) throw new Error('ssrContext requerido en ${u.name} (SSR)');
139
+ ${O}
132
140
  } catch (error) {
133
- console.error('\u274C [B-SSR Error] ${i.name}:', error);
141
+ console.error('\u274C [B-SSR Error] ${u.name}:', error);
134
142
  throw error;
135
143
  }
136
144
  };`}).join(`
137
145
  `)}
138
- `}async function oe(){let t=await pe(x,{absolute:!0});await Promise.all(t.map(u=>I(u)))}return{name:"b-ssr-vite-plugin-rpc-universal-generator",enforce:"pre",async buildStart(){await oe()},configureServer(t){let u=r=>r.endsWith(".mts")||r.endsWith(".ts");t.watcher.on("add",r=>u(r)&&I(r)),t.watcher.on("change",r=>u(r)&&I(r)),t.watcher.on("unlink",r=>{if(u(r)){let c=o.resolve(r);C.delete(c),q.delete(c);let f=o.extname(r),i=r.substring(0,r.length-f.length)+".universal.d.ts";ee(i).catch(()=>{})}})},async resolveId(t,u,r){if(t.startsWith(L))return null;if(t.includes(".universal")){let c=t.split("?")[0],f=c;if(c.endsWith(".universal"))f=c;else if(c.endsWith(".universal.ts"))f=c.slice(0,-3);else if(c.endsWith(".universal.mts"))f=c.slice(0,-4);else if(c.endsWith(".universal.js"))f=c.slice(0,-3);else return null;let i=[".mts",".ts"];for(let v of i){let w=f.slice(0,-10)+v,S=await this.resolve(w,u,{skipSelf:!0});if(S){let D=r?.ssr?"?mode=ssr":"?mode=client";return L+S.id+D}try{await ue(w);let D=r?.ssr?"?mode=ssr":"?mode=client";return L+w+D}catch{}}}return null},async load(t,u){if(t.startsWith(L)){let r=t.slice(L.length).split("?")[0],c=C.get(r);return c||(await I(r),c=C.get(r)),c?u?.ssr===!0?c.server:c.client:null}if(u?.ssr!==!0){let r=o.resolve(t);if(q.has(r))return`throw new Error("\u{1F6A8} [B-SSR FIREWALL] BLOCKED: Backend File imported in Client: ${o.basename(t)}");`}return null},transform:re}}function he(T){let x=[];return T.paramsType!=="unknown"&&x.push(`params: ${T.paramsType}`),T.queryType!=="unknown"&&x.push(`query: ${T.queryType}`),T.bodyType!=="unknown"&&x.push(`body: ${T.bodyType}`),x.push("signal?: AbortSignal"),x}export{Re as rpcGeneratorPlugin};
146
+ `}async function oe(){let n=await Ee(w,{absolute:!0});await Promise.all(n.map(o=>re(o)))}return{name:"b-ssr-vite-plugin-rpc-universal-generator",enforce:"pre",async buildStart(){await oe()},configureServer(n){let o=s=>s.endsWith(".mts")||s.endsWith(".ts");n.watcher.on("add",s=>o(s)&&re(s)),n.watcher.on("change",s=>o(s)&&re(s)),n.watcher.on("unlink",s=>{if(o(s)){let T=b.resolve(s);M.delete(T),N.delete(T);let E=b.extname(s),u=s.substring(0,s.length-E.length)+".universal.d.ts";ye(u).catch(()=>{})}})},async resolveId(n,o,s){if(n.startsWith(ee))return null;if(n.includes(".universal")){let T=n.split("?")[0],E=T;if(T.endsWith(".universal"))E=T;else if(T.endsWith(".universal.ts"))E=T.slice(0,-3);else if(T.endsWith(".universal.mts"))E=T.slice(0,-4);else if(T.endsWith(".universal.js"))E=T.slice(0,-3);else return null;let u=[".mts",".ts"];for(let D of u){let j=E.slice(0,-10)+D,O=await this.resolve(j,o,{skipSelf:!0});if(O){let V=s?.ssr?"?mode=ssr":"?mode=client";return ee+O.id+V}try{await Re(j);let V=s?.ssr?"?mode=ssr":"?mode=client";return ee+j+V}catch{}}}return null},async load(n,o){if(n.startsWith(ee)){let s=n.slice(ee.length).split("?")[0],T=M.get(s);return T||(await re(s),T=M.get(s)),T?o?.ssr===!0?T.server:T.client:null}if(o?.ssr!==!0){let s=b.resolve(n);if(N.has(s))return`throw new Error("\u{1F6A8} [B-SSR FIREWALL] BLOCKED: Backend File imported in Client: ${b.basename(n)}");`}return null},transform:I}}function Oe(S){let w=[];return S.paramsType!=="unknown"&&w.push(`params: ${S.paramsType}`),S.queryType!=="unknown"&&w.push(`query: ${S.queryType}`),S.bodyType!=="unknown"&&w.push(`body: ${S.bodyType}`),w.push("signal?: AbortSignal"),w}export{Se as generateRpcTypes,_e as rpcGeneratorPlugin};
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@bobtail.software/b-ssr",
3
- "version": "1.0.64",
3
+ "version": "1.0.65",
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",
7
7
  "type": "module",
8
8
  "main": "./dist/fastify-b-ssr-plugin.js",
9
9
  "types": "./dist/fastify-b-ssr-plugin.d.ts",
10
+ "bin": {
11
+ "generate-rpc-types": "./bin/generate-rpc-types.mjs"
12
+ },
10
13
  "exports": {
11
14
  ".": {
12
15
  "import": "./dist/fastify-b-ssr-plugin.js",
@@ -18,6 +21,11 @@
18
21
  "require": "./dist/vite-rpc-plugin.cjs",
19
22
  "types": "./dist/vite-rpc-plugin.d.ts"
20
23
  },
24
+ "./type-generator": {
25
+ "import": "./dist/rpc-type-generator.js",
26
+ "require": "./dist/rpc-type-generator.cjs",
27
+ "types": "./dist/rpc-type-generator.d.ts"
28
+ },
21
29
  "./client": {
22
30
  "import": "./dist/rpc-client.js",
23
31
  "require": "./dist/rpc-client.cjs",
@@ -35,7 +43,8 @@
35
43
  }
36
44
  },
37
45
  "files": [
38
- "dist"
46
+ "dist",
47
+ "bin"
39
48
  ],
40
49
  "keywords": [
41
50
  "fastify",
@@ -57,23 +66,35 @@
57
66
  "fast-glob": "^3.3.3",
58
67
  "fastify-plugin": "^5.1.0",
59
68
  "fastify-type-provider-zod": "^6.1.0",
60
- "ts-morph": "^27.0.2"
69
+ "ts-morph": "^27.0.2",
70
+ "zod": "^4.1.12"
61
71
  },
62
72
  "devDependencies": {
73
+ "@tanstack/react-router": "^1.139.1",
63
74
  "@types/node": "^24.10.0",
64
75
  "@types/react": "^19.0.0",
65
76
  "@types/react-dom": "^19.0.0",
66
- "@tanstack/react-router": "^1.139.1",
77
+ "@types/supertest": "^6.0.0",
78
+ "@vitest/ui": "^2.0.0",
79
+ "fastify": "^5.6.2",
80
+ "happy-dom": "^16.0.0",
67
81
  "react": "^18.0.0 || ^19.0.0",
68
82
  "react-dom": "^18.0.0 || ^19.0.0",
69
- "fastify": "^5.6.2",
83
+ "supertest": "^7.0.0",
70
84
  "tsup": "^8.5.0",
71
85
  "typescript": "^5.9.3",
72
86
  "vite": "^7.2.4",
87
+ "vitest": "^2.0.0",
73
88
  "zod": "^4.1.12"
74
89
  },
75
90
  "scripts": {
76
91
  "build": "tsup",
77
- "dev": "tsup --watch"
92
+ "dev": "tsup --watch",
93
+ "generate:types": "node bin/generate-rpc-types.mjs",
94
+ "generate:types:clean": "node bin/generate-rpc-types.mjs --clean",
95
+ "test": "vitest",
96
+ "test:ui": "vitest --ui",
97
+ "test:coverage": "vitest --coverage",
98
+ "test:watch": "vitest --watch"
78
99
  }
79
100
  }