@ngcompass/engine 0.1.1-beta → 0.1.3-beta

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.d.cts CHANGED
@@ -172,6 +172,7 @@ interface PerformanceReport {
172
172
  */
173
173
  declare const runSinglePassAnalysis: (rules: ReadonlyArray<RuleHandler<any>>, context: RuleContext, options?: {
174
174
  errorCollector?: InfrastructureErrorCollector;
175
+ collectRuleTimings?: boolean;
175
176
  }) => {
176
177
  results: RuleResult[];
177
178
  performance: PerformanceReport;
@@ -270,6 +271,10 @@ interface AnalysisContext {
270
271
  * @param filePath The path of the file to evict from internal caches.
271
272
  */
272
273
  readonly evict: (filePath: string) => void;
274
+ /**
275
+ * Clears every cached artifact owned by this context.
276
+ */
277
+ readonly dispose: () => void;
273
278
  }
274
279
  /**
275
280
  * Instantiates an AnalysisContext provider with integrated memoization logic.
@@ -296,6 +301,7 @@ interface AnalysisFileProgress {
296
301
  readonly warningCount: number;
297
302
  readonly duration: number;
298
303
  readonly cached?: boolean;
304
+ readonly typeAware?: boolean;
299
305
  }
300
306
 
301
307
  /**
@@ -349,9 +355,34 @@ interface AnalysisOptions {
349
355
  * starts. Smaller values reduce peak memory; larger values reduce the
350
356
  * number of (expensive) `ts.createProgram` calls.
351
357
  *
352
- * Default: 400 files per chunk. Set to `Infinity` to disable chunking.
358
+ * Default: 100 files per chunk, or 50 for very large type-aware runs.
359
+ * Set to `Infinity` to disable chunking.
353
360
  */
354
361
  readonly typeAwareChunkSize?: number;
362
+ /**
363
+ * Runs type-aware chunks in a separate Node process. This is slower than
364
+ * in-process execution, but gives the OS a hard memory boundary because
365
+ * each chunk process exits after producing results.
366
+ */
367
+ readonly typeAwareIsolation?: 'auto' | 'process' | 'off';
368
+ /**
369
+ * Controls how type-aware files are ordered before chunking.
370
+ * `dependency` attempts to keep nearby dependency groups together.
371
+ * `simple` skips the dependency pre-pass and sorts files by path.
372
+ */
373
+ readonly typeAwareChunkStrategy?: 'dependency' | 'simple';
374
+ /**
375
+ * Maximum number of type-aware chunks allowed to run at the same time.
376
+ * Each concurrent chunk may create its own TypeScript Program, so values
377
+ * above one trade memory for speed.
378
+ */
379
+ readonly typeAwareConcurrency?: number;
380
+ /**
381
+ * Maximum number of files to process concurrently inside a single
382
+ * type-aware chunk. This reuses one TypeScript Program but may hold more
383
+ * file/template ASTs at once.
384
+ */
385
+ readonly typeAwareFileConcurrency?: number;
355
386
  /**
356
387
  * When true, type-checker-dependent rules are skipped entirely.
357
388
  * Use this as an escape valve for very large repos where even a chunked
@@ -425,6 +456,15 @@ interface TypeAwareAnalysisContext extends AnalysisContext {
425
456
  * Performs an explicit initialization phase for type-aware resources.
426
457
  */
427
458
  readonly warmup: () => Promise<void>;
459
+ /**
460
+ * Releases references to the TypeScript Program, TypeChecker, ProjectContext,
461
+ * and baseline parsed artifacts after a type-aware chunk finishes.
462
+ */
463
+ readonly dispose: () => void;
464
+ }
465
+ interface TypeAwareAnalysisContextOptions {
466
+ readonly buildProjectContext?: boolean;
467
+ readonly programRootFiles?: ReadonlyArray<string>;
428
468
  }
429
469
  /**
430
470
  * Initializes a TypeAwareAnalysisContext for the specified root directory.
@@ -433,7 +473,7 @@ interface TypeAwareAnalysisContext extends AnalysisContext {
433
473
  * @param files A collection of file paths identified during the scanning phase.
434
474
  * @returns A fully initialized TypeAwareAnalysisContext instance.
435
475
  */
436
- declare const createTypeAwareAnalysisContext: (rootDir: string, files?: ReadonlyArray<string>, parserOptions?: ParserOptions) => TypeAwareAnalysisContext;
476
+ declare const createTypeAwareAnalysisContext: (rootDir: string, files?: ReadonlyArray<string>, parserOptions?: ParserOptions, contextOptions?: TypeAwareAnalysisContextOptions) => TypeAwareAnalysisContext;
437
477
 
438
478
  /**
439
479
  * @fileoverview
package/dist/index.d.ts CHANGED
@@ -172,6 +172,7 @@ interface PerformanceReport {
172
172
  */
173
173
  declare const runSinglePassAnalysis: (rules: ReadonlyArray<RuleHandler<any>>, context: RuleContext, options?: {
174
174
  errorCollector?: InfrastructureErrorCollector;
175
+ collectRuleTimings?: boolean;
175
176
  }) => {
176
177
  results: RuleResult[];
177
178
  performance: PerformanceReport;
@@ -270,6 +271,10 @@ interface AnalysisContext {
270
271
  * @param filePath The path of the file to evict from internal caches.
271
272
  */
272
273
  readonly evict: (filePath: string) => void;
274
+ /**
275
+ * Clears every cached artifact owned by this context.
276
+ */
277
+ readonly dispose: () => void;
273
278
  }
274
279
  /**
275
280
  * Instantiates an AnalysisContext provider with integrated memoization logic.
@@ -296,6 +301,7 @@ interface AnalysisFileProgress {
296
301
  readonly warningCount: number;
297
302
  readonly duration: number;
298
303
  readonly cached?: boolean;
304
+ readonly typeAware?: boolean;
299
305
  }
300
306
 
301
307
  /**
@@ -349,9 +355,34 @@ interface AnalysisOptions {
349
355
  * starts. Smaller values reduce peak memory; larger values reduce the
350
356
  * number of (expensive) `ts.createProgram` calls.
351
357
  *
352
- * Default: 400 files per chunk. Set to `Infinity` to disable chunking.
358
+ * Default: 100 files per chunk, or 50 for very large type-aware runs.
359
+ * Set to `Infinity` to disable chunking.
353
360
  */
354
361
  readonly typeAwareChunkSize?: number;
362
+ /**
363
+ * Runs type-aware chunks in a separate Node process. This is slower than
364
+ * in-process execution, but gives the OS a hard memory boundary because
365
+ * each chunk process exits after producing results.
366
+ */
367
+ readonly typeAwareIsolation?: 'auto' | 'process' | 'off';
368
+ /**
369
+ * Controls how type-aware files are ordered before chunking.
370
+ * `dependency` attempts to keep nearby dependency groups together.
371
+ * `simple` skips the dependency pre-pass and sorts files by path.
372
+ */
373
+ readonly typeAwareChunkStrategy?: 'dependency' | 'simple';
374
+ /**
375
+ * Maximum number of type-aware chunks allowed to run at the same time.
376
+ * Each concurrent chunk may create its own TypeScript Program, so values
377
+ * above one trade memory for speed.
378
+ */
379
+ readonly typeAwareConcurrency?: number;
380
+ /**
381
+ * Maximum number of files to process concurrently inside a single
382
+ * type-aware chunk. This reuses one TypeScript Program but may hold more
383
+ * file/template ASTs at once.
384
+ */
385
+ readonly typeAwareFileConcurrency?: number;
355
386
  /**
356
387
  * When true, type-checker-dependent rules are skipped entirely.
357
388
  * Use this as an escape valve for very large repos where even a chunked
@@ -425,6 +456,15 @@ interface TypeAwareAnalysisContext extends AnalysisContext {
425
456
  * Performs an explicit initialization phase for type-aware resources.
426
457
  */
427
458
  readonly warmup: () => Promise<void>;
459
+ /**
460
+ * Releases references to the TypeScript Program, TypeChecker, ProjectContext,
461
+ * and baseline parsed artifacts after a type-aware chunk finishes.
462
+ */
463
+ readonly dispose: () => void;
464
+ }
465
+ interface TypeAwareAnalysisContextOptions {
466
+ readonly buildProjectContext?: boolean;
467
+ readonly programRootFiles?: ReadonlyArray<string>;
428
468
  }
429
469
  /**
430
470
  * Initializes a TypeAwareAnalysisContext for the specified root directory.
@@ -433,7 +473,7 @@ interface TypeAwareAnalysisContext extends AnalysisContext {
433
473
  * @param files A collection of file paths identified during the scanning phase.
434
474
  * @returns A fully initialized TypeAwareAnalysisContext instance.
435
475
  */
436
- declare const createTypeAwareAnalysisContext: (rootDir: string, files?: ReadonlyArray<string>, parserOptions?: ParserOptions) => TypeAwareAnalysisContext;
476
+ declare const createTypeAwareAnalysisContext: (rootDir: string, files?: ReadonlyArray<string>, parserOptions?: ParserOptions, contextOptions?: TypeAwareAnalysisContextOptions) => TypeAwareAnalysisContext;
437
477
 
438
478
  /**
439
479
  * @fileoverview
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import {toNewExpressionStream,toCallExpressionStream,toDecoratedPropertyStream,toAnyAngularClassStream,toAngularClassStream,resetComponentCacheStats,walkProgram,analyzeTemplate,getComponentCacheStats,parseCss,parseHtml,extractTemplateFromProgram,parseTs}from'@ngcompass/ast';import {createInfrastructureError,Locator,debug,stableSerialize,SerializationError,Ok,Err}from'@ngcompass/common';import S from'typescript';import Qe from'os';import at from'p-limit';import {groupTasksByFile}from'@ngcompass/planner';import {readFile}from'fs/promises';import*as $ from'path';import $__default,{dirname,join}from'path';import {LRUCache}from'lru-cache';import {createRequire}from'module';import {fileURLToPath}from'url';import {existsSync}from'fs';var gt=(t,e,a)=>({name:t,streamType:"AngularClass",handle:e,meta:a}),dt=(t,e,a)=>({name:t,streamType:"AnyAngularClass",handle:e,meta:a}),ht=(t,e)=>({name:t,streamType:"DecoratedProperty",handle:e}),xt=(t,e,a)=>({name:t,streamType:"TemplateExpression",handle:e,meta:a}),yt=(t,e,a)=>({name:t,streamType:"TemplateAttribute",handle:e,meta:a}),wt=(t,e,a)=>({name:t,streamType:"CallExpression",handle:e,meta:a}),kt=(t,e,a)=>({name:t,streamType:"NewExpression",handle:e,meta:a}),Ct=(t,e,a)=>({name:t,streamType:"TemplateBlock",handle:e,meta:a}),Et=(t,e,a)=>({name:t,streamType:"Template",handle:e,meta:a});var Ee={AngularClass:"ClassDeclaration",AnyAngularClass:"ClassDeclaration",DecoratedProperty:"PropertyDefinition",TemplateExpression:"__template_expression__",TemplateAttribute:"__template_attribute__",TemplateBlock:"__template_block__",Template:"__template_analysis__",CallExpression:"CallExpression",NewExpression:"NewExpression"};function Z(t,e){let a=new Map;for(let o of t){let l=Ee[o.streamType];if(!l||l.startsWith("__"))continue;let p=e[o.streamType];if(!p)continue;let f={ruleName:o.name,filter:p,handle:o.handle.bind(o)},r=a.get(l);r?r.push(f):a.set(l,[f]);}return a}var Te=2,Se=80,q=6e4,ve=2,Pe=5;var G=(t,e,a,o,l,p)=>{if(e.length!==0)for(let f of t)for(let r=0;r<e.length;r++){let s=e[r],u=performance.now();try{let g=s.handle(f,a);if(g){let d=o.get(s.name)??[];Array.isArray(g)?d.push(...g):d.push(g),o.set(s.name,d);}}catch(g){p?.record(createInfrastructureError("RuleExecutionError",{cause:`Rule ${s.name} failed on template node: ${g instanceof Error?g.message:String(g)}`,recoverable:true,phase:"engine",details:{ruleName:s.name,errorName:g instanceof Error?g.name:void 0}}));}let i=performance.now()-u,y=l.get(s.name);y&&(y.totalMs+=i,y.invocations++);}},Nt=(t,e,a)=>{let{program:o}=e;if(!o)return {results:t.map(n=>({ruleName:n.name,failures:[]})),performance:{traversalMs:0,nodesVisited:0,ruleTimings:[],cacheStats:{hits:0,misses:0},budgetViolations:[],hasBudgetViolations:false}};let l=performance.now(),p=Z(t,{AngularClass:toAngularClassStream,AnyAngularClass:toAnyAngularClassStream,DecoratedProperty:toDecoratedPropertyStream,CallExpression:toCallExpressionStream,NewExpression:toNewExpressionStream}),f=t.filter(n=>n.streamType==="TemplateExpression"),r=t.filter(n=>n.streamType==="TemplateAttribute"),s=t.filter(n=>n.streamType==="TemplateBlock"),u=t.filter(n=>n.streamType==="Template"),i=new Map,y=new Map,g=0;for(let n of t)y.set(n.name,{ruleName:n.name,totalMs:0,invocations:0});if(resetComponentCacheStats(),walkProgram(o,n=>{if(!n?.type)return;g++;let h=p.get(n.type);if(h)for(let m=0;m<h.length;m++){let c=h[m],x=performance.now();try{let v=c.filter(n);if(v!==null){let I=c.handle(v,e);if(I){let b=i.get(c.ruleName)??[];Array.isArray(I)?b.push(...I):b.push(I),i.set(c.ruleName,b);}}}catch(v){a?.errorCollector?.record(createInfrastructureError("RuleExecutionError",{cause:`Rule ${c.ruleName} failed: ${v instanceof Error?v.message:String(v)}`,recoverable:true,phase:"engine",details:{ruleName:c.ruleName,errorName:v instanceof Error?v.name:void 0}}));}let A=performance.now()-x,T=y.get(c.ruleName);T&&(T.totalMs+=A,T.invocations++);}}),e.template&&(f.length>0||r.length>0||s.length>0||u.length>0)){let n=analyzeTemplate(e.template),h=e.templateFilePath&&e.templateFileContent&&e.templateLocator?{...e,filePath:e.templateFilePath,fileContent:e.templateFileContent,locator:e.templateLocator}:e;G(n.expressions,f,h,i,y,a?.errorCollector),G(n.attributes,r,h,i,y,a?.errorCollector),G(n.blocks,s,h,i,y,a?.errorCollector),G([n],u,h,i,y,a?.errorCollector);}let d=[];for(let n of t)d.push({ruleName:n.name,failures:i.get(n.name)??[]});let C=performance.now()-l,k=[],w=e.typeChecker?5:2;for(let n of(C>w&&k.push(`Total traversal time ${C.toFixed(2)}ms exceeds budget ${w}ms`),y.values())){if(n.invocations===0)continue;let h=n.totalMs/n.invocations;h>1&&k.push(`Rule ${n.ruleName} averages ${h.toFixed(2)}ms per invocation (threshold: 1ms)`);}return {results:d,performance:{traversalMs:C,nodesVisited:g,ruleTimings:Array.from(y.values()),cacheStats:getComponentCacheStats(),budgetViolations:k,hasBudgetViolations:k.length>0}}};var K=class{context;constructor(e){this.context=e;}async build(e,a,o){let l,p,f,r,s,[u,i]=await Promise.all([this.context.readFile(e),this.context.getProgram(e)]),y=new Locator(u);this.context.getTypeChecker&&(l=await this.context.getTypeChecker(e)),o&&(p=await this.context.getTemplate(e));let g=this.context.getProjectContext?.();o&&!p&&g&&(f=this.resolveExternalTemplatePath(e,g))&&(p=await this.context.getTemplate(f),s=new Locator(r=await this.context.readFile(f)));let d=g?await this.buildCrossRef(e,p,g):void 0;return {filePath:e,fileContent:u,locator:y,program:i,typeChecker:l,template:p,templateFilePath:f,templateFileContent:r,templateLocator:s,options:a,project:g,crossRef:d}}resolveExternalTemplatePath(e,a){let o=e.endsWith(".component.ts")?e:a.templateToComponent.get(e);if(o)return a.componentGraph.get(o)?.templatePath}async buildCrossRef(e,a,o){let l,p,f,r=e.endsWith(".component.ts")?e:o.templateToComponent.get(e);if(!r)return;let s=o.componentGraph.get(r),u=s?.templatePath,i=s?.stylePaths??[],y=s?.specPath;try{let d=await this.getComponentSourceFile(r);d&&(l=(function(C){let k=new Set;for(let w of C.statements)if(S.isClassDeclaration(w))for(let n of w.members){let h=S.canHaveModifiers(n)?S.getModifiers(n):void 0;if(h&&h.some(c=>c.kind===S.SyntaxKind.PrivateKeyword||c.kind===S.SyntaxKind.ProtectedKeyword))continue;let m=n.name;m&&!S.isPrivateIdentifier(m)&&(S.isIdentifier(m)||S.isStringLiteral(m))&&k.add(m.text);}return k})(d),p=(function(C){let k=new Set;for(let w of C.statements)if(S.isClassDeclaration(w))for(let n of w.members){if(!S.isPropertyDeclaration(n)||!n.initializer||!n.name||S.isPrivateIdentifier(n.name))continue;let h=(function(m){let c=S.isAsExpression(m)||S.isSatisfiesExpression(m)?m.expression:m;if(!S.isCallExpression(c))return;let x=c.expression;return S.isIdentifier(x)?x.text:S.isPropertyAccessExpression(x)?S.isIdentifier(x.expression)&&x.expression.text==="input"?"input":x.name.text:void 0})(n.initializer);h&&De.has(h)&&(S.isIdentifier(n.name)||S.isStringLiteral(n.name))&&k.add(n.name.text);}return k})(d));}catch{}let g=a;if(!g&&u)try{g=await this.context.getTemplate(u);}catch{}if(g)try{f=(function(d){let C=new Set,k=/\{\{([\s\S]*?)\}\}/g;for(let w of d.rootNodes)(function n(h){if(h&&typeof h=="object"){if(Array.isArray(h.attrs))for(let m of h.attrs){if((typeof m.name=="string"?m.name:"").startsWith("("))continue;let c=m.value;typeof c=="string"&&c&&ee(c,C);}if(typeof h.value=="string"&&h.value){let m;for(k.lastIndex=0;(m=k.exec(h.value))!==null;)ee(m[1],C);}if(Array.isArray(h.children))for(let m of h.children)n(m);}})(w);return C})(g);}catch{}return {componentPath:r,templatePath:u,stylePaths:i,specPath:y,publicMembers:l,signalMembers:p,templateReferences:f}}async getComponentSourceFile(e){let a=this.context.getTsSourceFile?.(e);if(a)return a;let o=await this.context.readFile(e);return S.createSourceFile(e,o,S.ScriptTarget.Latest,true)}},De=new Set(["signal","computed","linkedSignal","input","model","toSignal"]),Q=/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g;function ee(t,e){let a;for(Q.lastIndex=0;(a=Q.exec(t))!==null;)e.add(a[1]);}var Ge=new Set([".css",".scss",".sass",".less"]),F=t=>{let e=new LRUCache({max:128}),a=new Map,o=new Map,l=new Map,p=r=>{let s=e.get(r);if(s)return s;let u=Ke(t,r);return e.set(r,u),u},f=r=>{let s=a.get(r);if(s)return s;let u=(async()=>parseTs(await p(r),r).program)();return a.set(r,u),u};return {rootDir:t,readFile:p,getProgram:f,getTemplate:r=>{let s=o.get(r);if(s)return s;let u=(async()=>{let i=await He(r,p,f);if(i&&i.content)return parseHtml(i.content,i.startOffset)})();return o.set(r,u),u},getStyle:r=>{let s=l.get(r);if(s)return s;let u=$.extname(r).toLowerCase();if(!Ge.has(u)){let y=Promise.resolve(void 0);return l.set(r,y),y}let i=(async()=>parseCss(await p(r),r))();return l.set(r,i),i},evict:r=>{e.delete(r),a.delete(r),o.delete(r),l.delete(r);}}},Ke=async(t,e)=>{try{return await readFile($.resolve(t,e),"utf-8")}catch(a){let o=a instanceof Error?a.message:String(a);throw Error(`Cannot read file: ${e}. ${o}`)}},He=async(t,e,a)=>{let o=$.extname(t);if(o===".html")return {content:await e(t),startOffset:0};if(o===".ts"){let l=extractTemplateFromProgram(await a(t));return l.content?l:null}return null};function U(t,e,a,o){let l=performance.now(),p=(function(w,n,h){var m;let c=new Set;for(let A of w)c.add($.resolve(n,A));let x=(m=n).endsWith($.sep)?m:m+$.sep;for(let A of h.getSourceFiles())!A.isDeclarationFile&&A.fileName.startsWith(x)&&c.add(A.fileName);return c})(e,a,t),{importGraph:f,reverseImportGraph:r,externalDeps:s}=(function(w,n){let h=w.getCompilerOptions(),m=new Map,c=new Map,x=new Map;for(let A of n)m.set(A,new Set),c.set(A,new Set);for(let A of w.getSourceFiles()){if(A.isDeclarationFile||!n.has(A.fileName))continue;let T=A.fileName;for(let v of (function(I){let b=[];return S.forEachChild(I,function P(E){S.isImportDeclaration(E)&&S.isStringLiteral(E.moduleSpecifier)||S.isExportDeclaration(E)&&E.moduleSpecifier&&S.isStringLiteral(E.moduleSpecifier)?b.push(E.moduleSpecifier.text):(S.isCallExpression(E)&&E.expression.kind===S.SyntaxKind.ImportKeyword&&E.arguments.length>0&&S.isStringLiteralLike(E.arguments[0])&&b.push(E.arguments[0].text),S.forEachChild(E,P));}),b})(A)){let I=S.resolveModuleName(v,T,h,S.sys),b=I.resolvedModule?.resolvedFileName;if(b&&n.has(b)){m.get(T).add(b);let P=c.get(b);P||(P=new Set,c.set(b,P)),P.add(T);}else {let P=(function(E){if(E.startsWith(".")||$.isAbsolute(E))return null;if(E.startsWith("@")){let j=E.indexOf("/",1);if(j===-1)return null;let D=E.indexOf("/",j+1);return D===-1?E:E.slice(0,D)}let R=E.indexOf("/");return R===-1?E:E.slice(0,R)})(v);if(P){let E=x.get(T);E||(E=new Set,x.set(T,E)),E.add(P);}}}}return {importGraph:m,reverseImportGraph:c,externalDeps:x}})(t,p),u=(function(w,n){let h=new Set;for(let m of w.getSourceFiles()){if(m.isDeclarationFile||!n.has(m.fileName))continue;let{statements:c}=m;c.length!==0&&c.every(x=>S.isExportDeclaration(x)&&x.moduleSpecifier!=null)&&h.add(m.fileName);}return h})(t,p),i=o??(function(w){let n=new Map,h=[".scss",".sass",".css",".less"];for(let m of w){if(!m.endsWith(".component.ts"))continue;let c=$.dirname(m),x=$.basename(m,".ts"),A=$.join(c,x+".html"),T=w.has(A)?A:void 0,v=[];for(let P of h){let E=$.join(c,x+P);w.has(E)&&v.push(E);}let I=$.join(c,x+".spec.ts"),b=w.has(I)?I:void 0;n.set(m,{tsPath:m,templatePath:T,stylePaths:v,specPath:b});}return n})(p),y=(function(w){let n=new Map;for(let[h,m]of w)m.templatePath&&n.set(m.templatePath,h);return n})(i),{ngModuleMap:g,standaloneComponents:d,classToFile:C}=(function(w,n){let h=new Map,m=new Set,c=(function(x,A){let T=new Map;for(let v of x.getSourceFiles())if(!v.isDeclarationFile&&A.has(v.fileName))for(let I of v.statements){if(!S.isClassDeclaration(I)||!I.name)continue;(S.canHaveModifiers(I)?S.getModifiers(I):void 0)?.some(P=>P.kind===S.SyntaxKind.ExportKeyword)&&T.set(I.name.text,v.fileName);}return T})(w,n);for(let x of w.getSourceFiles())if(!x.isDeclarationFile&&n.has(x.fileName))for(let A of x.statements){if(!S.isClassDeclaration(A))continue;let T=S.canHaveDecorators(A)?S.getDecorators(A):void 0;if(T?.length)for(let v of T){let I=(function(E){let R=E.expression;if(!S.isCallExpression(R))return;let j=R.expression;if(!S.isIdentifier(j))return;let D=R.arguments[0],Ce=D&&S.isObjectLiteralExpression(D)?D:void 0;return {name:j.text,arg:Ce}})(v);if(!I)continue;let{name:b,arg:P}=I;if(b==="NgModule"){P&&h.set(x.fileName,{filePath:x.fileName,declarations:new Set(W(P,"declarations")),imports:new Set(W(P,"imports")),exports:new Set(W(P,"exports")),providers:new Set(W(P,"providers")),isStandalone:false});break}if(b==="Component"){P&&te(P,"standalone")&&(m.add(x.fileName),h.set(x.fileName,{filePath:x.fileName,declarations:new Set,imports:new Set(P?W(P,"imports"):[]),exports:new Set,providers:new Set(P?W(P,"providers"):[]),isStandalone:true}));break}if(b==="Directive"||b==="Pipe"){P&&te(P,"standalone")&&m.add(x.fileName);break}}}return {ngModuleMap:h,standaloneComponents:m,classToFile:c}})(t,p),k=(function(w){let n=0;for(let h of w.values())n+=h.size;return n})(f);return debug("engine",`ProjectContext built in ${(performance.now()-l).toFixed(2)}ms \u2014 ${p.size} files, ${k} import edges, ${u.size} barrels, ${s.size} files with ext deps, ${i.size} components, ${y.size} template\u2194component links, ${g.size} NgModules/standalone, ${d.size} standalone`),{importGraph:f,reverseImportGraph:r,ngModuleMap:g,standaloneComponents:d,classToFile:C,componentGraph:i,projectFiles:p,rootDir:a,barrelFiles:u,externalDeps:s,templateToComponent:y}}function W(t,e){for(let a of t.properties){if(!S.isPropertyAssignment(a)||!S.isIdentifier(a.name)||a.name.text!==e)continue;let o=a.initializer;if(!S.isArrayLiteralExpression(o))break;let l=[];for(let p of o.elements)l.push(...(function f(r){return S.isIdentifier(r)?[r.text]:S.isPropertyAccessExpression(r)||S.isCallExpression(r)?f(r.expression):[]})(p));return l}return []}function te(t,e){for(let a of t.properties)if(S.isPropertyAssignment(a)&&S.isIdentifier(a.name)&&a.name.text===e)return a.initializer.kind===S.SyntaxKind.TrueKeyword;return false}var V=(t,e=[],a)=>{let o,l,p=F(t);debug("engine","Initializing Type-Aware Context (ts.createProgram)...");let f=performance.now(),r=a?.tsconfigRootDir?$__default.resolve(t,a.tsconfigRootDir):t,s=a?.project?$__default.resolve(r,a.project):S.findConfigFile(r,S.sys.fileExists,"tsconfig.json");if(s){let i=S.readConfigFile(s,S.sys.readFile),y=S.parseJsonConfigFileContent(i.config,S.sys,r),g=e.filter(C=>(C.endsWith(".ts")||C.endsWith(".tsx"))&&!C.endsWith(".d.ts")),d=g.length>0?g:y.fileNames;o=S.createProgram({rootNames:d,options:y.options}),debug("engine",`TypeScript Program initialized in ${(performance.now()-f).toFixed(2)}ms with ${d.length} roots (tsconfig had ${y.fileNames.length})`);}else debug("engine","Could not find tsconfig.json; TypeChecker and ProjectContext will be unavailable.");let u=o?.getTypeChecker();if(o)try{l=U(o,e,t);}catch(i){let y=i instanceof Error?i.message:String(i);debug("engine",`ProjectContext build failed (non-fatal): ${y}`);}return {...p,getTypeChecker:async i=>u,getProjectContext:()=>l,getTsSourceFile:i=>o?.getSourceFile(i),warmup:async()=>{debug("engine",`Type-aware context ready: ${o?`ts.Program with ${o.getSourceFiles().length} source files`:"no tsconfig found, TypeChecker unavailable"}`);}}};var z=(t,e,a)=>{let o=performance.now()-e,l=t.flatMap(s=>s.failures),p=new Set(l.map(s=>s.filePath)),f=l.filter(s=>Ve(s.severity)).length,r=l.filter(s=>Ye(s.severity)).length;return {totalFiles:p.size,totalErrors:f,totalWarnings:r,duration:o,cacheHitRate:a}},Ve=t=>t==="error",Ye=t=>t==="warn";var ae=()=>{throw Error("[ngcompass] Rule executor not configured. Call configureRuleExecutor(executeBatchedNewEngineRules, isNewEngineRule) before running analysis.")},se=()=>false,Ze=(t,e)=>{ae=t,se=e;},oe=()=>ae,ne=()=>se;var B=async(t,e,a)=>{if(t.length===0)return [];let o=t[0].filePath,l=new K(e),p=new Map,f=[];for(let r of t){let s;if(!ne()(r.ruleName)){debug("engine",`Skipping task ${r.taskId}: Rule "${r.ruleName}" not registered in engine.`),f.push({ruleName:r.ruleName,taskId:r.taskId,failures:[]});continue}try{s=stableSerialize(r.options||{});}catch(i){let y=i instanceof SerializationError?i.message:String(i);debug("engine",`Skipping task ${r.taskId}: failed to serialize options \u2014 ${y}`),a?.record(createInfrastructureError("SerializationError",{cause:y,phase:"engine",recoverable:true})),f.push({ruleName:r.ruleName,taskId:r.taskId,failures:[]});continue}let u=p.get(s)??{options:r.options,ruleNames:[],taskIds:[],severities:new Map};u.ruleNames.push(r.ruleName),u.taskIds.push(r.taskId),u.severities.set(r.ruleName,r.severity),p.set(s,u);}for(let r of p.values())try{let s=new Set(r.taskIds),u=t.some(d=>s.has(d.taskId)&&d.inputs.template?.needsAst),i=await l.build(o,r.options,u),y=oe()(r.ruleNames,i),g=new Map;for(let d=0;d<r.ruleNames.length;d++){let C=r.ruleNames[d],k=r.taskIds[d],w=g.get(C)??[];w.push(k),g.set(C,w);}for(let d of y){let C=g.get(d.ruleName),k=r.severities.get(d.ruleName),w=k?{...d,failures:d.failures.map(n=>({...n,severity:k}))}:d;if(C&&C.length>0){let n=C.shift();f.push({...w,taskId:n});}else f.push(w);}}catch(s){let u=s instanceof Error?s.message:String(s);debug("engine",`Failed to execute batch for ${o}: ${u}`),a?.record(createInfrastructureError("ParseError",{filePath:o,cause:u,phase:"engine",recoverable:true}));for(let i=0;i<r.ruleNames.length;i++)f.push({ruleName:r.ruleNames[i],failures:[],taskId:r.taskIds[i]});}return f};var fe=async(t,e,a,o,l,p)=>{let f,{Worker:r}=await import('worker_threads'),s=o??Math.max(2,Qe.cpus().length),u=await it();if(!u)return debug("workers","Execution worker not found, falling back to local execution."),st(t,e,a,l??s,p);let i=lt(t,s),y=0,g=()=>{y++,debug("workers",`Worker progress: ${y}/${s} complete`);},d=[],C=i.map(w=>new Promise((n,h)=>{let m=false,c=new r(u,{workerData:{rootDir:e,tasks:w}});d.push(c);let x=()=>{clearTimeout(A),c.removeAllListeners();},A=setTimeout(()=>{m||(m=true,x(),g(),c.terminate(),h(Error(`Worker timed out after ${6e4/1e3}s`)));},6e4);c.on("message",T=>{ot(T)?p?.(T):m||(m=true,x(),T.errors&&T.errors.length>0&&T.errors.forEach(v=>{debug("workers",`Worker failed task ${v.task.taskId}: ${v.error}`);}),g(),n(T.results));}),c.on("error",T=>{m||(m=true,x(),g(),h(T instanceof Error?T:Error(String(T))));}),c.on("exit",T=>{if(m||T===0)return;m=true,x();let v=createInfrastructureError("WorkerCrash",{cause:`Worker exited with code ${T}`,phase:"engine",recoverable:true,details:{exitCode:T}});debug("workers",`Worker crashed: ${v.cause}`),h(Error(v.cause));});}));try{f=await Promise.all(C);}catch(w){throw await Promise.allSettled(d.map(n=>n.terminate())),w}let k=f.flat();return Ok({results:k,parseErrors:[],stats:z(k,a)})},st=async(t,e,a,o,l)=>{let p=F(e),f=at(o),r=groupTasksByFile(t),s=(await Promise.all(Array.from(r.values()).map(u=>f(async()=>{let i=u[0]?.filePath,y=performance.now(),g=await B(u,p);return i&&p.evict(i),i&&l?.(nt(i,u.length,g,performance.now()-y)),g})))).flat();return Ok({results:s,parseErrors:[],stats:z(s,a)})},ot=t=>!!t&&typeof t=="object"&&t.kind==="file-progress",nt=(t,e,a,o)=>{let l=0,p=0;for(let f of a)for(let r of f.failures)r.severity==="error"?l++:r.severity==="warn"&&p++;return {filePath:t,taskCount:e,issueCount:l+p,errorCount:l,warningCount:p,duration:o}},it=async()=>{let t=dirname(fileURLToPath(import.meta.url));try{let e=createRequire(import.meta.url).resolve("@ngcompass/rules/execution-worker");if(existsSync(e))return e}catch{}for(let e of [join(t,"..","..","rules","dist","execution-worker.js"),join(t,"..","..","rules","dist","execution-worker.cjs")])if(existsSync(e))return e;return null},lt=(t,e)=>{let a=Array.from(groupTasksByFile(t).values()).sort((p,f)=>f.length-p.length),o=Array.from({length:e},()=>[]),l=Array(e).fill(0);for(let p of a){let f=0,r=l[0];for(let s=1;s<e;s++)l[s]<r&&(r=l[s],f=s);o[f].push(...p),l[f]+=p.length;}return o};function ge(t){if(!t||typeof t!="object"||typeof t.ruleName!="string"||!Array.isArray(t.failures))return false;for(let e of t.failures)if(!e||typeof e!="object"||typeof e.filePath!="string"||typeof e.line!="number"||typeof e.column!="number"||typeof e.severity!="string")return false;return true}var kr=async(t,e)=>{try{if(t.precomputedAnalysis){if((function(c){if(!c||typeof c!="object"||!Array.isArray(c.results)||!Array.isArray(c.parseErrors)||!c.stats||typeof c.stats!="object")return !1;let x=c.stats;return typeof x.totalFiles=="number"&&typeof x.totalErrors=="number"&&typeof x.totalWarnings=="number"&&typeof x.duration=="number"})(t.precomputedAnalysis))return debug("engine","Returning precomputed analysis from cache (global hash match)"),Ok(t.precomputedAnalysis);debug("engine","Precomputed analysis failed schema validation \u2014 discarding stale cache entry and re-running analysis");}let a=performance.now(),{tasks:o,skippedTasks:l,cachedResults:p}=t,f=Qe.cpus().length,r=Math.max(1,Math.min(e.maxWorkers??f,f)),s=e.parallelThreshold??150,u=o.filter(c=>!!c.needsTypeChecker||!!c.needsProjectContext),i=o.filter(c=>!c.needsTypeChecker&&!c.needsProjectContext);debug("engine",`workerTasks: ${i.length}, typeAwareTasks: ${u.length}`);let y=o.length+l.length,g=l.length,d=c=>{g=Math.min(g+c,y),e.onProgress?.(g,y);};l.length>0&&e.onProgress?.(g,y);let C=[];if(i.length>0)if(i.length>s){debug("engine",`Running analysis on ${i.length} syntax-only tasks using workers (max: ${r})...`);let c=await fe(i,e.rootDir,a,r,void 0,e.onFileProgress);if(!c.ok)return c;C=c.data.results,d(i.length);}else debug("engine",`Running analysis on ${i.length} syntax-only tasks locally with batching (concurrency: ${r})...`),C=await ye(i,e.rootDir,r,!1,e.errorCollector,void 0,void 0,d,e.onFileProgress);if(u.length>0&&!e.skipTypeCheck){let c=e.typeAwareChunkSize??400,x=await ft(u,e.rootDir,r,c,e,d,e.onFileProgress);C=[...C,...x];}else u.length>0&&e.skipTypeCheck&&debug("engine",`Skipping ${u.length} type-aware tasks (--skip-type-check)`);let k=await ut(l,p,e.cache),w=[...C,...k],n=o.length+l.length,h=n>0?k.length/n:void 0,m={results:w,parseErrors:[],stats:z(w,a,h)};if(e.cache&&t.globalHash){debug("engine","Caching full analysis result for global hash..."),e.debug&&(debug("engine",`Analysis Results: ${m.results.length} items`),m.results.length>0&&debug("engine",`Sample item keys: ${Object.keys(m.results[0]).join(", ")}`));try{await e.cache.analysis.set(t.globalHash,m);}catch(c){let x=c instanceof Error?c.message:String(c);debug("engine",`Failed to cache analysis result: ${x}`),e.errorCollector?.record(createInfrastructureError("IOError",{cause:`Failed to write analysis cache: ${x}`,phase:"engine",recoverable:!0}));}}return Ok(m)}catch(a){return Err(a instanceof Error?a:Error(String(a)))}},ye=async(t,e,a,o,l,p,f,r,s)=>{let u=o?V(e,p??[],f):F(e);o&&(await u.warmup(),debug("engine",`Phase 1 complete \u2014 TypeScript Program ready. Starting Phase 2: ${a} concurrent file batches.`));let i=groupTasksByFile(t);debug("engine",`Grouped ${t.length} tasks into ${i.size} file batches`);let y=at(a);return (await Promise.all(Array.from(i.values()).map(g=>y(async()=>{let d=g[0]?.filePath,C=performance.now();try{let k=await B(g,u);return u.evict(d),r?.(g.length),d&&s?.(de(d,g.length,k,performance.now()-C)),k}catch(k){let w=k instanceof Error?k.message:String(k);return u.evict(d),r?.(g.length),d&&s?.(de(d,g.length,[],performance.now()-C)),l?.record(createInfrastructureError("IOError",{filePath:d,cause:`Batch execution failed: ${w}`,phase:"engine",recoverable:true})),[]}})))).flat().filter(g=>g!==null)},ft=async(t,e,a,o,l,p,f)=>{let r=Array.from(groupTasksByFile(t).entries()),s=[];for(let i=0;i<r.length;i+=o)s.push(r.slice(i,i+o));debug("engine",`Type-aware: ${t.length} tasks across ${r.length} files \u2192 ${s.length} chunk(s) of \u2264${o} files`);let u=[];for(let i=0;i<s.length;i++){let y=s[i],g=y.flatMap(([,k])=>k),d=y.map(([k])=>k);debug("engine",`Type-aware chunk ${i+1}/${s.length}: ${d.length} files, ${g.length} tasks`);let C=await ye(g,e,a,true,l.errorCollector,d,l.parserOptions,p,f);u.push(...C);}return u},de=(t,e,a,o)=>{let l=0,p=0;for(let f of a)for(let r of f.failures)r.severity==="error"?l++:r.severity==="warn"&&p++;return {filePath:t,taskCount:e,issueCount:l+p,errorCount:l,warningCount:p,duration:o}},ut=async(t,e,a)=>{if(t.length===0)return [];debug("engine",`Retrieving results for ${t.length} skipped tasks...`);let o=[],l=[];if(e)for(let p of t){let f=e.get(p.taskId);f&&ge(f)?o.push(f):l.push(p);}else l.push(...t);if(l.length>0&&a){debug("engine",`Fetching ${l.length} results from cache service...`);let p=l.map(r=>r.taskId),f=await a.results.getMany(p);for(let r of l){let s=f.get(r.taskId);s&&ge(s)&&o.push(s);}}return debug("engine",`Retrieved ${o.length} results from cache`),o};var we=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],ke=class{frameIndex=0;interval=null;message="";start(e){this.message=e,this.frameIndex=0,process.stdout.write("\x1B[?25l"),this.interval=setInterval(()=>{process.stdout.write(`\r${we[this.frameIndex]} ${this.message}`),this.frameIndex=(this.frameIndex+1)%we.length;},80);}update(e){this.message=e;}stop(e){this.interval&&(clearInterval(this.interval),this.interval=null),process.stdout.write("\r\x1B[K"),e&&process.stdout.write(e+`
2
- `),process.stdout.write("\x1B[?25h");}};export{ve as BUDGET_MS_PER_FILE_WITHOUT_TYPES,Pe as BUDGET_MS_PER_FILE_WITH_TYPES,Te as MIN_WORKER_COUNT,K as RuleContextFactory,Se as SPINNER_FRAME_INTERVAL_MS,Ee as STREAM_TO_NODE_TYPE,ke as Spinner,q as WORKER_TIMEOUT_MS,U as buildProjectContext,Z as buildVisitorMap,z as calculateStats,Ze as configureRuleExecutor,F as createAnalysisContext,dt as createAnyAngularClassRule,wt as createCallExpressionRule,gt as createComponentRule,ht as createDecoratedPropertyRule,kt as createNewExpressionRule,yt as createTemplateAttributeRule,Ct as createTemplateBlockRule,xt as createTemplateExpressionRule,Et as createTemplateRule,V as createTypeAwareAnalysisContext,B as executeBatchedTasks,kr as runAnalysis,fe as runAnalysisParallel,Nt as runSinglePassAnalysis};//# sourceMappingURL=index.js.map
1
+ import {toNewExpressionStream,toCallExpressionStream,toDecoratedPropertyStream,toAnyAngularClassStream,toAngularClassStream,resetComponentCacheStats,walkProgram,analyzeTemplate,getComponentCacheStats,parseCss,parseHtml,extractTemplateFromProgram,parseTs}from'@ngcompass/ast';import {isDebugEnabled,createInfrastructureError,Locator,debug,stableSerialize,SerializationError,Ok,Err}from'@ngcompass/common';import T from'typescript';import V from'os';import {readFile}from'fs/promises';import {createRequire}from'module';import {fork}from'child_process';import*as F from'path';import F__default,{dirname,join}from'path';import {fileURLToPath}from'url';import {existsSync}from'fs';import ve from'v8';import ee from'p-limit';import {groupTasksByFile}from'@ngcompass/planner';import {LRUCache}from'lru-cache';var Ot=(e,t,r)=>({name:e,streamType:"AngularClass",handle:t,meta:r}),Bt=(e,t,r)=>({name:e,streamType:"AnyAngularClass",handle:t,meta:r}),Ht=(e,t)=>({name:e,streamType:"DecoratedProperty",handle:t}),Gt=(e,t,r)=>({name:e,streamType:"TemplateExpression",handle:t,meta:r}),Kt=(e,t,r)=>({name:e,streamType:"TemplateAttribute",handle:t,meta:r}),Ut=(e,t,r)=>({name:e,streamType:"CallExpression",handle:t,meta:r}),Vt=(e,t,r)=>({name:e,streamType:"NewExpression",handle:t,meta:r}),Yt=(e,t,r)=>({name:e,streamType:"TemplateBlock",handle:t,meta:r}),qt=(e,t,r)=>({name:e,streamType:"Template",handle:t,meta:r});var $e={AngularClass:"ClassDeclaration",AnyAngularClass:"ClassDeclaration",DecoratedProperty:"PropertyDefinition",TemplateExpression:"__template_expression__",TemplateAttribute:"__template_attribute__",TemplateBlock:"__template_block__",Template:"__template_analysis__",CallExpression:"CallExpression",NewExpression:"NewExpression"};function ae(e,t){let r=new Map;for(let o of e){let n=$e[o.streamType];if(!n||n.startsWith("__"))continue;let s=t[o.streamType];if(!s)continue;let l={ruleName:o.name,filter:s,handle:o.handle.bind(o)},a=r.get(n);a?a.push(l):r.set(n,[l]);}return r}var Fe=2,Ne=80,oe=6e4,Re=2,_e=5;var G=(e,t,r,o,n,s,l)=>{if(t.length!==0)for(let a of e)for(let i=0;i<t.length;i++){let d=t[i],f=s?performance.now():0;try{let p=d.handle(a,r);if(p){let u=o.get(d.name)??[];Array.isArray(p)?u.push(...p):u.push(p),o.set(d.name,u);}}catch(p){l?.record(createInfrastructureError("RuleExecutionError",{cause:`Rule ${d.name} failed on template node: ${p instanceof Error?p.message:String(p)}`,recoverable:true,phase:"engine",details:{ruleName:d.name,errorName:p instanceof Error?p.name:void 0}}));}if(s){let p=performance.now()-f,u=n.get(d.name);u&&(u.totalMs+=p,u.invocations++);}}},rr=(e,t,r)=>{let{program:o}=t;if(!o)return {results:e.map(c=>({ruleName:c.name,failures:[]})),performance:{traversalMs:0,nodesVisited:0,ruleTimings:[],cacheStats:{hits:0,misses:0},budgetViolations:[],hasBudgetViolations:false}};let n=performance.now(),s=ae(e,{AngularClass:toAngularClassStream,AnyAngularClass:toAnyAngularClassStream,DecoratedProperty:toDecoratedPropertyStream,CallExpression:toCallExpressionStream,NewExpression:toNewExpressionStream}),l=e.filter(c=>c.streamType==="TemplateExpression"),a=e.filter(c=>c.streamType==="TemplateAttribute"),i=e.filter(c=>c.streamType==="TemplateBlock"),d=e.filter(c=>c.streamType==="Template"),f=new Map,p=new Map,u=r?.collectRuleTimings??isDebugEnabled(),x=0;for(let c of e)p.set(c.name,{ruleName:c.name,totalMs:0,invocations:0});if(resetComponentCacheStats(),walkProgram(o,c=>{if(!c?.type)return;x++;let h=s.get(c.type);if(h)for(let S=0;S<h.length;S++){let m=h[S],E=u?performance.now():0;try{let C=m.filter(c);if(C!==null){let v=m.handle(C,t);if(v){let $=f.get(m.ruleName)??[];Array.isArray(v)?$.push(...v):$.push(v),f.set(m.ruleName,$);}}}catch(C){r?.errorCollector?.record(createInfrastructureError("RuleExecutionError",{cause:`Rule ${m.ruleName} failed: ${C instanceof Error?C.message:String(C)}`,recoverable:true,phase:"engine",details:{ruleName:m.ruleName,errorName:C instanceof Error?C.name:void 0}}));}if(u){let C=performance.now()-E,v=p.get(m.ruleName);v&&(v.totalMs+=C,v.invocations++);}}}),t.template&&(l.length>0||a.length>0||i.length>0||d.length>0)){let c=analyzeTemplate(t.template),h=t.templateFilePath&&t.templateFileContent&&t.templateLocator?{...t,filePath:t.templateFilePath,fileContent:t.templateFileContent,locator:t.templateLocator}:t;G(c.expressions,l,h,f,p,u,r?.errorCollector),G(c.attributes,a,h,f,p,u,r?.errorCollector),G(c.blocks,i,h,f,p,u,r?.errorCollector),G([c],d,h,f,p,u,r?.errorCollector);}let w=[];for(let c of e)w.push({ruleName:c.name,failures:f.get(c.name)??[]});let k=performance.now()-n,y=[],g=t.typeChecker?5:2;if(k>g&&y.push(`Total traversal time ${k.toFixed(2)}ms exceeds budget ${g}ms`),u)for(let c of p.values()){if(c.invocations===0)continue;let h=c.totalMs/c.invocations;h>1&&y.push(`Rule ${c.ruleName} averages ${h.toFixed(2)}ms per invocation (threshold: 1ms)`);}return {results:w,performance:{traversalMs:k,nodesVisited:x,ruleTimings:Array.from(p.values()),cacheStats:getComponentCacheStats(),budgetViolations:y,hasBudgetViolations:y.length>0}}};var K=class{context;constructor(t){this.context=t;}async build(t,r,o){let n,s,l,a,i,[d,f]=await Promise.all([this.context.readFile(t),this.context.getProgram(t)]),p=new Locator(d);this.context.getTypeChecker&&(n=await this.context.getTypeChecker(t)),o&&(s=await this.context.getTemplate(t));let u=this.context.getProjectContext?.();o&&!s&&u&&(l=this.resolveExternalTemplatePath(t,u))&&(s=await this.context.getTemplate(l),i=new Locator(a=await this.context.readFile(l)));let x=u?await this.buildCrossRef(t,s,u):void 0;return {filePath:t,fileContent:d,locator:p,program:f,typeChecker:n,template:s,templateFilePath:l,templateFileContent:a,templateLocator:i,options:r,project:u,crossRef:x}}resolveExternalTemplatePath(t,r){let o=t.endsWith(".component.ts")?t:r.templateToComponent.get(t);if(o)return r.componentGraph.get(o)?.templatePath}async buildCrossRef(t,r,o){let n,s,l,a=t.endsWith(".component.ts")?t:o.templateToComponent.get(t);if(!a)return;let i=o.componentGraph.get(a),d=i?.templatePath,f=i?.stylePaths??[],p=i?.specPath;try{let x=await this.getComponentSourceFile(a);x&&(n=(function(w){let k=new Set;for(let y of w.statements)if(T.isClassDeclaration(y))for(let g of y.members){let c=T.canHaveModifiers(g)?T.getModifiers(g):void 0;if(c&&c.some(S=>S.kind===T.SyntaxKind.PrivateKeyword||S.kind===T.SyntaxKind.ProtectedKeyword))continue;let h=g.name;h&&!T.isPrivateIdentifier(h)&&(T.isIdentifier(h)||T.isStringLiteral(h))&&k.add(h.text);}return k})(x),s=(function(w){let k=new Set;for(let y of w.statements)if(T.isClassDeclaration(y))for(let g of y.members){if(!T.isPropertyDeclaration(g)||!g.initializer||!g.name||T.isPrivateIdentifier(g.name))continue;let c=(function(h){let S=T.isAsExpression(h)||T.isSatisfiesExpression(h)?h.expression:h;if(!T.isCallExpression(S))return;let m=S.expression;return T.isIdentifier(m)?m.text:T.isPropertyAccessExpression(m)?T.isIdentifier(m.expression)&&m.expression.text==="input"?"input":m.name.text:void 0})(g.initializer);c&&Ke.has(c)&&(T.isIdentifier(g.name)||T.isStringLiteral(g.name))&&k.add(g.name.text);}return k})(x));}catch{}let u=r;if(!u&&d)try{u=await this.context.getTemplate(d);}catch{}if(u)try{l=(function(x){let w=new Set,k=/\{\{([\s\S]*?)\}\}/g;for(let y of x.rootNodes)(function g(c){if(c&&typeof c=="object"){if(Array.isArray(c.attrs))for(let h of c.attrs){if((typeof h.name=="string"?h.name:"").startsWith("("))continue;let S=h.value;typeof S=="string"&&S&&le(S,w);}if(typeof c.value=="string"&&c.value){let h;for(k.lastIndex=0;(h=k.exec(c.value))!==null;)le(h[1],w);}if(Array.isArray(c.children))for(let h of c.children)g(h);}})(y);return w})(u);}catch{}return {componentPath:a,templatePath:d,stylePaths:f,specPath:p,publicMembers:n,signalMembers:s,templateReferences:l}}async getComponentSourceFile(t){let r=this.context.getTsSourceFile?.(t);if(r)return r;let o=await this.context.readFile(t);return T.createSourceFile(t,o,T.ScriptTarget.Latest,true)}},Ke=new Set(["signal","computed","linkedSignal","input","model","toSignal"]),ie=/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g;function le(e,t){let r;for(ie.lastIndex=0;(r=ie.exec(e))!==null;)t.add(r[1]);}var Xe=new Set([".css",".scss",".sass",".less"]),_=e=>{let t=new LRUCache({max:128}),r=new Map,o=new Map,n=new Map,s=a=>{let i=t.get(a);if(i)return i;let d=Qe(e,a);return t.set(a,d),d},l=a=>{let i=r.get(a);if(i)return i;let d=(async()=>parseTs(await s(a),a).program)();return r.set(a,d),d};return {rootDir:e,readFile:s,getProgram:l,getTemplate:a=>{let i=o.get(a);if(i)return i;let d=(async()=>{let f=await et(a,s,l);if(f&&f.content)return parseHtml(f.content,f.startOffset)})();return o.set(a,d),d},getStyle:a=>{let i=n.get(a);if(i)return i;let d=F.extname(a).toLowerCase();if(!Xe.has(d)){let p=Promise.resolve(void 0);return n.set(a,p),p}let f=(async()=>parseCss(await s(a),a))();return n.set(a,f),f},evict:a=>{t.delete(a),r.delete(a),o.delete(a),n.delete(a);},dispose:()=>{t.clear(),r.clear(),o.clear(),n.clear();}}},Qe=async(e,t)=>{try{return await readFile(F.resolve(e,t),"utf-8")}catch(r){let o=r instanceof Error?r.message:String(r);throw Error(`Cannot read file: ${t}. ${o}`)}},et=async(e,t,r)=>{let o=F.extname(e);if(o===".html")return {content:await t(e),startOffset:0};if(o===".ts"){let n=extractTemplateFromProgram(await r(e));return n.content?n:null}return null};function q(e,t,r,o){let n=performance.now(),s=(function(y,g,c){var h;let S=new Set;for(let E of y)S.add(F.resolve(g,E));let m=(h=g).endsWith(F.sep)?h:h+F.sep;for(let E of c.getSourceFiles())!E.isDeclarationFile&&E.fileName.startsWith(m)&&S.add(E.fileName);return S})(t,r,e),{importGraph:l,reverseImportGraph:a,externalDeps:i}=(function(y,g){let c=y.getCompilerOptions(),h=T.createModuleResolutionCache(y.getCurrentDirectory(),T.sys.useCaseSensitiveFileNames?C=>C:C=>C.toLowerCase(),c),S=new Map,m=new Map,E=new Map;for(let C of g)S.set(C,new Set),m.set(C,new Set);for(let C of y.getSourceFiles()){if(C.isDeclarationFile||!g.has(C.fileName))continue;let v=C.fileName;for(let $ of (function(R){let A=[];return T.forEachChild(R,function N(P){T.isImportDeclaration(P)&&T.isStringLiteral(P.moduleSpecifier)||T.isExportDeclaration(P)&&P.moduleSpecifier&&T.isStringLiteral(P.moduleSpecifier)?A.push(P.moduleSpecifier.text):(T.isCallExpression(P)&&P.expression.kind===T.SyntaxKind.ImportKeyword&&P.arguments.length>0&&T.isStringLiteralLike(P.arguments[0])&&A.push(P.arguments[0].text),T.forEachChild(P,N));}),A})(C)){let R=T.resolveModuleName($,v,c,T.sys,h),A=R.resolvedModule?.resolvedFileName;if(A&&g.has(A)){S.get(v).add(A);let N=m.get(A);N||(N=new Set,m.set(A,N)),N.add(v);}else {let N=(function(P){if(P.startsWith(".")||F.isAbsolute(P))return null;if(P.startsWith("@")){let D=P.indexOf("/",1);if(D===-1)return null;let H=P.indexOf("/",D+1);return H===-1?P:P.slice(0,H)}let W=P.indexOf("/");return W===-1?P:P.slice(0,W)})($);if(N){let P=E.get(v);P||(P=new Set,E.set(v,P)),P.add(N);}}}}return {importGraph:S,reverseImportGraph:m,externalDeps:E}})(e,s),d=(function(y,g){let c=new Set;for(let h of y.getSourceFiles()){if(h.isDeclarationFile||!g.has(h.fileName))continue;let{statements:S}=h;S.length!==0&&S.every(m=>T.isExportDeclaration(m)&&m.moduleSpecifier!=null)&&c.add(h.fileName);}return c})(e,s),f=o??(function(y){let g=new Map,c=[".scss",".sass",".css",".less"];for(let h of y){if(!h.endsWith(".component.ts"))continue;let S=F.dirname(h),m=F.basename(h,".ts"),E=F.join(S,m+".html"),C=y.has(E)?E:void 0,v=[];for(let A of c){let N=F.join(S,m+A);y.has(N)&&v.push(N);}let $=F.join(S,m+".spec.ts"),R=y.has($)?$:void 0;g.set(h,{tsPath:h,templatePath:C,stylePaths:v,specPath:R});}return g})(s),p=(function(y){let g=new Map;for(let[c,h]of y)h.templatePath&&g.set(h.templatePath,c);return g})(f),{ngModuleMap:u,standaloneComponents:x,classToFile:w}=(function(y,g){let c=new Map,h=new Set,S=(function(m,E){let C=new Map;for(let v of m.getSourceFiles())if(!v.isDeclarationFile&&E.has(v.fileName))for(let $ of v.statements){if(!T.isClassDeclaration($)||!$.name)continue;(T.canHaveModifiers($)?T.getModifiers($):void 0)?.some(A=>A.kind===T.SyntaxKind.ExportKeyword)&&C.set($.name.text,v.fileName);}return C})(y,g);for(let m of y.getSourceFiles())if(!m.isDeclarationFile&&g.has(m.fileName))for(let E of m.statements){if(!T.isClassDeclaration(E))continue;let C=T.canHaveDecorators(E)?T.getDecorators(E):void 0;if(C?.length)for(let v of C){let $=(function(N){let P=N.expression;if(!T.isCallExpression(P))return;let W=P.expression;if(!T.isIdentifier(W))return;let D=P.arguments[0],H=D&&T.isObjectLiteralExpression(D)?D:void 0;return {name:W.text,arg:H}})(v);if(!$)continue;let{name:R,arg:A}=$;if(R==="NgModule"){A&&c.set(m.fileName,{filePath:m.fileName,declarations:new Set(j(A,"declarations")),imports:new Set(j(A,"imports")),exports:new Set(j(A,"exports")),providers:new Set(j(A,"providers")),isStandalone:false});break}if(R==="Component"){A&&pe(A,"standalone")&&(h.add(m.fileName),c.set(m.fileName,{filePath:m.fileName,declarations:new Set,imports:new Set(A?j(A,"imports"):[]),exports:new Set,providers:new Set(A?j(A,"providers"):[]),isStandalone:true}));break}if(R==="Directive"||R==="Pipe"){A&&pe(A,"standalone")&&h.add(m.fileName);break}}}return {ngModuleMap:c,standaloneComponents:h,classToFile:S}})(e,s),k=(function(y){let g=0;for(let c of y.values())g+=c.size;return g})(l);return debug("engine",`ProjectContext built in ${(performance.now()-n).toFixed(2)}ms \u2014 ${s.size} files, ${k} import edges, ${d.size} barrels, ${i.size} files with ext deps, ${f.size} components, ${p.size} template\u2194component links, ${u.size} NgModules/standalone, ${x.size} standalone`),{importGraph:l,reverseImportGraph:a,ngModuleMap:u,standaloneComponents:x,classToFile:w,componentGraph:f,projectFiles:s,rootDir:r,barrelFiles:d,externalDeps:i,templateToComponent:p}}function j(e,t){for(let r of e.properties){if(!T.isPropertyAssignment(r)||!T.isIdentifier(r.name)||r.name.text!==t)continue;let o=r.initializer;if(!T.isArrayLiteralExpression(o))break;let n=[];for(let s of o.elements)n.push(...(function l(a){return T.isIdentifier(a)?[a.text]:T.isPropertyAccessExpression(a)||T.isCallExpression(a)?l(a.expression):[]})(s));return n}return []}function pe(e,t){for(let r of e.properties)if(T.isPropertyAssignment(r)&&T.isIdentifier(r.name)&&r.name.text===t)return r.initializer.kind===T.SyntaxKind.TrueKeyword;return false}var Z=(e,t=[],r,o={})=>{let n,s,l=_(e);debug("engine","Initializing Type-Aware Context (ts.createProgram)...");let a=performance.now(),i=r?.tsconfigRootDir?F__default.resolve(e,r.tsconfigRootDir):e,d=r?.project?F__default.resolve(i,r.project):T.findConfigFile(i,T.sys.fileExists,"tsconfig.json");if(d){let p=T.readConfigFile(d,T.sys.readFile),u=T.parseJsonConfigFileContent(p.config,T.sys,i),x=(o.programRootFiles??t).filter(k=>(k.endsWith(".ts")||k.endsWith(".tsx"))&&!k.endsWith(".d.ts")),w=x.length>0?x:u.fileNames;n=T.createProgram({rootNames:w,options:u.options}),debug("engine",`TypeScript Program initialized in ${(performance.now()-a).toFixed(2)}ms with ${w.length} roots (tsconfig had ${u.fileNames.length})`);}else debug("engine","Could not find tsconfig.json; TypeChecker and ProjectContext will be unavailable.");let f=n?.getTypeChecker();if(n&&o.buildProjectContext!==false)try{s=q(n,t,e);}catch(p){let u=p instanceof Error?p.message:String(p);debug("engine",`ProjectContext build failed (non-fatal): ${u}`);}else n&&debug("engine","Skipping ProjectContext build for type-checker-only chunk");return {...l,getTypeChecker:async p=>f,getProjectContext:()=>s,getTsSourceFile:p=>n?.getSourceFile(p),warmup:async()=>{debug("engine",`Type-aware context ready: ${n?`ts.Program with ${n.getSourceFiles().length} source files`:"no tsconfig found, TypeChecker unavailable"}`);},dispose:()=>{s=void 0,f=void 0,n=void 0,l.dispose();}}};var O=(e,t,r)=>{let o=performance.now()-t,n=e.flatMap(i=>i.failures),s=new Set(n.map(i=>i.filePath)),l=n.filter(i=>rt(i.severity)).length,a=n.filter(i=>at(i.severity)).length;return {totalFiles:s.size,totalErrors:l,totalWarnings:a,duration:o,cacheHitRate:r}},rt=e=>e==="error",at=e=>e==="warn";var ue=()=>{throw Error("[ngcompass] Rule executor not configured. Call configureRuleExecutor(executeBatchedNewEngineRules, isNewEngineRule) before running analysis.")},me=()=>false,ot=(e,t)=>{ue=e,me=t;},fe=()=>ue,he=()=>me;var B=async(e,t,r)=>{if(e.length===0)return [];let o=e[0].filePath,n=new K(t),s=new Map,l=[];for(let a of e){let i;if(!he()(a.ruleName)){debug("engine",`Skipping task ${a.taskId}: Rule "${a.ruleName}" not registered in engine.`),l.push({ruleName:a.ruleName,taskId:a.taskId,failures:[]});continue}try{i=stableSerialize(a.options||{});}catch(f){let p=f instanceof SerializationError?f.message:String(f);debug("engine",`Skipping task ${a.taskId}: failed to serialize options \u2014 ${p}`),r?.record(createInfrastructureError("SerializationError",{cause:p,phase:"engine",recoverable:true})),l.push({ruleName:a.ruleName,taskId:a.taskId,failures:[]});continue}let d=s.get(i)??{options:a.options,ruleNames:[],taskIds:[],severities:new Map};d.ruleNames.push(a.ruleName),d.taskIds.push(a.taskId),d.severities.set(a.ruleName,a.severity),s.set(i,d);}for(let a of s.values())try{let i=new Set(a.taskIds),d=e.some(x=>i.has(x.taskId)&&x.inputs.template?.needsAst),f=await n.build(o,a.options,d),p=fe()(a.ruleNames,f),u=new Map;for(let x=0;x<a.ruleNames.length;x++){let w=a.ruleNames[x],k=a.taskIds[x],y=u.get(w)??[];y.push(k),u.set(w,y);}for(let x of p){let w=u.get(x.ruleName),k=a.severities.get(x.ruleName),y=k?{...x,failures:x.failures.map(g=>({...g,severity:k}))}:x;if(w&&w.length>0){let g=w.shift();l.push({...y,taskId:g});}else l.push(y);}}catch(i){let d=i instanceof Error?i.message:String(i);debug("engine",`Failed to execute batch for ${o}: ${d}`),r?.record(createInfrastructureError("ParseError",{filePath:o,cause:d,phase:"engine",recoverable:true}));for(let f=0;f<a.ruleNames.length;f++)l.push({ruleName:a.ruleNames[f],failures:[],taskId:a.taskIds[f]});}return l};var ke=async(e,t,r,o,n,s)=>{let l,{Worker:a}=await import('worker_threads'),i=o??Math.max(2,V.cpus().length),d=await gt();if(!d)return debug("workers","Execution worker not found, falling back to local execution."),ft(e,t,r,n??i,s);let f=yt(e,i),p=0,u=()=>{p++,debug("workers",`Worker progress: ${p}/${i} complete`);},x=[],w=f.map(y=>new Promise((g,c)=>{let h=false,S=new a(d,{workerData:{rootDir:t,tasks:y}});x.push(S);let m=()=>{clearTimeout(E),S.removeAllListeners();},E=setTimeout(()=>{h||(h=true,m(),u(),S.terminate(),c(Error(`Worker timed out after ${6e4/1e3}s`)));},6e4);S.on("message",C=>{ht(C)?s?.(C):h||(h=true,m(),C.errors&&C.errors.length>0&&C.errors.forEach(v=>{debug("workers",`Worker failed task ${v.task.taskId}: ${v.error}`);}),u(),g(C.results));}),S.on("error",C=>{h||(h=true,m(),u(),c(C instanceof Error?C:Error(String(C))));}),S.on("exit",C=>{if(h||C===0)return;h=true,m();let v=createInfrastructureError("WorkerCrash",{cause:`Worker exited with code ${C}`,phase:"engine",recoverable:true,details:{exitCode:C}});debug("workers",`Worker crashed: ${v.cause}`),c(Error(v.cause));});}));try{l=await Promise.all(w);}catch(y){throw await Promise.allSettled(x.map(g=>g.terminate())),y}let k=l.flat();return Ok({results:k,parseErrors:[],stats:O(k,r)})},ft=async(e,t,r,o,n)=>{let s=_(t),l=ee(o),a=groupTasksByFile(e),i=(await Promise.all(Array.from(a.values()).map(d=>l(async()=>{let f=d[0]?.filePath,p=performance.now(),u=await B(d,s);return f&&s.evict(f),f&&n?.(dt(f,d.length,u,performance.now()-p)),u})))).flat();return Ok({results:i,parseErrors:[],stats:O(i,r)})},ht=e=>!!e&&typeof e=="object"&&e.kind==="file-progress",dt=(e,t,r,o)=>{let n=0,s=0;for(let l of r)for(let a of l.failures)a.severity==="error"?n++:a.severity==="warn"&&s++;return {filePath:e,taskCount:t,issueCount:n+s,errorCount:n,warningCount:s,duration:o}},gt=async()=>{let e=dirname(fileURLToPath(import.meta.url));try{let t=createRequire(import.meta.url).resolve("@ngcompass/rules/execution-worker");if(existsSync(t))return t}catch{}for(let t of [join(e,"..","..","rules","dist","execution-worker.js"),join(e,"..","..","rules","dist","execution-worker.cjs")])if(existsSync(t))return t;return null},yt=(e,t)=>{let r=Array.from(groupTasksByFile(e).values()).sort((s,l)=>l.length-s.length),o=Array.from({length:t},()=>[]),n=Array(t).fill(0);for(let s of r){let l=0,a=n[0];for(let i=1;i<t;i++)n[i]<a&&(a=n[i],l=i);o[l].push(...s),n[l]+=s.length;}return o};function Te(e){if(!e||typeof e!="object"||typeof e.ruleName!="string"||!Array.isArray(e.failures))return false;for(let t of e.failures)if(!t||typeof t!="object"||typeof t.filePath!="string"||typeof t.line!="number"||typeof t.column!="number"||typeof t.severity!="string")return false;return true}var ea=async(e,t)=>{try{if(e.precomputedAnalysis){if((function(m){if(!m||typeof m!="object"||!Array.isArray(m.results)||!Array.isArray(m.parseErrors)||!m.stats||typeof m.stats!="object")return !1;let E=m.stats;return typeof E.totalFiles=="number"&&typeof E.totalErrors=="number"&&typeof E.totalWarnings=="number"&&typeof E.duration=="number"})(e.precomputedAnalysis))return debug("engine","Returning precomputed analysis from cache (global hash match)"),Ok(e.precomputedAnalysis);debug("engine","Precomputed analysis failed schema validation \u2014 discarding stale cache entry and re-running analysis");}let r=performance.now(),{tasks:o,skippedTasks:n,cachedResults:s}=e,l=V.cpus().length,a=Math.max(1,Math.min(4,l-1)),i=Math.max(1,Math.min(t.maxWorkers??a,l)),d=t.parallelThreshold??150,f=o.filter(m=>!!m.needsTypeChecker||!!m.needsProjectContext),p=o.filter(m=>!m.needsTypeChecker&&!m.needsProjectContext);debug("engine",`workerTasks: ${p.length}, typeAwareTasks: ${f.length}`);let u=o.length+n.length,x=n.length,w=m=>{x=Math.min(x+m,u),t.onProgress?.(x,u);};n.length>0&&t.onProgress?.(x,u);let k=[];if(p.length>0)if(p.length>d){debug("engine",`Running analysis on ${p.length} syntax-only tasks using workers (max: ${i})...`);let m=await ke(p,t.rootDir,r,i,void 0,t.onFileProgress);if(!m.ok)return m;k=m.data.results,w(p.length);}else debug("engine",`Running analysis on ${p.length} syntax-only tasks locally with batching (concurrency: ${i})...`),k=await re(p,t.rootDir,i,!1,t.errorCollector,void 0,void 0,!0,void 0,w,t.onFileProgress);if(f.length>0&&!t.skipTypeCheck){let m=groupTasksByFile(f).size,E=t.typeAwareChunkSize??(m>=1e3?50:100),C=vt(t.typeAwareConcurrency,i),v=Pt(t.typeAwareFileConcurrency,i),$=await Tt(f,t.rootDir,C,v,E,t,w,t.onFileProgress);k=[...k,...$];}else f.length>0&&t.skipTypeCheck&&debug("engine",`Skipping ${f.length} type-aware tasks (--skip-type-check)`);let y=await Lt(n,s,t.cache),g=[...k,...y],c=o.length+n.length,h=c>0?y.length/c:void 0,S={results:g,parseErrors:[],stats:O(g,r,h)};if(t.cache&&e.globalHash&&S.results.length<=2e4){debug("engine","Caching full analysis result for global hash..."),t.debug&&(debug("engine",`Analysis Results: ${S.results.length} items`),S.results.length>0&&debug("engine",`Sample item keys: ${Object.keys(S.results[0]).join(", ")}`));try{await t.cache.analysis.set(e.globalHash,S);}catch(m){let E=m instanceof Error?m.message:String(m);debug("engine",`Failed to cache analysis result: ${E}`),t.errorCollector?.record(createInfrastructureError("IOError",{cause:`Failed to write analysis cache: ${E}`,phase:"engine",recoverable:!0}));}}else t.cache&&e.globalHash&&debug("engine",`Skipping full analysis cache: ${S.results.length} results exceeds 20000 result safety limit`);return Ok(S)}catch(r){return Err(r instanceof Error?r:Error(String(r)))}},re=async(e,t,r,o,n,s,l,a=true,i,d,f)=>{let p=o?Z(t,s??[],l,{buildProjectContext:a,programRootFiles:i}):_(t);o&&(await p.warmup(),debug("engine",`Phase 1 complete \u2014 TypeScript Program ready. Starting Phase 2: ${r} concurrent file batches.`));let u=groupTasksByFile(e);debug("engine",`Grouped ${e.length} tasks into ${u.size} file batches`);let x=ee(r),w=await Promise.all(Array.from(u.values()).map(k=>x(async()=>{let y=k[0]?.filePath,g=performance.now();try{let c=await B(k,p);return p.evict(y),d?.(k.length),y&&f?.(Ee(y,k.length,c,performance.now()-g,o)),c}catch(c){let h=c instanceof Error?c.message:String(c);return p.evict(y),d?.(k.length),y&&f?.(Ee(y,k.length,[],performance.now()-g,o)),n?.record(createInfrastructureError("IOError",{filePath:y,cause:`Batch execution failed: ${h}`,phase:"engine",recoverable:true})),[]}})));return p.dispose(),w.flat().filter(k=>k!==null)},Tt=async(e,t,r,o,n,s,l,a)=>{let i=groupTasksByFile(e),d=await Ft(i,t,s.typeAwareChunkStrategy??"dependency"),f=s.typeAwareIsolation??"auto",p=f==="process"||f==="auto"&&d.length>=500,u=Mt();debug("engine",`Type-aware: ${e.length} tasks across ${d.length} files; requested chunk size ${n}; adaptive cap ${u}; chunk concurrency=${r}; file concurrency=${o}; isolation=${p?"process":"in-process"}`);let x=[],w=ee(r);for(let k of bt(d,n,u,r)){let y=await Promise.all(k.map(g=>w(async()=>{debug("engine",`Type-aware chunk ${g.index}: ${g.files.length} files, ${g.programRootFiles.length} TS roots, ${g.tasks.length} tasks`);let c=p?await It(g.tasks,t,g.files,g.programRootFiles,g.buildProjectContext,o,s,a):await re(g.tasks,t,o,true,s.errorCollector,g.files,s.parserOptions,g.buildProjectContext,g.programRootFiles,l,a);return p&&l?.(g.tasks.length),c})));x.push(...y.flat()),Et();}return x},Et=()=>{let e=globalThis.gc;typeof e=="function"&&e();},vt=(e,t)=>Math.max(1,Math.min(e==null||Number.isNaN(e)?1:Math.floor(e),t,4)),Pt=(e,t)=>Math.max(1,Math.min(e==null||Number.isNaN(e)?1:Math.floor(e),t,8)),bt=(e,t,r,o)=>{let n=[],s=At(t,r),l=0,a=1;for(let i=0;i<e.length;){let d=[];for(let p=0;p<o&&i<e.length;p++){let u=e.slice(i,i+s),x=u.flatMap(([,k])=>k),w=be(x);w.length>0?d.push({index:a,tasks:x,files:u.map(([k])=>k),programRootFiles:w,buildProjectContext:x.some(k=>!!k.needsProjectContext)}):debug("engine",`Skipping type-aware chunk ${a} with no TypeScript roots (${x.length} tasks)`),a++,i+=u.length;}d.length>0&&n.push(d);let f=$t(s,l,r);s=f.chunkSize,l=f.lowHeapStreak;}return n},At=(e,t)=>Number.isFinite(e)?Math.max(10,Math.min(t,Math.floor(e))):t,Mt=()=>{let e,t=V.totalmem()/1073741824,r=V.freemem()/1073741824,o=ve.getHeapStatistics().heap_size_limit/1073741824,n=V.cpus().length;return e=r<1.5||t<4?100:r<3||t<8?300:r<6||t<16?650:r<12||t<32?1e3:1500,n<=4?e=Math.min(e,500):n>=12&&(e=Math.min(2e3,Math.round(1.2*e))),o<2?e=Math.min(e,250):o<4&&(e=Math.min(e,650)),e=Math.max(10,Math.min(2e3,e)),debug("engine",`Adaptive type-aware chunk cap: ${e} files (free memory ${r.toFixed(1)}GB, total memory ${t.toFixed(1)}GB, V8 heap limit ${o.toFixed(1)}GB, CPUs ${n})`),e},$t=(e,t,r)=>{let o=process.memoryUsage(),n=ve.getHeapStatistics().heap_size_limit,s=n>0?o.heapUsed/n:0;if(s>=.94&&e>10){let l=Math.max(10,Math.floor(e/2));return debug("engine",`Critical heap pressure after type-aware chunk (${Math.round(100*s)}% of V8 heap limit); reducing chunk size to ${l}`),{chunkSize:l,lowHeapStreak:0}}if(s>=.88&&e>10){let l=Math.max(10,Math.floor(.8*e));return debug("engine",`High heap pressure after type-aware chunk (${Math.round(100*s)}% of V8 heap limit); reducing chunk size to ${l}`),{chunkSize:l,lowHeapStreak:0}}if(s<=.35&&e<r){let l=t+1;if(l<3)return {chunkSize:e,lowHeapStreak:l};let a=Math.min(r,e+Math.max(10,Math.floor(.1*e)));return debug("engine",`Sustained low heap pressure after type-aware chunk (${Math.round(100*s)}% of V8 heap limit); increasing chunk size to ${a}`),{chunkSize:a,lowHeapStreak:0}}return {chunkSize:e,lowHeapStreak:0}},be=e=>{let t=new Set;for(let r of e){let o=r.inputs.typescript.path;(o.endsWith(".ts")||o.endsWith(".tsx"))&&!o.endsWith(".d.ts")&&t.add(o);}return [...t]},Ft=async(e,t,r)=>{let o=Array.from(e.entries());if(r==="simple")return debug("engine",`Type-aware chunk ordering: simple path sort for ${o.length} files`),Q(o);debug("engine",`Type-aware chunk ordering: dependency pre-pass for ${o.length} files`);let n=performance.now(),s=await Nt(o,t,n+5e3);return s?(debug("engine",`Dependency chunk ordering complete in ${(performance.now()-n).toFixed(1)}ms`),s):(debug("engine","Dependency chunk ordering exceeded 5000ms; falling back to simple path sort"),Q(o))},Nt=async(e,t,r)=>{let o=new Map,n=ee(64);for(let s=0;s<e.length;s+=64){if(performance.now()>r)return null;let l=e.slice(s,s+64);await Promise.all(l.map(a=>n(async()=>{let[i,d]=a,f=be(d)[0]??i,p=await Rt(f,t),u=o.get(p)??[];u.push(a),o.set(p,u);})));}return [...o.entries()].sort(([s],[l])=>s.localeCompare(l)).flatMap(([,s])=>Q(s))},Q=e=>[...e].sort(([t],[r])=>t.localeCompare(r)),Rt=async(e,t)=>{let r=dirname(e);try{let o=await readFile(e,"utf8"),n=_t(o);return n?join(r,n.split("/")[0]??""):r}catch{return dirname(join(t,e))}},_t=e=>/\b(?:import|export)\b[^'"]*['"](\.{1,2}\/[^'"]+)['"]/g.exec(e)?.[1]??null,It=async(e,t,r,o,n,s,l,a)=>{let i=await Dt();return i?new Promise((d,f)=>{let p=fork(i,[],{cwd:t,execArgv:[],stdio:["ignore","pipe","pipe","ipc"]}),u=false,x=setTimeout(()=>{u||(u=true,p.kill(),f(Error("Type-aware child process timed out after 600s")));},6e5);p.stdout?.on("data",w=>debug("engine",`[type-aware-child] ${String(w).trim()}`)),p.stderr?.on("data",w=>debug("engine",`[type-aware-child:stderr] ${String(w).trim()}`)),p.on("message",w=>{if(jt(w))return void a?.(w);if(zt(w)){if(u)return;u=true,clearTimeout(x),d(w.results);return}if(Wt(w)){if(u)return;u=true,clearTimeout(x),f(Error(w.error));}}),p.on("error",w=>{u||(u=true,clearTimeout(x),f(w));}),p.on("exit",w=>{u||(u=true,clearTimeout(x),f(Error(`Type-aware child process exited before completion with code ${w}`)));}),p.send({rootDir:t,tasks:e,files:r,programRootFiles:o,parserOptions:l.parserOptions,buildProjectContext:n,fileConcurrency:s});}):(debug("engine","Type-aware child worker not found; falling back to in-process execution"),re(e,t,s,true,l.errorCollector,r,l.parserOptions,n,o,void 0,a))},Dt=async()=>{let e=dirname(fileURLToPath(import.meta.url));try{let t=createRequire(import.meta.url).resolve("@ngcompass/rules/type-aware-worker");if(existsSync(t))return t}catch{}for(let t of [join(e,"..","..","rules","dist","type-aware-worker.js"),join(e,"..","..","rules","dist","type-aware-worker.cjs")])if(existsSync(t))return t;return null},jt=e=>!!e&&typeof e=="object"&&e.kind==="file-progress"&&typeof e.filePath=="string"&&typeof e.taskCount=="number"&&typeof e.issueCount=="number"&&typeof e.errorCount=="number"&&typeof e.warningCount=="number"&&typeof e.duration=="number",zt=e=>!!e&&typeof e=="object"&&e.kind==="complete"&&Array.isArray(e.results),Wt=e=>!!e&&typeof e=="object"&&e.kind==="error"&&typeof e.error=="string",Ee=(e,t,r,o,n)=>{let s=0,l=0;for(let a of r)for(let i of a.failures)i.severity==="error"?s++:i.severity==="warn"&&l++;return {filePath:e,taskCount:t,issueCount:s+l,errorCount:s,warningCount:l,duration:o,typeAware:n}},Lt=async(e,t,r)=>{if(e.length===0)return [];debug("engine",`Retrieving results for ${e.length} skipped tasks...`);let o=[],n=[];if(t)for(let s of e){let l=t.get(s.taskId);l&&Te(l)?o.push(l):n.push(s);}else n.push(...e);if(n.length>0&&r){debug("engine",`Fetching ${n.length} results from cache service...`);let s=n.map(a=>a.taskId),l=await r.results.getMany(s);for(let a of n){let i=l.get(a.taskId);i&&Te(i)&&o.push(i);}}return debug("engine",`Retrieved ${o.length} results from cache`),o};var Ae=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Me=class{frameIndex=0;interval=null;message="";start(t){this.message=t,this.frameIndex=0,process.stdout.write("\x1B[?25l"),this.interval=setInterval(()=>{process.stdout.write(`\r${Ae[this.frameIndex]} ${this.message}`),this.frameIndex=(this.frameIndex+1)%Ae.length;},80);}update(t){this.message=t;}stop(t){this.interval&&(clearInterval(this.interval),this.interval=null),process.stdout.write("\r\x1B[K"),t&&process.stdout.write(t+`
2
+ `),process.stdout.write("\x1B[?25h");}};export{Re as BUDGET_MS_PER_FILE_WITHOUT_TYPES,_e as BUDGET_MS_PER_FILE_WITH_TYPES,Fe as MIN_WORKER_COUNT,K as RuleContextFactory,Ne as SPINNER_FRAME_INTERVAL_MS,$e as STREAM_TO_NODE_TYPE,Me as Spinner,oe as WORKER_TIMEOUT_MS,q as buildProjectContext,ae as buildVisitorMap,O as calculateStats,ot as configureRuleExecutor,_ as createAnalysisContext,Bt as createAnyAngularClassRule,Ut as createCallExpressionRule,Ot as createComponentRule,Ht as createDecoratedPropertyRule,Vt as createNewExpressionRule,Kt as createTemplateAttributeRule,Yt as createTemplateBlockRule,Gt as createTemplateExpressionRule,qt as createTemplateRule,Z as createTypeAwareAnalysisContext,B as executeBatchedTasks,ea as runAnalysis,ke as runAnalysisParallel,rr as runSinglePassAnalysis};//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map