UNPKG

@stacksjs/dtsx

Version:

A modern, fast .d.ts generation tool, powered by Bun.

13 lines (12 loc) 23.8 kB
#!/usr/bin/env bun // @bun import{Af as Y}from"../chunk-p0p65mbf.js";import V from"process";var f=V.argv[2];if(f==="stdin"||f==="emit"||f==="--project"){if(f==="stdin"){let{processSource:q}=await import("../src/process-source.js"),Q=[];for await(let N of V.stdin)Q.push(N);let K=Buffer.concat(Q).toString("utf-8");if(K.trim())V.stdout.write(q(K,"stdin.ts")),V.stdout.write(` `)}else if(f==="--project"){let{readdirSync:q,readFileSync:Q,writeFileSync:K,mkdirSync:N}=await import("fs"),A=typeof globalThis.Bun<"u",J=A?globalThis.Bun:null,$=V.argv.slice(3),z="",B="",G=!1;for(let X=0;X<$.length;X++)if($[X]==="--outdir"&&$[X+1])B=$[X+1],X++;else if($[X]==="--isolated-declarations")G=!0;else if(!z)z=$[X];N(B,{recursive:!0});let j=q(z).filter((X)=>X.endsWith(".ts")&&!X.endsWith(".d.ts")),Z=j.length,E=Array(Z),M=Array(Z);for(let X=0;X<Z;X++)E[X]=`${z}/${j[X]}`,M[X]=`${B}/${j[X].slice(0,-3)}.d.ts`;let T=["bun"],R=A&&Z>=64,I=!1,_=null;if(R){let X=null;try{let{createWorkerPool:F,calculateOptimalBatchSize:D}=await import("../src/worker.js"),{cpus:C}=await import("os"),w=Math.max(1,C().length-1),U=Math.min(64,Math.max(8,D(Z,w)*2)),L=Z>=256,a=!0,l=Z>=256;if(!L&&Z>=256){_=Array(Z);for(let x=0;x<Z;x++)_[x]=J.file(E[x]).text()}let O=Math.ceil(Z/U),u=Math.min(O,Math.max(2,w*2));X=F({maxWorkers:w,initialWorkers:w,recycleAfter:Math.max(100,O+1)}),await X.init();let d=X,i=0,r=Date.now(),t=async()=>{for(;;){let x=i++;if(x>=O)return;let S=x*U;if(S>=Z)return;let g=Math.min(Z,S+U)-S,m;if(l){let P=Array(g),y=Array(g),b;if(L)for(let W=0;W<g;W++){let v=S+W;P[W]=E[v],y[W]=M[v]}else{let W=Array(g);for(let v=0;v<g;v++){let c=S+v;P[v]=E[c],y[v]=M[c],W[v]=_?_[c]:J.file(E[c]).text()}b=await Promise.all(W)}m=await d.submit({id:`batch-${r}-${x}`,type:"process-batch",filePath:P[0]||"",filePaths:P,sources:b,outPaths:y,writeOutput:!0,config:{keepComments:!0,importOrder:T,isolatedDeclarations:G}})}else{let P=Array(g);if(L)for(let y=0;y<g;y++){let b=S+y;P[y]={filePath:E[b],outPath:M[b]}}else{let y=Array(g);for(let W=0;W<g;W++){let v=S+W;y[W]=_?_[v]:J.file(E[v]).text()}let b=await Promise.all(y);for(let W=0;W<g;W++){let v=S+W;P[W]={filePath:E[v],sourceCode:b[W],outPath:M[v]}}}m=await d.submit({id:`batch-${r}-${x}`,type:"process-batch",filePath:E[S]||"",files:P,writeOutput:!0,config:{keepComments:!0,importOrder:T,isolatedDeclarations:G}})}if(!m.success)throw Error(m.error||`Worker batch failed for ${E[S]}`);if(m.batchResults?.length){let P=m.batchResults[0];throw Error(P?.error||m.error||`Worker failed for ${E[S]}`)}}},n=[];for(let x=0;x<u;x++)n.push(t());await Promise.all(n),I=!0}catch{I=!1}finally{if(X)await X.shutdown()}}if(!I){let{scanDeclarations:X}=await import("../chunk-0c8y8m3a.js"),{processDeclarations:F}=await import("../src/processor.js"),D=Array(Z);if(A){let U=_?await Promise.all(_):await Promise.all(E.map((L)=>J.file(L).text()));for(let L=0;L<Z;L++)D[L]=U[L]}else for(let U=0;U<Z;U++)D[U]=Q(E[U],"utf-8");let C=Array(Z),w={filePath:"",sourceCode:"",declarations:[]};for(let U=0;U<Z;U++){let L=X(D[U],j[U],!0,G);w.filePath=j[U],w.sourceCode=D[U],w.declarations=L,C[U]=F(L,w,!0,T)}if(A){let U=Array(Z);for(let L=0;L<Z;L++)U[L]=J.write(M[L],C[L]);await Promise.all(U)}else for(let U=0;U<Z;U++)K(M[U],C[U])}}else{let{processSource:q}=await import("../src/process-source.js"),{readFileSync:Q,writeFileSync:K,mkdirSync:N}=await import("fs"),A=typeof globalThis.Bun<"u",J=A?globalThis.Bun:null,$=V.argv[3],z=A?await J.file($).text():Q($,"utf-8"),B=V.argv[4];if(B){let{dirname:G}=await import("path");N(G(B),{recursive:!0});let j=`${q(z,$)} `;if(A)await J.write(B,j);else K(B,j)}else V.stdout.write(q(z,$)),V.stdout.write(` `)}V.exit(0)}var{resolve:h}=await import("path"),{CLI:s}=await import("../chunk-gjaqjzas.js"),{version:e}=await import("../chunk-hmq9tffc.js"),{getConfig:o}=await import("../src/config.js"),{generate:qq,processSource:Hq,watch:Kq}=await import("../src/generator.js"),k=new s("dtsx"),H={cwd:V.cwd(),root:"./src",entrypoints:["**/*.ts"],outdir:"./dist",keepComments:!0,clean:!1,tsconfigPath:"tsconfig.json",verbose:!1,importOrder:["bun"],dryRun:!1,stats:!1,continueOnError:!1,logLevel:"info",exclude:[],outputFormat:"text",progress:!1,diff:!1,validate:!1,parallel:!1,concurrency:4};k.command("generate","Generate TypeScript declaration files").option("--cwd <path>","Current working directory",{default:H.cwd}).option("--root <path>","Root directory of the project",{default:H.root}).option("--entrypoints <files>","Entry point files (comma-separated)",{default:H.entrypoints?.join(","),type:[String]}).option("--outdir <path>","Output directory for generated .d.ts files",{default:H.outdir}).option("--keep-comments","Keep comments in generated .d.ts files",{default:H.keepComments}).option("--clean","Clean output directory before generation",{default:H.clean}).option("--tsconfig <path>","Path to tsconfig.json",{default:H.tsconfigPath}).option("--verbose","Enable verbose logging",{default:H.verbose}).option("--import-order <patterns>","Import order priority patterns (comma-separated)",{default:H.importOrder?.join(","),type:[String]}).option("--dry-run","Show what would be generated without writing files",{default:H.dryRun}).option("--stats","Show statistics after generation",{default:H.stats}).option("--continue-on-error","Continue processing other files if one fails",{default:H.continueOnError}).option("--log-level <level>","Log level (debug, info, warn, error, silent)",{default:H.logLevel}).option("--exclude <patterns>","Glob patterns to exclude (comma-separated)",{default:H.exclude?.join(","),type:[String]}).option("--output-format <format>","Output format: text or json",{default:H.outputFormat}).option("--progress","Show progress during generation",{default:H.progress}).option("--diff","Show diff of changes compared to existing files",{default:H.diff}).option("--validate","Validate generated .d.ts files against TypeScript",{default:H.validate}).option("--parallel","Process files in parallel",{default:H.parallel}).option("--concurrency <number>","Number of concurrent workers (with --parallel)",{default:H.concurrency}).option("--declaration-map","Generate declaration map files (.d.ts.map)",{default:!1}).option("--bundle","Bundle all declarations into a single output file",{default:!1}).option("--bundle-output <file>","Output filename when bundling (relative to outdir)",{default:"index.d.ts"}).option("--config <path>","Path to config file (dtsx.config.ts)",{default:""}).option("--incremental","Enable incremental builds (only regenerate changed files)",{default:!1}).option("--clear-cache","Clear the incremental build cache before generating",{default:!1}).option("--indent-style <style>","Indentation style: spaces or tabs",{default:"spaces"}).option("--indent-size <size>","Number of spaces for indentation",{default:2}).option("--prettier","Use Prettier for output formatting if available",{default:!1}).example("dtsx generate").example("dtsx generate --entrypoints src/index.ts,src/utils.ts --outdir dist/types").example('dtsx generate --import-order "node:,bun,@myorg/"').example("dtsx generate --dry-run --stats").example('dtsx generate --exclude "**/*.test.ts,**/__tests__/**"').example("dtsx generate --stats --output-format json").example("dtsx generate --bundle --bundle-output types.d.ts").action(async(q)=>{try{let Q=h(q.cwd||H.cwd),K=await o(Q),N={entrypoints:q.entrypoints?q.entrypoints:K.entrypoints||H.entrypoints,cwd:Q,root:h(q.root||K.root||H.root),outdir:h(q.outdir||K.outdir||H.outdir),tsconfigPath:h(q.tsconfigPath||K.tsconfigPath||H.tsconfigPath),keepComments:q.keepComments??K.keepComments??H.keepComments,clean:q.clean??K.clean??H.clean,verbose:q.verbose??K.verbose??H.verbose,importOrder:q.importOrder||K.importOrder||H.importOrder,dryRun:q.dryRun??K.dryRun??H.dryRun,stats:q.stats??K.stats??H.stats,continueOnError:q.continueOnError??K.continueOnError??H.continueOnError,logLevel:q.logLevel??K.logLevel??H.logLevel,exclude:q.exclude?q.exclude.flatMap((J)=>J.split(",").map(($)=>$.trim()).filter(Boolean)):K.exclude||H.exclude,outputFormat:q.outputFormat??K.outputFormat??H.outputFormat,progress:q.progress??K.progress??H.progress,diff:q.diff??K.diff??H.diff,validate:q.validate??K.validate??H.validate,parallel:q.parallel??K.parallel??H.parallel,concurrency:Number(q.concurrency)||K.concurrency||H.concurrency,declarationMap:q.declarationMap??K.declarationMap??!1,bundle:q.bundle??K.bundle??!1,bundleOutput:q.bundleOutput??K.bundleOutput??"index.d.ts",incremental:q.incremental??K.incremental??!1,clearCache:q.clearCache??!1,indentStyle:q.indentStyle??K.indentStyle??"spaces",indentSize:Number(q.indentSize)||K.indentSize||2,prettier:q.prettier??K.prettier??!1,plugins:K.plugins},A=await qq(N);if(A.filesFailed>0&&A.filesGenerated===0)V.exit(1);else if(A.filesFailed>0)V.exit(2)}catch(Q){console.error("Error generating .d.ts files:",Q),V.exit(1)}});k.command("watch","Watch for changes and regenerate .d.ts files").option("--cwd <path>","Current working directory",{default:H.cwd}).option("--root <path>","Root directory of the project",{default:H.root}).option("--entrypoints <files>","Entry point files (comma-separated)",{default:H.entrypoints?.join(","),type:[String]}).option("--outdir <path>","Output directory for generated .d.ts files",{default:H.outdir}).option("--keep-comments","Keep comments in generated .d.ts files",{default:H.keepComments}).option("--exclude <patterns>","Glob patterns to exclude (comma-separated)",{default:H.exclude?.join(","),type:[String]}).option("--log-level <level>","Log level (debug, info, warn, error, silent)",{default:H.logLevel}).example("dtsx watch").example("dtsx watch --root src --outdir dist/types").action(async(q)=>{try{let Q={entrypoints:q.entrypoints?q.entrypoints:H.entrypoints,cwd:h(q.cwd||H.cwd),root:h(q.root||H.root),outdir:h(q.outdir||H.outdir),keepComments:q.keepComments??H.keepComments,exclude:q.exclude?q.exclude.flatMap((K)=>K.split(",").map((N)=>N.trim()).filter(Boolean)):H.exclude,logLevel:q.logLevel??H.logLevel};await Kq(Q)}catch(Q){console.error("Error in watch mode:",Q),V.exit(1)}});k.command("stdin","Process TypeScript from stdin and output .d.ts to stdout").option("--keep-comments","Keep comments in generated .d.ts files",{default:!0}).option("--import-order <patterns>","Import order priority patterns (comma-separated)",{default:"bun",type:[String]}).example(`echo "export const foo: string = 'bar'" | dtsx stdin`).example("cat src/index.ts | dtsx stdin").action(async(q)=>{try{let Q=[];for await(let J of V.stdin)Q.push(J);let K=Buffer.concat(Q).toString("utf-8");if(!K.trim())console.error("Error: No input received from stdin"),V.exit(1);let N=["bun"];if(q.importOrder){if(Array.isArray(q.importOrder))N=q.importOrder.flatMap((J)=>J.split(",").map(($)=>$.trim()).filter(Boolean));else if(typeof q.importOrder==="string")N=q.importOrder.split(",").map((J)=>J.trim()).filter(Boolean)}let A=Hq(K,"stdin.ts",q.keepComments??!0,N);console.log(A)}catch(Q){console.error("Error processing stdin:",Q),V.exit(1)}});k.command("optimize","Optimize declaration files").option("--files <patterns>","Glob patterns for .d.ts files to optimize",{default:"**/*.d.ts",type:[String]}).option("--outdir <path>","Output directory (defaults to in-place)",{default:""}).option("--remove-unused-imports","Remove unused type imports",{default:!0}).option("--deduplicate","Remove duplicate declarations",{default:!0}).option("--merge-interfaces","Merge interface declarations with same name",{default:!0}).option("--inline-types","Inline simple type aliases",{default:!1}).option("--remove-empty","Remove empty interfaces",{default:!0}).option("--sort","Sort declarations alphabetically",{default:!1}).option("--sort-imports","Sort imports",{default:!0}).option("--minify","Minify output (remove whitespace)",{default:!1}).option("--remove-comments","Remove comments",{default:!1}).example('dtsx optimize --files "dist/**/*.d.ts"').example("dtsx optimize --minify --remove-comments").action(async(q)=>{try{let{optimizeFile:Q}=await import("../src/optimizer.js"),{Glob:K}=awaitPromise.resolve(globalThis.Bun),{resolve:N,join:A,relative:J,dirname:$,basename:z}=await import("path"),{mkdirSync:B,copyFileSync:G,existsSync:j}=await import("fs"),Z=V.cwd(),E=q.files||["**/*.d.ts"],M=[];for(let _ of E){let X=new K(_);for await(let F of X.scan({cwd:Z,absolute:!0,onlyFiles:!0}))if(F.endsWith(".d.ts")&&!F.includes("node_modules"))M.push(F)}if(M.length===0)console.error("No .d.ts files found"),V.exit(1);console.log(`Optimizing ${M.length} declaration files...`);let T=0,R=0;for(let _ of M){let X=_;if(q.outdir){let C=J(Z,_);X=A(N(q.outdir),C);let w=$(X);if(!j(w))B(w,{recursive:!0});G(_,X)}let F=await Q(X,{removeUnusedImports:q.removeUnusedImports??!0,deduplicateDeclarations:q.deduplicate??!0,mergeInterfaces:q.mergeInterfaces??!0,inlineSimpleTypes:q.inlineTypes??!1,removeEmptyInterfaces:q.removeEmpty??!0,sortDeclarations:q.sort??!1,sortImports:q.sortImports??!0,minify:q.minify??!1,removeComments:q.removeComments??!1});R+=F.originalSize,T+=F.savings;let D=J(Z,X);console.log(` ${D}: ${F.originalSize}B -> ${F.optimizedSize}B (-${F.savingsPercent}%)`)}let I=R>0?Math.round(T/R*100):0;console.log(` Total: ${R}B -> ${R-T}B (-${I}%)`)}catch(Q){console.error("Error optimizing files:",Q),V.exit(1)}});k.command("docs","Generate API documentation from source files").option("--root <path>","Root directory to scan for source files",{default:"./src"}).option("--outdir <path>","Output directory for documentation",{default:"./docs"}).option("--format <format>","Output format: markdown or html",{default:"markdown"}).option("--title <title>","Documentation title",{default:"API Documentation"}).option("--include-private","Include private members (prefixed with _)",{default:!1}).option("--include-internal","Include internal members (@internal)",{default:!1}).option("--group-by-category","Group entries by @category tag",{default:!1}).option("--source-url <url>","Base URL for source links").example("dtsx docs").example("dtsx docs --format html --outdir ./api-docs").example('dtsx docs --group-by-category --title "My API"').action(async(q)=>{try{let{generateDocs:Q}=await import("../src/docs.js"),{Glob:K}=awaitPromise.resolve(globalThis.Bun),{resolve:N}=await import("path"),A=N(q.root||"./src"),J=new K("**/*.ts"),$=[];for await(let z of J.scan({cwd:A,absolute:!0,onlyFiles:!0}))if(!z.endsWith(".d.ts")&&!z.includes("node_modules"))$.push(z);if($.length===0)console.error("No TypeScript files found"),V.exit(1);console.log(`Found ${$.length} source files`),await Q($,{format:q.format||"markdown",outdir:N(q.outdir||"./docs"),title:q.title||"API Documentation",includePrivate:q.includePrivate??!1,includeInternal:q.includeInternal??!1,groupByCategory:q.groupByCategory??!1,includeSourceLinks:!!q.sourceUrl,sourceBaseUrl:q.sourceUrl})}catch(Q){console.error("Error generating documentation:",Q),V.exit(1)}});k.command("workspace","Generate declarations for all projects in a monorepo/workspace").option("--cwd <path>","Workspace root directory",{default:V.cwd()}).option("--parallel","Process projects in parallel",{default:!1}).option("--continue-on-error","Continue if a project fails",{default:!0}).option("--log-level <level>","Log level (debug, info, warn, error, silent)",{default:"info"}).example("dtsx workspace").example("dtsx workspace --cwd /path/to/monorepo").action(async(q)=>{try{let{generateMonorepo:Q,generateFromPackageWorkspaces:K}=await import("../src/workspace.js"),{existsSync:N}=await import("fs"),{join:A,resolve:J}=await import("path"),$=J(q.cwd||V.cwd()),z=A($,"tsconfig.json"),B;if(N(z))B=await Q($,{logLevel:q.logLevel||"info",continueOnError:q.continueOnError??!0});else B=await K($,{logLevel:q.logLevel||"info",continueOnError:q.continueOnError??!0});if(!B.success)V.exit(1)}catch(Q){console.error("Error generating workspace declarations:",Q),V.exit(1)}});k.command("lsp","Start the Language Server Protocol server for IDE integration").example("dtsx lsp").action(async()=>{let{startLSPServer:q}=await import("../src/lsp.js");q()});k.command("check","Type check TypeScript files or validate generated declarations").option("--files <patterns>","Glob patterns for files to check",{default:"**/*.ts",type:[String]}).option("--declarations-only","Only check .d.ts files",{default:!1}).option("--tsconfig <path>","Path to tsconfig.json",{default:"tsconfig.json"}).option("--strict","Enable strict type checking",{default:!1}).option("--skip-lib-check","Skip checking library definitions",{default:!0}).option("--warnings-as-errors","Treat warnings as errors",{default:!1}).option("--max-errors <number>","Maximum errors before stopping",{default:0}).option("--isolated-declarations","Check if code follows isolated declarations best practices (recommended)",{default:!1}).option("--format <format>","Output format: text or json",{default:"text"}).example("dtsx check").example('dtsx check --files "src/**/*.ts" --strict').example('dtsx check --declarations-only --files "dist/**/*.d.ts"').example("dtsx check --isolated-declarations").action(async(q)=>{try{let{typeCheck:Q,checkIsolatedDeclarations:K,formatTypeCheckResults:N}=await import("../chunk-858n9dme.js"),{Glob:A}=awaitPromise.resolve(globalThis.Bun),{resolve:J,relative:$}=await import("path"),z=V.cwd(),B=q.files||["**/*.ts"],G=[];for(let Z of B){let E=new A(Z);for await(let M of E.scan({cwd:z,absolute:!0,onlyFiles:!0}))if(!M.includes("node_modules"))if(q.declarationsOnly){if(M.endsWith(".d.ts"))G.push(M)}else G.push(M)}if(G.length===0)console.error("No files found to check"),V.exit(1);if(q.isolatedDeclarations){console.log(`Checking ${G.length} files for isolated declarations best practices...`);let Z=await K(G,q.tsconfig?J(q.tsconfig):void 0),E=0,M=[];for(let[T,R]of Z){let I=$(z,T);if(!R.compatible)if(E+=R.issues.length,q.format==="json")M.push({file:I,compatible:!1,issues:R.issues});else{console.log(` \u2717 ${I}`);for(let _ of R.issues)if(console.log(` ${_.line}:${_.column} - ${_.message}`),_.missingAnnotation)console.log(` Missing: ${_.missingAnnotation} type annotation`)}else if(q.format==="json")M.push({file:I,compatible:!0,issues:[]})}if(q.format==="json")console.log(JSON.stringify(M,null,2));else if(E>0)console.log(` ${G.length} files checked, ${E} recommendations found`),console.log("Tip: Adding explicit type annotations improves .d.ts accuracy");else console.log(` ${G.length} files checked, all follow isolated declarations best practices`);V.exit(E>0?1:0)}console.log(`Type checking ${G.length} files...`);let j=await Q(G,{tsconfigPath:q.tsconfig?J(q.tsconfig):void 0,strict:q.strict??!1,declarationsOnly:q.declarationsOnly??!1,skipLibCheck:q.skipLibCheck??!0,warningsAsErrors:q.warningsAsErrors??!1,maxErrors:q.maxErrors||void 0});if(q.format==="json")console.log(JSON.stringify(j,null,2));else console.log(N(j));V.exit(j.success?0:1)}catch(Q){console.error("Error during type checking:",Q),V.exit(1)}});k.command("convert","Convert TypeScript types to different schema formats").option("--files <patterns>","Glob patterns for TypeScript files",{default:"**/*.ts",type:[String]}).option("--format <format>","Output format: json-schema, zod, valibot, io-ts, yup, arktype",{default:"json-schema"}).option("--outdir <path>","Output directory for converted files",{default:"./schemas"}).option("--include-descriptions","Include JSDoc descriptions in output",{default:!0}).option("--all-optional","Make all properties optional",{default:!1}).option("--use-infer","Include inferred types (for Zod, Valibot, etc.)",{default:!0}).option("--json-schema-draft <version>","JSON Schema draft version: 2020-12, 2019-09, draft-07",{default:"2020-12"}).example("dtsx convert --format zod").example('dtsx convert --format json-schema --files "src/types/**/*.ts"').example("dtsx convert --format valibot --outdir ./validation").action(async(q)=>{try{let Q=await import("../src/formats.js"),{extractDeclarations:K}=await import("../src/extractor.js"),{Glob:N}=awaitPromise.resolve(globalThis.Bun),{resolve:A,relative:J,join:$,dirname:z,basename:B}=await import("path"),{mkdirSync:G,existsSync:j,readFileSync:Z,writeFileSync:E}=await import("fs"),M=V.cwd(),T=q.files||["**/*.ts"],R=q.format||"json-schema",I=A(q.outdir||"./schemas"),_=[];for(let D of T){let C=new N(D);for await(let w of C.scan({cwd:M,absolute:!0,onlyFiles:!0}))if(!w.endsWith(".d.ts")&&!w.includes("node_modules"))_.push(w)}if(_.length===0)console.error("No TypeScript files found"),V.exit(1);if(console.log(`Converting ${_.length} files to ${R} format...`),!j(I))G(I,{recursive:!0});let X=0,F=0;for(let D of _){let C=Z(D,"utf-8"),U=K(C,D).filter((d)=>d.kind==="interface"||d.kind==="type");if(U.length===0)continue;let L=Q.convertToFormat(U,{format:R,includeDescriptions:q.includeDescriptions??!0,allOptional:q.allOptional??!1,useInfer:q.useInfer??!0,jsonSchemaDraft:q.jsonSchemaDraft||"2020-12"}),a=J(M,D),l=B(D,".ts"),p=Q.getFormatExtension(R),O=$(I,z(a),`${l}${p}`),u=z(O);if(!j(u))G(u,{recursive:!0});E(O,L),X+=U.length,F++,console.log(` ${J(M,O)} (${U.length} types)`)}console.log(` Converted ${X} declarations from ${F} files`)}catch(Q){console.error("Error converting files:",Q),V.exit(1)}});k.command("circular","Detect circular dependencies in TypeScript files").option("--files <patterns>","Glob patterns for files to check",{default:"**/*.ts",type:[String]}).option("--root <path>","Root directory for resolution",{default:"."}).option("--ignore <patterns>","Glob patterns to ignore (comma-separated)",{default:"",type:[String]}).option("--types-only","Only report type-level cycles",{default:!1}).option("--max-depth <number>","Maximum depth for cycle detection",{default:100}).option("--include-node-modules","Include node_modules in analysis",{default:!1}).option("--format <format>","Output format: text, json, dot",{default:"text"}).option("--summary","Show graph summary statistics",{default:!1}).example("dtsx circular").example('dtsx circular --files "src/**/*.ts"').example('dtsx circular --ignore "**/*.test.ts,**/__tests__/**"').example("dtsx circular --format dot > deps.dot").example("dtsx circular --summary").action(async(q)=>{try{let{analyzeCircularDependencies:Q,formatCircularAnalysis:K,getGraphSummary:N,exportGraphAsDot:A,exportGraphAsJson:J}=await import("../src/circular.js"),{Glob:$}=awaitPromise.resolve(globalThis.Bun),{resolve:z,relative:B}=await import("path"),G=V.cwd(),j=z(q.root||"."),Z=q.files||["**/*.ts"],E=[];for(let T of Z){let R=new $(T);for await(let I of R.scan({cwd:j,absolute:!0,onlyFiles:!0}))if(!I.endsWith(".d.ts")){if(!q.includeNodeModules&&I.includes("node_modules"))continue;E.push(I)}}if(E.length===0)console.error("No TypeScript files found"),V.exit(1);console.log(`Analyzing ${E.length} files for circular dependencies...`);let M=await Q(E,{rootDir:j,ignore:q.ignore?.filter(Boolean),typesOnly:q.typesOnly??!1,maxDepth:q.maxDepth??100,includeNodeModules:q.includeNodeModules??!1});if(q.format==="json")console.log(J(M.graph,j));else if(q.format==="dot")console.log(A(M.graph,j));else if(console.log(K(M,j)),q.summary){let T=N(M.graph);if(console.log(` --- Dependency Graph Summary ---`),console.log(`Total files: ${T.totalFiles}`),console.log(`Total dependencies: ${T.totalDependencies}`),console.log(`Average dependencies per file: ${T.avgDependencies.toFixed(2)}`),T.maxDependencies.count>0)console.log(`Most dependencies: ${B(j,T.maxDependencies.file)} (${T.maxDependencies.count})`);if(T.mostDepended.count>0)console.log(`Most depended on: ${B(j,T.mostDepended.file)} (${T.mostDepended.count} dependents)`);if(T.isolatedFiles.length>0)console.log(`Isolated files (no dependencies): ${T.isolatedFiles.length}`)}V.exit(M.hasCircular?1:0)}catch(Q){console.error("Error analyzing dependencies:",Q),V.exit(1)}});k.command("version","Show the version of dtsx").action(()=>{console.log(e)});k.version(e);k.help();k.parse();