rpc4next-cli 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4 -4
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as
|
|
2
|
+
import{Command as Ht}from"commander";import Pt from"path";var A=["page.tsx","route.ts"],w=0,P=1,F=1,W=20,M="\u2192";import Y from"path";var tt=(t,r)=>{let e=x(Y.relative(Y.dirname(t),r)).replace(/\.tsx?$/,"");return e.startsWith("../")||(e="./"+e),e},x=t=>t.replace(/\\/g,"/"),_=t=>Y.relative(process.cwd(),t);import yt from"fs";import Ut from"path";var et=["Query"];var U="Endpoint",j="QueryKey",H="ParamsKey",rt=[U,H,j],ot="rpc4next/client";import ut from"fs";import v from"path";import{CATCH_ALL_PREFIX as Ot,DYNAMIC_PREFIX as wt,HTTP_METHODS_EXCLUDE_OPTIONS as Ft,OPTIONAL_CATCH_ALL_PREFIX as Wt}from"rpc4next-shared";import G from"path";var E=new Map,C=new Map,nt=(t,r)=>{let e=G.resolve(r);[...t.keys()].forEach(o=>{let n=G.resolve(o);(n===e||e.startsWith(n+G.sep))&&t.delete(o)})},st=t=>{nt(E,t)},it=t=>{nt(C,t)};import Dt from"fs";import vt from"crypto";var at=(t,r)=>{let e=vt.createHash("md5").update(`${t}::${r}`).digest("hex").slice(0,16);return`${r}_${e}`};var R=(t,r)=>!t||!r?"":`Record<${t}, ${r}>`,b=t=>t.length===0||t.some(({name:r,type:e})=>!r||!e)?"":`{ ${t.map(({name:r,type:e})=>`"${r}": ${e}`).join(`${";"} `)}${t.length>1?";":""} }`,L=(t,r,e)=>!t||!r?"":e?`import type { ${t} as ${e} } from "${r}"${";"}`:`import type { ${t} } from "${r}"${";"}`;var ct=(t,r,e,o)=>{let n=Dt.readFileSync(r,"utf8"),i=e(n);if(!i)return;let s=tt(t,r),p=at(s,i);return{importName:p,importPath:s,importStatement:L(i,s,p),type:o(i,p)}},mt=(t,r)=>ct(t,r,e=>et.find(o=>new RegExp(`export (interface ${o} ?{|type ${o} ?=)`).test(e)),(e,o)=>R(j,o)),lt=(t,r,e)=>ct(t,r,o=>[e].find(n=>new RegExp(`export (async )?(function ${n} ?\\(|const ${n} ?=|\\{[^}]*\\b${n}\\b[^}]*\\} ?=|const \\{[^}]*\\b${n}\\b[^}]*\\} ?=|\\{[^}]*\\b${n}\\b[^}]*\\} from)`).test(o)),(o,n)=>b([{name:`$${o.toLowerCase()}`,type:`typeof ${n}`}]));var ft=new Set(A),ht=t=>{if(E.has(t))return E.get(t);let r=ut.readdirSync(t,{withFileTypes:!0});for(let e of r){let{name:o}=e,n=v.join(t,o);if(o==="node_modules"||o.startsWith("_")||o.startsWith("(.)")||o.startsWith("(..)")||o.startsWith("(...)"))return E.set(t,!1),!1;if(e.isFile()&&ft.has(o))return E.set(t,!0),!0;if(e.isDirectory()&&ht(n))return E.set(t,!0),!0}return E.set(t,!1),!1},Mt=(t,{isDynamic:r,isCatchAll:e,isOptionalCatchAll:o})=>{let n=t;return r&&(n=n.replace(/^\[+|\]+$/g,"")),(e||o)&&(n=n.replace(/^\.{3}/,"")),{paramName:n,keyName:`${o?Wt:e?Ot:r?wt:""}${n}`}},k=(t,r,e="",o=[])=>{if(C.has(r))return C.get(r);let n=e,i=e+" ",s=[],p=[],a=[],m=[],c=[...o],$=ut.readdirSync(r,{withFileTypes:!0}).filter(d=>{if(d.isDirectory()){let y=v.join(r,d.name);return ht(y)}return ft.has(d.name)}).sort();for(let d of $){let y=x(v.join(r,d.name));if(d.isDirectory()){let l=d.name,h=l.startsWith("(")&&l.endsWith(")"),u=l.startsWith("@"),f=l.startsWith("[[...")&&l.endsWith("]]"),g=l.startsWith("[...")&&l.endsWith("]"),S=l.startsWith("[")&&l.endsWith("]"),{paramName:It,keyName:At}=Mt(l,{isDynamic:S,isCatchAll:g,isOptionalCatchAll:f}),Rt=S||g||f?[...c,{paramName:It,routeType:{isDynamic:S,isCatchAll:g,isOptionalCatchAll:f,isGroup:h,isParallel:u}}]:c,z=h||u,{pathStructure:O,imports:bt,paramsTypes:Lt}=k(t,y,z?n:i,Rt);if(p.push(...bt),m.push(...Lt),z){let J=O.match(/^\s*\{([\s\S]*)\}\s*$/),Z=O.trim();if(J)s.push(`${i}${J[1].trim()}`);else if(Z)a.push(Z);else throw new Error(`Invalid empty child path structure in grouped/parallel route: ${y}`)}else s.push(`${i}"${At}": ${O}`)}else{let l=mt(t,y);if(l){let{importStatement:h,importPath:u,type:f}=l;p.push({statement:h,path:u}),a.push(f)}if(Ft.forEach(h=>{let u=lt(t,y,h);if(u){let{importStatement:f,importPath:g,type:S}=u;p.push({statement:f,path:g}),a.push(S)}}),a.push(U),c.length>0){let h=c.map(({paramName:f,routeType:g})=>{let S=g.isCatchAll?"string[]":g.isOptionalCatchAll?"string[] | undefined":"string";return{name:f,type:S}}),u=b(h);m.push({paramsType:u,dirPath:v.dirname(y)}),a.push(R(H,u))}}}let I=a.join(" & "),D=s.length>0?`{${`
|
|
3
3
|
`}${s.join(`,${`
|
|
4
4
|
`}`)}${`
|
|
5
|
-
`}${n}}`:"",
|
|
6
|
-
`)}`:"",p=
|
|
5
|
+
`}${n}}`:"",q={pathStructure:I&&D?`${I} & ${D}`:I||D,imports:p,paramsTypes:m};return C.set(r,q),q};var gt=(t,r)=>{let{pathStructure:e,imports:o,paramsTypes:n}=k(t,r),i=`export type PathStructure = ${e}${";"}`,s=o.length?`${o.sort((c,$)=>c.path.localeCompare($.path,void 0,{numeric:!0})).map(c=>c.statement).join(`
|
|
6
|
+
`)}`:"",p=rt.filter(c=>e.includes(c)),a=L(p.join(" ,"),ot),m=n.map(({paramsType:c,dirPath:$})=>({paramsType:`export type Params = ${c}${";"}`,dirPath:$}));return{pathStructure:`${a}${`
|
|
7
7
|
`}${s}${`
|
|
8
8
|
`}${`
|
|
9
|
-
`}${i}`,paramsTypes:m}};var
|
|
9
|
+
`}${i}`,paramsTypes:m}};var Yt=()=>!!process.stdout?.isTTY;var K=t=>r=>Yt()?`\x1B[${t}m${r}\x1B[0m`:r,Et=K(36),Tt=K(32),Q=K(31);var V=(t,r,e="\u2192",o=24)=>t.padEnd(o)+` ${e} ${r}`,B=(t=0)=>" ".repeat(t),dt=()=>({info:(t,r={})=>{let{indentLevel:e=0,event:o}=r,n=o?`${Et(`[${o}]`)} `:"";console.log(`${B(e)}${n}${t}`)},success:(t,r={})=>{let{indentLevel:e=0}=r;console.log(`${B(e)}${Tt("\u2713")} ${t}`)},error:(t,r={})=>{let{indentLevel:e=0}=r;console.error(`${B(e)}${Q("\u2717")} ${Q(t)}`)}});var St=({baseDir:t,outputPath:r,paramsFileName:e,logger:o})=>{o.info("Generating types...",{event:"generate"});let{pathStructure:n,paramsTypes:i}=gt(r,t);yt.writeFileSync(r,n),o.success(V("Path structure type",_(r),M,W),{indentLevel:F}),e&&(i.forEach(({paramsType:s,dirPath:p})=>{let a=Ut.join(p,e);yt.writeFileSync(a,s)}),o.success(V("Params types",e,M,W),{indentLevel:F}))};import jt from"chokidar";var xt=(t,r)=>{let e=null,o=!1,n=null,i=async(...s)=>{o=!0;try{await t(...s)}finally{if(o=!1,n){let p=n;n=null,i(...p)}}};return(...s)=>{e&&clearTimeout(e),e=setTimeout(()=>{if(o){n=s;return}i(...s)},r)}};var $t=(t,r,e)=>{e.info(`${_(t)}`,{event:"watch"});let o=a=>A.some(m=>a.endsWith(m)),n=new Set,i=xt(()=>{n.forEach(a=>{st(a),it(a)}),n.clear(),r()},300),s=jt.watch(t,{ignoreInitial:!0,ignored:(a,m)=>!!m?.isFile()&&!o(a)});s.on("ready",()=>{i(),s.on("all",(a,m)=>{if(o(m)){let c=_(m);e.info(c,{event:a}),n.add(m),i()}})}),s.on("error",a=>{a instanceof Error?e.error(`Watcher error: ${a.message}`):e.error(`Unknown watcher error: ${String(a)}`)});let p=()=>{s.close().then(()=>{e.info("Watcher closed.",{event:"watch"})}).catch(a=>{e.error(`Failed to close watcher: ${a.message}`)})};process.on("SIGINT",p),process.on("SIGTERM",p)};var _t=(t,r,e,o)=>{try{return St({baseDir:t,outputPath:r,paramsFileName:e,logger:o}),w}catch(n){return n instanceof Error?o.error(`Failed to generate: ${n.message}`):o.error(`Unknown error occurred during generate: ${String(n)}`),P}},Ct=(t,r,e,o)=>{let n=x(Pt.resolve(t)),i=x(Pt.resolve(r)),s=typeof e.paramsFile=="string"?e.paramsFile:null;return e.paramsFile!==void 0&&!s?(o.error("Error: --params-file requires a filename."),P):e.watch?($t(n,()=>{_t(n,i,s,o)},o),w):_t(n,i,s,o)};var Nt=(t,r=dt())=>{let e=new Ht;e.description("Generate RPC client type definitions based on the Next.js path structure.").argument("<baseDir>","Base directory containing Next.js paths for type generation").argument("<outputPath>","Output path for the generated type definitions").option("-w, --watch","Watch mode: regenerate on file changes").option("-p, --params-file [filename]","Generate params types file with specified filename").action(async(o,n,i)=>{try{let s=await Ct(o,n,i,r);i.watch||process.exit(s)}catch(s){r.error(`Unexpected error occurred:${s instanceof Error?s.message:String(s)}`),process.exit(P)}}),e.parse(t)};Nt(process.argv);
|
|
10
10
|
/*!
|
|
11
11
|
* Inspired by pathpida (https://github.com/aspida/pathpida),
|
|
12
12
|
* especially the design and UX of its CLI.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rpc4next-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Command line interface for rpc4next. Generates RPC client type definitions from Next.js routes.",
|
|
5
5
|
"author": "watanabe-1",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"test:coverage": "vitest run --coverage.enabled true",
|
|
28
28
|
"test:ui": "vitest --ui --coverage.enabled true",
|
|
29
29
|
"test:watch": "vitest --watch",
|
|
30
|
-
"lint": "eslint
|
|
31
|
-
"lint:fix": "eslint
|
|
30
|
+
"lint": "eslint src",
|
|
31
|
+
"lint:fix": "eslint src --fix",
|
|
32
32
|
"typecheck": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"chokidar": "^
|
|
36
|
-
"commander": "^14.0.
|
|
37
|
-
"rpc4next-shared": "^0.1.
|
|
35
|
+
"chokidar": "^5.0.0",
|
|
36
|
+
"commander": "^14.0.3",
|
|
37
|
+
"rpc4next-shared": "^0.1.5"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"next": "^14.0.0 || ^15.0.0"
|