@m4x_7/type-debt 1.0.2 → 1.0.4
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 +6 -6
- package/index.ts +66 -66
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var X=Object.defineProperty;var P=Object.getOwnPropertySymbols;var Z=Object.prototype.hasOwnProperty,V=Object.prototype.propertyIsEnumerable;var A=(t,e,s)=>e in t?X(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,w=(t,e)=>{for(var s in e||(e={}))Z.call(e,s)&&A(t,s,e[s]);if(P)for(var s of P(e))V.call(e,s)&&A(t,s,e[s]);return t};var c=(t,e,s)=>A(t,typeof e!="symbol"?e+"":e,s);var S=(t,e,s)=>new Promise((r,i)=>{var o=u=>{try{n(s.next(u))}catch(h){i(h)}},l=u=>{try{n(s.throw(u))}catch(h){i(h)}},n=u=>u.done?r(u.value):Promise.resolve(u.value).then(o,l);n((s=s.apply(t,e)).next())});import{createRequire as J}from"module";import{basename as tt,dirname as k,normalize as et,relative as st,resolve as rt,sep as I}from"path";import*as it from"fs";var Vt={};var _=J(Vt.url);function nt(t){let e=et(t);return e.length>1&&e[e.length-1]===I&&(e=e.substring(0,e.length-1)),e}var ot=/[\\/]/g;function R(t,e){return t.replace(ot,e)}var lt=/^[a-z]:[\\/]$/i;function ut(t){return t==="/"||lt.test(t)}function F(t,e){let{resolvePaths:s,normalizePath:r,pathSeparator:i}=e,o=process.platform==="win32"&&t.includes("/")||t.startsWith(".");if(s&&(t=rt(t)),(r||o)&&(t=nt(t)),t===".")return"";let l=t[t.length-1]!==i;return R(l?t+i:t,i)}function C(t,e){return e+t}function ct(t,e){return function(s,r){return r.startsWith(t)?r.slice(t.length)+s:R(st(t,r),e.pathSeparator)+e.pathSeparator+s}}function at(t){return t}function ht(t,e,s){return e+t+s}function pt(t,e){let{relativePaths:s,includeBasePath:r}=e;return s&&t?ct(t,e):r?C:at}function ft(t){return function(e,s){s.push(e.substring(t.length)||".")}}function yt(t){return function(e,s,r){let i=e.substring(t.length)||".";r.every(o=>o(i,!0))&&s.push(i)}}var mt=(t,e)=>{e.push(t||".")},gt=(t,e,s)=>{let r=t||".";s.every(i=>i(r,!0))&&e.push(r)},dt=()=>{};function St(t,e){let{includeDirs:s,filters:r,relativePaths:i}=e;return s?i?r&&r.length?yt(t):ft(t):r&&r.length?gt:mt:dt}var wt=(t,e,s,r)=>{r.every(i=>i(t,!1))&&s.files++},Tt=(t,e,s,r)=>{r.every(i=>i(t,!1))&&e.push(t)},Et=(t,e,s,r)=>{s.files++},bt=(t,e)=>{e.push(t)},xt=()=>{};function At(t){let{excludeFiles:e,filters:s,onlyCounts:r}=t;return e?xt:s&&s.length?r?wt:Tt:r?Et:bt}var Ft=t=>t,kt=()=>[""].slice(0,0);function Dt(t){return t.group?kt:Ft}var Pt=(t,e,s)=>{t.push({directory:e,files:s,dir:e})},_t=()=>{};function vt(t){return t.group?Pt:_t}var It=function(t,e,s){let{queue:r,fs:i,options:{suppressErrors:o}}=e;r.enqueue(),i.realpath(t,(l,n)=>{if(l)return r.dequeue(o?null:l,e);i.stat(n,(u,h)=>{if(u)return r.dequeue(o?null:u,e);if(h.isDirectory()&&N(t,n,e))return r.dequeue(null,e);s(h,n),r.dequeue(null,e)})})},Rt=function(t,e,s){let{queue:r,fs:i,options:{suppressErrors:o}}=e;r.enqueue();try{let l=i.realpathSync(t),n=i.statSync(l);if(n.isDirectory()&&N(t,l,e))return;s(n,l)}catch(l){if(!o)throw l}};function Ct(t,e){return!t.resolveSymlinks||t.excludeSymlinks?null:e?Rt:It}function N(t,e,s){if(s.options.useRealPaths)return Nt(e,s);let r=k(t),i=1;for(;r!==s.root&&i<2;){let o=s.symlinks.get(r);!!o&&(o===e||o.startsWith(e)||e.startsWith(o))?i++:r=k(r)}return s.symlinks.set(t,e),i>1}function Nt(t,e){return e.visited.includes(t+e.options.pathSeparator)}var Mt=t=>t.counts,Wt=t=>t.groups,$t=t=>t.paths,Ot=t=>t.paths.slice(0,t.options.maxFiles),qt=(t,e,s)=>(T(e,s,t.counts,t.options.suppressErrors),null),Kt=(t,e,s)=>(T(e,s,t.paths,t.options.suppressErrors),null),Gt=(t,e,s)=>(T(e,s,t.paths.slice(0,t.options.maxFiles),t.options.suppressErrors),null),Bt=(t,e,s)=>(T(e,s,t.groups,t.options.suppressErrors),null);function T(t,e,s,r){e(t&&!r?t:null,s)}function Ht(t,e){let{onlyCounts:s,group:r,maxFiles:i}=t;return s?e?Mt:qt:r?e?Wt:Bt:i?e?Ot:Gt:e?$t:Kt}var M={withFileTypes:!0},jt=(t,e,s,r,i)=>{if(t.queue.enqueue(),r<0)return t.queue.dequeue(null,t);let{fs:o}=t;t.visited.push(e),t.counts.directories++,o.readdir(e||".",M,(l,n=[])=>{i(n,s,r),t.queue.dequeue(t.options.suppressErrors?null:l,t)})},Lt=(t,e,s,r,i)=>{let{fs:o}=t;if(r<0)return;t.visited.push(e),t.counts.directories++;let l=[];try{l=o.readdirSync(e||".",M)}catch(n){if(!t.options.suppressErrors)throw n}i(l,s,r)};function Yt(t){return t?Lt:jt}var Ut=class{constructor(t){c(this,"count",0);this.onQueueEmpty=t}enqueue(){return this.count++,this.count}dequeue(t,e){this.onQueueEmpty&&(--this.count<=0||t)&&(this.onQueueEmpty(t,e),t&&(e.controller.abort(),this.onQueueEmpty=void 0))}},zt=class{constructor(){c(this,"_files",0);c(this,"_directories",0)}set files(t){this._files=t}get files(){return this._files}set directories(t){this._directories=t}get directories(){return this._directories}get dirs(){return this._directories}},Qt=class{constructor(){c(this,"aborted",!1)}abort(){this.aborted=!0}},W=class{constructor(t,e,s){c(this,"root");c(this,"isSynchronous");c(this,"state");c(this,"joinPath");c(this,"pushDirectory");c(this,"pushFile");c(this,"getArray");c(this,"groupFiles");c(this,"resolveSymlink");c(this,"walkDirectory");c(this,"callbackInvoker");c(this,"walk",(t,e,s)=>{let{paths:r,options:{filters:i,resolveSymlinks:o,excludeSymlinks:l,exclude:n,maxFiles:u,signal:h,useRealPaths:p,pathSeparator:f},controller:E}=this.state;if(E.aborted||h&&h.aborted||u&&r.length>u)return;let b=this.getArray(this.state.paths);for(let x=0;x<t.length;++x){let g=t[x];if(g.isFile()||g.isSymbolicLink()&&!o&&!l){let y=this.joinPath(g.name,e);this.pushFile(y,b,this.state.counts,i)}else if(g.isDirectory()){let y=ht(g.name,e,this.state.options.pathSeparator);if(n&&n(g.name,y))continue;this.pushDirectory(y,r,i),this.walkDirectory(this.state,y,y,s-1,this.walk)}else if(this.resolveSymlink&&g.isSymbolicLink()){let y=C(g.name,e);this.resolveSymlink(y,this.state,(U,m)=>{if(U.isDirectory()){if(m=F(m,this.state.options),n&&n(g.name,p?m:y+f))return;this.walkDirectory(this.state,m,p?m:y+f,s-1,this.walk)}else{m=p?m:y;let z=tt(m),Q=F(k(m),this.state.options);m=this.joinPath(z,Q),this.pushFile(m,b,this.state.counts,i)}})}}this.groupFiles(this.state.groups,e,b)});this.isSynchronous=!s,this.callbackInvoker=Ht(e,this.isSynchronous),this.root=F(t,e),this.state={root:ut(this.root)?this.root:this.root.slice(0,-1),paths:[""].slice(0,0),groups:[],counts:new zt,options:e,queue:new Ut((r,i)=>this.callbackInvoker(i,r,s)),symlinks:new Map,visited:[""].slice(0,0),controller:new Qt,fs:e.fs||it},this.joinPath=pt(this.root,e),this.pushDirectory=St(this.root,e),this.pushFile=At(e),this.getArray=Dt(e),this.groupFiles=vt(e),this.resolveSymlink=Ct(e,this.isSynchronous),this.walkDirectory=Yt(this.isSynchronous)}start(){return this.pushDirectory(this.root,this.state.paths,this.state.options.filters),this.walkDirectory(this.state,this.root,this.root,this.state.options.maxDepth,this.walk),this.isSynchronous?this.callbackInvoker(this.state,null):null}};function Xt(t,e){return new Promise((s,r)=>{$(t,e,(i,o)=>{if(i)return r(i);s(o)})})}function $(t,e,s){new W(t,e,s).start()}function Zt(t,e){return new W(t,e).start()}var v=class{constructor(t,e){this.root=t,this.options=e}withPromise(){return Xt(this.root,this.options)}withCallback(t){$(this.root,this.options,t)}sync(){return Zt(this.root,this.options)}},O=null;try{_.resolve("picomatch"),O=_("picomatch")}catch(t){}var q=class{constructor(t){c(this,"globCache",{});c(this,"options",{maxDepth:1/0,suppressErrors:!0,pathSeparator:I,filters:[]});c(this,"globFunction");this.options=w(w({},this.options),t),this.globFunction=this.options.globFunction}group(){return this.options.group=!0,this}withPathSeparator(t){return this.options.pathSeparator=t,this}withBasePath(){return this.options.includeBasePath=!0,this}withRelativePaths(){return this.options.relativePaths=!0,this}withDirs(){return this.options.includeDirs=!0,this}withMaxDepth(t){return this.options.maxDepth=t,this}withMaxFiles(t){return this.options.maxFiles=t,this}withFullPaths(){return this.options.resolvePaths=!0,this.options.includeBasePath=!0,this}withErrors(){return this.options.suppressErrors=!1,this}withSymlinks({resolvePaths:t=!0}={}){return this.options.resolveSymlinks=!0,this.options.useRealPaths=t,this.withFullPaths()}withAbortSignal(t){return this.options.signal=t,this}normalize(){return this.options.normalizePath=!0,this}filter(t){return this.options.filters.push(t),this}onlyDirs(){return this.options.excludeFiles=!0,this.options.includeDirs=!0,this}exclude(t){return this.options.exclude=t,this}onlyCounts(){return this.options.onlyCounts=!0,this}crawl(t){return new v(t||".",this.options)}withGlobFunction(t){return this.globFunction=t,this}crawlWithOptions(t,e){return this.options=w(w({},this.options),e),new v(t||".",this.options)}glob(...t){return this.globFunction?this.globWithOptions(t):this.globWithOptions(t,{dot:!0})}globWithOptions(t,...e){let s=this.globFunction||O;if(!s)throw new Error("Please specify a glob function to use glob matching.");var r=this.globCache[t.join("\0")];return r||(r=s(t,...e),this.globCache[t.join("\0")]=r),this.options.filters.push(i=>r(i)),this}};import{stat as Jt}from"fs/promises";function K(t){return new q().withFullPaths().exclude(s=>s==="node_modules"||s==="dist"||s==="build"||s===".git").filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).crawl(t).sync()}function G(t,e){let s=[];for(let r=0;r<t.length;r+=e)s.push(t.slice(r,r+e));return s}function B(t){return S(this,null,function*(){let e;try{e=yield Jt(t)}catch(s){throw new Error(`Directory "${t}" does not exist.`)}if(!e.isDirectory())throw new Error(`"${t}" is not a directory.`)})}import{Project as ie}from"ts-morph";import{SyntaxKind as a}from"ts-morph";var d={CHUNK_SIZE:50,TYPE_DEBT_METRICS:{EXPLICIT_ANY_WEIGHT:2,IMPLICIT_ANY_WEIGHT:3,AS_ANY_WEIGHT:2,SUPPRESSION_WEIGHT:4,NON_NULL_ASSERTION_WEIGHT:1}};var te=/(?:\/\/|\/\*)\s*@ts-(ignore|expect-error|nocheck)/g;function H(t){let e={explicitAny:0,implicitAny:0,asAny:0,suppressions:0,nonNullAssertions:0,validTypes:0,score:0};t.forEachDescendant(i=>{var l;let o=i.getKind();if(o===a.AnyKeyword){let n=i.getParent();(n==null?void 0:n.getKind())!==a.AsExpression&&e.explicitAny++}else o===a.AsExpression&&((l=i.asKindOrThrow(a.AsExpression).getTypeNode())==null?void 0:l.getKind())===a.AnyKeyword&&e.asAny++;if(o===a.Parameter){let n=i.asKindOrThrow(a.Parameter);if(!n.getTypeNode()&&!n.getInitializer()){let u=n.getParent(),h=u==null?void 0:u.getParent();((u==null?void 0:u.getKind())===a.ArrowFunction||(u==null?void 0:u.getKind())===a.FunctionExpression)&&(h==null?void 0:h.getKind())===a.CallExpression||e.implicitAny++}}o===a.NonNullExpression?e.nonNullAssertions++:re(o)&&e.validTypes++});let r=t.getFullText().match(te);return e.suppressions=r?r.length:0,e.score=ee(e),e}function ee(t){let e=t.explicitAny+t.implicitAny+t.asAny+t.suppressions+t.nonNullAssertions,s=t.validTypes+e;if(s==0)return 100;{let r=t.validTypes/s*100,o=se(t)/s*100;return Math.max(0,Math.round(r-o))}}function se(t){return t.explicitAny*d.TYPE_DEBT_METRICS.EXPLICIT_ANY_WEIGHT+t.implicitAny*d.TYPE_DEBT_METRICS.IMPLICIT_ANY_WEIGHT+t.asAny*d.TYPE_DEBT_METRICS.AS_ANY_WEIGHT+t.nonNullAssertions*d.TYPE_DEBT_METRICS.NON_NULL_ASSERTION_WEIGHT+t.suppressions*d.TYPE_DEBT_METRICS.SUPPRESSION_WEIGHT}function re(t){return t===a.TypeReference||t===a.StringKeyword||t===a.NumberKeyword||t===a.BooleanKeyword||t===a.InterfaceDeclaration||t===a.TypeAliasDeclaration}function j(t){let e=new ie({skipAddingFilesFromTsConfig:!0});e.addSourceFilesAtPaths(t);let s=[];e.forgetNodesCreatedInBlock(()=>{for(let r of e.getSourceFiles())s.push({filePath:r.getFilePath(),typeDebtMetrics:H(r)})});for(let r of e.getSourceFiles())e.removeSourceFile(r);return s}import{promises as ne}from"fs";import L from"path";function Y(t,e,s="type-debt-report.md"){return S(this,null,function*(){if(t.length===0)return;let r=t.length,i=t.reduce((p,f)=>p+f.typeDebtMetrics.score,0),o=Math.round(i/r),l=[...t].sort((p,f)=>p.typeDebtMetrics.score-f.typeDebtMetrics.score),n=`Type Debt Report
|
|
2
|
+
var V=Object.defineProperty;var v=Object.getOwnPropertySymbols;var J=Object.prototype.hasOwnProperty,tt=Object.prototype.propertyIsEnumerable;var k=(t,e,s)=>e in t?V(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s,E=(t,e)=>{for(var s in e||(e={}))J.call(e,s)&&k(t,s,e[s]);if(v)for(var s of v(e))tt.call(e,s)&&k(t,s,e[s]);return t};var c=(t,e,s)=>k(t,typeof e!="symbol"?e+"":e,s);var S=(t,e,s)=>new Promise((r,i)=>{var o=u=>{try{n(s.next(u))}catch(h){i(h)}},l=u=>{try{n(s.throw(u))}catch(h){i(h)}},n=u=>u.done?r(u.value):Promise.resolve(u.value).then(o,l);n((s=s.apply(t,e)).next())});import{createRequire as et}from"module";import{basename as st,dirname as P,normalize as rt,relative as it,resolve as nt,sep as C}from"path";import*as ot from"fs";var te={};var I=et(te.url);function lt(t){let e=rt(t);return e.length>1&&e[e.length-1]===C&&(e=e.substring(0,e.length-1)),e}var ut=/[\\/]/g;function N(t,e){return t.replace(ut,e)}var ct=/^[a-z]:[\\/]$/i;function at(t){return t==="/"||ct.test(t)}function D(t,e){let{resolvePaths:s,normalizePath:r,pathSeparator:i}=e,o=process.platform==="win32"&&t.includes("/")||t.startsWith(".");if(s&&(t=nt(t)),(r||o)&&(t=lt(t)),t===".")return"";let l=t[t.length-1]!==i;return N(l?t+i:t,i)}function M(t,e){return e+t}function ht(t,e){return function(s,r){return r.startsWith(t)?r.slice(t.length)+s:N(it(t,r),e.pathSeparator)+e.pathSeparator+s}}function pt(t){return t}function ft(t,e,s){return e+t+s}function yt(t,e){let{relativePaths:s,includeBasePath:r}=e;return s&&t?ht(t,e):r?M:pt}function mt(t){return function(e,s){s.push(e.substring(t.length)||".")}}function gt(t){return function(e,s,r){let i=e.substring(t.length)||".";r.every(o=>o(i,!0))&&s.push(i)}}var dt=(t,e)=>{e.push(t||".")},St=(t,e,s)=>{let r=t||".";s.every(i=>i(r,!0))&&e.push(r)},wt=()=>{};function Tt(t,e){let{includeDirs:s,filters:r,relativePaths:i}=e;return s?i?r&&r.length?gt(t):mt(t):r&&r.length?St:dt:wt}var Et=(t,e,s,r)=>{r.every(i=>i(t,!1))&&s.files++},bt=(t,e,s,r)=>{r.every(i=>i(t,!1))&&e.push(t)},xt=(t,e,s,r)=>{s.files++},At=(t,e)=>{e.push(t)},Ft=()=>{};function kt(t){let{excludeFiles:e,filters:s,onlyCounts:r}=t;return e?Ft:s&&s.length?r?Et:bt:r?xt:At}var Dt=t=>t,Pt=()=>[""].slice(0,0);function _t(t){return t.group?Pt:Dt}var vt=(t,e,s)=>{t.push({directory:e,files:s,dir:e})},It=()=>{};function Rt(t){return t.group?vt:It}var Ct=function(t,e,s){let{queue:r,fs:i,options:{suppressErrors:o}}=e;r.enqueue(),i.realpath(t,(l,n)=>{if(l)return r.dequeue(o?null:l,e);i.stat(n,(u,h)=>{if(u)return r.dequeue(o?null:u,e);if(h.isDirectory()&&W(t,n,e))return r.dequeue(null,e);s(h,n),r.dequeue(null,e)})})},Nt=function(t,e,s){let{queue:r,fs:i,options:{suppressErrors:o}}=e;r.enqueue();try{let l=i.realpathSync(t),n=i.statSync(l);if(n.isDirectory()&&W(t,l,e))return;s(n,l)}catch(l){if(!o)throw l}};function Mt(t,e){return!t.resolveSymlinks||t.excludeSymlinks?null:e?Nt:Ct}function W(t,e,s){if(s.options.useRealPaths)return Wt(e,s);let r=P(t),i=1;for(;r!==s.root&&i<2;){let o=s.symlinks.get(r);!!o&&(o===e||o.startsWith(e)||e.startsWith(o))?i++:r=P(r)}return s.symlinks.set(t,e),i>1}function Wt(t,e){return e.visited.includes(t+e.options.pathSeparator)}var $t=t=>t.counts,Ot=t=>t.groups,qt=t=>t.paths,Kt=t=>t.paths.slice(0,t.options.maxFiles),Gt=(t,e,s)=>(b(e,s,t.counts,t.options.suppressErrors),null),Bt=(t,e,s)=>(b(e,s,t.paths,t.options.suppressErrors),null),Ht=(t,e,s)=>(b(e,s,t.paths.slice(0,t.options.maxFiles),t.options.suppressErrors),null),jt=(t,e,s)=>(b(e,s,t.groups,t.options.suppressErrors),null);function b(t,e,s,r){e(t&&!r?t:null,s)}function Lt(t,e){let{onlyCounts:s,group:r,maxFiles:i}=t;return s?e?$t:Gt:r?e?Ot:jt:i?e?Kt:Ht:e?qt:Bt}var $={withFileTypes:!0},Yt=(t,e,s,r,i)=>{if(t.queue.enqueue(),r<0)return t.queue.dequeue(null,t);let{fs:o}=t;t.visited.push(e),t.counts.directories++,o.readdir(e||".",$,(l,n=[])=>{i(n,s,r),t.queue.dequeue(t.options.suppressErrors?null:l,t)})},Ut=(t,e,s,r,i)=>{let{fs:o}=t;if(r<0)return;t.visited.push(e),t.counts.directories++;let l=[];try{l=o.readdirSync(e||".",$)}catch(n){if(!t.options.suppressErrors)throw n}i(l,s,r)};function zt(t){return t?Ut:Yt}var Qt=class{constructor(t){c(this,"count",0);this.onQueueEmpty=t}enqueue(){return this.count++,this.count}dequeue(t,e){this.onQueueEmpty&&(--this.count<=0||t)&&(this.onQueueEmpty(t,e),t&&(e.controller.abort(),this.onQueueEmpty=void 0))}},Xt=class{constructor(){c(this,"_files",0);c(this,"_directories",0)}set files(t){this._files=t}get files(){return this._files}set directories(t){this._directories=t}get directories(){return this._directories}get dirs(){return this._directories}},Zt=class{constructor(){c(this,"aborted",!1)}abort(){this.aborted=!0}},O=class{constructor(t,e,s){c(this,"root");c(this,"isSynchronous");c(this,"state");c(this,"joinPath");c(this,"pushDirectory");c(this,"pushFile");c(this,"getArray");c(this,"groupFiles");c(this,"resolveSymlink");c(this,"walkDirectory");c(this,"callbackInvoker");c(this,"walk",(t,e,s)=>{let{paths:r,options:{filters:i,resolveSymlinks:o,excludeSymlinks:l,exclude:n,maxFiles:u,signal:h,useRealPaths:p,pathSeparator:f},controller:x}=this.state;if(x.aborted||h&&h.aborted||u&&r.length>u)return;let A=this.getArray(this.state.paths);for(let F=0;F<t.length;++F){let g=t[F];if(g.isFile()||g.isSymbolicLink()&&!o&&!l){let y=this.joinPath(g.name,e);this.pushFile(y,A,this.state.counts,i)}else if(g.isDirectory()){let y=ft(g.name,e,this.state.options.pathSeparator);if(n&&n(g.name,y))continue;this.pushDirectory(y,r,i),this.walkDirectory(this.state,y,y,s-1,this.walk)}else if(this.resolveSymlink&&g.isSymbolicLink()){let y=M(g.name,e);this.resolveSymlink(y,this.state,(Q,m)=>{if(Q.isDirectory()){if(m=D(m,this.state.options),n&&n(g.name,p?m:y+f))return;this.walkDirectory(this.state,m,p?m:y+f,s-1,this.walk)}else{m=p?m:y;let X=st(m),Z=D(P(m),this.state.options);m=this.joinPath(X,Z),this.pushFile(m,A,this.state.counts,i)}})}}this.groupFiles(this.state.groups,e,A)});this.isSynchronous=!s,this.callbackInvoker=Lt(e,this.isSynchronous),this.root=D(t,e),this.state={root:at(this.root)?this.root:this.root.slice(0,-1),paths:[""].slice(0,0),groups:[],counts:new Xt,options:e,queue:new Qt((r,i)=>this.callbackInvoker(i,r,s)),symlinks:new Map,visited:[""].slice(0,0),controller:new Zt,fs:e.fs||ot},this.joinPath=yt(this.root,e),this.pushDirectory=Tt(this.root,e),this.pushFile=kt(e),this.getArray=_t(e),this.groupFiles=Rt(e),this.resolveSymlink=Mt(e,this.isSynchronous),this.walkDirectory=zt(this.isSynchronous)}start(){return this.pushDirectory(this.root,this.state.paths,this.state.options.filters),this.walkDirectory(this.state,this.root,this.root,this.state.options.maxDepth,this.walk),this.isSynchronous?this.callbackInvoker(this.state,null):null}};function Vt(t,e){return new Promise((s,r)=>{q(t,e,(i,o)=>{if(i)return r(i);s(o)})})}function q(t,e,s){new O(t,e,s).start()}function Jt(t,e){return new O(t,e).start()}var R=class{constructor(t,e){this.root=t,this.options=e}withPromise(){return Vt(this.root,this.options)}withCallback(t){q(this.root,this.options,t)}sync(){return Jt(this.root,this.options)}},K=null;try{I.resolve("picomatch"),K=I("picomatch")}catch(t){}var G=class{constructor(t){c(this,"globCache",{});c(this,"options",{maxDepth:1/0,suppressErrors:!0,pathSeparator:C,filters:[]});c(this,"globFunction");this.options=E(E({},this.options),t),this.globFunction=this.options.globFunction}group(){return this.options.group=!0,this}withPathSeparator(t){return this.options.pathSeparator=t,this}withBasePath(){return this.options.includeBasePath=!0,this}withRelativePaths(){return this.options.relativePaths=!0,this}withDirs(){return this.options.includeDirs=!0,this}withMaxDepth(t){return this.options.maxDepth=t,this}withMaxFiles(t){return this.options.maxFiles=t,this}withFullPaths(){return this.options.resolvePaths=!0,this.options.includeBasePath=!0,this}withErrors(){return this.options.suppressErrors=!1,this}withSymlinks({resolvePaths:t=!0}={}){return this.options.resolveSymlinks=!0,this.options.useRealPaths=t,this.withFullPaths()}withAbortSignal(t){return this.options.signal=t,this}normalize(){return this.options.normalizePath=!0,this}filter(t){return this.options.filters.push(t),this}onlyDirs(){return this.options.excludeFiles=!0,this.options.includeDirs=!0,this}exclude(t){return this.options.exclude=t,this}onlyCounts(){return this.options.onlyCounts=!0,this}crawl(t){return new R(t||".",this.options)}withGlobFunction(t){return this.globFunction=t,this}crawlWithOptions(t,e){return this.options=E(E({},this.options),e),new R(t||".",this.options)}glob(...t){return this.globFunction?this.globWithOptions(t):this.globWithOptions(t,{dot:!0})}globWithOptions(t,...e){let s=this.globFunction||K;if(!s)throw new Error("Please specify a glob function to use glob matching.");var r=this.globCache[t.join("\0")];return r||(r=s(t,...e),this.globCache[t.join("\0")]=r),this.options.filters.push(i=>r(i)),this}};import{stat as ee}from"fs/promises";function B(t){return new G().withFullPaths().exclude(s=>s==="node_modules"||s==="dist"||s==="build"||s===".git").filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).crawl(t).sync()}function H(t,e){let s=[];for(let r=0;r<t.length;r+=e)s.push(t.slice(r,r+e));return s}function j(t){return S(this,null,function*(){let e;try{e=yield ee(t)}catch(s){throw new Error(`Directory "${t}" does not exist.`)}if(!e.isDirectory())throw new Error(`"${t}" is not a directory.`)})}import{Project as oe}from"ts-morph";import{SyntaxKind as a}from"ts-morph";var d={CHUNK_SIZE:50,TYPE_DEBT_METRICS:{EXPLICIT_ANY_WEIGHT:2,IMPLICIT_ANY_WEIGHT:3,AS_ANY_WEIGHT:2,SUPPRESSION_WEIGHT:4,NON_NULL_ASSERTION_WEIGHT:1}};var se=/(?:\/\/|\/\*)\s*@ts-(ignore|expect-error|nocheck)/g;function L(t){let e={explicitAny:0,implicitAny:0,asAny:0,suppressions:0,nonNullAssertions:0,validTypes:0,score:0};t.forEachDescendant(i=>{var l;let o=i.getKind();if(o===a.AnyKeyword){let n=i.getParent();(n==null?void 0:n.getKind())!==a.AsExpression&&e.explicitAny++}else o===a.AsExpression&&((l=i.asKindOrThrow(a.AsExpression).getTypeNode())==null?void 0:l.getKind())===a.AnyKeyword&&e.asAny++;if(o===a.Parameter){let n=i.asKindOrThrow(a.Parameter);if(!n.getTypeNode()&&!n.getInitializer()){let u=n.getParent(),h=u==null?void 0:u.getParent();((u==null?void 0:u.getKind())===a.ArrowFunction||(u==null?void 0:u.getKind())===a.FunctionExpression)&&(h==null?void 0:h.getKind())===a.CallExpression||e.implicitAny++}}o===a.NonNullExpression?e.nonNullAssertions++:ne(o)&&e.validTypes++});let r=t.getFullText().match(se);return e.suppressions=r?r.length:0,e.score=re(e),e}function re(t){let e=t.explicitAny+t.implicitAny+t.asAny+t.suppressions+t.nonNullAssertions,s=t.validTypes+e;if(s==0)return 100;{let r=t.validTypes/s*100,o=ie(t)/s*100;return Math.max(0,Math.round(r-o))}}function ie(t){return t.explicitAny*d.TYPE_DEBT_METRICS.EXPLICIT_ANY_WEIGHT+t.implicitAny*d.TYPE_DEBT_METRICS.IMPLICIT_ANY_WEIGHT+t.asAny*d.TYPE_DEBT_METRICS.AS_ANY_WEIGHT+t.nonNullAssertions*d.TYPE_DEBT_METRICS.NON_NULL_ASSERTION_WEIGHT+t.suppressions*d.TYPE_DEBT_METRICS.SUPPRESSION_WEIGHT}function ne(t){return t===a.TypeReference||t===a.StringKeyword||t===a.NumberKeyword||t===a.BooleanKeyword||t===a.InterfaceDeclaration||t===a.TypeAliasDeclaration}function Y(t){let e=new oe({skipAddingFilesFromTsConfig:!0});e.addSourceFilesAtPaths(t);let s=[];e.forgetNodesCreatedInBlock(()=>{for(let r of e.getSourceFiles())s.push({filePath:r.getFilePath(),typeDebtMetrics:L(r)})});for(let r of e.getSourceFiles())e.removeSourceFile(r);return s}import{promises as le}from"fs";import U from"path";function z(t,e,s="type-debt-report.md"){return S(this,null,function*(){if(t.length===0)return;let r=t.length,i=t.reduce((p,f)=>p+f.typeDebtMetrics.score,0),o=Math.round(i/r),l=[...t].sort((p,f)=>p.typeDebtMetrics.score-f.typeDebtMetrics.score),n=`Type Debt Report
|
|
3
3
|
|
|
4
4
|
`;n+=`> Generated on: ${new Date().toUTCString()}
|
|
5
5
|
|
|
@@ -10,13 +10,13 @@ var X=Object.defineProperty;var P=Object.getOwnPropertySymbols;var Z=Object.prot
|
|
|
10
10
|
`,n+=`## Top 10 Worst Offenders
|
|
11
11
|
|
|
12
12
|
`,n+="| Score | File Path | Suppressions | Implicit `any` | Explicit `any` | `as any` | Non-Null (`!`) |\n",n+=`| :---: | :--- | :---: | :---: | :---: | :---: | :---: |
|
|
13
|
-
`;let u=l.slice(0,10),h=
|
|
14
|
-
`}try{yield
|
|
13
|
+
`;let u=l.slice(0,10),h=U.resolve(e);for(let p of u){let f=p.typeDebtMetrics,x=U.relative(h,p.filePath);n+=`| ${f.score} | \`${x}\` | ${f.suppressions} | ${f.implicitAny} | ${f.explicitAny} | ${f.asAny} | ${f.nonNullAssertions} |
|
|
14
|
+
`}try{yield le.writeFile(s,n,"utf-8"),console.log(`
|
|
15
15
|
Markdown report successfully generated at: ${s}`)}catch(p){console.error(`
|
|
16
|
-
Failed to write Markdown report:`,p)}})}var
|
|
16
|
+
Failed to write Markdown report:`,p)}})}var _=process.argv.slice(2);(_.includes("--help")||_.includes("-h"))&&(ae(),process.exit(0));var ue=_[0]||".";ce(ue).catch(t=>{console.error(`
|
|
17
17
|
\x1B[31m Error: ${t.message}\x1B[0m
|
|
18
|
-
`),process.exit(1)});function
|
|
19
|
-
Scanning directory: ${t}`);let e=
|
|
18
|
+
`),process.exit(1)});function ce(t){return S(this,null,function*(){yield j(t),console.log(`
|
|
19
|
+
Scanning directory: ${t}`);let e=B(t);if(e.length===0)throw new Error("No TypeScript files found to process.");let s=H(e,d.CHUNK_SIZE),r=[];for(let[i,o]of s.entries()){let l=Y(o);r=r.concat(l),process.stdout.write(`\rProcessed chunk ${i+1}/${s.length}`)}yield z(r,t)})}function ae(){console.log(`
|
|
20
20
|
Type Debt Analyzer
|
|
21
21
|
|
|
22
22
|
Usage: npx tsx index.ts [directory]
|
package/index.ts
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { getTargetFiles } from "./utils.js";
|
|
4
|
-
import { chunkArray, validateDirectory } from "./utils.js";
|
|
5
|
-
import { processChunk } from "./core/chunkProcessor.js";
|
|
6
|
-
import { FileReport } from "./types.js";
|
|
7
|
-
import { CONSTANTS } from "./constants.js";
|
|
8
|
-
import { generateMarkdownReport } from "./core/reporter.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const args = process.argv.slice(2);
|
|
13
|
-
|
|
14
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
15
|
-
printHelp();
|
|
16
|
-
process.exit(0);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const target = args[0] || ".";
|
|
20
|
-
|
|
21
|
-
runCLI(target).catch((err) => {
|
|
22
|
-
console.error(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
|
|
23
|
-
process.exit(1);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
async function runCLI(targetDir: string) {
|
|
28
|
-
|
|
29
|
-
await validateDirectory(targetDir);
|
|
30
|
-
|
|
31
|
-
console.log(`\nScanning directory: ${targetDir}`);
|
|
32
|
-
const allFiles = getTargetFiles(targetDir);
|
|
33
|
-
|
|
34
|
-
if (allFiles.length === 0) {
|
|
35
|
-
throw new Error(`No TypeScript files found to process.`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const fileChunks = chunkArray(allFiles, CONSTANTS.CHUNK_SIZE);
|
|
39
|
-
|
|
40
|
-
let allResults: FileReport[] = [];
|
|
41
|
-
|
|
42
|
-
for (const [index, chunk] of fileChunks.entries()) {
|
|
43
|
-
|
|
44
|
-
const chunkResults = processChunk(chunk);
|
|
45
|
-
allResults = allResults.concat(chunkResults);
|
|
46
|
-
process.stdout.write(`\rProcessed chunk ${index + 1}/${fileChunks.length}`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
await generateMarkdownReport(allResults, targetDir);
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function printHelp() {
|
|
54
|
-
console.log(`
|
|
55
|
-
Type Debt Analyzer
|
|
56
|
-
|
|
57
|
-
Usage: npx tsx index.ts [directory]
|
|
58
|
-
|
|
59
|
-
Examples:
|
|
60
|
-
npx tsx index.ts .
|
|
61
|
-
npx tsx index.ts ./src
|
|
62
|
-
`);
|
|
63
|
-
process.exit(0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { getTargetFiles } from "./utils.js";
|
|
4
|
+
import { chunkArray, validateDirectory } from "./utils.js";
|
|
5
|
+
import { processChunk } from "./core/chunkProcessor.js";
|
|
6
|
+
import { FileReport } from "./types.js";
|
|
7
|
+
import { CONSTANTS } from "./constants.js";
|
|
8
|
+
import { generateMarkdownReport } from "./core/reporter.js";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
15
|
+
printHelp();
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const target = args[0] || ".";
|
|
20
|
+
|
|
21
|
+
runCLI(target).catch((err) => {
|
|
22
|
+
console.error(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async function runCLI(targetDir: string) {
|
|
28
|
+
|
|
29
|
+
await validateDirectory(targetDir);
|
|
30
|
+
|
|
31
|
+
console.log(`\nScanning directory: ${targetDir}`);
|
|
32
|
+
const allFiles = getTargetFiles(targetDir);
|
|
33
|
+
|
|
34
|
+
if (allFiles.length === 0) {
|
|
35
|
+
throw new Error(`No TypeScript files found to process.`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const fileChunks = chunkArray(allFiles, CONSTANTS.CHUNK_SIZE);
|
|
39
|
+
|
|
40
|
+
let allResults: FileReport[] = [];
|
|
41
|
+
|
|
42
|
+
for (const [index, chunk] of fileChunks.entries()) {
|
|
43
|
+
|
|
44
|
+
const chunkResults = processChunk(chunk);
|
|
45
|
+
allResults = allResults.concat(chunkResults);
|
|
46
|
+
process.stdout.write(`\rProcessed chunk ${index + 1}/${fileChunks.length}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await generateMarkdownReport(allResults, targetDir);
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function printHelp() {
|
|
54
|
+
console.log(`
|
|
55
|
+
Type Debt Analyzer
|
|
56
|
+
|
|
57
|
+
Usage: npx tsx index.ts [directory]
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
npx tsx index.ts .
|
|
61
|
+
npx tsx index.ts ./src
|
|
62
|
+
`);
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m4x_7/type-debt",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A high-performance TypeScript static analyzer that calculates Type Debt and generates reports.",
|
|
6
|
-
"main": "
|
|
6
|
+
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"type-debt": "
|
|
8
|
+
"type-debt": "dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsup index.ts --format esm --minify --clean",
|
|
11
|
+
"build": "tsup index.ts --format esm --minify --shims --clean",
|
|
12
12
|
"test": "vitest",
|
|
13
13
|
"dev": "nodemon --ignore temp_repos/ --exec ts-node main.ts"
|
|
14
14
|
},
|