🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@ngcompass/rules

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ngcompass/rules - npm Package Compare versions

Comparing version
0.1.6-beta
to
0.1.7-beta
+2
-2
dist/execution-worker.cjs

@@ -1,2 +0,2 @@

'use strict';var worker_threads=require('worker_threads'),engine=require('@ngcompass/engine'),common=require('@ngcompass/common'),ast=require('@ngcompass/ast'),er=require('typescript');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var er__default=/*#__PURE__*/_interopDefault(er);var Mt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var ge=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description||`Rule: ${e}`,category:r.category||"general",dependencyType:r.dependencyType||"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:{severity:"warn",options:{}}}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let i=this.getRegistryEntry(r);i&&e.set(r,i);}return e}get size(){return this._handlers.size}},he=null,X=()=>(he||(he=new ge),he);var N=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:{...t.meta?.requires}}};X().register(r),common.debug("engine",`Registered rule: ${t.name}`);},ke=t=>X().has(t);var De=(t,e)=>{let r=X(),i=[];for(let u of t){let a=r.get(u);a&&i.push(a);}if(i.length===0)return [];common.debug("engine",`Executing ${i.length} rules in single pass on ${e.filePath}`);let{results:o,performance:l}=engine.runSinglePassAnalysis(i,e);return common.debug("engine",`Single-pass complete: ${l.traversalMs.toFixed(2)}ms, ${l.nodesVisited} nodes`),common.debug("engine",`Cache hit rate: ${(l.cacheStats.hits/(l.cacheStats.hits+l.cacheStats.misses||1)*100).toFixed(1)}%`),l.budgetViolations.length>0&&common.debug("engine","Performance budget violations:",l.budgetViolations),o};var je;function s(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function x(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function v(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function O(t,e){let r=s(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!x(r)&&v(r)===e)}function j(t){let e=s(t);if(!e||e.type!=="CallExpression")return "";let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}function Y(t){let e=s(t?.callee);return !!x(e)&&v(e)==="subscribe"}function W(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let i of r){if(!i||i.type!=="Property")continue;let o=i.key;if((o?.type==="Identifier"?o.name:o?.type==="Literal"&&typeof o.value=="string"?o.value:"")===e)return i}return null}function Ee(t){let e=s(t);return !!(e&&e.type==="Literal"&&e.value===true)}function xe(t){let e=s(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Ot=new Set(["parent","span","loc","range","start","end","type"]);function*C(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Ot.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let i of r)i&&typeof i=="object"&&(yield i);else typeof r=="object"&&r.type&&(yield r);}}}function be(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function B(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function U(t){for(let e of t)if(e&&B(e)&&be(e))return e;return null}function L(t){return t?(t.value??t)?.body??null:null}function $e(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function w(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Tt(t){let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let i=s(r[1]);if(!i||i.type!=="ObjectExpression")return false;let o=W(i,"injector");if(o&&!xe(o.value))return true;let l=W(i,"manualCleanup");return !!(l&&Ee(l.value))}function _e(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let i=s(r.pop());if(i)for(let o of(i.type==="CallExpression"&&O(i.callee,"effect")&&!Tt(i)&&e.push(i),C(i)))r.push(o);}return e}function G(t){let e=t?.arguments;if(!Array.isArray(e)||e.length===0)return null;let r=s(e[0]);return r&&(r.type==="ArrowFunctionExpression"||r.type==="FunctionExpression")?r:null}function K(t){if(!t)return null;let e=t.body;return e?s(e):null}function Be(t,e){let r=new Map([...e].map(o=>[o,new Set([o])]));if(typeof t!="string"||t.length===0)return r;let i=new Map([...e].map(o=>[o,RegExp(`^${o}(?:\\s+as\\s+([A-Za-z_$][\\w$]*))?$`)]));for(let o of [/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs['"]/g,/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs\/[^'"]+['"]/g]){let l;for(;(l=o.exec(t))!==null;)for(let u of (l[1]??"").split(",").map(a=>a.trim()).filter(Boolean))for(let[a,p]of i){let c=p.exec(u);c&&r.get(a).add(c[1]??a);}}return r}var It=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function kt(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}return x(e)?v(e):""}function Dt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(It.has(kt(r)))return true;return false}function Z(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let i=s(r.callee);if(!x(i))break;if(v(i)==="pipe"&&Dt(r))return true;e=i?.object;}return false}function k(t,e){let r=t.template?.templateStartOffset;return typeof r=="number"&&Number.isFinite(r)?e+r:e}var jt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),Lt=new Set(["http","httpClient","_http","_httpClient"]),$t=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function Q(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let i=s(r.callee);if(!x(i))break;if(v(i)!=="pipe")return r;e=i?.object;}return null}function J(t){if(!t)return false;let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=s(e.callee);if(!x(r))return false;let i=v(r);if(!i)return false;let o=s(r?.object),l=Array.isArray(e.arguments)?e.arguments:[];if(jt.has(i)&&x(o)){let u=v(o);if(Lt.has(u))return true}if(l.length>0){let u=i.toLowerCase();for(let a of $t)if(u.startsWith(a)&&i.length>a.length)return true}return false}function ee(t){if(!t)return [];let e=t.params;if(Array.isArray(e))return e;if(e&&typeof e=="object"){if("items"in e&&Array.isArray(e.items))return e.items;if("elements"in e&&Array.isArray(e.elements))return e.elements}return []}function F(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="TSParameterProperty")return F(e.parameter);if(e.type==="AssignmentPattern"){let r=s(e.left);return r?.type==="Identifier"?r.name??"":""}if(e.type==="RestElement"){let r=s(e.argument);return r?.type==="Identifier"?r.name??"":""}return ""}function $(t){let e=s(t);if(!e)return "";if(e.type==="TSParameterProperty")return $(e.parameter);let r=e.typeAnnotation,i=s(r?.typeAnnotation??r);if(!i)return "";if(i.type==="TSTypeReference"||i.type==="TypeReference"){let o=i.typeName??i.name;if(o&&typeof o=="object"){if(o.type==="Identifier")return o.name??"";if(o.type==="TSQualifiedName")return o.right?.name??""}if(typeof o=="string")return o}return ""}var Le=false;function Ue(){if(!Le){try{je=Mt("typescript");}catch{}Le=true;}return je}function q(t,e){if(!t||!e.typeChecker)return;let r=Ue();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let i=e.sourceFile;if(!i)return;let o=(function(l,u,a){if(u<l.getStart()||u>=l.getEnd())return;let p=l;for(;;){let c=a.forEachChild(p,n=>{if(u>=n.getStart()&&u<n.getEnd())return n});if(!c)break;p=c;}return p})(i,b(t),r);return o?e.typeChecker.getSymbolAtLocation(o):void 0}catch{return}}var _t=["Service","Facade","Store","Client","Repository","Adapter","Controller","Provider","Registry","Logger","Router","Injector","Handler","Interceptor","Guard","Resolver","Validator"];function Fe(t){if(!t)return false;let e=Ue();if(!e)return false;try{let r=t.getName();if(_t.some(l=>r.endsWith(l)))return !0;let i=t.getDeclarations();if(!i||i.length===0)return !1;let o=i[0];if(!e.canHaveDecorators(o))return !1;for(let l of e.getDecorators(o)??[]){let u=l.expression;if(e.isCallExpression(u)&&e.isIdentifier(u.expression)&&u.expression.text==="Injectable")return !0}return !1}catch{return false}}var E={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},R={"prefer-on-push-component-change-detection":`// Before:
'use strict';var worker_threads=require('worker_threads'),engine=require('@ngcompass/engine'),common=require('@ngcompass/common'),M=require('typescript'),ast=require('@ngcompass/ast');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var M__default=/*#__PURE__*/_interopDefault(M);var Ht=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var zt={severity:"warn",options:{}},Ne=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description??`Rule: ${e}`,category:r.category??"general",dependencyType:r.dependencyType??"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:zt}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let n=this.getRegistryEntry(r);n&&e.set(r,n);}return e}get size(){return this._handlers.size}},ve=null,J=()=>(ve||(ve=new Ne),ve);var R=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:t.meta?.requires??{}}};J().register(r),common.debug("engine",`Registered rule: ${t.name}`);},Ge=t=>J().has(t),Ye=(t,e)=>{let r=J(),n=[];for(let p of t){let d=r.get(p);d&&n.push(d);}if(n.length===0)return [];common.debug("engine",`Executing ${n.length} rules in single pass on ${e.filePath}`);let{results:a,performance:l}=engine.runSinglePassAnalysis(n,e);common.debug("engine",`Single-pass complete: ${l.traversalMs.toFixed(2)}ms, ${l.nodesVisited} nodes`);let c=l.cacheStats.hits+l.cacheStats.misses;if(c>0){let p=l.cacheStats.hits/c*100;common.debug("engine",`Component metadata cache hit rate: ${p.toFixed(1)}%`);}return l.budgetViolations.length>0&&common.debug("engine",`Performance budget violations: ${l.budgetViolations.join("; ")}`),a};var x={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},P={"prefer-on-push-component-change-detection":`// Before:
@Component({ selector: 'app-foo', template: '...' })

@@ -216,3 +216,3 @@ export class FooComponent { }

it('should render', () => { ... });
});`};var te="component-no-manual-detect-changes",Ft=new Set(["detectChanges","markForCheck"]),qt=new Set(["cdr","cdref","changedetectorref","_cdr","_cdref","changedetector","_changedetector","changedetectionref","cd","_cd"]),He=engine.createAnyAngularClassRule(te,(t,e)=>{var r,i;let o,l,u=t.node;if(i=u,ast.analyzeComponent(i)?.type!=="Component")return null;let a=(l=(r=(function(n){let f=new Set,m=w(n),d=U(m);if(d){for(let h of ee(d.value??d))if($(h)==="ChangeDetectorRef"){let y=F(h);y&&f.add(y);}}for(let h of m)if(h.type==="PropertyDefinition"&&h.value){let y=s(h.value);if(y&&(function(g){if(g.type!=="CallExpression")return false;let S=s(g.callee);if(S?.type!=="Identifier"||S.name!=="inject")return false;let[A]=g.arguments??[],M=s(A);return M?.type==="Identifier"&&M.name==="ChangeDetectorRef"})(y)){let g=h.key;g?.type==="Identifier"&&f.add(g.name);}}return f})(u)).size>0,n=>!!r.has(n)||!l&&qt.has(n.toLowerCase())),p=(o=ast.analyzeComponent(u),o?.type==="Component"&&o.changeDetection?.kind==="literal"&&o.changeDetection.value===ast.ChangeDetectionStrategy.OnPush),c=(function(n,f,m,d){let h=[],y=[...w(n)];for(;y.length>0;){let g=s(y.pop());if(!g)continue;let S=(function(A){if(A.type!=="CallExpression")return null;let M=s(A.callee);if(!x(M))return null;let P=v(M);return P&&Ft.has(P)?P:null})(g);for(let A of(S&&(function(M,P){if(M.type!=="CallExpression")return false;let I=s(M.callee);if(!I||!x(I))return false;let T=s(I.object);if(!T)return false;if(T.type==="Identifier")return P(T.name);if(!x(T))return false;let D=s(T.object),_=v(T);return (D?.type==="ThisExpression"||D?.type==="Identifier"&&D.name==="this")&&!!_&&P(_)})(g,d)&&(m&&S==="markForCheck"||h.push((function(M,P,I,T){let D=b(M),{line:_,column:V}=P.locator.location(D);return {filePath:P.filePath,ruleName:te,message:T?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${I}) can hide state-flow bugs and make rendering harder to predict.`,line:_,column:V,severity:T?"warn":"error",fix:E[te],codeExample:R[te]}})(g,f,S,m))),C(g)))y.push(A);}return h})(u,e,p,a);return c.length>0?c:null});var Se="signal-no-side-effects-in-computed",zt=new Set(["post","put","patch","subscribe","unsubscribe","next","complete","setItem","removeItem","appendChild","removeChild","dispatch"]),Wt=new Set(["set","update","mutate"]),Vt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]),ze=engine.createCallExpressionRule(Se,(t,e)=>{if(!O(t.callee,"computed"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let o=(function(l){let u=[l];for(;u.length>0;){var a;let p=s(u.pop());if(p){if(p!==l){if((function(c){let n=s(c);if(!n)return false;if(n.type==="AssignmentExpression"){let f=s(n.left);return !!f&&x(f)}if(n.type==="UpdateExpression"||n.type==="UnaryExpression"&&n.operator==="delete"){let f=s(n.argument);return !!f&&x(f)}return false})(p))return {node:p,type:"write"};if(p.type==="CallExpression"){let c=(function(n){let f=s(n);if(!f||f.type!=="CallExpression")return "";let m=s(f.callee);return x(m)&&v(m)||""})(p);if(Wt.has(c))return {node:p,type:"write"};if(zt.has(c))return {node:p,type:"effect"}}}if(!(p!==l&&(a=p).type&&Vt.has(a.type)))for(let c of C(p))u.push(c);}}return null})(i);return o?(function(l,u,a,p){let c=b(l)||b(u),{line:n,column:f}=a.locator.location(c);return {filePath:a.filePath,ruleName:Se,message:p==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:n,column:f,severity:"error",fix:E[Se]}})(o.node,t,e,o.type):null});var ve="signal-effect-must-be-destroy-scoped",We=engine.createAnyAngularClassRule(ve,(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=[];for(let o of r)o&&B(o)&&!be(o)&&i.push(...(function(l,u){let a=L(l);if(!a)return [];let p=$e(l),c=[];for(let n of _e(a))(function(f){if(f.type!=="CallExpression")return false;let m=s(f.callee);return !!m&&(m.type==="Identifier"?m.name==="effect":!!x(m)&&v(m)==="effect")})(n)&&!(function(f){let m=s((Array.isArray(f.arguments)?f.arguments:[])[1]);if(!m||m.type!=="ObjectExpression")return false;for(let d of Array.isArray(m.properties)?m.properties:[]){let h=s(d);if(h?.type==="Property"){let y=s(h.key),g=y?.type==="Identifier"?y.name:v(y)||"";if(g==="injector")return true;if(g==="manualCleanup"){let S=s(h.value);if(S?.type==="Literal"&&S.value===true)return true}}}return false})(n)&&c.push((function(f,m,d){let h=b(f),{line:y,column:g}=d.locator.location(h);return {filePath:d.filePath,ruleName:ve,message:`effect() inside "${m}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:g,severity:"error",fix:E[ve]}})(n,p,u));return c})(o,e));return i.length>0?i:null});var re="rxjs-no-nested-subscribe",Gt=new Set(["next","error","complete"]),Kt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function Ae(t){if(t.type!=="CallExpression")return false;let e=s(t.callee);return !!x(e)&&v(e)==="subscribe"}function Ve(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var Xe=engine.createCallExpressionRule(re,(t,e)=>{if(!Ae(t))return null;for(let r of (function(i){if(!Ae(i))return [];let o=Array.isArray(i.arguments)?i.arguments:[];if(o.length===0)return [];let l=s(o[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let a=[];for(let p of Array.isArray(l.properties)?l.properties:[]){let c=s(p);if(c?.type==="Property"&&Gt.has((function(n){let f=s(n.key);return f?f.type==="Identifier"?f.name:v(f)||"":""})(c))){let n=s(c.value);Ve(n)&&a.push(n);}}return a}let u=[];for(let a=0;a<Math.min(o.length,3);a++){let p=s(o[a]);Ve(p)&&u.push(p);}return u})(t)){let i=s(r.body);if(i&&(function(o){let l=[o];for(;l.length>0;){var u;let a=s(l.pop());if(a){if(a!==o&&Ae(a))return true;if(!(a!==o&&(u=a).type&&Kt.has(u.type)))for(let p of C(a))l.push(p);}}return false})(i))return (function(o,l){let u=b(o),{line:a,column:p}=l.locator.location(u);return {filePath:l.filePath,ruleName:re,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:a,column:p,severity:"error",fix:E[re],codeExample:R[re]}})(t,e)}return null});var ne="prefer-on-push-component-change-detection";function ie(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function oe(t){return t.replace(/\\/g,"/")}var Ye=engine.createComponentRule(ne,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(i){if(!i||typeof i!="object")return false;let{kind:o,value:l}=i;return o!=="non-literal"&&(o==="literal"?l!==ast.ChangeDetectionStrategy.OnPush:o==="missing")})(r.changeDetection)?null:(function(i,o){let l,u,a,p,c=(l=i.metadata??{},u=i.node,ie(l,"decoratorStart")??ie(l,"start")??ie(u,"start")??ie(i,"start")??0),{line:n,column:f}=o.locator.location(c),m=(a=i.metadata,typeof(p=a?.className)=="string"?p:"AnonymousComponent"),d=(function(h,y){if(!y.project)return null;let g=h.metadata,S=g?.className;if(typeof S!="string"||!S)return null;let A=oe(y.filePath),{ngModuleMap:M,classToFile:P}=y.project;for(let[T,D]of M){var I;if(D.isStandalone||!D.declarations.has(S))continue;let _=P.get(S);if(_&&oe(_)!==A)continue;let V=0;for(let Ie of D.declarations)Ie!==S&&(I=P.get(Ie))&&oe(I).endsWith(".component.ts")&&V++;return {moduleName:(oe(T).split("/").pop()??T).replace(/\.ts$/,""),siblingComponentCount:V}}return null})(i,o);return {filePath:o.filePath,ruleName:ne,message:(function(h,y){if(!y)return `Component '${h}' uses default change detection, which can re-render more often than needed.`;let{moduleName:g,siblingComponentCount:S}=y,A=S>0?` ${S} other component${S===1?"":"s"} are declared in '${g}'.`:"";return `Component '${h}' uses default change detection, which can re-render more often than needed.${A}`})(m,d),line:n,column:f,severity:"error",fix:E[ne],codeExample:R[ne]}})(t,e)},{requires:{projectContext:true}});var Ne="template-no-call-expression",tr=new Set(["translate","$localize","$any"]),rr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function Ge(t){let e=s(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var Ke=engine.createTemplateExpressionRule(Ne,(t,e)=>(function(r,i){let o=r?[r]:[];for(;o.length>0;){let l=s(o.pop());if(l){if(Ge(l)&&!(function(u){let a=s(u);if(!a||!Ge(a))return false;let p=s(a.callee);if(!p)return false;if(p.type==="Identifier")return tr.has(p.name);if(!x(p))return false;let c=v(p);return !!c&&rr.has(c)})(l)){if((function(a){let p;return (p=s(a),Array.isArray(p?.arguments)?p.arguments:[]).length>0})(l))return true;let u=(function(a){let p=s(a);if(!p)return "";let c=s(p.callee);return c?c.type==="Identifier"?c.name??"":x(c)?v(c):"":""})(l);if(u&&!(function(a,p){let c=a.startsWith("get")||a.startsWith("is")||a.startsWith("has");if(p.crossRef?.signalMembers?.has(a))return true;if(p.typeChecker&&p.crossRef?.componentPath)try{let n=p.typeChecker,f=p.crossRef.componentPath,m=n.getProgram().getSourceFile(f);if(m){let d=m.statements.find(h=>er__default.default.isClassDeclaration(h));if(d&&d.name){let h=n.getTypeAtLocation(d),y=n.getPropertyOfType(h,a);if(y){if(!y)return !1;let g=y.valueDeclaration??y.declarations?.[0];if(!g)return !1;let S=n.getTypeOfSymbolAtLocation(y,g);if(!S)return !1;let A=n.typeToString(S);return A.includes("Signal")||A.includes("writable")||A.includes("computed")}}}}catch{}return !c})(u,i))return true}for(let u of C(l))o.push(u);}}return false})(t.expression,e)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ne,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:u,severity:"error",fix:E[Ne]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function Ze(t,e,r,i){let o=k(t,e.sourceSpan.start),{line:l,column:u}=t.locator.location(o);return {filePath:t.filePath,ruleName:r,message:i,line:l,column:u,severity:"error",fix:E[r]}}var Qe=engine.createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let i of t.attributes)i.name==="*ngFor"&&!(function(o){return !!o.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(i.value??"")&&r.push(Ze(e,i,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let i of t.blocks)i.name!=="for"||i.parameters.some(o=>{let l=o.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(Ze(e,i,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Ce="template-no-object-literal-binding",Je=engine.createTemplateExpressionRule(Ce,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ObjectExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ce,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ce]}})(t,e)]:null,{requires:{htmlAst:true}});var Re="template-no-array-literal-binding",et=engine.createTemplateExpressionRule(Re,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ArrayExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Re,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Re]}})(t,e)]:null,{requires:{htmlAst:true}});var we=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),tt=engine.createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let u=s(l.callee);if(!u)return null;if(u.type==="Identifier"&&u.name)return we.has(u.name)?u.name:null;if(x(u)){let a=v(u);return a&&we.has(a)?a:null}return null})(t);if(!r)return null;let{line:i,column:o}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${we.get(r)} sanitization, which can expose unsafe content.`,line:i,column:o,severity:"error",fix:E["no-bypass-sanitization"]}});var lr=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),ur=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,cr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,rt=engine.createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=lr.get(t.name);if(!r)return null;let i=t.value??"";if(ur.test(i)||cr.test(i)||t.name==="[style]"&&!/[.(|?]/.test(i))return null;let{line:o,column:l}=e.locator.location(k(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:o,column:l,severity:r.severity,fix:E["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var fr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),nt=engine.createAnyAngularClassRule("no-document-access",(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=new Set,c=[...a];for(;c.length;){let n=s(c.pop());if(n){if(n.type==="VariableDeclarator"&&n.init){let f=s(n.init);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=n.id??n.key;m?.type==="Identifier"&&m.name&&p.add(m.name);}}if(n.type==="AssignmentExpression"&&n.right){let f=s(n.right);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=s(n.left);if(m&&x(m)&&s(m.object)?.type==="ThisExpression"){let d=m.property?.name;typeof d=="string"&&d&&p.add(d);}}}for(let f of C(n))c.push(f);}}return p})(r),o=[],l=new Set,u=[...r];for(;u.length;){let a=s(u.pop());if(a){if(a.type==="IfStatement"&&a.test){let p=s(a.test);if(p){let c=(function(n,f){let m=[n];for(;m.length;){let d=s(m.pop());if(d){if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformBrowser"))return "browser";if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformServer"))return "server";if(d.type==="UnaryExpression"&&d.operator==="!"&&d.argument){let h=s(d.argument);if(h?.type==="CallExpression"&&h.callee&&O(h.callee,"isPlatformServer"))return "browser"}if(d.type==="Identifier"&&f.has(d.name))return "browser";for(let h of C(d))m.push(h);}}return null})(p,i);if(c==="browser"){a.alternate&&u.push(a.alternate);continue}if(c==="server"){a.consequent&&u.push(a.consequent);continue}}}if(a.type==="CallExpression"&&a.callee){let p=s(a.callee);if(p&&(O(p,"afterNextRender")||O(p,"afterRender"))){let c=a.arguments??[];for(let n=1;n<c.length;n++)u.push(c[n]);continue}}if(x(a)){let p=(function(c){let n=c;for(;n&&x(n);)n=s(n.object);return n?.type==="Identifier"?n.name??null:null})(a);if(p&&fr.has(p)){let c=a;for(;c&&x(c);)c=s(c.object);let n=b(c);if(n!==void 0&&!l.has(n)){l.add(n);let{line:f,column:m}=e.locator.location(n);o.push({filePath:e.filePath,ruleName:"no-document-access",message:`Direct access to \`${p}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:E["no-document-access"],codeExample:R["no-document-access"]});}}}for(let p of C(a))u.push(p);}}return o.length?o:null});var dr=new Set(["nativeElement","getBoundingClientRect","querySelector","querySelectorAll","getElementById","createElement","scrollIntoView","focus","blur","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollTop","scrollLeft","innerHTML","outerHTML","textContent","parentElement","parentNode","firstChild","lastChild","nextSibling","previousSibling","children","ownerDocument","insertBefore","appendChild","removeChild","replaceChild","cloneNode","setAttribute","getAttribute","removeAttribute","hasAttribute","classList","dispatchEvent","contains","matches","closest","getClientRects","addEventListener","removeEventListener","requestAnimationFrame","cancelAnimationFrame"]),yr=["getElementsBy","offset","client","scroll"],it=engine.createAnyAngularClassRule("prefer-after-render-over-after-view-init",(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of ["ngAfterViewInit","ngAfterContentInit"]){let l=r.find(c=>c.key?.name===o),u=l?L(l):null;if(!u||!l||!(function(c){let n=[c];for(;n.length;){let f=s(n.pop());if(f){if((f.type==="MemberExpression"||f.type==="StaticMemberExpression"||f.type==="OptionalMemberExpression")&&!f.computed){let m=f.property?.name??"";if(dr.has(m))return true;for(let d of yr)if(m.startsWith(d))return true}if(f.type==="Identifier"&&(f.name==="document"||f.name==="window"))return true;for(let m of C(f))n.push(m);}}return false})(u))continue;let{line:a,column:p}=e.locator.location(b(l));i.push({filePath:e.filePath,ruleName:"prefer-after-render-over-after-view-init",message:`\`${o}\` contains DOM access that can run before browser-only APIs are safe.`,line:a,column:p,severity:"warn",fix:E["prefer-after-render-over-after-view-init"],codeExample:R["prefer-after-render-over-after-view-init"]});}return i.length?i:null});var ae=new Map;function Me(t){return /ngOnDestroy\s*\([^)]*\)\s*\{[^}]*\.unsubscribe\s*\(\)/s.test(t)}var ot=engine.createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t))return null;let l=s(t.callee),u=x(l)?l?.object:null;if(u&&Z(u)||J(Q(u))||(r=e.filePath,i=e.fileContent,(o=ae.get(r))!==void 0||(o=Me(i),ae.size>=500&&ae.clear(),ae.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:p,column:c,severity:"error",fix:E["rxjs-require-takeUntilDestroyed"]}});var se=new Map,le="rxjs-no-subscribe-in-component",at=engine.createCallExpressionRule(le,(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t)||(function(n){let f=s(n.callee);if(!f||!x(f))return false;let m=s(f.object);if(!m)return false;if(m.type==="CallExpression"){let d=s(m.callee);if(x(d)&&v(d)==="pipe"&&(Array.isArray(m.arguments)?m.arguments:[]).some(h=>{let y=s(h);if(y?.type!=="CallExpression")return false;let g=s(y.callee)?.name;return g==="take"||g==="first"}))return true}return J(Q(m))})(t))return null;let l=s(t.callee),u=s(l?.object);if(u&&Z(u)||(r=e.filePath,i=e.fileContent,(o=se.get(r))!==void 0||(o=Me(i),se.size>=500&&se.clear(),se.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:le,message:(function(n,f){let m="Open-ended subscriptions in components can outlive the component and make state harder to track.",d=f.crossRef?.templateReferences;if(!d)return m;let h=s(n.callee),y=s(h?.object),g=y?v(y):null;if(!g)return m;let S=g.endsWith("$")?g.slice(0,-1):g;return d.has(g)||d.has(S)?`'${g}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:m})(t,e),line:p,column:c,severity:"error",fix:E[le],codeExample:R[le]}},{requires:{projectContext:true}});var ue="rxjs-avoid-subject-as-event-bus",st=new Set(["Subject","ReplaySubject","AsyncSubject","BehaviorSubject"]),xr=new Set(["destroy$","destroyed$","ondestroy$","ngondestroy$","unsubscribe$","unsub$","teardown$","dispose$","cleanup$","cleanupsubject$"]),br=/state|loading|error|active|selected|open|visible|disabled|count|value|data|hidden|expanded|pending|success|failed/i;function H(t,e,r){let i=[t];for(;i.length;){let o=s(i.pop());if(!o)continue;let l=s(o.callee);if(o.type==="CallExpression"&&v(l)===e){let u=s(l?.object);if(u&&x(u)&&s(u.object)?.type==="ThisExpression"){let a=v(u);a&&r.add(a);}}for(let u of C(o))i.push(u);}}var lt=engine.createAnyAngularClassRule(ue,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=Be(a.sourceText,st),c=new Map;for(let[n,f]of p)for(let m of f)c.set(m,n);return c})(e),o=(function(a){let p=new Set,c=U(a);if(c){let n=L(c);n&&H(n,"next",p);}for(let n of a)if(B(n)){n.kind==="set"&&(function(m){let d=m.decorators;if(!Array.isArray(d))return false;for(let h of d){let y=s(h.expression);if(y?.name==="Input"||s(y?.callee)?.name==="Input")return true}return false})(n)&&H(n,"next",p);let f=n.key?.name;if(f==="ngOnChanges"){let m=L(n);m&&H(m,"next",p);}if(f==="ngOnDestroy"){let m=L(n);m&&H(m,"complete",p);}}else n.type==="PropertyDefinition"&&n.value&&H(n.value,"next",p);return p})(r),l=(function(a){let p=new Set;for(let c of a){let n=B(c)?L(c):c.type==="PropertyDefinition"?c.value:null;n&&H(n,"pipe",p);}return p})(r),u=[];for(let a of r){if(a.type!=="PropertyDefinition"||a.accessibility==="public")continue;let p=s(a.value??a.initializer);if(!p||p.type!=="NewExpression")continue;let c=(function(d,h){let y=s(d);if(!y)return null;if(y.type==="Identifier")return h.get(y.name)??null;if(x(y)){let g=v(y);return g&&st.has(g)?g:null}return null})(p.callee,i),n=a.key?.name??"";if(!c||!n||xr.has(n.toLowerCase())||o.has(n)||l.has(n))continue;let{line:f,column:m}=e.locator.location(b(a));u.push({filePath:e.filePath,ruleName:ue,message:br.test(n)?`${c} '${n}' is used for component UI state, which adds stream overhead to local state updates.`:`${c} '${n}' is acting as a local event bus, which makes component interactions harder to trace.`,line:f,column:m,severity:"warn",fix:E[ue],codeExample:R[ue]});}return u.length?u:null});var Pe="rxjs-prefer-toSignal-for-template-state",ut=new Set(["Observable","Subject","BehaviorSubject","ReplaySubject","AsyncSubject"]),vr=new Set(["destroy$","destroyed$","unsub$","teardown$","dispose$"]),ct=engine.createAnyAngularClassRule(Pe,(t,e)=>{if(t.metadata?.type!=="Component")return null;let i=e.crossRef?.templateReferences;if(i===void 0)return null;let o=w(t.node),l=[];for(let u of o){if(u.type!=="PropertyDefinition")continue;let a=u.key?.name??"";if(!a||!a.endsWith("$")||vr.has(a.toLowerCase())||(function(f){let m=f.modifiers,d=f.decorators??(Array.isArray(m)?m.filter(h=>h.type==="Decorator"):void 0);return Array.isArray(d)&&d.some(h=>{let y=s(h.expression);return (y?.type==="CallExpression"?j(y):y?.type==="Identifier"?y.name:null)==="Output"})})(u))continue;let p=a.slice(0,-1);if(!i.has(a)&&!i.has(p)||!(function(f){if(ut.has((function(y){let g=y.typeAnnotation,S=s(g?.typeAnnotation);if(!S||S.type!=="TSTypeReference"&&S.type!=="TypeReference")return "";let A=S.typeName??S.name;if(typeof A=="string")return A;if(A&&typeof A=="object"){if(A.type==="Identifier")return A.name??"";if(A.type==="TSQualifiedName")return s(A.right)?.name??""}return ""})(f)))return true;let m=s(f.value??f.initializer);if(!m)return false;let d=j(m);if(d==="toSignal"||d==="signal"||d==="computed")return false;if(m.type==="NewExpression"){let y=s(m.callee),g=y?.type==="Identifier"?y.name:v(y);return !!g&&ut.has(g)}let h=[m];for(;h.length>0;){let y=s(h.pop());if(y){if(y.type==="CallExpression"&&j(y)==="pipe")return true;for(let g of C(y))h.push(g);}}return false})(u))continue;let{line:c,column:n}=e.locator.location(b(u));l.push({filePath:e.filePath,ruleName:Pe,message:`Observable "${a}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:c,column:n,severity:"warn",fix:E[Pe]});}return l.length?l:null},{requires:{projectContext:true,htmlAst:true}});var Oe="toSignal-require-initialValue",pt=engine.createCallExpressionRule(Oe,(t,e)=>{if(!O(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],i=r[1]?s(r[1]):null;if(!i||i.type!=="ObjectExpression"||!(function(o){let l=W(o,"initialValue");if(l&&!xe(l.value))return true;let u=W(o,"requireSync");return !!u&&Ee(u.value)})(i)){let{line:o,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:Oe,message:"toSignal() can emit undefined before the observable produces a value.",line:o,column:l,severity:"warn",fix:E[Oe]}}return null});var Cr=new Set(["set","update","mutate"]),Rr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame","then","catch","finally","subscribe"]),ft=engine.createCallExpressionRule("signal-prefer-computed-over-sync-effect",(t,e)=>{if(!O(t.callee,"effect"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let{hasRead:o,hasWrite:l,hasAsync:u,hasLinked:a,firstWrite:p}=(function(f,m){let d={hasRead:false,hasWrite:false,hasAsync:false,hasLinked:false,firstWrite:null},h=[f];for(;h.length;){let y=s(h.pop());if(y){if((y.type==="AwaitExpression"||y.type==="YieldExpression")&&(d.hasAsync=true),y.type==="CallExpression"){let g=j(y);g&&Rr.has(g)&&(d.hasAsync=true),g==="linkedSignal"&&(d.hasLinked=true),(function(S){let A=s(S);if(!A||A.type!=="CallExpression")return false;let M=s(A.callee);return x(M)&&Cr.has(v(M)||"")})(y)?(d.hasWrite=true,d.firstWrite||(d.firstWrite=y)):(function(S,A,M){let P=s(S);if(!P||P.type!=="CallExpression"||Array.isArray(P.arguments)&&P.arguments.length>0)return false;let I=s(P.callee);if(!I)return false;if(A.typeChecker)try{let T=q(I,A);if(T){let D=A.typeChecker.getTypeOfSymbolAtLocation(T,T.valueDeclaration);if(D&&A.typeChecker.typeToString(D).includes("Signal"))return !0}}catch{}return x(I)?s(I.object)?.type==="ThisExpression":M&&I.type==="Identifier"})(y,m,true)&&(d.hasRead=true);}for(let g of C(y))h.push(g);}}return d})(i,e);if(!l||!o||u||a)return null;let{line:c,column:n}=e.locator.location(b(p||t));return {filePath:e.filePath,ruleName:"signal-prefer-computed-over-sync-effect",message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:c,column:n,severity:"warn",fix:E["signal-prefer-computed-over-sync-effect"]}},{requires:{typeChecker:true}});var mt=new Set(["afterRender","afterNextRender"]),Mr=/\bafterNextRender\s*\(|\bafterRender\s*\(/,ce=new Map,dt=engine.createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!O(t.callee,"untracked")||(function(o,l){let u=l.sourceText??l.fileContent;if(typeof u=="string"&&!Mr.test(u))return false;let a=o.parent;for(;a;){if(a.type==="CallExpression"&&mt.has(j(a)))return true;a=a.parent;}let p=b(o);return (function(c){let n=ce.get(c.filePath);if(n!==void 0)return n;let f=c.program;return n=f?(function(m){let d=[],h=m.body,y=Array.isArray(h)?[...h]:[m];for(;y.length;){let g=s(y.pop());if(g){if(g.type==="CallExpression"&&mt.has(j(g))){let S=s(g.arguments?.[0]);if(S){let A=b(S),M=S.end??S.span?.end??b(S);M>A&&d.push([A,M]);}}for(let S of C(g))y.push(S);}}return d})(f):[],ce.size>=300&&ce.clear(),ce.set(c.filePath,n),n})(l).some(([c,n])=>p>=c&&p<n)})(t,e))return null;let{line:r,column:i}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:i,severity:"warn",fix:E["signal-avoid-untracked-overuse"]}});var pe="prefer-inject-over-constructor-di",Or=new Set(["http","router","route","cdr","cdref","changedetectorref","injector","ngzone","zone","renderer","renderer2","elementref","el","document","platform","location","dialog","snack","toast","store","facade","logger","translate","i18n","auth","api","client","matdialog","overlay","breakpointobserver","snackbar","matsnackbar","bottomsheet","matbottomsheet","clipboard","directionality","focusmonitor","mediamatcher","viewportruler","scrolldispatcher","dragdrop","liveannouncer","activatedroute","fb","firestore","angularfire","formbuilder","titleservice","metaservice","title","meta","sanitizer","domsanitizer","compiler","applicationref","componentfactoryresolver","viewcontainerref","templateref","destroyref"]),Tr=new Set(["data","config","options","opts","params","payload","input","value","values","items","item","context","ctx","model","vm","state","initialstate","result","name","id","label","text","title","message","url","path","index","count","size","length","width","height","color","type","key","mode","flag","enabled","disabled","visible","hidden"]),Ir=["Service","Facade","Store","Client","Repository","Adapter","Manager","Controller","Provider","Registry","Logger","Router","ActivatedRoute","ChangeDetectorRef","DestroyRef","Injector","NgZone","Renderer2","ElementRef","HttpClient","ViewContainerRef","TemplateRef","ComponentFactoryResolver","ApplicationRef","MatDialog","MatDialogRef","MatSnackBar","MatBottomSheet","Overlay","OverlayRef","BreakpointObserver","Clipboard","FocusMonitor","MediaMatcher","ScrollDispatcher","DragDrop","LiveAnnouncer","Directionality","ViewportRuler","FormBuilder","DomSanitizer","Title","Meta","Dispatcher","Gateway","Handler","Interceptor","Guard","Resolver","Factory","Strategy","Validator"],kr=new Set(["string","number","boolean","symbol","bigint","any","unknown","void"]),yt=engine.createAnyAngularClassRule(pe,(t,e)=>{let r=U(w(t.node));if(!r)return null;let i=ee(r.value??r).filter(a=>(function(p,c){let n=s(p);if(!n)return false;if(Array.isArray(n.decorators)&&n.decorators.length>0||n.accessibility||n.readonly)return true;if(c.typeChecker){let d=q(p,c);if(d&&Fe(d))return true}let f=(F(p)||"").toLowerCase().trim();if(!f||Tr.has(f))return false;if(Or.has(f))return true;let m=($(p)||"").trim();return !(!m||kr.has(m.toLowerCase()))&&Ir.some(d=>m.endsWith(d))})(a,e));if(i.length===0)return null;let{line:o,column:l}=e.locator.location(b(r)),u=i.map(a=>`${F(a)}: ${$(a)}`).join(", ");return {filePath:e.filePath,ruleName:pe,message:`Constructor dependency injection makes class setup less composable than inject().${u?` Offending params: ${u}.`:""}`,line:o,column:l,severity:"warn",fix:E[pe],codeExample:R[pe]}},{requires:{typeChecker:true}});var fe="signal-prefer-input-signal";function jr(t){let e=s(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var ht=engine.createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[],o=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let u=s(l);if(u&&(u.type==="PropertyDefinition"||u.type==="AccessorProperty")&&Array.isArray(u.decorators)&&u.decorators.some(jr)){let a=b(u),{line:p,column:c}=e.locator.location(a),n=s(u.key),f=(n?.type==="Identifier"?n.name:n?.type==="Literal"?String(n.value):"")||"(unknown)",m=`'${f}' uses @Input(), which keeps this input outside Angular's signal graph.`;o&&(m+=" Standalone declarations benefit most from signal inputs."),i.push({filePath:e.filePath,ruleName:fe,message:m,line:p,column:c,severity:o?"error":"warn",fix:E[fe],codeExample:R[fe]});}}return i.length>0?i:null},{requires:{projectContext:true}});var me="signal-prefer-output-function",gt=engine.createAnyAngularClassRule(me,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of r){let l=s(o);if(l&&(l.type==="PropertyDefinition"||l.type==="AccessorProperty")&&Array.isArray(l.decorators)&&l.decorators.some(u=>{let a=s(u.expression??u);if(!a)return false;if(a.type==="Identifier")return a.name==="Output";if(a.type==="CallExpression"){let p=s(a.callee);return p?.type==="Identifier"&&p.name==="Output"}return false})&&(function(u,a){let p=s(u.value);if(p?.type==="NewExpression"){let n=s(p.callee);if(n?.type==="Identifier"&&n.name==="EventEmitter")return true}let c=s(u.typeAnnotation);if(c&&$(c).includes("EventEmitter"))return true;if(a.typeChecker){let n=q(u,a);if(n&&(typeof n.getName=="function"?n.getName():"").includes("EventEmitter"))return true}return false})(l,e)){let u=b(l),{line:a,column:p}=e.locator.location(u),c=s(l.key),n=(c?.type==="Identifier"?c.name:c?.type==="Literal"?String(c.value):"")||"(unknown)";i.push({filePath:e.filePath,ruleName:me,message:`'${n}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:a,column:p,severity:"warn",fix:E[me],codeExample:R[me]});}}return i.length>0?i:null},{requires:{typeChecker:true}});var de="signal-prefer-model";function Et(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let i=s(r.expression??r);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(i.type==="CallExpression"){let o=s(i.callee);return o?.type==="Identifier"&&o.name===e}return false})}function xt(t,e){let r=s(t.value);if(!r||r.type!=="CallExpression")return false;let i=s(r.callee);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(x(i)){let o=s(i.object);return o?.type==="Identifier"&&o.name===e}return false}var bt=engine.createAnyAngularClassRule(de,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=new Map,o=new Map;for(let u of r){let a=s(u);if(!a||a.type!=="PropertyDefinition"&&a.type!=="AccessorProperty")continue;let p=(function(c){let n=s(c.key);return n?n.type==="Identifier"?n.name??null:n.type==="Literal"?String(n.value):null:null})(a);p&&((Et(a,"Input")||xt(a,"input"))&&i.set(p,a),(Et(a,"Output")||xt(a,"output"))&&o.set(p,a));}let l=[];for(let[u,a]of o){if(!u.endsWith("Change"))continue;let p=u.slice(0,-6),c=i.get(p);if(c){let n=b(c),{line:f,column:m}=e.locator.location(n);l.push({filePath:e.filePath,ruleName:de,message:`The \`${p}\` / \`${u}\` pair implements two-way binding with extra wiring that model() avoids.`,line:f,column:m,severity:"warn",fix:E[de],codeExample:R[de]});}}return l.length>0?l:null});var Br=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Te="template-prefer-control-flow",St=engine.createTemplateAttributeRule(Te,(t,e)=>{var r;let i=(r=t.name,Br.get(r)??null);if(!i)return null;let o=k(e,t.sourceSpan.start),{line:l,column:u}=e.locator.location(o);return {filePath:e.filePath,ruleName:Te,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${i}\` control flow benefits.`,line:l,column:u,severity:"error",fix:E[Te]}},{requires:{htmlAst:true}});var vt=new WeakMap,At=engine.createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,i,o=(function c(n){let f=s(n);if(!f)return null;if(f.type==="BinaryExpression"&&f.operator==="|"){let m=s(f.right);return m?.type==="Identifier"&&m.name==="async"?s(f.left):c(f.left)}return null})(t.expression),l=o?(function c(n,f=0){if(!n||f>10)return null;if(n.type==="Identifier")return n.name;if(n.type==="ThisExpression")return "this";if(n.type==="Literal"){let m=n.value;return m===null?"null":typeof m=="string"||typeof m=="number"||typeof m=="boolean"||typeof m=="bigint"?String(m):null}if(n.type==="CallExpression"){let m=c(n.callee,f+1),d=(Array.isArray(n.arguments)?n.arguments:[]).map(h=>c(h,f+1)??"?");return `${m}(${d.join(",")})`}if(x(n)){let m=c(n.object,f+1),d=v(n);if(m&&d)return `${m}.${d}`}if(n.type==="UnaryExpression")return `${n.operator}${c(n.argument,f+1)}`;if(n.type==="ConditionalExpression")return `${c(n.test,f+1)}?${c(n.consequent,f+1)}:${c(n.alternate,f+1)}`;if(n.type==="OptionalExpression"||n.type==="ChainExpression")return c(n.expression,f+1);if(n.type==="LogicalExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="BinaryExpression"&&n.operator!=="|"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="ArrayExpression")return `[${(n.elements??[]).map(d=>c(d,f+1)??"?").join(",")}]`;if(n.type==="ObjectExpression")return `{${(n.properties??[]).map(d=>{let h=d.key?c(d.key,f+1):"?",y=d.value?c(d.value,f+1):"?";return `${h}:${y}`}).join(",")}}`;if(n.type==="TemplateLiteral")return "`tmpl`";if(n.type==="AssignmentExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}return null})(o):null;if(!l)return null;let u=(r=e.template,i=r?.templateStartOffset,`${e.filePath}@${typeof i=="number"&&Number.isFinite(i)?i:0}`),a=vt.get(e);a||(a=new Map,vt.set(e,a));let p=a.get(u);if(p||(p=new Set,a.set(u,p)),p.has(l)){let c=k(e,t.sourceSpan.start),{line:n,column:f}=e.locator.location(c);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:n,column:f,severity:"warn",fix:E["template-no-async-pipe-duplication"]}}return p.add(l),null},{requires:{htmlAst:true}});var qr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Hr=new Set(["xdescribe","xit","xtest","xcontext"]);function Nt(t){return t.type==="Identifier"?t.name??null:null}var Ct=engine.createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let i;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let o=s(t.callee);if(!o)return null;let l=(i=Nt(o)||(function(n){if(n.type==="MemberExpression"||n.type==="StaticMemberExpression"||n.type==="OptionalMemberExpression"){let f=s(n.object),m=n.property?.name??"",d=(f?.type==="Identifier"?f.name:"")??"";return d?`${d}.${m}`:null}return null})(o))&&qr.has(i)?i:null;if(!l){if(Nt(o)==="pending"){let n=b(t),{line:f,column:m}=e.locator.location(n);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:f,column:m,severity:"error",fix:E["spec-no-focused-test"]}}return null}let u=b(t),{line:a,column:p}=e.locator.location(u),c=Hr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:c,line:a,column:p,severity:"error",fix:E["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Rt(){N(He,"correctness"),N(ze,"correctness"),N(We,"correctness"),N(Xe,"correctness"),N(Ye,"performance"),N(Ke,"performance"),N(Qe,"performance"),N(Je,"performance"),N(et,"performance"),N(tt,"security"),N(rt,"security"),N(nt,"ssr"),N(it,"ssr"),N(at,"reactivity"),N(ot,"reactivity"),N(lt,"reactivity"),N(ct,"reactivity"),N(pt,"reactivity"),N(ft,"reactivity"),N(dt,"reactivity"),N(yt,"modern-api"),N(ht,"modern-api"),N(gt,"modern-api"),N(bt,"modern-api"),N(St,"template"),N(At,"template"),N(Ct,"testing");}(async()=>{if(Rt(),engine.configureRuleExecutor(De,ke),!worker_threads.parentPort)return;let{rootDir:t,tasks:e}=worker_threads.workerData,r=[],i=[],o=engine.createAnalysisContext(t),l=new Map;for(let u of e){let a=l.get(u.filePath)??[];a.push(u),l.set(u.filePath,a);}for(let[u,a]of l){let p=performance.now();try{let c=await engine.executeBatchedTasks(a,o);r.push(...c),worker_threads.parentPort.postMessage(wt(u,a.length,c,performance.now()-p));}catch(c){for(let n of a)i.push({task:n,error:c instanceof Error?c.message:String(c)});worker_threads.parentPort.postMessage(wt(u,a.length,[],performance.now()-p));}finally{o.evict(u);}}worker_threads.parentPort.postMessage({results:r,errors:i});})();var wt=(t,e,r,i)=>{let o=0,l=0;for(let u of r)for(let a of u.failures)a.severity==="error"?o++:a.severity==="warn"&&l++;return {kind:"file-progress",filePath:t,taskCount:e,typeAware:false,issueCount:o+l,errorCount:o,warningCount:l,duration:i}};//# sourceMappingURL=execution-worker.cjs.map
});`};var Qe;function g(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function C(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function N(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function T(t,e){let r=g(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!C(r)&&N(r)===e)}function Re(t){let e=g(t);if(!e||e.type!=="CallExpression")return "";let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}function te(t){let e=g(t?.callee);return !!C(e)&&N(e)==="subscribe"}function Y(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let n of r){if(!n||n.type!=="Property")continue;let a=n.key;if((a?.type==="Identifier"?a.name:a?.type==="Literal"&&typeof a.value=="string"?a.value:"")===e)return n}return null}function we(t){let e=g(t);return !!(e&&e.type==="Literal"&&e.value===true)}function Me(t){let e=g(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Vt=new Set(["parent","span","loc","range","start","end","type"]);function*O(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Vt.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let n of r)n&&typeof n=="object"&&(yield n);else typeof r=="object"&&r.type&&(yield r);}}}function Pe(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function H(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function Je(t){for(let e of t)if(e&&H(e)&&Pe(e))return e;return null}function z(t){return t?(t.value??t)?.body??null:null}function et(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function F(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Kt(t){let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let n=g(r[1]);if(!n||n.type!=="ObjectExpression")return false;let a=Y(n,"injector");if(a&&!Me(a.value))return true;let l=Y(n,"manualCleanup");return !!(l&&we(l.value))}function tt(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&T(n.callee,"effect")&&!Kt(n)&&e.push(n),O(n)))r.push(a);}return e}var Xt=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function Gt(t){let e=g(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}return C(e)?N(e):""}function Yt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(Xt.has(Gt(r)))return true;return false}function re(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)==="pipe"&&Yt(r))return true;e=n?.object;}return false}function I(t,e){return e}var Qt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),Zt=new Set(["http","httpClient","_http","_httpClient"]),Jt=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function ne(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)!=="pipe")return r;e=n?.object;}return null}function ie(t){if(!t)return false;let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=g(e.callee);if(!C(r))return false;let n=N(r);if(!n)return false;let a=g(r?.object),l=Array.isArray(e.arguments)?e.arguments:[];if(Qt.has(n)&&C(a)){let c=N(a);if(Zt.has(c))return true}if(l.length>0){let c=n.toLowerCase();for(let p of Jt)if(c.startsWith(p)&&n.length>p.length)return true}return false}var Ze=false;function Te(){if(!Ze){try{Qe=Ht("typescript");}catch{}Ze=true;}return Qe}function rt(t,e){if(!t||!e.typeChecker)return;let r=Te();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let n=e.sourceFile;if(!n)return;let a=(function(l,c,p){if(c<l.getStart()||c>=l.getEnd())return;let d=l;for(;;){let u=p.forEachChild(d,i=>{if(c>=i.getStart()&&c<i.getEnd())return i});if(!u)break;d=u;}return d})(n,b(t),r);return a?e.typeChecker.getSymbolAtLocation(a):void 0}catch{return}}function D(t){if(t.sourceFile)return t.sourceFile;if(!t.fileContent)return;let e=Te();if(e)return t.sourceFile=e.createSourceFile(t.filePath,t.fileContent,e.ScriptTarget.Latest,true),t.sourceFile}var ee=new Map;function oe(t){let e=ee.get(t.filePath);if(e!==void 0)return e;let r=(function(n){let{typeChecker:a,angularTypes:l}=n;if(!a||!l)return false;let c=Te(),p=D(n);if(!c||!p)return false;for(let d of p.statements){if(!c.isClassDeclaration(d)||!c.canHaveDecorators(d))continue;let u=c.getDecorators(d);if(u)for(let i of u){let s=c.isCallExpression(i.expression)?i.expression.expression:i.expression;if(!c.isIdentifier(s)||s.text!=="Component"&&s.text!=="Directive")continue;let o=a.getSymbolAtLocation(s),f=o&&o.flags&c.SymbolFlags.Alias?a.getAliasedSymbol(o):o;if(l.isFromAngularCore(f))return true}}return false})(t);return ee.size>=1024&&ee.clear(),ee.set(t.filePath,r),r}function Q(t){if(!t)return false;let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib.dom"))return true;return false}var se="component-no-manual-detect-changes",nr=new Set(["detectChanges","markForCheck"]),nt=engine.createAnyAngularClassRule(se,(t,e)=>{let r,n=t.node,a=(r=ast.analyzeComponent(n),r?.type!=="Component"?{isComponent:false,isOnPush:false}:{isComponent:true,isOnPush:r.changeDetection?.kind==="literal"&&r.changeDetection.value===ast.ChangeDetectionStrategy.OnPush});if(!a.isComponent)return null;let{typeChecker:l,angularTypes:c}=e;if(!l||!c)return null;let p=(function(i,s){let o=D(s);if(!o)return;let f=b(i);for(let m of o.statements)if(M__default.default.isClassDeclaration(m)&&m.pos<=f&&f<=m.end)return m})(n,e);if(!p)return null;let d=[],u=i=>{if(M__default.default.isCallExpression(i)){let s=(function(o,f,m,y,h){if(!M__default.default.isPropertyAccessExpression(o.expression))return null;let E=o.expression.name.text;if(!nr.has(E)||y.isOnPush&&E==="markForCheck")return null;let S=f.getTypeAtLocation(o.expression.expression);if(!m.isChangeDetectorRef(S))return null;let{line:A,column:v}=h.locator.location(o.getStart());return {filePath:h.filePath,ruleName:se,message:y.isOnPush?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${E}) can hide state-flow bugs and make rendering harder to predict.`,line:A,column:v,severity:y.isOnPush?"warn":"error",fix:x[se],codeExample:P[se]}})(i,l,c,a,e);s&&d.push(s);}M__default.default.forEachChild(i,u);};return u(p),d.length>0?d:null});var Oe="signal-no-side-effects-in-computed",or=new Set(["set","update","mutate"]),ar=new Set(["next","complete","error"]),it=engine.createCallExpressionRule(Oe,(t,e)=>{var r,n;let a,l;if(!T(t.callee,"computed"))return null;let{typeChecker:c,angularTypes:p}=e;if(!c||!p)return null;let d=(function(s,o){var f;let m,y=(f=s).sourceFile?f.sourceFile:f.fileContent?(f.sourceFile=M__default.default.createSourceFile(f.filePath,f.fileContent,M__default.default.ScriptTarget.Latest,true),f.sourceFile):void 0;if(!y)return;let h=E=>{if(!m){if(M__default.default.isCallExpression(E)&&E.getStart()===o){m=E;return}M__default.default.forEachChild(E,h);}};return h(y),m})(e,b(t));if(!d)return null;let u=d.arguments[0];if(!u||!(M__default.default.isArrowFunction(u)||M__default.default.isFunctionExpression(u)))return null;let i=(r=u.body,n={typeChecker:c,angularTypes:p},(l=s=>{var o,f,m,y;if(a)return;let h=(o=s,f=n,M__default.default.isBinaryExpression(o)&&(m=o.operatorToken.kind)>=M__default.default.SyntaxKind.FirstAssignment&&m<=M__default.default.SyntaxKind.LastAssignment?ke(o.left)?{node:o,kind:"write"}:void 0:M__default.default.isPostfixUnaryExpression(o)||M__default.default.isPrefixUnaryExpression(o)?(o.operator===M__default.default.SyntaxKind.PlusPlusToken||o.operator===M__default.default.SyntaxKind.MinusMinusToken)&&ke(o.operand)?{node:o,kind:"write"}:void 0:M__default.default.isDeleteExpression(o)&&ke(o.expression)?{node:o,kind:"write"}:M__default.default.isCallExpression(o)?(function(E,S){if(!M__default.default.isPropertyAccessExpression(E.expression))return;let A=E.expression.name.text,v=E.expression.expression,w=S.typeChecker.getTypeAtLocation(v);return or.has(A)&&S.angularTypes.isWritableSignal(w)?{node:E,kind:"write"}:ar.has(A)&&S.angularTypes.isSubjectLike(w)||S.angularTypes.isHttpClient(w)?{node:E,kind:"effect"}:void 0})(o,f):void 0);if(h){a=h;return}y=s,M__default.default.isArrowFunction(y)||M__default.default.isFunctionExpression(y)||M__default.default.isFunctionDeclaration(y)||M__default.default.isMethodDeclaration(y)||M__default.default.isGetAccessorDeclaration(y)||M__default.default.isSetAccessorDeclaration(y)||M__default.default.forEachChild(s,l);})(r),a);return i?(function(s,o,f){let m=s.node.getStart(),{line:y,column:h}=f.locator.location(m||b(o));return {filePath:f.filePath,ruleName:Oe,message:s.kind==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:y,column:h,severity:"error",fix:x[Oe]}})(i,t,e):null},{requires:{typeChecker:true}});function ke(t){return M__default.default.isPropertyAccessExpression(t)||M__default.default.isElementAccessExpression(t)}var De="signal-effect-must-be-destroy-scoped",ot=engine.createAnyAngularClassRule(De,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let n=[];for(let a of r)a&&H(a)&&!Pe(a)&&n.push(...(function(l,c){let p=z(l);if(!p)return [];let d=et(l),u=[];for(let i of tt(p))(function(s){if(s.type!=="CallExpression")return false;let o=g(s.callee);return !!o&&(o.type==="Identifier"?o.name==="effect":!!C(o)&&N(o)==="effect")})(i)&&!(function(s){let o=g((Array.isArray(s.arguments)?s.arguments:[])[1]);if(!o||o.type!=="ObjectExpression")return false;for(let f of Array.isArray(o.properties)?o.properties:[]){let m=g(f);if(m?.type==="Property"){let y=g(m.key),h=y?.type==="Identifier"?y.name:N(y)||"";if(h==="injector")return true;if(h==="manualCleanup"){let E=g(m.value);if(E?.type==="Literal"&&E.value===true)return true}}}return false})(i)&&u.push((function(s,o,f){let m=b(s),{line:y,column:h}=f.locator.location(m);return {filePath:f.filePath,ruleName:De,message:`effect() inside "${o}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:h,severity:"error",fix:x[De]}})(i,d,c));return u})(a,e));return n.length>0?n:null});var le="rxjs-no-nested-subscribe",ur=new Set(["next","error","complete"]),cr=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function Ie(t){if(t.type!=="CallExpression")return false;let e=g(t.callee);return !!C(e)&&N(e)==="subscribe"}function at(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var st=engine.createCallExpressionRule(le,(t,e)=>{if(!Ie(t))return null;for(let r of (function(n){if(!Ie(n))return [];let a=Array.isArray(n.arguments)?n.arguments:[];if(a.length===0)return [];let l=g(a[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let p=[];for(let d of Array.isArray(l.properties)?l.properties:[]){let u=g(d);if(u?.type==="Property"&&ur.has((function(i){let s=g(i.key);return s?s.type==="Identifier"?s.name:N(s)||"":""})(u))){let i=g(u.value);at(i)&&p.push(i);}}return p}let c=[];for(let p=0;p<Math.min(a.length,3);p++){let d=g(a[p]);at(d)&&c.push(d);}return c})(t)){let n=g(r.body);if(n&&(function(a){let l=[a];for(;l.length>0;){var c;let p=g(l.pop());if(p){if(p!==a&&Ie(p))return true;if(!(p!==a&&(c=p).type&&cr.has(c.type)))for(let d of O(p))l.push(d);}}return false})(n))return (function(a,l){let c=b(a),{line:p,column:d}=l.locator.location(c);return {filePath:l.filePath,ruleName:le,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:p,column:d,severity:"error",fix:x[le],codeExample:P[le]}})(t,e)}return null});var ue="prefer-on-push-component-change-detection";function ce(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function Le(t){return t.replace(/\\/g,"/")}var lt=engine.createComponentRule(ue,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(n){if(!n||typeof n!="object")return false;let{kind:a,value:l}=n;return a!=="non-literal"&&(a==="literal"?l!==ast.ChangeDetectionStrategy.OnPush:a==="missing")})(r.changeDetection)?null:(function(n,a){let l,c,p,d,u=(l=n.metadata??{},c=n.node,ce(l,"decoratorStart")??ce(l,"start")??ce(c,"start")??ce(n,"start")??0),{line:i,column:s}=a.locator.location(u),o=(p=n.metadata,typeof(d=p?.className)=="string"?d:"AnonymousComponent"),f=(function(m,y){if(!y.project)return null;let h=m.metadata,E=h?.className;if(typeof E!="string"||!E)return null;let S=Le(y.filePath),{ngModuleMap:A,classToFile:v}=y.project;for(let[w,L]of A){if(L.isStandalone||!L.declarations.has(E))continue;let k=v.get(E);if(!k||Le(k)===S)return {moduleName:(Le(w).split("/").pop()??w).replace(/\.ts$/,""),siblingDeclarationCount:Math.max(0,L.declarations.size-1)}}return null})(n,a);return {filePath:a.filePath,ruleName:ue,message:(function(m,y){let h=`Component '${m}' uses default change detection, which can re-render more often than needed.`;if(!y)return h;let{moduleName:E,siblingDeclarationCount:S}=y;return S===0?`${h} It is declared in '${E}'.`:`${h} It is declared in '${E}' alongside ${S} other declaration${S===1?"":"s"}.`})(o,f),line:i,column:s,severity:"error",fix:x[ue],codeExample:P[ue]}})(t,e)},{requires:{projectContext:true}});var je="template-no-call-expression",gr=new Set(["translate","$localize","$any"]),yr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function ut(t){let e=g(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var ct=engine.createTemplateExpressionRule(je,(t,e)=>(function(r,n){let a=r?[r]:[];for(;a.length>0;){let l=g(a.pop());if(l){if(ut(l)&&!(function(c){let p=g(c);if(!p||!ut(p))return false;let d=g(p.callee);if(!d)return false;if(d.type==="Identifier")return gr.has(d.name);if(!C(d))return false;let u=N(d);return !!u&&yr.has(u)})(l)){if((function(p){let d=g(p);return Array.isArray(d?.arguments)?d.arguments:[]})(l).length>0)return true;let c=(function(p){let d=g(p);if(!d)return "";let u=g(d.callee);return u?u.type==="Identifier"?u.name??"":C(u)?N(u):"":""})(l);if(c&&!(function(p,d){if(d.crossRef?.signalMembers?.has(p))return true;let{typeChecker:u,angularTypes:i,crossRef:s}=d;if(!u||!i||!s?.componentPath)return false;let o=(function(f,m,y){let h=y.getProgram?.(),E=h?.getSourceFile(m);if(!E)return;let S=E.statements.find(M__default.default.isClassDeclaration);if(!S)return;let A=y.getTypeAtLocation(S),v=y.getPropertyOfType(A,f);if(!v)return;let w=v.valueDeclaration??v.declarations?.[0];if(w)return y.getTypeOfSymbolAtLocation(v,w)})(p,s.componentPath,u);return !!o&&i.isSignal(o)})(c,n))return true}for(let c of O(l))a.push(c);}}return false})(t.expression,e)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:l,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:je,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:c,severity:"error",fix:x[je]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function ft(t,e,r,n){let a=I(t,e.sourceSpan.start),{line:l,column:c}=t.locator.location(a);return {filePath:t.filePath,ruleName:r,message:n,line:l,column:c,severity:"error",fix:x[r]}}var pt=engine.createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let n of t.attributes)n.name==="*ngFor"&&!(function(a){return !!a.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(n.value??"")&&r.push(ft(e,n,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let n of t.blocks)n.name!=="for"||n.parameters.some(a=>{let l=a.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(ft(e,n,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Fe="template-no-object-literal-binding",mt=engine.createTemplateExpressionRule(Fe,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ObjectExpression")return true;for(let l of O(a))n.push(l);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:l,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:Fe,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:c,severity:"warn",fix:x[Fe]}})(t,e)]:null,{requires:{htmlAst:true}});var _e="template-no-array-literal-binding",dt=engine.createTemplateExpressionRule(_e,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ArrayExpression")return true;for(let l of O(a))n.push(l);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:l,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:_e,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:c,severity:"warn",fix:x[_e]}})(t,e)]:null,{requires:{htmlAst:true}});var $e=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),gt=engine.createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let c=g(l.callee);if(!c)return null;if(c.type==="Identifier"&&c.name)return $e.has(c.name)?c.name:null;if(C(c)){let p=N(c);return p&&$e.has(p)?p:null}return null})(t);if(!r)return null;let{line:n,column:a}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${$e.get(r)} sanitization, which can expose unsafe content.`,line:n,column:a,severity:"error",fix:x["no-bypass-sanitization"]}});var Ar=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),Cr=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,vr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,yt=engine.createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=Ar.get(t.name);if(!r)return null;let n=t.value??"";if(Cr.test(n)||vr.test(n)||t.name==="[style]"&&!/[.(|?]/.test(n))return null;let{line:a,column:l}=e.locator.location(I(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:a,column:l,severity:r.severity,fix:x["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var fe="no-document-access",Rr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),ht=engine.createAnyAngularClassRule(fe,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let{typeChecker:n}=e;if(!n)return null;let a=D(e);if(!a)return null;let l=(function(u){let i=new Set,s=[...u];for(;s.length;){let o=g(s.pop());if(o){if(o.type==="VariableDeclarator"&&o.init){let f=g(o.init);if(f?.type==="CallExpression"&&f.callee&&T(f.callee,"isPlatformBrowser")){let m=o.id??o.key;m?.type==="Identifier"&&m.name&&i.add(m.name);}}if(o.type==="AssignmentExpression"&&o.right){let f=g(o.right);if(f?.type==="CallExpression"&&f.callee&&T(f.callee,"isPlatformBrowser")){let m=g(o.left);if(m&&C(m)&&g(m.object)?.type==="ThisExpression"){let y=m.property?.name;typeof y=="string"&&y&&i.add(y);}}}for(let f of O(o))s.push(f);}}return i})(r),c=[],p=new Set,d=[...r];for(;d.length;){let u=g(d.pop());if(u){if(u.type==="IfStatement"&&u.test){let i=g(u.test);if(i){let s=(function(o,f){let m=[o];for(;m.length;){let y=g(m.pop());if(y){if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformBrowser"))return "browser";if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformServer"))return "server";if(y.type==="UnaryExpression"&&y.operator==="!"&&y.argument){let h=g(y.argument);if(h?.type==="CallExpression"&&h.callee&&T(h.callee,"isPlatformServer"))return "browser"}if(y.type==="Identifier"&&f.has(y.name))return "browser";for(let h of O(y))m.push(h);}}return null})(i,l);if(s==="browser"){u.alternate&&d.push(u.alternate);continue}if(s==="server"){u.consequent&&d.push(u.consequent);continue}}}if(u.type==="CallExpression"&&u.callee){let i=g(u.callee);if(i&&(T(i,"afterNextRender")||T(i,"afterRender"))){let s=u.arguments??[];for(let o=1;o<s.length;o++)d.push(s[o]);continue}}if(C(u)){let i=(function(o){let f=o;for(;f&&C(f);)f=g(f.object);return f?.type==="Identifier"?f:null})(u),s=i?.name;if(i&&s&&Rr.has(s)&&(function(o,f,m){let y=(function(E,S){let A,v=w=>{if(!A){if(M__default.default.isIdentifier(w)&&w.getStart()===S){A=w;return}M__default.default.forEachChild(w,v);}};return v(E),A})(f,b(o));if(!y)return false;let h=m.getSymbolAtLocation(y);return Q((h&&h.flags&M__default.default.SymbolFlags.Alias?m.getAliasedSymbol(h):h)??void 0)})(i,a,n)){let o=b(i);if(o!==void 0&&!p.has(o)){p.add(o);let{line:f,column:m}=e.locator.location(o);c.push({filePath:e.filePath,ruleName:fe,message:`Direct access to \`${s}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:x[fe],codeExample:P[fe]});}}}for(let i of O(u))d.push(i);}}return c.length?c:null},{requires:{typeChecker:true}});var pe="prefer-after-render-over-after-view-init",Mr=new Set(["ngAfterViewInit","ngAfterContentInit"]),Et=engine.createAnyAngularClassRule(pe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r}=e;if(!r)return null;let n=(function(l,c){let p=D(c);if(!p)return;let d=b(l);for(let u of p.statements)if(M__default.default.isClassDeclaration(u)&&u.pos<=d&&d<=u.end)return u})(t.node,e);if(!n)return null;let a=[];for(let l of n.members){if(!M__default.default.isMethodDeclaration(l)||!l.body||!M__default.default.isIdentifier(l.name))continue;let c=l.name.text;if(!Mr.has(c)||!(function(u,i){let s=false,o=f=>{if(!s){if(M__default.default.isPropertyAccessExpression(f)){if(xt(i.getTypeAtLocation(f.expression))){s=true;return}}else if(M__default.default.isElementAccessExpression(f)){if(xt(i.getTypeAtLocation(f.expression))){s=true;return}}else if(M__default.default.isIdentifier(f)&&!(function(m){let y=m.parent;return !!y&&!!(M__default.default.isPropertyAccessExpression(y)&&y.name===m||M__default.default.isQualifiedName(y)&&y.right===m)})(f)){let m=i.getSymbolAtLocation(f);if(Q((m&&m.flags&M__default.default.SymbolFlags.Alias?i.getAliasedSymbol(m):m)??void 0)){s=true;return}}M__default.default.forEachChild(f,o);}};return o(u),s})(l.body,r))continue;let{line:p,column:d}=e.locator.location(l.getStart());a.push({filePath:e.filePath,ruleName:pe,message:`\`${c}\` contains DOM access that can run before browser-only APIs are safe.`,line:p,column:d,severity:"warn",fix:x[pe],codeExample:P[pe]});}return a.length?a:null},{requires:{typeChecker:true}});function xt(t){let e=t.aliasSymbol??t.symbol;return !!e&&Q(e)}var me=new Map;function Ue(t){let e=D(t);if(!e)return false;for(let r of e.statements)if(M__default.default.isClassDeclaration(r))for(let n of r.members){if(!M__default.default.isMethodDeclaration(n)||!n.name||!M__default.default.isIdentifier(n.name)||n.name.text!=="ngOnDestroy"||!n.body)continue;let a=false,l=c=>{if(!a){if(M__default.default.isCallExpression(c)&&M__default.default.isPropertyAccessExpression(c.expression)&&c.expression.name.text==="unsubscribe"&&c.arguments.length===0){a=true;return}M__default.default.forEachChild(c,l);}};if(l(n.body),a)return true}return false}var bt=engine.createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{if(!oe(e)||!te(t))return null;let r=g(t.callee),n=C(r)?r?.object:null;if(n&&re(n)||ie(ne(n))||(function(p){let d=me.get(p.filePath);if(d!==void 0)return d;let u=Ue(p);return me.size>=500&&me.clear(),me.set(p.filePath,u),u})(e))return null;let a=b(t),{line:l,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:l,column:c,severity:"error",fix:x["rxjs-require-takeUntilDestroyed"]}},{requires:{typeChecker:true}});var de=new Map,ge="rxjs-no-subscribe-in-component",St=engine.createCallExpressionRule(ge,(t,e)=>{if(!oe(e)||!te(t)||(function(p){let d=g(p.callee);if(!d||!C(d))return false;let u=g(d.object);if(!u)return false;if(u.type==="CallExpression"){let i=g(u.callee);if(C(i)&&N(i)==="pipe"&&(Array.isArray(u.arguments)?u.arguments:[]).some(s=>{let o=g(s);if(o?.type!=="CallExpression")return false;let f=g(o.callee)?.name;return f==="take"||f==="first"}))return true}return ie(ne(u))})(t))return null;let r=g(t.callee),n=g(r?.object);if(n&&re(n)||(function(p){let d=de.get(p.filePath);if(d!==void 0)return d;let u=Ue(p);return de.size>=500&&de.clear(),de.set(p.filePath,u),u})(e))return null;let a=b(t),{line:l,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:ge,message:(function(p,d){let u="Open-ended subscriptions in components can outlive the component and make state harder to track.",i=d.crossRef?.templateReferences;if(!i)return u;let s=g(p.callee),o=g(s?.object),f=o?N(o):null;if(!f)return u;let m=f.endsWith("$")?f.slice(0,-1):f;return i.has(f)||i.has(m)?`'${f}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:u})(t,e),line:l,column:c,severity:"error",fix:x[ge],codeExample:P[ge]}},{requires:{typeChecker:true,projectContext:true}});var ye="rxjs-avoid-subject-as-event-bus",At=engine.createAnyAngularClassRule(ye,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=F(t.node);if(a.length===0)return null;let l=(function(i){let s=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,f=>{let m=g(f.callee);if(m&&(m.type==="Identifier"?m.name:C(m)?N(m):"")==="takeUntil")for(let y of Array.isArray(f.arguments)?f.arguments:[]){let h=Ct(y);h&&s.add(h);}});return s})(a),c=(function(i){let s=new Set,o=m=>{he(m??null,y=>{let h=qe(y,"next");h&&s.add(h);});},f=Je(i);for(let m of(f&&o(z(f)),i))if(H(m)){let y=m.key?.name;m.kind==="set"&&(function(h){let E=h.decorators;if(!Array.isArray(E))return false;for(let S of E){let A=g(S.expression);if(A?.name==="Input"||g(A?.callee)?.name==="Input")return true}return false})(m)&&o(m),y==="ngOnChanges"&&o(z(m));}else m.type==="PropertyDefinition"&&m.value&&o(m.value);return s})(a),p=(function(i){let s=new Set;for(let o of i)H(o)&&o.key?.name==="ngOnDestroy"&&he(z(o),f=>{let m=qe(f,"complete");m&&s.add(m);});return s})(a),d=(function(i){let s=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,f=>{let m=qe(f,"pipe");m&&s.add(m);});return s})(a),u=[];for(let i of a){if(i.type!=="PropertyDefinition"||i.accessibility==="public")continue;let s=i.key?.name??"";if(!s||l.has(s)||c.has(s)||p.has(s)||d.has(s))continue;let o=rt(i.key,e);if(!o)continue;let f=o.valueDeclaration??o.declarations?.[0];if(!f)continue;let m=r.getTypeOfSymbolAtLocation(o,f);if(!n.isSubjectLike(m))continue;let{line:y,column:h}=e.locator.location(b(i));u.push({filePath:e.filePath,ruleName:ye,message:`'${s}' is a Subject the class signals into without piping or external exposure \u2014 components are easier to follow when local state lives in fields or signals.`,line:y,column:h,severity:"warn",fix:x[ye],codeExample:P[ye]});}return u.length>0?u:null});function he(t,e){if(!t)return;let r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&e(n),O(n)))r.push(a);}}function Ct(t){let e=g(t);if(!e||!C(e))return null;let r=g(e.object),n=N(e);return n&&r?.type==="ThisExpression"?n:null}function qe(t,e){let r=g(t.callee);return r&&C(r)&&N(r)===e?Ct(r.object):null}var He="rxjs-prefer-toSignal-for-template-state",vt=engine.createAnyAngularClassRule(He,(t,e)=>{if(t.metadata?.type!=="Component")return null;let n=e.crossRef?.templateReferences;if(n===void 0)return null;let{typeChecker:a,angularTypes:l}=e;if(!a||!l)return null;let c=(function(u,i){let s=D(i);if(!s)return;let o=b(u);for(let f of s.statements)if(M__default.default.isClassDeclaration(f)&&f.pos<=o&&o<=f.end)return f})(t.node,e);if(!c)return null;let p=[];for(let u of c.members){var d;if(!M__default.default.isPropertyDeclaration(u))continue;let i=(function(m){if(M__default.default.isIdentifier(m.name)||M__default.default.isStringLiteral(m.name))return m.name.text})(u);if(!i||!n.has(i)&&!n.has((d=i).endsWith("$")?d.slice(0,-1):d)||(function(m,y,h){let E=M__default.default.getDecorators(m);if(!E)return false;for(let S of E){let A=M__default.default.isCallExpression(S.expression)?S.expression.expression:S.expression;if(!M__default.default.isIdentifier(A)||A.text!=="Output")continue;let v=y.getSymbolAtLocation(A),w=v&&v.flags&M__default.default.SymbolFlags.Alias?y.getAliasedSymbol(v):v;if(h.isFromAngularCore(w))return true}return false})(u,a,l))continue;let s=a.getTypeAtLocation(u);if(!l.isObservable(s)&&!l.isSubjectLike(s))continue;let{line:o,column:f}=e.locator.location(u.getStart());p.push({filePath:e.filePath,ruleName:He,message:`Observable "${i}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:o,column:f,severity:"warn",fix:x[He]});}return p.length?p:null},{requires:{projectContext:true,htmlAst:true,typeChecker:true}});var ze="toSignal-require-initialValue",Nt=engine.createCallExpressionRule(ze,(t,e)=>{if(!T(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],n=r[1]?g(r[1]):null;if(!n||n.type!=="ObjectExpression"||!(function(a){let l=Y(a,"initialValue");if(l&&!Me(l.value))return true;let c=Y(a,"requireSync");return !!c&&we(c.value)})(n)){let{line:a,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:ze,message:"toSignal() can emit undefined before the observable produces a value.",line:a,column:l,severity:"warn",fix:x[ze]}}return null});var We="signal-prefer-computed-over-sync-effect",Lr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame"]),jr=new Set(["then","catch","finally"]),Fr=new Set(["set","update","mutate"]),wt=engine.createCallExpressionRule(We,(t,e)=>{var r,n;let a,l,c,p,d,u;if(!T(t.callee,"effect"))return null;let{typeChecker:i,angularTypes:s}=e;if(!i||!s)return null;let o=(function(S,A){let v,w=D(S);if(!w)return;let L=k=>{if(!v){if(M__default.default.isCallExpression(k)&&k.getStart()===A){v=k;return}M__default.default.forEachChild(k,L);}};return L(w),v})(e,b(t));if(!o)return null;let f=o.arguments[0];if(!f||!(M__default.default.isArrowFunction(f)||M__default.default.isFunctionExpression(f)))return null;let m=(r=f.body,n={typeChecker:i,angularTypes:s},l=false,c=false,p=false,d=false,(u=S=>{p&&d&&l&&c||((S.kind===M__default.default.SyntaxKind.AwaitExpression||S.kind===M__default.default.SyntaxKind.YieldExpression)&&(p=true),M__default.default.isCallExpression(S)&&(function(A,v,w){var L,k;if(M__default.default.isPropertyAccessExpression(A.expression)){let U,j=A.expression.name.text,K=A.expression.expression,q=v.typeChecker.getTypeAtLocation(K);return Fr.has(j)&&v.angularTypes.isWritableSignal(q)?w.onSignalWrite():(j==="subscribe"&&(v.angularTypes.isObservable(q)||v.angularTypes.isSubjectLike(q))||jr.has(j)&&(U=(L=q).aliasSymbol??L.symbol)&&U.name==="Promise"&&Rt(U))&&w.onAsync()}if(M__default.default.isIdentifier(A.expression)){let U,j=A.expression.text;if(j==="linkedSignal")return w.onLinkedSignal();if(Lr.has(j)&&(k=A.expression,(U=v.typeChecker.getSymbolAtLocation(k))&&Rt(U)))return w.onAsync();A.arguments.length===0&&(function(K,q){let Z=q.typeChecker.getSymbolAtLocation(K);if(!Z)return false;let Xe=Z.valueDeclaration??Z.declarations?.[0];if(!Xe)return false;let qt=q.typeChecker.getTypeOfSymbolAtLocation(Z,Xe);return q.angularTypes.isSignal(qt)})(A.expression,v)&&w.onSignalRead();}})(S,n,{onSignalRead:()=>{l=true;},onSignalWrite:()=>{c=true,a??=S;},onAsync:()=>{p=true;},onLinkedSignal:()=>{d=true;}}),M__default.default.forEachChild(S,u));})(r),{hasSignalRead:l,hasSignalWrite:c,hasAsync:p,hasLinkedSignal:d,firstWrite:a});if(!m.hasSignalRead||!m.hasSignalWrite||m.hasAsync||m.hasLinkedSignal)return null;let y=m.firstWrite??o,{line:h,column:E}=e.locator.location(y.getStart());return {filePath:e.filePath,ruleName:We,message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:h,column:E,severity:"warn",fix:x[We]}},{requires:{typeChecker:true}});function Rt(t){let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib."))return true;return false}var Mt=new Set(["afterRender","afterNextRender"]),$r=/\bafterNextRender\s*\(|\bafterRender\s*\(/,xe=new Map,Pt=engine.createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!T(t.callee,"untracked")||(function(a,l){let c=l.sourceText??l.fileContent;if(typeof c=="string"&&!$r.test(c))return false;let p=a.parent;for(;p;){if(p.type==="CallExpression"&&Mt.has(Re(p)))return true;p=p.parent;}let d=b(a);return (function(u){let i=xe.get(u.filePath);if(i!==void 0)return i;let s=u.program;return i=s?(function(o){let f=[],m=o.body,y=Array.isArray(m)?[...m]:[o];for(;y.length;){let h=g(y.pop());if(h){if(h.type==="CallExpression"&&Mt.has(Re(h))){let E=g(h.arguments?.[0]);if(E){let S=b(E),A=E.end??E.span?.end??b(E);A>S&&f.push([S,A]);}}for(let E of O(h))y.push(E);}}return f})(s):[],xe.size>=300&&xe.clear(),xe.set(u.filePath,i),i})(l).some(([u,i])=>d>=u&&d<i)})(t,e))return null;let{line:r,column:n}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:n,severity:"warn",fix:x["signal-avoid-untracked-overuse"]}});var Ee="prefer-inject-over-constructor-di",Ur=new Set(["Inject","Optional","Self","SkipSelf","Host"]),Tt=engine.createAnyAngularClassRule(Ee,(t,e)=>{let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(s,o){var f;let m=(f=o).sourceFile?f.sourceFile:f.fileContent?(f.sourceFile=M__default.default.createSourceFile(f.filePath,f.fileContent,M__default.default.ScriptTarget.Latest,true),f.sourceFile):void 0;if(!m)return;let y=b(s);for(let h of m.statements)if(M__default.default.isClassDeclaration(h)&&h.pos<=y&&y<=h.end)return h})(t.node,e);if(!a)return null;let l=a.members.find(M__default.default.isConstructorDeclaration);if(!l||l.parameters.length===0)return null;let c=[];for(let s of l.parameters){var p;(function(o,f,m){if((function(E,S,A){let v=M__default.default.getDecorators(E);if(!v||v.length===0)return false;for(let w of v){let L=(function(j){let K=M__default.default.isCallExpression(j.expression)?j.expression.expression:j.expression;return M__default.default.isIdentifier(K)?K:void 0})(w);if(!L||!Ur.has(L.text))continue;let k=S.getSymbolAtLocation(L),U=k&&k.flags&M__default.default.SymbolFlags.Alias?S.getAliasedSymbol(k):k;if(A.isFromAngularCore(U))return true}return false})(o,f,m))return true;if(!o.type)return false;let y=f.getTypeFromTypeNode(o.type);if(m.isInjectionToken(y))return true;let h=y.aliasSymbol??y.symbol;return !!h&&m.isInjectableClass(h)})(s,r,n)&&c.push((p=s,{name:M__default.default.isIdentifier(p.name)?p.name.text:"<binding>",typeText:p.type?p.type.getText():"<inferred>"}));}if(c.length===0)return null;let{line:d,column:u}=e.locator.location(b(l)),i=c.map(s=>`${s.name}: ${s.typeText}`).join(", ");return {filePath:e.filePath,ruleName:Ee,message:`Constructor dependency injection makes class setup less composable than inject(). Offending params: ${i}.`,line:d,column:u,severity:"warn",fix:x[Ee],codeExample:P[Ee]}},{requires:{typeChecker:true}});var be="signal-prefer-input-signal";function Hr(t){let e=g(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var Ot=engine.createAnyAngularClassRule(be,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=[],a=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let c=g(l);if(c&&(c.type==="PropertyDefinition"||c.type==="AccessorProperty")&&Array.isArray(c.decorators)&&c.decorators.some(Hr)){let p=b(c),{line:d,column:u}=e.locator.location(p),i=g(c.key),s=(i?.type==="Identifier"?i.name:i?.type==="Literal"?String(i.value):"")||"(unknown)",o=`'${s}' uses @Input(), which keeps this input outside Angular's signal graph.`;a&&(o+=" Standalone declarations benefit most from signal inputs."),n.push({filePath:e.filePath,ruleName:be,message:o,line:d,column:u,severity:a?"error":"warn",fix:x[be],codeExample:P[be]});}}return n.length>0?n:null},{requires:{projectContext:true}});var Se="signal-prefer-output-function",kt=engine.createAnyAngularClassRule(Se,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(c,p){let d=D(p);if(!d)return;let u=b(c);for(let i of d.statements)if(M__default.default.isClassDeclaration(i)&&i.pos<=u&&u<=i.end)return i})(t.node,e);if(!a)return null;let l=[];for(let c of a.members){if(!M__default.default.isPropertyDeclaration(c)||!(function(i,s,o){let f=M__default.default.getDecorators(i);if(!f)return false;for(let m of f){let y=M__default.default.isCallExpression(m.expression)?m.expression.expression:m.expression;if(!M__default.default.isIdentifier(y)||y.text!=="Output")continue;let h=s.getSymbolAtLocation(y),E=h&&h.flags&M__default.default.SymbolFlags.Alias?s.getAliasedSymbol(h):h;if(o.isFromAngularCore(E))return true}return false})(c,r,n)||!(function(i,s,o){if(i.type){let m=s.getTypeFromTypeNode(i.type);if(o.isEventEmitter(m))return true}if(i.initializer){let m=s.getTypeAtLocation(i.initializer);if(o.isEventEmitter(m))return true}let f=s.getSymbolAtLocation(i.name);if(f){let m=s.getTypeOfSymbolAtLocation(f,i);if(o.isEventEmitter(m))return true}return false})(c,r,n))continue;let p=(function(i){let s=i.name;if(M__default.default.isIdentifier(s)||M__default.default.isStringLiteral(s))return s.text})(c)??"(unknown)",{line:d,column:u}=e.locator.location(c.getStart());l.push({filePath:e.filePath,ruleName:Se,message:`'${p}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:d,column:u,severity:"warn",fix:x[Se],codeExample:P[Se]});}return l.length>0?l:null},{requires:{typeChecker:true}});var Ae="signal-prefer-model";function Dt(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let n=g(r.expression??r);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(n.type==="CallExpression"){let a=g(n.callee);return a?.type==="Identifier"&&a.name===e}return false})}function It(t,e){let r=g(t.value);if(!r||r.type!=="CallExpression")return false;let n=g(r.callee);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(C(n)){let a=g(n.object);return a?.type==="Identifier"&&a.name===e}return false}var Lt=engine.createAnyAngularClassRule(Ae,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=new Map,a=new Map;for(let c of r){let p=g(c);if(!p||p.type!=="PropertyDefinition"&&p.type!=="AccessorProperty")continue;let d=(function(u){let i=g(u.key);return i?i.type==="Identifier"?i.name??null:i.type==="Literal"?String(i.value):null:null})(p);d&&((Dt(p,"Input")||It(p,"input"))&&n.set(d,p),(Dt(p,"Output")||It(p,"output"))&&a.set(d,p));}let l=[];for(let[c,p]of a){if(!c.endsWith("Change"))continue;let d=c.slice(0,-6),u=n.get(d);if(u){let i=b(u),{line:s,column:o}=e.locator.location(i);l.push({filePath:e.filePath,ruleName:Ae,message:`The \`${d}\` / \`${c}\` pair implements two-way binding with extra wiring that model() avoids.`,line:s,column:o,severity:"warn",fix:x[Ae],codeExample:P[Ae]});}}return l.length>0?l:null});var Kr=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Ve="template-prefer-control-flow",jt=engine.createTemplateAttributeRule(Ve,(t,e)=>{var r;let n=(r=t.name,Kr.get(r)??null);if(!n)return null;let a=I(e,t.sourceSpan.start),{line:l,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:Ve,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${n}\` control flow benefits.`,line:l,column:c,severity:"error",fix:x[Ve]}},{requires:{htmlAst:true}});var Ft=new WeakMap,_t=engine.createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,n,a=(function u(i){let s=g(i);if(!s)return null;if(s.type==="BinaryExpression"&&s.operator==="|"){let o=g(s.right);return o?.type==="Identifier"&&o.name==="async"?g(s.left):u(s.left)}return null})(t.expression),l=a?(function u(i,s=0){if(!i||s>10)return null;if(i.type==="Identifier")return i.name;if(i.type==="ThisExpression")return "this";if(i.type==="Literal"){let o=i.value;return o===null?"null":typeof o=="string"||typeof o=="number"||typeof o=="boolean"||typeof o=="bigint"?String(o):null}if(i.type==="CallExpression"){let o=u(i.callee,s+1),f=(Array.isArray(i.arguments)?i.arguments:[]).map(m=>u(m,s+1)??"?");return `${o}(${f.join(",")})`}if(C(i)){let o=u(i.object,s+1),f=N(i);if(o&&f)return `${o}.${f}`}if(i.type==="UnaryExpression")return `${i.operator}${u(i.argument,s+1)}`;if(i.type==="ConditionalExpression")return `${u(i.test,s+1)}?${u(i.consequent,s+1)}:${u(i.alternate,s+1)}`;if(i.type==="OptionalExpression"||i.type==="ChainExpression")return u(i.expression,s+1);if(i.type==="LogicalExpression"){let o=u(i.left,s+1),f=u(i.right,s+1);if(o&&f)return `${o}${i.operator}${f}`}if(i.type==="BinaryExpression"&&i.operator!=="|"){let o=u(i.left,s+1),f=u(i.right,s+1);if(o&&f)return `${o}${i.operator}${f}`}if(i.type==="ArrayExpression")return `[${(i.elements??[]).map(f=>u(f,s+1)??"?").join(",")}]`;if(i.type==="ObjectExpression")return `{${(i.properties??[]).map(f=>{let m=f.key?u(f.key,s+1):"?",y=f.value?u(f.value,s+1):"?";return `${m}:${y}`}).join(",")}}`;if(i.type==="TemplateLiteral")return "`tmpl`";if(i.type==="AssignmentExpression"){let o=u(i.left,s+1),f=u(i.right,s+1);if(o&&f)return `${o}${i.operator}${f}`}return null})(a):null;if(!l)return null;let c=(r=e.template,n=r?.templateStartOffset,`${e.filePath}@${typeof n=="number"&&Number.isFinite(n)?n:0}`),p=Ft.get(e);p||(p=new Map,Ft.set(e,p));let d=p.get(c);if(d||(d=new Set,p.set(c,d)),d.has(l)){let u=I(e,t.sourceSpan.start),{line:i,column:s}=e.locator.location(u);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:i,column:s,severity:"warn",fix:x["template-no-async-pipe-duplication"]}}return d.add(l),null},{requires:{htmlAst:true}});var Yr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Qr=new Set(["xdescribe","xit","xtest","xcontext"]);function $t(t){return t.type==="Identifier"?t.name??null:null}var Bt=engine.createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let n;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let a=g(t.callee);if(!a)return null;let l=(n=$t(a)||(function(i){if(i.type==="MemberExpression"||i.type==="StaticMemberExpression"||i.type==="OptionalMemberExpression"){let s=g(i.object),o=i.property?.name??"",f=(s?.type==="Identifier"?s.name:"")??"";return f?`${f}.${o}`:null}return null})(a))&&Yr.has(n)?n:null;if(!l){if($t(a)==="pending"){let i=b(t),{line:s,column:o}=e.locator.location(i);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:s,column:o,severity:"error",fix:x["spec-no-focused-test"]}}return null}let c=b(t),{line:p,column:d}=e.locator.location(c),u=Qr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:u,line:p,column:d,severity:"error",fix:x["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Ut(){R(nt,"correctness"),R(it,"correctness"),R(ot,"correctness"),R(st,"correctness"),R(lt,"performance"),R(ct,"performance"),R(pt,"performance"),R(mt,"performance"),R(dt,"performance"),R(gt,"security"),R(yt,"security"),R(ht,"ssr"),R(Et,"ssr"),R(St,"reactivity"),R(bt,"reactivity"),R(At,"reactivity"),R(vt,"reactivity"),R(Nt,"reactivity"),R(wt,"reactivity"),R(Pt,"reactivity"),R(Tt,"modern-api"),R(Ot,"modern-api"),R(kt,"modern-api"),R(Lt,"modern-api"),R(jt,"template"),R(_t,"template"),R(Bt,"testing");}var Ke=(t,e,r,n,a)=>{let l=0,c=0;for(let p of r)for(let d of p.failures)d.severity==="error"?l++:d.severity==="warn"&&c++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:l+c,errorCount:l,warningCount:c,duration:n,typeAware:a}};(async()=>{if(Ut(),engine.configureRuleExecutor(Ye,Ge),!worker_threads.parentPort)return;let{rootDir:t,tasks:e}=worker_threads.workerData,r=[],n=[],a=engine.createAnalysisContext(t),l=new Map;for(let c of e){let p=l.get(c.filePath)??[];p.push(c),l.set(c.filePath,p);}for(let[c,p]of l){let d=performance.now();try{let u=await engine.executeBatchedTasks(p,a);r.push(...u),worker_threads.parentPort.postMessage(Ke(c,p.length,u,performance.now()-d,!1));}catch(u){let i=u instanceof Error?u.message:String(u);for(let s of p)n.push({task:s,error:i});worker_threads.parentPort.postMessage(Ke(c,p.length,[],performance.now()-d,false));}finally{a.evict(c);}}worker_threads.parentPort.postMessage({results:r,errors:n});})();//# sourceMappingURL=execution-worker.cjs.map
//# sourceMappingURL=execution-worker.cjs.map
import { RuleResult } from '@ngcompass/common';
import { Task } from '@ngcompass/planner';
/**
* Worker input payload.
*/
interface ExecutionWorkerData {

@@ -11,5 +8,2 @@ rootDir: string;

}
/**
* Worker output payload.
*/
interface ExecutionWorkerResult {

@@ -16,0 +10,0 @@ results: RuleResult[];

import { RuleResult } from '@ngcompass/common';
import { Task } from '@ngcompass/planner';
/**
* Worker input payload.
*/
interface ExecutionWorkerData {

@@ -11,5 +8,2 @@ rootDir: string;

}
/**
* Worker output payload.
*/
interface ExecutionWorkerResult {

@@ -16,0 +10,0 @@ results: RuleResult[];

@@ -1,2 +0,2 @@

import {parentPort,workerData}from'worker_threads';import {createAnyAngularClassRule,createCallExpressionRule,createComponentRule,createTemplateExpressionRule,createTemplateRule,createTemplateAttributeRule,configureRuleExecutor,createAnalysisContext,executeBatchedTasks,runSinglePassAnalysis}from'@ngcompass/engine';import {debug}from'@ngcompass/common';import {analyzeComponent,ChangeDetectionStrategy}from'@ngcompass/ast';import er from'typescript';var Mt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var ge=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description||`Rule: ${e}`,category:r.category||"general",dependencyType:r.dependencyType||"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:{severity:"warn",options:{}}}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let i=this.getRegistryEntry(r);i&&e.set(r,i);}return e}get size(){return this._handlers.size}},he=null,X=()=>(he||(he=new ge),he);var N=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:{...t.meta?.requires}}};X().register(r),debug("engine",`Registered rule: ${t.name}`);},ke=t=>X().has(t);var De=(t,e)=>{let r=X(),i=[];for(let u of t){let a=r.get(u);a&&i.push(a);}if(i.length===0)return [];debug("engine",`Executing ${i.length} rules in single pass on ${e.filePath}`);let{results:o,performance:l}=runSinglePassAnalysis(i,e);return debug("engine",`Single-pass complete: ${l.traversalMs.toFixed(2)}ms, ${l.nodesVisited} nodes`),debug("engine",`Cache hit rate: ${(l.cacheStats.hits/(l.cacheStats.hits+l.cacheStats.misses||1)*100).toFixed(1)}%`),l.budgetViolations.length>0&&debug("engine","Performance budget violations:",l.budgetViolations),o};var je;function s(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function x(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function v(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function O(t,e){let r=s(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!x(r)&&v(r)===e)}function j(t){let e=s(t);if(!e||e.type!=="CallExpression")return "";let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}function Y(t){let e=s(t?.callee);return !!x(e)&&v(e)==="subscribe"}function W(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let i of r){if(!i||i.type!=="Property")continue;let o=i.key;if((o?.type==="Identifier"?o.name:o?.type==="Literal"&&typeof o.value=="string"?o.value:"")===e)return i}return null}function Ee(t){let e=s(t);return !!(e&&e.type==="Literal"&&e.value===true)}function xe(t){let e=s(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Ot=new Set(["parent","span","loc","range","start","end","type"]);function*C(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Ot.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let i of r)i&&typeof i=="object"&&(yield i);else typeof r=="object"&&r.type&&(yield r);}}}function be(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function B(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function U(t){for(let e of t)if(e&&B(e)&&be(e))return e;return null}function L(t){return t?(t.value??t)?.body??null:null}function $e(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function w(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Tt(t){let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let i=s(r[1]);if(!i||i.type!=="ObjectExpression")return false;let o=W(i,"injector");if(o&&!xe(o.value))return true;let l=W(i,"manualCleanup");return !!(l&&Ee(l.value))}function _e(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let i=s(r.pop());if(i)for(let o of(i.type==="CallExpression"&&O(i.callee,"effect")&&!Tt(i)&&e.push(i),C(i)))r.push(o);}return e}function G(t){let e=t?.arguments;if(!Array.isArray(e)||e.length===0)return null;let r=s(e[0]);return r&&(r.type==="ArrowFunctionExpression"||r.type==="FunctionExpression")?r:null}function K(t){if(!t)return null;let e=t.body;return e?s(e):null}function Be(t,e){let r=new Map([...e].map(o=>[o,new Set([o])]));if(typeof t!="string"||t.length===0)return r;let i=new Map([...e].map(o=>[o,RegExp(`^${o}(?:\\s+as\\s+([A-Za-z_$][\\w$]*))?$`)]));for(let o of [/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs['"]/g,/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs\/[^'"]+['"]/g]){let l;for(;(l=o.exec(t))!==null;)for(let u of (l[1]??"").split(",").map(a=>a.trim()).filter(Boolean))for(let[a,p]of i){let c=p.exec(u);c&&r.get(a).add(c[1]??a);}}return r}var It=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function kt(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}return x(e)?v(e):""}function Dt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(It.has(kt(r)))return true;return false}function Z(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let i=s(r.callee);if(!x(i))break;if(v(i)==="pipe"&&Dt(r))return true;e=i?.object;}return false}function k(t,e){let r=t.template?.templateStartOffset;return typeof r=="number"&&Number.isFinite(r)?e+r:e}var jt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),Lt=new Set(["http","httpClient","_http","_httpClient"]),$t=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function Q(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let i=s(r.callee);if(!x(i))break;if(v(i)!=="pipe")return r;e=i?.object;}return null}function J(t){if(!t)return false;let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=s(e.callee);if(!x(r))return false;let i=v(r);if(!i)return false;let o=s(r?.object),l=Array.isArray(e.arguments)?e.arguments:[];if(jt.has(i)&&x(o)){let u=v(o);if(Lt.has(u))return true}if(l.length>0){let u=i.toLowerCase();for(let a of $t)if(u.startsWith(a)&&i.length>a.length)return true}return false}function ee(t){if(!t)return [];let e=t.params;if(Array.isArray(e))return e;if(e&&typeof e=="object"){if("items"in e&&Array.isArray(e.items))return e.items;if("elements"in e&&Array.isArray(e.elements))return e.elements}return []}function F(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="TSParameterProperty")return F(e.parameter);if(e.type==="AssignmentPattern"){let r=s(e.left);return r?.type==="Identifier"?r.name??"":""}if(e.type==="RestElement"){let r=s(e.argument);return r?.type==="Identifier"?r.name??"":""}return ""}function $(t){let e=s(t);if(!e)return "";if(e.type==="TSParameterProperty")return $(e.parameter);let r=e.typeAnnotation,i=s(r?.typeAnnotation??r);if(!i)return "";if(i.type==="TSTypeReference"||i.type==="TypeReference"){let o=i.typeName??i.name;if(o&&typeof o=="object"){if(o.type==="Identifier")return o.name??"";if(o.type==="TSQualifiedName")return o.right?.name??""}if(typeof o=="string")return o}return ""}var Le=false;function Ue(){if(!Le){try{je=Mt("typescript");}catch{}Le=true;}return je}function q(t,e){if(!t||!e.typeChecker)return;let r=Ue();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let i=e.sourceFile;if(!i)return;let o=(function(l,u,a){if(u<l.getStart()||u>=l.getEnd())return;let p=l;for(;;){let c=a.forEachChild(p,n=>{if(u>=n.getStart()&&u<n.getEnd())return n});if(!c)break;p=c;}return p})(i,b(t),r);return o?e.typeChecker.getSymbolAtLocation(o):void 0}catch{return}}var _t=["Service","Facade","Store","Client","Repository","Adapter","Controller","Provider","Registry","Logger","Router","Injector","Handler","Interceptor","Guard","Resolver","Validator"];function Fe(t){if(!t)return false;let e=Ue();if(!e)return false;try{let r=t.getName();if(_t.some(l=>r.endsWith(l)))return !0;let i=t.getDeclarations();if(!i||i.length===0)return !1;let o=i[0];if(!e.canHaveDecorators(o))return !1;for(let l of e.getDecorators(o)??[]){let u=l.expression;if(e.isCallExpression(u)&&e.isIdentifier(u.expression)&&u.expression.text==="Injectable")return !0}return !1}catch{return false}}var E={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},R={"prefer-on-push-component-change-detection":`// Before:
import {parentPort,workerData}from'worker_threads';import {createAnyAngularClassRule,createCallExpressionRule,createComponentRule,createTemplateExpressionRule,createTemplateRule,createTemplateAttributeRule,configureRuleExecutor,createAnalysisContext,executeBatchedTasks,runSinglePassAnalysis}from'@ngcompass/engine';import {debug}from'@ngcompass/common';import M from'typescript';import {analyzeComponent,ChangeDetectionStrategy}from'@ngcompass/ast';var Ht=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var zt={severity:"warn",options:{}},Ne=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description??`Rule: ${e}`,category:r.category??"general",dependencyType:r.dependencyType??"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:zt}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let n=this.getRegistryEntry(r);n&&e.set(r,n);}return e}get size(){return this._handlers.size}},ve=null,J=()=>(ve||(ve=new Ne),ve);var R=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:t.meta?.requires??{}}};J().register(r),debug("engine",`Registered rule: ${t.name}`);},Ge=t=>J().has(t),Ye=(t,e)=>{let r=J(),n=[];for(let p of t){let d=r.get(p);d&&n.push(d);}if(n.length===0)return [];debug("engine",`Executing ${n.length} rules in single pass on ${e.filePath}`);let{results:a,performance:l}=runSinglePassAnalysis(n,e);debug("engine",`Single-pass complete: ${l.traversalMs.toFixed(2)}ms, ${l.nodesVisited} nodes`);let c=l.cacheStats.hits+l.cacheStats.misses;if(c>0){let p=l.cacheStats.hits/c*100;debug("engine",`Component metadata cache hit rate: ${p.toFixed(1)}%`);}return l.budgetViolations.length>0&&debug("engine",`Performance budget violations: ${l.budgetViolations.join("; ")}`),a};var x={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},P={"prefer-on-push-component-change-detection":`// Before:
@Component({ selector: 'app-foo', template: '...' })

@@ -216,3 +216,3 @@ export class FooComponent { }

it('should render', () => { ... });
});`};var te="component-no-manual-detect-changes",Ft=new Set(["detectChanges","markForCheck"]),qt=new Set(["cdr","cdref","changedetectorref","_cdr","_cdref","changedetector","_changedetector","changedetectionref","cd","_cd"]),He=createAnyAngularClassRule(te,(t,e)=>{var r,i;let o,l,u=t.node;if(i=u,analyzeComponent(i)?.type!=="Component")return null;let a=(l=(r=(function(n){let f=new Set,m=w(n),d=U(m);if(d){for(let h of ee(d.value??d))if($(h)==="ChangeDetectorRef"){let y=F(h);y&&f.add(y);}}for(let h of m)if(h.type==="PropertyDefinition"&&h.value){let y=s(h.value);if(y&&(function(g){if(g.type!=="CallExpression")return false;let S=s(g.callee);if(S?.type!=="Identifier"||S.name!=="inject")return false;let[A]=g.arguments??[],M=s(A);return M?.type==="Identifier"&&M.name==="ChangeDetectorRef"})(y)){let g=h.key;g?.type==="Identifier"&&f.add(g.name);}}return f})(u)).size>0,n=>!!r.has(n)||!l&&qt.has(n.toLowerCase())),p=(o=analyzeComponent(u),o?.type==="Component"&&o.changeDetection?.kind==="literal"&&o.changeDetection.value===ChangeDetectionStrategy.OnPush),c=(function(n,f,m,d){let h=[],y=[...w(n)];for(;y.length>0;){let g=s(y.pop());if(!g)continue;let S=(function(A){if(A.type!=="CallExpression")return null;let M=s(A.callee);if(!x(M))return null;let P=v(M);return P&&Ft.has(P)?P:null})(g);for(let A of(S&&(function(M,P){if(M.type!=="CallExpression")return false;let I=s(M.callee);if(!I||!x(I))return false;let T=s(I.object);if(!T)return false;if(T.type==="Identifier")return P(T.name);if(!x(T))return false;let D=s(T.object),_=v(T);return (D?.type==="ThisExpression"||D?.type==="Identifier"&&D.name==="this")&&!!_&&P(_)})(g,d)&&(m&&S==="markForCheck"||h.push((function(M,P,I,T){let D=b(M),{line:_,column:V}=P.locator.location(D);return {filePath:P.filePath,ruleName:te,message:T?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${I}) can hide state-flow bugs and make rendering harder to predict.`,line:_,column:V,severity:T?"warn":"error",fix:E[te],codeExample:R[te]}})(g,f,S,m))),C(g)))y.push(A);}return h})(u,e,p,a);return c.length>0?c:null});var Se="signal-no-side-effects-in-computed",zt=new Set(["post","put","patch","subscribe","unsubscribe","next","complete","setItem","removeItem","appendChild","removeChild","dispatch"]),Wt=new Set(["set","update","mutate"]),Vt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]),ze=createCallExpressionRule(Se,(t,e)=>{if(!O(t.callee,"computed"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let o=(function(l){let u=[l];for(;u.length>0;){var a;let p=s(u.pop());if(p){if(p!==l){if((function(c){let n=s(c);if(!n)return false;if(n.type==="AssignmentExpression"){let f=s(n.left);return !!f&&x(f)}if(n.type==="UpdateExpression"||n.type==="UnaryExpression"&&n.operator==="delete"){let f=s(n.argument);return !!f&&x(f)}return false})(p))return {node:p,type:"write"};if(p.type==="CallExpression"){let c=(function(n){let f=s(n);if(!f||f.type!=="CallExpression")return "";let m=s(f.callee);return x(m)&&v(m)||""})(p);if(Wt.has(c))return {node:p,type:"write"};if(zt.has(c))return {node:p,type:"effect"}}}if(!(p!==l&&(a=p).type&&Vt.has(a.type)))for(let c of C(p))u.push(c);}}return null})(i);return o?(function(l,u,a,p){let c=b(l)||b(u),{line:n,column:f}=a.locator.location(c);return {filePath:a.filePath,ruleName:Se,message:p==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:n,column:f,severity:"error",fix:E[Se]}})(o.node,t,e,o.type):null});var ve="signal-effect-must-be-destroy-scoped",We=createAnyAngularClassRule(ve,(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=[];for(let o of r)o&&B(o)&&!be(o)&&i.push(...(function(l,u){let a=L(l);if(!a)return [];let p=$e(l),c=[];for(let n of _e(a))(function(f){if(f.type!=="CallExpression")return false;let m=s(f.callee);return !!m&&(m.type==="Identifier"?m.name==="effect":!!x(m)&&v(m)==="effect")})(n)&&!(function(f){let m=s((Array.isArray(f.arguments)?f.arguments:[])[1]);if(!m||m.type!=="ObjectExpression")return false;for(let d of Array.isArray(m.properties)?m.properties:[]){let h=s(d);if(h?.type==="Property"){let y=s(h.key),g=y?.type==="Identifier"?y.name:v(y)||"";if(g==="injector")return true;if(g==="manualCleanup"){let S=s(h.value);if(S?.type==="Literal"&&S.value===true)return true}}}return false})(n)&&c.push((function(f,m,d){let h=b(f),{line:y,column:g}=d.locator.location(h);return {filePath:d.filePath,ruleName:ve,message:`effect() inside "${m}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:g,severity:"error",fix:E[ve]}})(n,p,u));return c})(o,e));return i.length>0?i:null});var re="rxjs-no-nested-subscribe",Gt=new Set(["next","error","complete"]),Kt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function Ae(t){if(t.type!=="CallExpression")return false;let e=s(t.callee);return !!x(e)&&v(e)==="subscribe"}function Ve(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var Xe=createCallExpressionRule(re,(t,e)=>{if(!Ae(t))return null;for(let r of (function(i){if(!Ae(i))return [];let o=Array.isArray(i.arguments)?i.arguments:[];if(o.length===0)return [];let l=s(o[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let a=[];for(let p of Array.isArray(l.properties)?l.properties:[]){let c=s(p);if(c?.type==="Property"&&Gt.has((function(n){let f=s(n.key);return f?f.type==="Identifier"?f.name:v(f)||"":""})(c))){let n=s(c.value);Ve(n)&&a.push(n);}}return a}let u=[];for(let a=0;a<Math.min(o.length,3);a++){let p=s(o[a]);Ve(p)&&u.push(p);}return u})(t)){let i=s(r.body);if(i&&(function(o){let l=[o];for(;l.length>0;){var u;let a=s(l.pop());if(a){if(a!==o&&Ae(a))return true;if(!(a!==o&&(u=a).type&&Kt.has(u.type)))for(let p of C(a))l.push(p);}}return false})(i))return (function(o,l){let u=b(o),{line:a,column:p}=l.locator.location(u);return {filePath:l.filePath,ruleName:re,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:a,column:p,severity:"error",fix:E[re],codeExample:R[re]}})(t,e)}return null});var ne="prefer-on-push-component-change-detection";function ie(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function oe(t){return t.replace(/\\/g,"/")}var Ye=createComponentRule(ne,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(i){if(!i||typeof i!="object")return false;let{kind:o,value:l}=i;return o!=="non-literal"&&(o==="literal"?l!==ChangeDetectionStrategy.OnPush:o==="missing")})(r.changeDetection)?null:(function(i,o){let l,u,a,p,c=(l=i.metadata??{},u=i.node,ie(l,"decoratorStart")??ie(l,"start")??ie(u,"start")??ie(i,"start")??0),{line:n,column:f}=o.locator.location(c),m=(a=i.metadata,typeof(p=a?.className)=="string"?p:"AnonymousComponent"),d=(function(h,y){if(!y.project)return null;let g=h.metadata,S=g?.className;if(typeof S!="string"||!S)return null;let A=oe(y.filePath),{ngModuleMap:M,classToFile:P}=y.project;for(let[T,D]of M){var I;if(D.isStandalone||!D.declarations.has(S))continue;let _=P.get(S);if(_&&oe(_)!==A)continue;let V=0;for(let Ie of D.declarations)Ie!==S&&(I=P.get(Ie))&&oe(I).endsWith(".component.ts")&&V++;return {moduleName:(oe(T).split("/").pop()??T).replace(/\.ts$/,""),siblingComponentCount:V}}return null})(i,o);return {filePath:o.filePath,ruleName:ne,message:(function(h,y){if(!y)return `Component '${h}' uses default change detection, which can re-render more often than needed.`;let{moduleName:g,siblingComponentCount:S}=y,A=S>0?` ${S} other component${S===1?"":"s"} are declared in '${g}'.`:"";return `Component '${h}' uses default change detection, which can re-render more often than needed.${A}`})(m,d),line:n,column:f,severity:"error",fix:E[ne],codeExample:R[ne]}})(t,e)},{requires:{projectContext:true}});var Ne="template-no-call-expression",tr=new Set(["translate","$localize","$any"]),rr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function Ge(t){let e=s(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var Ke=createTemplateExpressionRule(Ne,(t,e)=>(function(r,i){let o=r?[r]:[];for(;o.length>0;){let l=s(o.pop());if(l){if(Ge(l)&&!(function(u){let a=s(u);if(!a||!Ge(a))return false;let p=s(a.callee);if(!p)return false;if(p.type==="Identifier")return tr.has(p.name);if(!x(p))return false;let c=v(p);return !!c&&rr.has(c)})(l)){if((function(a){let p;return (p=s(a),Array.isArray(p?.arguments)?p.arguments:[]).length>0})(l))return true;let u=(function(a){let p=s(a);if(!p)return "";let c=s(p.callee);return c?c.type==="Identifier"?c.name??"":x(c)?v(c):"":""})(l);if(u&&!(function(a,p){let c=a.startsWith("get")||a.startsWith("is")||a.startsWith("has");if(p.crossRef?.signalMembers?.has(a))return true;if(p.typeChecker&&p.crossRef?.componentPath)try{let n=p.typeChecker,f=p.crossRef.componentPath,m=n.getProgram().getSourceFile(f);if(m){let d=m.statements.find(h=>er.isClassDeclaration(h));if(d&&d.name){let h=n.getTypeAtLocation(d),y=n.getPropertyOfType(h,a);if(y){if(!y)return !1;let g=y.valueDeclaration??y.declarations?.[0];if(!g)return !1;let S=n.getTypeOfSymbolAtLocation(y,g);if(!S)return !1;let A=n.typeToString(S);return A.includes("Signal")||A.includes("writable")||A.includes("computed")}}}}catch{}return !c})(u,i))return true}for(let u of C(l))o.push(u);}}return false})(t.expression,e)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ne,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:u,severity:"error",fix:E[Ne]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function Ze(t,e,r,i){let o=k(t,e.sourceSpan.start),{line:l,column:u}=t.locator.location(o);return {filePath:t.filePath,ruleName:r,message:i,line:l,column:u,severity:"error",fix:E[r]}}var Qe=createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let i of t.attributes)i.name==="*ngFor"&&!(function(o){return !!o.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(i.value??"")&&r.push(Ze(e,i,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let i of t.blocks)i.name!=="for"||i.parameters.some(o=>{let l=o.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(Ze(e,i,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Ce="template-no-object-literal-binding",Je=createTemplateExpressionRule(Ce,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ObjectExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ce,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ce]}})(t,e)]:null,{requires:{htmlAst:true}});var Re="template-no-array-literal-binding",et=createTemplateExpressionRule(Re,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ArrayExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Re,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Re]}})(t,e)]:null,{requires:{htmlAst:true}});var we=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),tt=createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let u=s(l.callee);if(!u)return null;if(u.type==="Identifier"&&u.name)return we.has(u.name)?u.name:null;if(x(u)){let a=v(u);return a&&we.has(a)?a:null}return null})(t);if(!r)return null;let{line:i,column:o}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${we.get(r)} sanitization, which can expose unsafe content.`,line:i,column:o,severity:"error",fix:E["no-bypass-sanitization"]}});var lr=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),ur=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,cr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,rt=createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=lr.get(t.name);if(!r)return null;let i=t.value??"";if(ur.test(i)||cr.test(i)||t.name==="[style]"&&!/[.(|?]/.test(i))return null;let{line:o,column:l}=e.locator.location(k(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:o,column:l,severity:r.severity,fix:E["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var fr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),nt=createAnyAngularClassRule("no-document-access",(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=new Set,c=[...a];for(;c.length;){let n=s(c.pop());if(n){if(n.type==="VariableDeclarator"&&n.init){let f=s(n.init);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=n.id??n.key;m?.type==="Identifier"&&m.name&&p.add(m.name);}}if(n.type==="AssignmentExpression"&&n.right){let f=s(n.right);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=s(n.left);if(m&&x(m)&&s(m.object)?.type==="ThisExpression"){let d=m.property?.name;typeof d=="string"&&d&&p.add(d);}}}for(let f of C(n))c.push(f);}}return p})(r),o=[],l=new Set,u=[...r];for(;u.length;){let a=s(u.pop());if(a){if(a.type==="IfStatement"&&a.test){let p=s(a.test);if(p){let c=(function(n,f){let m=[n];for(;m.length;){let d=s(m.pop());if(d){if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformBrowser"))return "browser";if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformServer"))return "server";if(d.type==="UnaryExpression"&&d.operator==="!"&&d.argument){let h=s(d.argument);if(h?.type==="CallExpression"&&h.callee&&O(h.callee,"isPlatformServer"))return "browser"}if(d.type==="Identifier"&&f.has(d.name))return "browser";for(let h of C(d))m.push(h);}}return null})(p,i);if(c==="browser"){a.alternate&&u.push(a.alternate);continue}if(c==="server"){a.consequent&&u.push(a.consequent);continue}}}if(a.type==="CallExpression"&&a.callee){let p=s(a.callee);if(p&&(O(p,"afterNextRender")||O(p,"afterRender"))){let c=a.arguments??[];for(let n=1;n<c.length;n++)u.push(c[n]);continue}}if(x(a)){let p=(function(c){let n=c;for(;n&&x(n);)n=s(n.object);return n?.type==="Identifier"?n.name??null:null})(a);if(p&&fr.has(p)){let c=a;for(;c&&x(c);)c=s(c.object);let n=b(c);if(n!==void 0&&!l.has(n)){l.add(n);let{line:f,column:m}=e.locator.location(n);o.push({filePath:e.filePath,ruleName:"no-document-access",message:`Direct access to \`${p}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:E["no-document-access"],codeExample:R["no-document-access"]});}}}for(let p of C(a))u.push(p);}}return o.length?o:null});var dr=new Set(["nativeElement","getBoundingClientRect","querySelector","querySelectorAll","getElementById","createElement","scrollIntoView","focus","blur","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollTop","scrollLeft","innerHTML","outerHTML","textContent","parentElement","parentNode","firstChild","lastChild","nextSibling","previousSibling","children","ownerDocument","insertBefore","appendChild","removeChild","replaceChild","cloneNode","setAttribute","getAttribute","removeAttribute","hasAttribute","classList","dispatchEvent","contains","matches","closest","getClientRects","addEventListener","removeEventListener","requestAnimationFrame","cancelAnimationFrame"]),yr=["getElementsBy","offset","client","scroll"],it=createAnyAngularClassRule("prefer-after-render-over-after-view-init",(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of ["ngAfterViewInit","ngAfterContentInit"]){let l=r.find(c=>c.key?.name===o),u=l?L(l):null;if(!u||!l||!(function(c){let n=[c];for(;n.length;){let f=s(n.pop());if(f){if((f.type==="MemberExpression"||f.type==="StaticMemberExpression"||f.type==="OptionalMemberExpression")&&!f.computed){let m=f.property?.name??"";if(dr.has(m))return true;for(let d of yr)if(m.startsWith(d))return true}if(f.type==="Identifier"&&(f.name==="document"||f.name==="window"))return true;for(let m of C(f))n.push(m);}}return false})(u))continue;let{line:a,column:p}=e.locator.location(b(l));i.push({filePath:e.filePath,ruleName:"prefer-after-render-over-after-view-init",message:`\`${o}\` contains DOM access that can run before browser-only APIs are safe.`,line:a,column:p,severity:"warn",fix:E["prefer-after-render-over-after-view-init"],codeExample:R["prefer-after-render-over-after-view-init"]});}return i.length?i:null});var ae=new Map;function Me(t){return /ngOnDestroy\s*\([^)]*\)\s*\{[^}]*\.unsubscribe\s*\(\)/s.test(t)}var ot=createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t))return null;let l=s(t.callee),u=x(l)?l?.object:null;if(u&&Z(u)||J(Q(u))||(r=e.filePath,i=e.fileContent,(o=ae.get(r))!==void 0||(o=Me(i),ae.size>=500&&ae.clear(),ae.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:p,column:c,severity:"error",fix:E["rxjs-require-takeUntilDestroyed"]}});var se=new Map,le="rxjs-no-subscribe-in-component",at=createCallExpressionRule(le,(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t)||(function(n){let f=s(n.callee);if(!f||!x(f))return false;let m=s(f.object);if(!m)return false;if(m.type==="CallExpression"){let d=s(m.callee);if(x(d)&&v(d)==="pipe"&&(Array.isArray(m.arguments)?m.arguments:[]).some(h=>{let y=s(h);if(y?.type!=="CallExpression")return false;let g=s(y.callee)?.name;return g==="take"||g==="first"}))return true}return J(Q(m))})(t))return null;let l=s(t.callee),u=s(l?.object);if(u&&Z(u)||(r=e.filePath,i=e.fileContent,(o=se.get(r))!==void 0||(o=Me(i),se.size>=500&&se.clear(),se.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:le,message:(function(n,f){let m="Open-ended subscriptions in components can outlive the component and make state harder to track.",d=f.crossRef?.templateReferences;if(!d)return m;let h=s(n.callee),y=s(h?.object),g=y?v(y):null;if(!g)return m;let S=g.endsWith("$")?g.slice(0,-1):g;return d.has(g)||d.has(S)?`'${g}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:m})(t,e),line:p,column:c,severity:"error",fix:E[le],codeExample:R[le]}},{requires:{projectContext:true}});var ue="rxjs-avoid-subject-as-event-bus",st=new Set(["Subject","ReplaySubject","AsyncSubject","BehaviorSubject"]),xr=new Set(["destroy$","destroyed$","ondestroy$","ngondestroy$","unsubscribe$","unsub$","teardown$","dispose$","cleanup$","cleanupsubject$"]),br=/state|loading|error|active|selected|open|visible|disabled|count|value|data|hidden|expanded|pending|success|failed/i;function H(t,e,r){let i=[t];for(;i.length;){let o=s(i.pop());if(!o)continue;let l=s(o.callee);if(o.type==="CallExpression"&&v(l)===e){let u=s(l?.object);if(u&&x(u)&&s(u.object)?.type==="ThisExpression"){let a=v(u);a&&r.add(a);}}for(let u of C(o))i.push(u);}}var lt=createAnyAngularClassRule(ue,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=Be(a.sourceText,st),c=new Map;for(let[n,f]of p)for(let m of f)c.set(m,n);return c})(e),o=(function(a){let p=new Set,c=U(a);if(c){let n=L(c);n&&H(n,"next",p);}for(let n of a)if(B(n)){n.kind==="set"&&(function(m){let d=m.decorators;if(!Array.isArray(d))return false;for(let h of d){let y=s(h.expression);if(y?.name==="Input"||s(y?.callee)?.name==="Input")return true}return false})(n)&&H(n,"next",p);let f=n.key?.name;if(f==="ngOnChanges"){let m=L(n);m&&H(m,"next",p);}if(f==="ngOnDestroy"){let m=L(n);m&&H(m,"complete",p);}}else n.type==="PropertyDefinition"&&n.value&&H(n.value,"next",p);return p})(r),l=(function(a){let p=new Set;for(let c of a){let n=B(c)?L(c):c.type==="PropertyDefinition"?c.value:null;n&&H(n,"pipe",p);}return p})(r),u=[];for(let a of r){if(a.type!=="PropertyDefinition"||a.accessibility==="public")continue;let p=s(a.value??a.initializer);if(!p||p.type!=="NewExpression")continue;let c=(function(d,h){let y=s(d);if(!y)return null;if(y.type==="Identifier")return h.get(y.name)??null;if(x(y)){let g=v(y);return g&&st.has(g)?g:null}return null})(p.callee,i),n=a.key?.name??"";if(!c||!n||xr.has(n.toLowerCase())||o.has(n)||l.has(n))continue;let{line:f,column:m}=e.locator.location(b(a));u.push({filePath:e.filePath,ruleName:ue,message:br.test(n)?`${c} '${n}' is used for component UI state, which adds stream overhead to local state updates.`:`${c} '${n}' is acting as a local event bus, which makes component interactions harder to trace.`,line:f,column:m,severity:"warn",fix:E[ue],codeExample:R[ue]});}return u.length?u:null});var Pe="rxjs-prefer-toSignal-for-template-state",ut=new Set(["Observable","Subject","BehaviorSubject","ReplaySubject","AsyncSubject"]),vr=new Set(["destroy$","destroyed$","unsub$","teardown$","dispose$"]),ct=createAnyAngularClassRule(Pe,(t,e)=>{if(t.metadata?.type!=="Component")return null;let i=e.crossRef?.templateReferences;if(i===void 0)return null;let o=w(t.node),l=[];for(let u of o){if(u.type!=="PropertyDefinition")continue;let a=u.key?.name??"";if(!a||!a.endsWith("$")||vr.has(a.toLowerCase())||(function(f){let m=f.modifiers,d=f.decorators??(Array.isArray(m)?m.filter(h=>h.type==="Decorator"):void 0);return Array.isArray(d)&&d.some(h=>{let y=s(h.expression);return (y?.type==="CallExpression"?j(y):y?.type==="Identifier"?y.name:null)==="Output"})})(u))continue;let p=a.slice(0,-1);if(!i.has(a)&&!i.has(p)||!(function(f){if(ut.has((function(y){let g=y.typeAnnotation,S=s(g?.typeAnnotation);if(!S||S.type!=="TSTypeReference"&&S.type!=="TypeReference")return "";let A=S.typeName??S.name;if(typeof A=="string")return A;if(A&&typeof A=="object"){if(A.type==="Identifier")return A.name??"";if(A.type==="TSQualifiedName")return s(A.right)?.name??""}return ""})(f)))return true;let m=s(f.value??f.initializer);if(!m)return false;let d=j(m);if(d==="toSignal"||d==="signal"||d==="computed")return false;if(m.type==="NewExpression"){let y=s(m.callee),g=y?.type==="Identifier"?y.name:v(y);return !!g&&ut.has(g)}let h=[m];for(;h.length>0;){let y=s(h.pop());if(y){if(y.type==="CallExpression"&&j(y)==="pipe")return true;for(let g of C(y))h.push(g);}}return false})(u))continue;let{line:c,column:n}=e.locator.location(b(u));l.push({filePath:e.filePath,ruleName:Pe,message:`Observable "${a}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:c,column:n,severity:"warn",fix:E[Pe]});}return l.length?l:null},{requires:{projectContext:true,htmlAst:true}});var Oe="toSignal-require-initialValue",pt=createCallExpressionRule(Oe,(t,e)=>{if(!O(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],i=r[1]?s(r[1]):null;if(!i||i.type!=="ObjectExpression"||!(function(o){let l=W(o,"initialValue");if(l&&!xe(l.value))return true;let u=W(o,"requireSync");return !!u&&Ee(u.value)})(i)){let{line:o,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:Oe,message:"toSignal() can emit undefined before the observable produces a value.",line:o,column:l,severity:"warn",fix:E[Oe]}}return null});var Cr=new Set(["set","update","mutate"]),Rr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame","then","catch","finally","subscribe"]),ft=createCallExpressionRule("signal-prefer-computed-over-sync-effect",(t,e)=>{if(!O(t.callee,"effect"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let{hasRead:o,hasWrite:l,hasAsync:u,hasLinked:a,firstWrite:p}=(function(f,m){let d={hasRead:false,hasWrite:false,hasAsync:false,hasLinked:false,firstWrite:null},h=[f];for(;h.length;){let y=s(h.pop());if(y){if((y.type==="AwaitExpression"||y.type==="YieldExpression")&&(d.hasAsync=true),y.type==="CallExpression"){let g=j(y);g&&Rr.has(g)&&(d.hasAsync=true),g==="linkedSignal"&&(d.hasLinked=true),(function(S){let A=s(S);if(!A||A.type!=="CallExpression")return false;let M=s(A.callee);return x(M)&&Cr.has(v(M)||"")})(y)?(d.hasWrite=true,d.firstWrite||(d.firstWrite=y)):(function(S,A,M){let P=s(S);if(!P||P.type!=="CallExpression"||Array.isArray(P.arguments)&&P.arguments.length>0)return false;let I=s(P.callee);if(!I)return false;if(A.typeChecker)try{let T=q(I,A);if(T){let D=A.typeChecker.getTypeOfSymbolAtLocation(T,T.valueDeclaration);if(D&&A.typeChecker.typeToString(D).includes("Signal"))return !0}}catch{}return x(I)?s(I.object)?.type==="ThisExpression":M&&I.type==="Identifier"})(y,m,true)&&(d.hasRead=true);}for(let g of C(y))h.push(g);}}return d})(i,e);if(!l||!o||u||a)return null;let{line:c,column:n}=e.locator.location(b(p||t));return {filePath:e.filePath,ruleName:"signal-prefer-computed-over-sync-effect",message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:c,column:n,severity:"warn",fix:E["signal-prefer-computed-over-sync-effect"]}},{requires:{typeChecker:true}});var mt=new Set(["afterRender","afterNextRender"]),Mr=/\bafterNextRender\s*\(|\bafterRender\s*\(/,ce=new Map,dt=createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!O(t.callee,"untracked")||(function(o,l){let u=l.sourceText??l.fileContent;if(typeof u=="string"&&!Mr.test(u))return false;let a=o.parent;for(;a;){if(a.type==="CallExpression"&&mt.has(j(a)))return true;a=a.parent;}let p=b(o);return (function(c){let n=ce.get(c.filePath);if(n!==void 0)return n;let f=c.program;return n=f?(function(m){let d=[],h=m.body,y=Array.isArray(h)?[...h]:[m];for(;y.length;){let g=s(y.pop());if(g){if(g.type==="CallExpression"&&mt.has(j(g))){let S=s(g.arguments?.[0]);if(S){let A=b(S),M=S.end??S.span?.end??b(S);M>A&&d.push([A,M]);}}for(let S of C(g))y.push(S);}}return d})(f):[],ce.size>=300&&ce.clear(),ce.set(c.filePath,n),n})(l).some(([c,n])=>p>=c&&p<n)})(t,e))return null;let{line:r,column:i}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:i,severity:"warn",fix:E["signal-avoid-untracked-overuse"]}});var pe="prefer-inject-over-constructor-di",Or=new Set(["http","router","route","cdr","cdref","changedetectorref","injector","ngzone","zone","renderer","renderer2","elementref","el","document","platform","location","dialog","snack","toast","store","facade","logger","translate","i18n","auth","api","client","matdialog","overlay","breakpointobserver","snackbar","matsnackbar","bottomsheet","matbottomsheet","clipboard","directionality","focusmonitor","mediamatcher","viewportruler","scrolldispatcher","dragdrop","liveannouncer","activatedroute","fb","firestore","angularfire","formbuilder","titleservice","metaservice","title","meta","sanitizer","domsanitizer","compiler","applicationref","componentfactoryresolver","viewcontainerref","templateref","destroyref"]),Tr=new Set(["data","config","options","opts","params","payload","input","value","values","items","item","context","ctx","model","vm","state","initialstate","result","name","id","label","text","title","message","url","path","index","count","size","length","width","height","color","type","key","mode","flag","enabled","disabled","visible","hidden"]),Ir=["Service","Facade","Store","Client","Repository","Adapter","Manager","Controller","Provider","Registry","Logger","Router","ActivatedRoute","ChangeDetectorRef","DestroyRef","Injector","NgZone","Renderer2","ElementRef","HttpClient","ViewContainerRef","TemplateRef","ComponentFactoryResolver","ApplicationRef","MatDialog","MatDialogRef","MatSnackBar","MatBottomSheet","Overlay","OverlayRef","BreakpointObserver","Clipboard","FocusMonitor","MediaMatcher","ScrollDispatcher","DragDrop","LiveAnnouncer","Directionality","ViewportRuler","FormBuilder","DomSanitizer","Title","Meta","Dispatcher","Gateway","Handler","Interceptor","Guard","Resolver","Factory","Strategy","Validator"],kr=new Set(["string","number","boolean","symbol","bigint","any","unknown","void"]),yt=createAnyAngularClassRule(pe,(t,e)=>{let r=U(w(t.node));if(!r)return null;let i=ee(r.value??r).filter(a=>(function(p,c){let n=s(p);if(!n)return false;if(Array.isArray(n.decorators)&&n.decorators.length>0||n.accessibility||n.readonly)return true;if(c.typeChecker){let d=q(p,c);if(d&&Fe(d))return true}let f=(F(p)||"").toLowerCase().trim();if(!f||Tr.has(f))return false;if(Or.has(f))return true;let m=($(p)||"").trim();return !(!m||kr.has(m.toLowerCase()))&&Ir.some(d=>m.endsWith(d))})(a,e));if(i.length===0)return null;let{line:o,column:l}=e.locator.location(b(r)),u=i.map(a=>`${F(a)}: ${$(a)}`).join(", ");return {filePath:e.filePath,ruleName:pe,message:`Constructor dependency injection makes class setup less composable than inject().${u?` Offending params: ${u}.`:""}`,line:o,column:l,severity:"warn",fix:E[pe],codeExample:R[pe]}},{requires:{typeChecker:true}});var fe="signal-prefer-input-signal";function jr(t){let e=s(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var ht=createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[],o=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let u=s(l);if(u&&(u.type==="PropertyDefinition"||u.type==="AccessorProperty")&&Array.isArray(u.decorators)&&u.decorators.some(jr)){let a=b(u),{line:p,column:c}=e.locator.location(a),n=s(u.key),f=(n?.type==="Identifier"?n.name:n?.type==="Literal"?String(n.value):"")||"(unknown)",m=`'${f}' uses @Input(), which keeps this input outside Angular's signal graph.`;o&&(m+=" Standalone declarations benefit most from signal inputs."),i.push({filePath:e.filePath,ruleName:fe,message:m,line:p,column:c,severity:o?"error":"warn",fix:E[fe],codeExample:R[fe]});}}return i.length>0?i:null},{requires:{projectContext:true}});var me="signal-prefer-output-function",gt=createAnyAngularClassRule(me,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of r){let l=s(o);if(l&&(l.type==="PropertyDefinition"||l.type==="AccessorProperty")&&Array.isArray(l.decorators)&&l.decorators.some(u=>{let a=s(u.expression??u);if(!a)return false;if(a.type==="Identifier")return a.name==="Output";if(a.type==="CallExpression"){let p=s(a.callee);return p?.type==="Identifier"&&p.name==="Output"}return false})&&(function(u,a){let p=s(u.value);if(p?.type==="NewExpression"){let n=s(p.callee);if(n?.type==="Identifier"&&n.name==="EventEmitter")return true}let c=s(u.typeAnnotation);if(c&&$(c).includes("EventEmitter"))return true;if(a.typeChecker){let n=q(u,a);if(n&&(typeof n.getName=="function"?n.getName():"").includes("EventEmitter"))return true}return false})(l,e)){let u=b(l),{line:a,column:p}=e.locator.location(u),c=s(l.key),n=(c?.type==="Identifier"?c.name:c?.type==="Literal"?String(c.value):"")||"(unknown)";i.push({filePath:e.filePath,ruleName:me,message:`'${n}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:a,column:p,severity:"warn",fix:E[me],codeExample:R[me]});}}return i.length>0?i:null},{requires:{typeChecker:true}});var de="signal-prefer-model";function Et(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let i=s(r.expression??r);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(i.type==="CallExpression"){let o=s(i.callee);return o?.type==="Identifier"&&o.name===e}return false})}function xt(t,e){let r=s(t.value);if(!r||r.type!=="CallExpression")return false;let i=s(r.callee);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(x(i)){let o=s(i.object);return o?.type==="Identifier"&&o.name===e}return false}var bt=createAnyAngularClassRule(de,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=new Map,o=new Map;for(let u of r){let a=s(u);if(!a||a.type!=="PropertyDefinition"&&a.type!=="AccessorProperty")continue;let p=(function(c){let n=s(c.key);return n?n.type==="Identifier"?n.name??null:n.type==="Literal"?String(n.value):null:null})(a);p&&((Et(a,"Input")||xt(a,"input"))&&i.set(p,a),(Et(a,"Output")||xt(a,"output"))&&o.set(p,a));}let l=[];for(let[u,a]of o){if(!u.endsWith("Change"))continue;let p=u.slice(0,-6),c=i.get(p);if(c){let n=b(c),{line:f,column:m}=e.locator.location(n);l.push({filePath:e.filePath,ruleName:de,message:`The \`${p}\` / \`${u}\` pair implements two-way binding with extra wiring that model() avoids.`,line:f,column:m,severity:"warn",fix:E[de],codeExample:R[de]});}}return l.length>0?l:null});var Br=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Te="template-prefer-control-flow",St=createTemplateAttributeRule(Te,(t,e)=>{var r;let i=(r=t.name,Br.get(r)??null);if(!i)return null;let o=k(e,t.sourceSpan.start),{line:l,column:u}=e.locator.location(o);return {filePath:e.filePath,ruleName:Te,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${i}\` control flow benefits.`,line:l,column:u,severity:"error",fix:E[Te]}},{requires:{htmlAst:true}});var vt=new WeakMap,At=createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,i,o=(function c(n){let f=s(n);if(!f)return null;if(f.type==="BinaryExpression"&&f.operator==="|"){let m=s(f.right);return m?.type==="Identifier"&&m.name==="async"?s(f.left):c(f.left)}return null})(t.expression),l=o?(function c(n,f=0){if(!n||f>10)return null;if(n.type==="Identifier")return n.name;if(n.type==="ThisExpression")return "this";if(n.type==="Literal"){let m=n.value;return m===null?"null":typeof m=="string"||typeof m=="number"||typeof m=="boolean"||typeof m=="bigint"?String(m):null}if(n.type==="CallExpression"){let m=c(n.callee,f+1),d=(Array.isArray(n.arguments)?n.arguments:[]).map(h=>c(h,f+1)??"?");return `${m}(${d.join(",")})`}if(x(n)){let m=c(n.object,f+1),d=v(n);if(m&&d)return `${m}.${d}`}if(n.type==="UnaryExpression")return `${n.operator}${c(n.argument,f+1)}`;if(n.type==="ConditionalExpression")return `${c(n.test,f+1)}?${c(n.consequent,f+1)}:${c(n.alternate,f+1)}`;if(n.type==="OptionalExpression"||n.type==="ChainExpression")return c(n.expression,f+1);if(n.type==="LogicalExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="BinaryExpression"&&n.operator!=="|"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="ArrayExpression")return `[${(n.elements??[]).map(d=>c(d,f+1)??"?").join(",")}]`;if(n.type==="ObjectExpression")return `{${(n.properties??[]).map(d=>{let h=d.key?c(d.key,f+1):"?",y=d.value?c(d.value,f+1):"?";return `${h}:${y}`}).join(",")}}`;if(n.type==="TemplateLiteral")return "`tmpl`";if(n.type==="AssignmentExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}return null})(o):null;if(!l)return null;let u=(r=e.template,i=r?.templateStartOffset,`${e.filePath}@${typeof i=="number"&&Number.isFinite(i)?i:0}`),a=vt.get(e);a||(a=new Map,vt.set(e,a));let p=a.get(u);if(p||(p=new Set,a.set(u,p)),p.has(l)){let c=k(e,t.sourceSpan.start),{line:n,column:f}=e.locator.location(c);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:n,column:f,severity:"warn",fix:E["template-no-async-pipe-duplication"]}}return p.add(l),null},{requires:{htmlAst:true}});var qr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Hr=new Set(["xdescribe","xit","xtest","xcontext"]);function Nt(t){return t.type==="Identifier"?t.name??null:null}var Ct=createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let i;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let o=s(t.callee);if(!o)return null;let l=(i=Nt(o)||(function(n){if(n.type==="MemberExpression"||n.type==="StaticMemberExpression"||n.type==="OptionalMemberExpression"){let f=s(n.object),m=n.property?.name??"",d=(f?.type==="Identifier"?f.name:"")??"";return d?`${d}.${m}`:null}return null})(o))&&qr.has(i)?i:null;if(!l){if(Nt(o)==="pending"){let n=b(t),{line:f,column:m}=e.locator.location(n);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:f,column:m,severity:"error",fix:E["spec-no-focused-test"]}}return null}let u=b(t),{line:a,column:p}=e.locator.location(u),c=Hr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:c,line:a,column:p,severity:"error",fix:E["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Rt(){N(He,"correctness"),N(ze,"correctness"),N(We,"correctness"),N(Xe,"correctness"),N(Ye,"performance"),N(Ke,"performance"),N(Qe,"performance"),N(Je,"performance"),N(et,"performance"),N(tt,"security"),N(rt,"security"),N(nt,"ssr"),N(it,"ssr"),N(at,"reactivity"),N(ot,"reactivity"),N(lt,"reactivity"),N(ct,"reactivity"),N(pt,"reactivity"),N(ft,"reactivity"),N(dt,"reactivity"),N(yt,"modern-api"),N(ht,"modern-api"),N(gt,"modern-api"),N(bt,"modern-api"),N(St,"template"),N(At,"template"),N(Ct,"testing");}(async()=>{if(Rt(),configureRuleExecutor(De,ke),!parentPort)return;let{rootDir:t,tasks:e}=workerData,r=[],i=[],o=createAnalysisContext(t),l=new Map;for(let u of e){let a=l.get(u.filePath)??[];a.push(u),l.set(u.filePath,a);}for(let[u,a]of l){let p=performance.now();try{let c=await executeBatchedTasks(a,o);r.push(...c),parentPort.postMessage(wt(u,a.length,c,performance.now()-p));}catch(c){for(let n of a)i.push({task:n,error:c instanceof Error?c.message:String(c)});parentPort.postMessage(wt(u,a.length,[],performance.now()-p));}finally{o.evict(u);}}parentPort.postMessage({results:r,errors:i});})();var wt=(t,e,r,i)=>{let o=0,l=0;for(let u of r)for(let a of u.failures)a.severity==="error"?o++:a.severity==="warn"&&l++;return {kind:"file-progress",filePath:t,taskCount:e,typeAware:false,issueCount:o+l,errorCount:o,warningCount:l,duration:i}};//# sourceMappingURL=execution-worker.js.map
});`};var Qe;function g(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function C(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function N(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function T(t,e){let r=g(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!C(r)&&N(r)===e)}function Re(t){let e=g(t);if(!e||e.type!=="CallExpression")return "";let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}function te(t){let e=g(t?.callee);return !!C(e)&&N(e)==="subscribe"}function Y(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let n of r){if(!n||n.type!=="Property")continue;let a=n.key;if((a?.type==="Identifier"?a.name:a?.type==="Literal"&&typeof a.value=="string"?a.value:"")===e)return n}return null}function we(t){let e=g(t);return !!(e&&e.type==="Literal"&&e.value===true)}function Me(t){let e=g(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Vt=new Set(["parent","span","loc","range","start","end","type"]);function*O(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Vt.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let n of r)n&&typeof n=="object"&&(yield n);else typeof r=="object"&&r.type&&(yield r);}}}function Pe(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function H(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function Je(t){for(let e of t)if(e&&H(e)&&Pe(e))return e;return null}function z(t){return t?(t.value??t)?.body??null:null}function et(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function F(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Kt(t){let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let n=g(r[1]);if(!n||n.type!=="ObjectExpression")return false;let a=Y(n,"injector");if(a&&!Me(a.value))return true;let l=Y(n,"manualCleanup");return !!(l&&we(l.value))}function tt(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&T(n.callee,"effect")&&!Kt(n)&&e.push(n),O(n)))r.push(a);}return e}var Xt=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function Gt(t){let e=g(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}return C(e)?N(e):""}function Yt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(Xt.has(Gt(r)))return true;return false}function re(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)==="pipe"&&Yt(r))return true;e=n?.object;}return false}function I(t,e){return e}var Qt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),Zt=new Set(["http","httpClient","_http","_httpClient"]),Jt=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function ne(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)!=="pipe")return r;e=n?.object;}return null}function ie(t){if(!t)return false;let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=g(e.callee);if(!C(r))return false;let n=N(r);if(!n)return false;let a=g(r?.object),l=Array.isArray(e.arguments)?e.arguments:[];if(Qt.has(n)&&C(a)){let c=N(a);if(Zt.has(c))return true}if(l.length>0){let c=n.toLowerCase();for(let p of Jt)if(c.startsWith(p)&&n.length>p.length)return true}return false}var Ze=false;function Te(){if(!Ze){try{Qe=Ht("typescript");}catch{}Ze=true;}return Qe}function rt(t,e){if(!t||!e.typeChecker)return;let r=Te();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let n=e.sourceFile;if(!n)return;let a=(function(l,c,p){if(c<l.getStart()||c>=l.getEnd())return;let d=l;for(;;){let u=p.forEachChild(d,i=>{if(c>=i.getStart()&&c<i.getEnd())return i});if(!u)break;d=u;}return d})(n,b(t),r);return a?e.typeChecker.getSymbolAtLocation(a):void 0}catch{return}}function D(t){if(t.sourceFile)return t.sourceFile;if(!t.fileContent)return;let e=Te();if(e)return t.sourceFile=e.createSourceFile(t.filePath,t.fileContent,e.ScriptTarget.Latest,true),t.sourceFile}var ee=new Map;function oe(t){let e=ee.get(t.filePath);if(e!==void 0)return e;let r=(function(n){let{typeChecker:a,angularTypes:l}=n;if(!a||!l)return false;let c=Te(),p=D(n);if(!c||!p)return false;for(let d of p.statements){if(!c.isClassDeclaration(d)||!c.canHaveDecorators(d))continue;let u=c.getDecorators(d);if(u)for(let i of u){let s=c.isCallExpression(i.expression)?i.expression.expression:i.expression;if(!c.isIdentifier(s)||s.text!=="Component"&&s.text!=="Directive")continue;let o=a.getSymbolAtLocation(s),f=o&&o.flags&c.SymbolFlags.Alias?a.getAliasedSymbol(o):o;if(l.isFromAngularCore(f))return true}}return false})(t);return ee.size>=1024&&ee.clear(),ee.set(t.filePath,r),r}function Q(t){if(!t)return false;let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib.dom"))return true;return false}var se="component-no-manual-detect-changes",nr=new Set(["detectChanges","markForCheck"]),nt=createAnyAngularClassRule(se,(t,e)=>{let r,n=t.node,a=(r=analyzeComponent(n),r?.type!=="Component"?{isComponent:false,isOnPush:false}:{isComponent:true,isOnPush:r.changeDetection?.kind==="literal"&&r.changeDetection.value===ChangeDetectionStrategy.OnPush});if(!a.isComponent)return null;let{typeChecker:l,angularTypes:c}=e;if(!l||!c)return null;let p=(function(i,s){let o=D(s);if(!o)return;let f=b(i);for(let m of o.statements)if(M.isClassDeclaration(m)&&m.pos<=f&&f<=m.end)return m})(n,e);if(!p)return null;let d=[],u=i=>{if(M.isCallExpression(i)){let s=(function(o,f,m,y,h){if(!M.isPropertyAccessExpression(o.expression))return null;let E=o.expression.name.text;if(!nr.has(E)||y.isOnPush&&E==="markForCheck")return null;let S=f.getTypeAtLocation(o.expression.expression);if(!m.isChangeDetectorRef(S))return null;let{line:A,column:v}=h.locator.location(o.getStart());return {filePath:h.filePath,ruleName:se,message:y.isOnPush?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${E}) can hide state-flow bugs and make rendering harder to predict.`,line:A,column:v,severity:y.isOnPush?"warn":"error",fix:x[se],codeExample:P[se]}})(i,l,c,a,e);s&&d.push(s);}M.forEachChild(i,u);};return u(p),d.length>0?d:null});var Oe="signal-no-side-effects-in-computed",or=new Set(["set","update","mutate"]),ar=new Set(["next","complete","error"]),it=createCallExpressionRule(Oe,(t,e)=>{var r,n;let a,l;if(!T(t.callee,"computed"))return null;let{typeChecker:c,angularTypes:p}=e;if(!c||!p)return null;let d=(function(s,o){var f;let m,y=(f=s).sourceFile?f.sourceFile:f.fileContent?(f.sourceFile=M.createSourceFile(f.filePath,f.fileContent,M.ScriptTarget.Latest,true),f.sourceFile):void 0;if(!y)return;let h=E=>{if(!m){if(M.isCallExpression(E)&&E.getStart()===o){m=E;return}M.forEachChild(E,h);}};return h(y),m})(e,b(t));if(!d)return null;let u=d.arguments[0];if(!u||!(M.isArrowFunction(u)||M.isFunctionExpression(u)))return null;let i=(r=u.body,n={typeChecker:c,angularTypes:p},(l=s=>{var o,f,m,y;if(a)return;let h=(o=s,f=n,M.isBinaryExpression(o)&&(m=o.operatorToken.kind)>=M.SyntaxKind.FirstAssignment&&m<=M.SyntaxKind.LastAssignment?ke(o.left)?{node:o,kind:"write"}:void 0:M.isPostfixUnaryExpression(o)||M.isPrefixUnaryExpression(o)?(o.operator===M.SyntaxKind.PlusPlusToken||o.operator===M.SyntaxKind.MinusMinusToken)&&ke(o.operand)?{node:o,kind:"write"}:void 0:M.isDeleteExpression(o)&&ke(o.expression)?{node:o,kind:"write"}:M.isCallExpression(o)?(function(E,S){if(!M.isPropertyAccessExpression(E.expression))return;let A=E.expression.name.text,v=E.expression.expression,w=S.typeChecker.getTypeAtLocation(v);return or.has(A)&&S.angularTypes.isWritableSignal(w)?{node:E,kind:"write"}:ar.has(A)&&S.angularTypes.isSubjectLike(w)||S.angularTypes.isHttpClient(w)?{node:E,kind:"effect"}:void 0})(o,f):void 0);if(h){a=h;return}y=s,M.isArrowFunction(y)||M.isFunctionExpression(y)||M.isFunctionDeclaration(y)||M.isMethodDeclaration(y)||M.isGetAccessorDeclaration(y)||M.isSetAccessorDeclaration(y)||M.forEachChild(s,l);})(r),a);return i?(function(s,o,f){let m=s.node.getStart(),{line:y,column:h}=f.locator.location(m||b(o));return {filePath:f.filePath,ruleName:Oe,message:s.kind==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:y,column:h,severity:"error",fix:x[Oe]}})(i,t,e):null},{requires:{typeChecker:true}});function ke(t){return M.isPropertyAccessExpression(t)||M.isElementAccessExpression(t)}var De="signal-effect-must-be-destroy-scoped",ot=createAnyAngularClassRule(De,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let n=[];for(let a of r)a&&H(a)&&!Pe(a)&&n.push(...(function(l,c){let p=z(l);if(!p)return [];let d=et(l),u=[];for(let i of tt(p))(function(s){if(s.type!=="CallExpression")return false;let o=g(s.callee);return !!o&&(o.type==="Identifier"?o.name==="effect":!!C(o)&&N(o)==="effect")})(i)&&!(function(s){let o=g((Array.isArray(s.arguments)?s.arguments:[])[1]);if(!o||o.type!=="ObjectExpression")return false;for(let f of Array.isArray(o.properties)?o.properties:[]){let m=g(f);if(m?.type==="Property"){let y=g(m.key),h=y?.type==="Identifier"?y.name:N(y)||"";if(h==="injector")return true;if(h==="manualCleanup"){let E=g(m.value);if(E?.type==="Literal"&&E.value===true)return true}}}return false})(i)&&u.push((function(s,o,f){let m=b(s),{line:y,column:h}=f.locator.location(m);return {filePath:f.filePath,ruleName:De,message:`effect() inside "${o}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:h,severity:"error",fix:x[De]}})(i,d,c));return u})(a,e));return n.length>0?n:null});var le="rxjs-no-nested-subscribe",ur=new Set(["next","error","complete"]),cr=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function Ie(t){if(t.type!=="CallExpression")return false;let e=g(t.callee);return !!C(e)&&N(e)==="subscribe"}function at(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var st=createCallExpressionRule(le,(t,e)=>{if(!Ie(t))return null;for(let r of (function(n){if(!Ie(n))return [];let a=Array.isArray(n.arguments)?n.arguments:[];if(a.length===0)return [];let l=g(a[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let p=[];for(let d of Array.isArray(l.properties)?l.properties:[]){let u=g(d);if(u?.type==="Property"&&ur.has((function(i){let s=g(i.key);return s?s.type==="Identifier"?s.name:N(s)||"":""})(u))){let i=g(u.value);at(i)&&p.push(i);}}return p}let c=[];for(let p=0;p<Math.min(a.length,3);p++){let d=g(a[p]);at(d)&&c.push(d);}return c})(t)){let n=g(r.body);if(n&&(function(a){let l=[a];for(;l.length>0;){var c;let p=g(l.pop());if(p){if(p!==a&&Ie(p))return true;if(!(p!==a&&(c=p).type&&cr.has(c.type)))for(let d of O(p))l.push(d);}}return false})(n))return (function(a,l){let c=b(a),{line:p,column:d}=l.locator.location(c);return {filePath:l.filePath,ruleName:le,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:p,column:d,severity:"error",fix:x[le],codeExample:P[le]}})(t,e)}return null});var ue="prefer-on-push-component-change-detection";function ce(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function Le(t){return t.replace(/\\/g,"/")}var lt=createComponentRule(ue,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(n){if(!n||typeof n!="object")return false;let{kind:a,value:l}=n;return a!=="non-literal"&&(a==="literal"?l!==ChangeDetectionStrategy.OnPush:a==="missing")})(r.changeDetection)?null:(function(n,a){let l,c,p,d,u=(l=n.metadata??{},c=n.node,ce(l,"decoratorStart")??ce(l,"start")??ce(c,"start")??ce(n,"start")??0),{line:i,column:s}=a.locator.location(u),o=(p=n.metadata,typeof(d=p?.className)=="string"?d:"AnonymousComponent"),f=(function(m,y){if(!y.project)return null;let h=m.metadata,E=h?.className;if(typeof E!="string"||!E)return null;let S=Le(y.filePath),{ngModuleMap:A,classToFile:v}=y.project;for(let[w,L]of A){if(L.isStandalone||!L.declarations.has(E))continue;let k=v.get(E);if(!k||Le(k)===S)return {moduleName:(Le(w).split("/").pop()??w).replace(/\.ts$/,""),siblingDeclarationCount:Math.max(0,L.declarations.size-1)}}return null})(n,a);return {filePath:a.filePath,ruleName:ue,message:(function(m,y){let h=`Component '${m}' uses default change detection, which can re-render more often than needed.`;if(!y)return h;let{moduleName:E,siblingDeclarationCount:S}=y;return S===0?`${h} It is declared in '${E}'.`:`${h} It is declared in '${E}' alongside ${S} other declaration${S===1?"":"s"}.`})(o,f),line:i,column:s,severity:"error",fix:x[ue],codeExample:P[ue]}})(t,e)},{requires:{projectContext:true}});var je="template-no-call-expression",gr=new Set(["translate","$localize","$any"]),yr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function ut(t){let e=g(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var ct=createTemplateExpressionRule(je,(t,e)=>(function(r,n){let a=r?[r]:[];for(;a.length>0;){let l=g(a.pop());if(l){if(ut(l)&&!(function(c){let p=g(c);if(!p||!ut(p))return false;let d=g(p.callee);if(!d)return false;if(d.type==="Identifier")return gr.has(d.name);if(!C(d))return false;let u=N(d);return !!u&&yr.has(u)})(l)){if((function(p){let d=g(p);return Array.isArray(d?.arguments)?d.arguments:[]})(l).length>0)return true;let c=(function(p){let d=g(p);if(!d)return "";let u=g(d.callee);return u?u.type==="Identifier"?u.name??"":C(u)?N(u):"":""})(l);if(c&&!(function(p,d){if(d.crossRef?.signalMembers?.has(p))return true;let{typeChecker:u,angularTypes:i,crossRef:s}=d;if(!u||!i||!s?.componentPath)return false;let o=(function(f,m,y){let h=y.getProgram?.(),E=h?.getSourceFile(m);if(!E)return;let S=E.statements.find(M.isClassDeclaration);if(!S)return;let A=y.getTypeAtLocation(S),v=y.getPropertyOfType(A,f);if(!v)return;let w=v.valueDeclaration??v.declarations?.[0];if(w)return y.getTypeOfSymbolAtLocation(v,w)})(p,s.componentPath,u);return !!o&&i.isSignal(o)})(c,n))return true}for(let c of O(l))a.push(c);}}return false})(t.expression,e)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:l,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:je,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:c,severity:"error",fix:x[je]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function ft(t,e,r,n){let a=I(t,e.sourceSpan.start),{line:l,column:c}=t.locator.location(a);return {filePath:t.filePath,ruleName:r,message:n,line:l,column:c,severity:"error",fix:x[r]}}var pt=createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let n of t.attributes)n.name==="*ngFor"&&!(function(a){return !!a.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(n.value??"")&&r.push(ft(e,n,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let n of t.blocks)n.name!=="for"||n.parameters.some(a=>{let l=a.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(ft(e,n,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Fe="template-no-object-literal-binding",mt=createTemplateExpressionRule(Fe,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ObjectExpression")return true;for(let l of O(a))n.push(l);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:l,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:Fe,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:c,severity:"warn",fix:x[Fe]}})(t,e)]:null,{requires:{htmlAst:true}});var _e="template-no-array-literal-binding",dt=createTemplateExpressionRule(_e,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ArrayExpression")return true;for(let l of O(a))n.push(l);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:l,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:_e,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:c,severity:"warn",fix:x[_e]}})(t,e)]:null,{requires:{htmlAst:true}});var $e=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),gt=createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let c=g(l.callee);if(!c)return null;if(c.type==="Identifier"&&c.name)return $e.has(c.name)?c.name:null;if(C(c)){let p=N(c);return p&&$e.has(p)?p:null}return null})(t);if(!r)return null;let{line:n,column:a}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${$e.get(r)} sanitization, which can expose unsafe content.`,line:n,column:a,severity:"error",fix:x["no-bypass-sanitization"]}});var Ar=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),Cr=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,vr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,yt=createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=Ar.get(t.name);if(!r)return null;let n=t.value??"";if(Cr.test(n)||vr.test(n)||t.name==="[style]"&&!/[.(|?]/.test(n))return null;let{line:a,column:l}=e.locator.location(I(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:a,column:l,severity:r.severity,fix:x["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var fe="no-document-access",Rr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),ht=createAnyAngularClassRule(fe,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let{typeChecker:n}=e;if(!n)return null;let a=D(e);if(!a)return null;let l=(function(u){let i=new Set,s=[...u];for(;s.length;){let o=g(s.pop());if(o){if(o.type==="VariableDeclarator"&&o.init){let f=g(o.init);if(f?.type==="CallExpression"&&f.callee&&T(f.callee,"isPlatformBrowser")){let m=o.id??o.key;m?.type==="Identifier"&&m.name&&i.add(m.name);}}if(o.type==="AssignmentExpression"&&o.right){let f=g(o.right);if(f?.type==="CallExpression"&&f.callee&&T(f.callee,"isPlatformBrowser")){let m=g(o.left);if(m&&C(m)&&g(m.object)?.type==="ThisExpression"){let y=m.property?.name;typeof y=="string"&&y&&i.add(y);}}}for(let f of O(o))s.push(f);}}return i})(r),c=[],p=new Set,d=[...r];for(;d.length;){let u=g(d.pop());if(u){if(u.type==="IfStatement"&&u.test){let i=g(u.test);if(i){let s=(function(o,f){let m=[o];for(;m.length;){let y=g(m.pop());if(y){if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformBrowser"))return "browser";if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformServer"))return "server";if(y.type==="UnaryExpression"&&y.operator==="!"&&y.argument){let h=g(y.argument);if(h?.type==="CallExpression"&&h.callee&&T(h.callee,"isPlatformServer"))return "browser"}if(y.type==="Identifier"&&f.has(y.name))return "browser";for(let h of O(y))m.push(h);}}return null})(i,l);if(s==="browser"){u.alternate&&d.push(u.alternate);continue}if(s==="server"){u.consequent&&d.push(u.consequent);continue}}}if(u.type==="CallExpression"&&u.callee){let i=g(u.callee);if(i&&(T(i,"afterNextRender")||T(i,"afterRender"))){let s=u.arguments??[];for(let o=1;o<s.length;o++)d.push(s[o]);continue}}if(C(u)){let i=(function(o){let f=o;for(;f&&C(f);)f=g(f.object);return f?.type==="Identifier"?f:null})(u),s=i?.name;if(i&&s&&Rr.has(s)&&(function(o,f,m){let y=(function(E,S){let A,v=w=>{if(!A){if(M.isIdentifier(w)&&w.getStart()===S){A=w;return}M.forEachChild(w,v);}};return v(E),A})(f,b(o));if(!y)return false;let h=m.getSymbolAtLocation(y);return Q((h&&h.flags&M.SymbolFlags.Alias?m.getAliasedSymbol(h):h)??void 0)})(i,a,n)){let o=b(i);if(o!==void 0&&!p.has(o)){p.add(o);let{line:f,column:m}=e.locator.location(o);c.push({filePath:e.filePath,ruleName:fe,message:`Direct access to \`${s}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:x[fe],codeExample:P[fe]});}}}for(let i of O(u))d.push(i);}}return c.length?c:null},{requires:{typeChecker:true}});var pe="prefer-after-render-over-after-view-init",Mr=new Set(["ngAfterViewInit","ngAfterContentInit"]),Et=createAnyAngularClassRule(pe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r}=e;if(!r)return null;let n=(function(l,c){let p=D(c);if(!p)return;let d=b(l);for(let u of p.statements)if(M.isClassDeclaration(u)&&u.pos<=d&&d<=u.end)return u})(t.node,e);if(!n)return null;let a=[];for(let l of n.members){if(!M.isMethodDeclaration(l)||!l.body||!M.isIdentifier(l.name))continue;let c=l.name.text;if(!Mr.has(c)||!(function(u,i){let s=false,o=f=>{if(!s){if(M.isPropertyAccessExpression(f)){if(xt(i.getTypeAtLocation(f.expression))){s=true;return}}else if(M.isElementAccessExpression(f)){if(xt(i.getTypeAtLocation(f.expression))){s=true;return}}else if(M.isIdentifier(f)&&!(function(m){let y=m.parent;return !!y&&!!(M.isPropertyAccessExpression(y)&&y.name===m||M.isQualifiedName(y)&&y.right===m)})(f)){let m=i.getSymbolAtLocation(f);if(Q((m&&m.flags&M.SymbolFlags.Alias?i.getAliasedSymbol(m):m)??void 0)){s=true;return}}M.forEachChild(f,o);}};return o(u),s})(l.body,r))continue;let{line:p,column:d}=e.locator.location(l.getStart());a.push({filePath:e.filePath,ruleName:pe,message:`\`${c}\` contains DOM access that can run before browser-only APIs are safe.`,line:p,column:d,severity:"warn",fix:x[pe],codeExample:P[pe]});}return a.length?a:null},{requires:{typeChecker:true}});function xt(t){let e=t.aliasSymbol??t.symbol;return !!e&&Q(e)}var me=new Map;function Ue(t){let e=D(t);if(!e)return false;for(let r of e.statements)if(M.isClassDeclaration(r))for(let n of r.members){if(!M.isMethodDeclaration(n)||!n.name||!M.isIdentifier(n.name)||n.name.text!=="ngOnDestroy"||!n.body)continue;let a=false,l=c=>{if(!a){if(M.isCallExpression(c)&&M.isPropertyAccessExpression(c.expression)&&c.expression.name.text==="unsubscribe"&&c.arguments.length===0){a=true;return}M.forEachChild(c,l);}};if(l(n.body),a)return true}return false}var bt=createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{if(!oe(e)||!te(t))return null;let r=g(t.callee),n=C(r)?r?.object:null;if(n&&re(n)||ie(ne(n))||(function(p){let d=me.get(p.filePath);if(d!==void 0)return d;let u=Ue(p);return me.size>=500&&me.clear(),me.set(p.filePath,u),u})(e))return null;let a=b(t),{line:l,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:l,column:c,severity:"error",fix:x["rxjs-require-takeUntilDestroyed"]}},{requires:{typeChecker:true}});var de=new Map,ge="rxjs-no-subscribe-in-component",St=createCallExpressionRule(ge,(t,e)=>{if(!oe(e)||!te(t)||(function(p){let d=g(p.callee);if(!d||!C(d))return false;let u=g(d.object);if(!u)return false;if(u.type==="CallExpression"){let i=g(u.callee);if(C(i)&&N(i)==="pipe"&&(Array.isArray(u.arguments)?u.arguments:[]).some(s=>{let o=g(s);if(o?.type!=="CallExpression")return false;let f=g(o.callee)?.name;return f==="take"||f==="first"}))return true}return ie(ne(u))})(t))return null;let r=g(t.callee),n=g(r?.object);if(n&&re(n)||(function(p){let d=de.get(p.filePath);if(d!==void 0)return d;let u=Ue(p);return de.size>=500&&de.clear(),de.set(p.filePath,u),u})(e))return null;let a=b(t),{line:l,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:ge,message:(function(p,d){let u="Open-ended subscriptions in components can outlive the component and make state harder to track.",i=d.crossRef?.templateReferences;if(!i)return u;let s=g(p.callee),o=g(s?.object),f=o?N(o):null;if(!f)return u;let m=f.endsWith("$")?f.slice(0,-1):f;return i.has(f)||i.has(m)?`'${f}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:u})(t,e),line:l,column:c,severity:"error",fix:x[ge],codeExample:P[ge]}},{requires:{typeChecker:true,projectContext:true}});var ye="rxjs-avoid-subject-as-event-bus",At=createAnyAngularClassRule(ye,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=F(t.node);if(a.length===0)return null;let l=(function(i){let s=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,f=>{let m=g(f.callee);if(m&&(m.type==="Identifier"?m.name:C(m)?N(m):"")==="takeUntil")for(let y of Array.isArray(f.arguments)?f.arguments:[]){let h=Ct(y);h&&s.add(h);}});return s})(a),c=(function(i){let s=new Set,o=m=>{he(m??null,y=>{let h=qe(y,"next");h&&s.add(h);});},f=Je(i);for(let m of(f&&o(z(f)),i))if(H(m)){let y=m.key?.name;m.kind==="set"&&(function(h){let E=h.decorators;if(!Array.isArray(E))return false;for(let S of E){let A=g(S.expression);if(A?.name==="Input"||g(A?.callee)?.name==="Input")return true}return false})(m)&&o(m),y==="ngOnChanges"&&o(z(m));}else m.type==="PropertyDefinition"&&m.value&&o(m.value);return s})(a),p=(function(i){let s=new Set;for(let o of i)H(o)&&o.key?.name==="ngOnDestroy"&&he(z(o),f=>{let m=qe(f,"complete");m&&s.add(m);});return s})(a),d=(function(i){let s=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,f=>{let m=qe(f,"pipe");m&&s.add(m);});return s})(a),u=[];for(let i of a){if(i.type!=="PropertyDefinition"||i.accessibility==="public")continue;let s=i.key?.name??"";if(!s||l.has(s)||c.has(s)||p.has(s)||d.has(s))continue;let o=rt(i.key,e);if(!o)continue;let f=o.valueDeclaration??o.declarations?.[0];if(!f)continue;let m=r.getTypeOfSymbolAtLocation(o,f);if(!n.isSubjectLike(m))continue;let{line:y,column:h}=e.locator.location(b(i));u.push({filePath:e.filePath,ruleName:ye,message:`'${s}' is a Subject the class signals into without piping or external exposure \u2014 components are easier to follow when local state lives in fields or signals.`,line:y,column:h,severity:"warn",fix:x[ye],codeExample:P[ye]});}return u.length>0?u:null});function he(t,e){if(!t)return;let r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&e(n),O(n)))r.push(a);}}function Ct(t){let e=g(t);if(!e||!C(e))return null;let r=g(e.object),n=N(e);return n&&r?.type==="ThisExpression"?n:null}function qe(t,e){let r=g(t.callee);return r&&C(r)&&N(r)===e?Ct(r.object):null}var He="rxjs-prefer-toSignal-for-template-state",vt=createAnyAngularClassRule(He,(t,e)=>{if(t.metadata?.type!=="Component")return null;let n=e.crossRef?.templateReferences;if(n===void 0)return null;let{typeChecker:a,angularTypes:l}=e;if(!a||!l)return null;let c=(function(u,i){let s=D(i);if(!s)return;let o=b(u);for(let f of s.statements)if(M.isClassDeclaration(f)&&f.pos<=o&&o<=f.end)return f})(t.node,e);if(!c)return null;let p=[];for(let u of c.members){var d;if(!M.isPropertyDeclaration(u))continue;let i=(function(m){if(M.isIdentifier(m.name)||M.isStringLiteral(m.name))return m.name.text})(u);if(!i||!n.has(i)&&!n.has((d=i).endsWith("$")?d.slice(0,-1):d)||(function(m,y,h){let E=M.getDecorators(m);if(!E)return false;for(let S of E){let A=M.isCallExpression(S.expression)?S.expression.expression:S.expression;if(!M.isIdentifier(A)||A.text!=="Output")continue;let v=y.getSymbolAtLocation(A),w=v&&v.flags&M.SymbolFlags.Alias?y.getAliasedSymbol(v):v;if(h.isFromAngularCore(w))return true}return false})(u,a,l))continue;let s=a.getTypeAtLocation(u);if(!l.isObservable(s)&&!l.isSubjectLike(s))continue;let{line:o,column:f}=e.locator.location(u.getStart());p.push({filePath:e.filePath,ruleName:He,message:`Observable "${i}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:o,column:f,severity:"warn",fix:x[He]});}return p.length?p:null},{requires:{projectContext:true,htmlAst:true,typeChecker:true}});var ze="toSignal-require-initialValue",Nt=createCallExpressionRule(ze,(t,e)=>{if(!T(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],n=r[1]?g(r[1]):null;if(!n||n.type!=="ObjectExpression"||!(function(a){let l=Y(a,"initialValue");if(l&&!Me(l.value))return true;let c=Y(a,"requireSync");return !!c&&we(c.value)})(n)){let{line:a,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:ze,message:"toSignal() can emit undefined before the observable produces a value.",line:a,column:l,severity:"warn",fix:x[ze]}}return null});var We="signal-prefer-computed-over-sync-effect",Lr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame"]),jr=new Set(["then","catch","finally"]),Fr=new Set(["set","update","mutate"]),wt=createCallExpressionRule(We,(t,e)=>{var r,n;let a,l,c,p,d,u;if(!T(t.callee,"effect"))return null;let{typeChecker:i,angularTypes:s}=e;if(!i||!s)return null;let o=(function(S,A){let v,w=D(S);if(!w)return;let L=k=>{if(!v){if(M.isCallExpression(k)&&k.getStart()===A){v=k;return}M.forEachChild(k,L);}};return L(w),v})(e,b(t));if(!o)return null;let f=o.arguments[0];if(!f||!(M.isArrowFunction(f)||M.isFunctionExpression(f)))return null;let m=(r=f.body,n={typeChecker:i,angularTypes:s},l=false,c=false,p=false,d=false,(u=S=>{p&&d&&l&&c||((S.kind===M.SyntaxKind.AwaitExpression||S.kind===M.SyntaxKind.YieldExpression)&&(p=true),M.isCallExpression(S)&&(function(A,v,w){var L,k;if(M.isPropertyAccessExpression(A.expression)){let U,j=A.expression.name.text,K=A.expression.expression,q=v.typeChecker.getTypeAtLocation(K);return Fr.has(j)&&v.angularTypes.isWritableSignal(q)?w.onSignalWrite():(j==="subscribe"&&(v.angularTypes.isObservable(q)||v.angularTypes.isSubjectLike(q))||jr.has(j)&&(U=(L=q).aliasSymbol??L.symbol)&&U.name==="Promise"&&Rt(U))&&w.onAsync()}if(M.isIdentifier(A.expression)){let U,j=A.expression.text;if(j==="linkedSignal")return w.onLinkedSignal();if(Lr.has(j)&&(k=A.expression,(U=v.typeChecker.getSymbolAtLocation(k))&&Rt(U)))return w.onAsync();A.arguments.length===0&&(function(K,q){let Z=q.typeChecker.getSymbolAtLocation(K);if(!Z)return false;let Xe=Z.valueDeclaration??Z.declarations?.[0];if(!Xe)return false;let qt=q.typeChecker.getTypeOfSymbolAtLocation(Z,Xe);return q.angularTypes.isSignal(qt)})(A.expression,v)&&w.onSignalRead();}})(S,n,{onSignalRead:()=>{l=true;},onSignalWrite:()=>{c=true,a??=S;},onAsync:()=>{p=true;},onLinkedSignal:()=>{d=true;}}),M.forEachChild(S,u));})(r),{hasSignalRead:l,hasSignalWrite:c,hasAsync:p,hasLinkedSignal:d,firstWrite:a});if(!m.hasSignalRead||!m.hasSignalWrite||m.hasAsync||m.hasLinkedSignal)return null;let y=m.firstWrite??o,{line:h,column:E}=e.locator.location(y.getStart());return {filePath:e.filePath,ruleName:We,message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:h,column:E,severity:"warn",fix:x[We]}},{requires:{typeChecker:true}});function Rt(t){let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib."))return true;return false}var Mt=new Set(["afterRender","afterNextRender"]),$r=/\bafterNextRender\s*\(|\bafterRender\s*\(/,xe=new Map,Pt=createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!T(t.callee,"untracked")||(function(a,l){let c=l.sourceText??l.fileContent;if(typeof c=="string"&&!$r.test(c))return false;let p=a.parent;for(;p;){if(p.type==="CallExpression"&&Mt.has(Re(p)))return true;p=p.parent;}let d=b(a);return (function(u){let i=xe.get(u.filePath);if(i!==void 0)return i;let s=u.program;return i=s?(function(o){let f=[],m=o.body,y=Array.isArray(m)?[...m]:[o];for(;y.length;){let h=g(y.pop());if(h){if(h.type==="CallExpression"&&Mt.has(Re(h))){let E=g(h.arguments?.[0]);if(E){let S=b(E),A=E.end??E.span?.end??b(E);A>S&&f.push([S,A]);}}for(let E of O(h))y.push(E);}}return f})(s):[],xe.size>=300&&xe.clear(),xe.set(u.filePath,i),i})(l).some(([u,i])=>d>=u&&d<i)})(t,e))return null;let{line:r,column:n}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:n,severity:"warn",fix:x["signal-avoid-untracked-overuse"]}});var Ee="prefer-inject-over-constructor-di",Ur=new Set(["Inject","Optional","Self","SkipSelf","Host"]),Tt=createAnyAngularClassRule(Ee,(t,e)=>{let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(s,o){var f;let m=(f=o).sourceFile?f.sourceFile:f.fileContent?(f.sourceFile=M.createSourceFile(f.filePath,f.fileContent,M.ScriptTarget.Latest,true),f.sourceFile):void 0;if(!m)return;let y=b(s);for(let h of m.statements)if(M.isClassDeclaration(h)&&h.pos<=y&&y<=h.end)return h})(t.node,e);if(!a)return null;let l=a.members.find(M.isConstructorDeclaration);if(!l||l.parameters.length===0)return null;let c=[];for(let s of l.parameters){var p;(function(o,f,m){if((function(E,S,A){let v=M.getDecorators(E);if(!v||v.length===0)return false;for(let w of v){let L=(function(j){let K=M.isCallExpression(j.expression)?j.expression.expression:j.expression;return M.isIdentifier(K)?K:void 0})(w);if(!L||!Ur.has(L.text))continue;let k=S.getSymbolAtLocation(L),U=k&&k.flags&M.SymbolFlags.Alias?S.getAliasedSymbol(k):k;if(A.isFromAngularCore(U))return true}return false})(o,f,m))return true;if(!o.type)return false;let y=f.getTypeFromTypeNode(o.type);if(m.isInjectionToken(y))return true;let h=y.aliasSymbol??y.symbol;return !!h&&m.isInjectableClass(h)})(s,r,n)&&c.push((p=s,{name:M.isIdentifier(p.name)?p.name.text:"<binding>",typeText:p.type?p.type.getText():"<inferred>"}));}if(c.length===0)return null;let{line:d,column:u}=e.locator.location(b(l)),i=c.map(s=>`${s.name}: ${s.typeText}`).join(", ");return {filePath:e.filePath,ruleName:Ee,message:`Constructor dependency injection makes class setup less composable than inject(). Offending params: ${i}.`,line:d,column:u,severity:"warn",fix:x[Ee],codeExample:P[Ee]}},{requires:{typeChecker:true}});var be="signal-prefer-input-signal";function Hr(t){let e=g(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var Ot=createAnyAngularClassRule(be,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=[],a=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let c=g(l);if(c&&(c.type==="PropertyDefinition"||c.type==="AccessorProperty")&&Array.isArray(c.decorators)&&c.decorators.some(Hr)){let p=b(c),{line:d,column:u}=e.locator.location(p),i=g(c.key),s=(i?.type==="Identifier"?i.name:i?.type==="Literal"?String(i.value):"")||"(unknown)",o=`'${s}' uses @Input(), which keeps this input outside Angular's signal graph.`;a&&(o+=" Standalone declarations benefit most from signal inputs."),n.push({filePath:e.filePath,ruleName:be,message:o,line:d,column:u,severity:a?"error":"warn",fix:x[be],codeExample:P[be]});}}return n.length>0?n:null},{requires:{projectContext:true}});var Se="signal-prefer-output-function",kt=createAnyAngularClassRule(Se,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(c,p){let d=D(p);if(!d)return;let u=b(c);for(let i of d.statements)if(M.isClassDeclaration(i)&&i.pos<=u&&u<=i.end)return i})(t.node,e);if(!a)return null;let l=[];for(let c of a.members){if(!M.isPropertyDeclaration(c)||!(function(i,s,o){let f=M.getDecorators(i);if(!f)return false;for(let m of f){let y=M.isCallExpression(m.expression)?m.expression.expression:m.expression;if(!M.isIdentifier(y)||y.text!=="Output")continue;let h=s.getSymbolAtLocation(y),E=h&&h.flags&M.SymbolFlags.Alias?s.getAliasedSymbol(h):h;if(o.isFromAngularCore(E))return true}return false})(c,r,n)||!(function(i,s,o){if(i.type){let m=s.getTypeFromTypeNode(i.type);if(o.isEventEmitter(m))return true}if(i.initializer){let m=s.getTypeAtLocation(i.initializer);if(o.isEventEmitter(m))return true}let f=s.getSymbolAtLocation(i.name);if(f){let m=s.getTypeOfSymbolAtLocation(f,i);if(o.isEventEmitter(m))return true}return false})(c,r,n))continue;let p=(function(i){let s=i.name;if(M.isIdentifier(s)||M.isStringLiteral(s))return s.text})(c)??"(unknown)",{line:d,column:u}=e.locator.location(c.getStart());l.push({filePath:e.filePath,ruleName:Se,message:`'${p}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:d,column:u,severity:"warn",fix:x[Se],codeExample:P[Se]});}return l.length>0?l:null},{requires:{typeChecker:true}});var Ae="signal-prefer-model";function Dt(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let n=g(r.expression??r);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(n.type==="CallExpression"){let a=g(n.callee);return a?.type==="Identifier"&&a.name===e}return false})}function It(t,e){let r=g(t.value);if(!r||r.type!=="CallExpression")return false;let n=g(r.callee);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(C(n)){let a=g(n.object);return a?.type==="Identifier"&&a.name===e}return false}var Lt=createAnyAngularClassRule(Ae,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=new Map,a=new Map;for(let c of r){let p=g(c);if(!p||p.type!=="PropertyDefinition"&&p.type!=="AccessorProperty")continue;let d=(function(u){let i=g(u.key);return i?i.type==="Identifier"?i.name??null:i.type==="Literal"?String(i.value):null:null})(p);d&&((Dt(p,"Input")||It(p,"input"))&&n.set(d,p),(Dt(p,"Output")||It(p,"output"))&&a.set(d,p));}let l=[];for(let[c,p]of a){if(!c.endsWith("Change"))continue;let d=c.slice(0,-6),u=n.get(d);if(u){let i=b(u),{line:s,column:o}=e.locator.location(i);l.push({filePath:e.filePath,ruleName:Ae,message:`The \`${d}\` / \`${c}\` pair implements two-way binding with extra wiring that model() avoids.`,line:s,column:o,severity:"warn",fix:x[Ae],codeExample:P[Ae]});}}return l.length>0?l:null});var Kr=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Ve="template-prefer-control-flow",jt=createTemplateAttributeRule(Ve,(t,e)=>{var r;let n=(r=t.name,Kr.get(r)??null);if(!n)return null;let a=I(e,t.sourceSpan.start),{line:l,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:Ve,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${n}\` control flow benefits.`,line:l,column:c,severity:"error",fix:x[Ve]}},{requires:{htmlAst:true}});var Ft=new WeakMap,_t=createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,n,a=(function u(i){let s=g(i);if(!s)return null;if(s.type==="BinaryExpression"&&s.operator==="|"){let o=g(s.right);return o?.type==="Identifier"&&o.name==="async"?g(s.left):u(s.left)}return null})(t.expression),l=a?(function u(i,s=0){if(!i||s>10)return null;if(i.type==="Identifier")return i.name;if(i.type==="ThisExpression")return "this";if(i.type==="Literal"){let o=i.value;return o===null?"null":typeof o=="string"||typeof o=="number"||typeof o=="boolean"||typeof o=="bigint"?String(o):null}if(i.type==="CallExpression"){let o=u(i.callee,s+1),f=(Array.isArray(i.arguments)?i.arguments:[]).map(m=>u(m,s+1)??"?");return `${o}(${f.join(",")})`}if(C(i)){let o=u(i.object,s+1),f=N(i);if(o&&f)return `${o}.${f}`}if(i.type==="UnaryExpression")return `${i.operator}${u(i.argument,s+1)}`;if(i.type==="ConditionalExpression")return `${u(i.test,s+1)}?${u(i.consequent,s+1)}:${u(i.alternate,s+1)}`;if(i.type==="OptionalExpression"||i.type==="ChainExpression")return u(i.expression,s+1);if(i.type==="LogicalExpression"){let o=u(i.left,s+1),f=u(i.right,s+1);if(o&&f)return `${o}${i.operator}${f}`}if(i.type==="BinaryExpression"&&i.operator!=="|"){let o=u(i.left,s+1),f=u(i.right,s+1);if(o&&f)return `${o}${i.operator}${f}`}if(i.type==="ArrayExpression")return `[${(i.elements??[]).map(f=>u(f,s+1)??"?").join(",")}]`;if(i.type==="ObjectExpression")return `{${(i.properties??[]).map(f=>{let m=f.key?u(f.key,s+1):"?",y=f.value?u(f.value,s+1):"?";return `${m}:${y}`}).join(",")}}`;if(i.type==="TemplateLiteral")return "`tmpl`";if(i.type==="AssignmentExpression"){let o=u(i.left,s+1),f=u(i.right,s+1);if(o&&f)return `${o}${i.operator}${f}`}return null})(a):null;if(!l)return null;let c=(r=e.template,n=r?.templateStartOffset,`${e.filePath}@${typeof n=="number"&&Number.isFinite(n)?n:0}`),p=Ft.get(e);p||(p=new Map,Ft.set(e,p));let d=p.get(c);if(d||(d=new Set,p.set(c,d)),d.has(l)){let u=I(e,t.sourceSpan.start),{line:i,column:s}=e.locator.location(u);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:i,column:s,severity:"warn",fix:x["template-no-async-pipe-duplication"]}}return d.add(l),null},{requires:{htmlAst:true}});var Yr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Qr=new Set(["xdescribe","xit","xtest","xcontext"]);function $t(t){return t.type==="Identifier"?t.name??null:null}var Bt=createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let n;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let a=g(t.callee);if(!a)return null;let l=(n=$t(a)||(function(i){if(i.type==="MemberExpression"||i.type==="StaticMemberExpression"||i.type==="OptionalMemberExpression"){let s=g(i.object),o=i.property?.name??"",f=(s?.type==="Identifier"?s.name:"")??"";return f?`${f}.${o}`:null}return null})(a))&&Yr.has(n)?n:null;if(!l){if($t(a)==="pending"){let i=b(t),{line:s,column:o}=e.locator.location(i);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:s,column:o,severity:"error",fix:x["spec-no-focused-test"]}}return null}let c=b(t),{line:p,column:d}=e.locator.location(c),u=Qr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:u,line:p,column:d,severity:"error",fix:x["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Ut(){R(nt,"correctness"),R(it,"correctness"),R(ot,"correctness"),R(st,"correctness"),R(lt,"performance"),R(ct,"performance"),R(pt,"performance"),R(mt,"performance"),R(dt,"performance"),R(gt,"security"),R(yt,"security"),R(ht,"ssr"),R(Et,"ssr"),R(St,"reactivity"),R(bt,"reactivity"),R(At,"reactivity"),R(vt,"reactivity"),R(Nt,"reactivity"),R(wt,"reactivity"),R(Pt,"reactivity"),R(Tt,"modern-api"),R(Ot,"modern-api"),R(kt,"modern-api"),R(Lt,"modern-api"),R(jt,"template"),R(_t,"template"),R(Bt,"testing");}var Ke=(t,e,r,n,a)=>{let l=0,c=0;for(let p of r)for(let d of p.failures)d.severity==="error"?l++:d.severity==="warn"&&c++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:l+c,errorCount:l,warningCount:c,duration:n,typeAware:a}};(async()=>{if(Ut(),configureRuleExecutor(Ye,Ge),!parentPort)return;let{rootDir:t,tasks:e}=workerData,r=[],n=[],a=createAnalysisContext(t),l=new Map;for(let c of e){let p=l.get(c.filePath)??[];p.push(c),l.set(c.filePath,p);}for(let[c,p]of l){let d=performance.now();try{let u=await executeBatchedTasks(p,a);r.push(...u),parentPort.postMessage(Ke(c,p.length,u,performance.now()-d,!1));}catch(u){let i=u instanceof Error?u.message:String(u);for(let s of p)n.push({task:s,error:i});parentPort.postMessage(Ke(c,p.length,[],performance.now()-d,false));}finally{a.evict(c);}}parentPort.postMessage({results:r,errors:n});})();//# sourceMappingURL=execution-worker.js.map
//# sourceMappingURL=execution-worker.js.map

@@ -5,3 +5,3 @@ import * as _ngcompass_engine from '@ngcompass/engine';

import { AnyAngularClassNode, CallExpression, AngularClassNode, TemplateExpressionNode, TemplateAnalysis, TemplateAttributeNode } from '@ngcompass/ast';
import { RuleMetadata, PluginManifest, RuleRegistryEntry, RuleListEntry, RuleContext, RuleResult, ResolvedRulesMap, ResolvedRule, NormalizedAnalyzerConfig, Result, RuleResolutionResult, PresetReference, PresetConfig, RuleConfig, RuleConfigFull, RulesConfig, BuiltinPreset } from '@ngcompass/common';
import { RuleContext, RuleMetadata, PluginManifest, RuleRegistryEntry, RuleListEntry, RuleResult, ResolvedRulesMap, ResolvedRule, NormalizedAnalyzerConfig, Result, RuleResolutionResult, PresetReference, PresetConfig, RuleConfig, RuleConfigFull, RulesConfig, BuiltinPreset } from '@ngcompass/common';
import * as typescript from 'typescript';

@@ -37,3 +37,3 @@

declare function hasManualTeardownInNgOnDestroy(fileContent: string): boolean;
declare function hasManualTeardownInNgOnDestroy(context: RuleContext): boolean;
declare const rxjsRequireTakeUntilDestroyedRule: _ngcompass_engine.RuleHandler<CallExpression>;

@@ -65,152 +65,31 @@

/**
* RuleRegistry — Plugin Boundary
*
* Replaces the mutable bare Map in adapter.ts with a class that:
* - Throws on duplicate registration (prevents silent stomping)
* - Exposes a controlled surface for plugin authors
* - Provides a global singleton for CLI / built-in usage
* - Provides a reset helper for isolated test runs
*
* Plugin authors export an array of RulePlugin objects from their package.
* The plugin-loader reads the config `plugins` array and calls registry.register()
* for each plugin — no core files need to be modified.
*
* Example plugin package:
* ```ts
* // my-org-rules/src/index.ts
* import type { RulePlugin } from '@ngcompass/rules';
* import { createComponentRule } from '@ngcompass/engine';
*
* const noBareSelectorRule: RulePlugin = {
* name: 'my-org/no-bare-selectors',
* handler: createComponentRule('my-org/no-bare-selectors', (node, ctx) => { ... }),
* meta: { category: 'style', dependencyType: 'component' },
* };
*
* export default [noBareSelectorRule];
* ```
*
* ngcompass.config.ts:
* ```ts
* export default {
* plugins: ['my-org-rules'],
* rules: { 'my-org/no-bare-selectors': 'high' },
* };
* ```
*/
/**
* A plugin descriptor — the unit external rule authors export.
*/
interface RulePlugin {
/** Globally unique rule name. Use namespacing: 'my-org/rule-name' */
readonly name: string;
/** The rule handler (created via createComponentRule, createDecoratedPropertyRule, etc.) */
readonly handler: RuleHandler<unknown>;
/** Optional metadata overrides (category, description, dependencyType, etc.) */
readonly meta?: Partial<RuleMetadata>;
/** Optional manifest (RFC §7.6) */
readonly manifest?: PluginManifest;
}
/**
* Options controlling registration behaviour.
*/
interface RegisterOptions {
/**
* Allow overwriting an existing rule with the same name.
* Default: false — throws on duplicate to prevent silent errors.
*/
allowOverride?: boolean;
}
/**
* Central registry for rule handlers.
*
* Responsibilities:
* - Store handler instances keyed by rule name
* - Prevent accidental duplicate registration
* - Expose read-only views for the engine and adapter
*/
declare class RuleRegistry {
private readonly _handlers;
private readonly _meta;
/**
* Registers a rule plugin.
*
* @throws {Error} if the rule name is already registered and allowOverride is false
*/
register(plugin: RulePlugin, opts?: RegisterOptions): void;
/**
* Returns the handler for a rule name, or undefined if not registered.
*/
get(name: string): RuleHandler<unknown> | undefined;
/**
* Returns true if a rule with this name is registered.
*/
has(name: string): boolean;
/**
* Returns all registered rule names.
*/
getRuleNames(): ReadonlyArray<string>;
/**
* Returns the full handler map (read-only view).
* Used by the engine adapter for batched execution.
*/
getAll(): ReadonlyMap<string, RuleHandler<unknown>>;
/**
* Returns metadata overrides for a rule name, if any.
*/
getMeta(name: string): Partial<RuleMetadata> | undefined;
/**
* Returns resolved RuleMetadata for a rule name.
* Fills in defaults for fields not specified in the plugin's meta.
*/
getMetadata(name: string): RuleMetadata | undefined;
/**
* Returns a full RuleRegistryEntry (metadata + default config).
* Used for backward compatibility with the legacy registry API.
*/
getRegistryEntry(name: string): RuleRegistryEntry | undefined;
/**
* Returns a ReadonlyMap compatible with the legacy RuleRegistry type.
*/
toReadonlyMap(): ReadonlyMap<string, RuleRegistryEntry>;
/**
* Total number of registered rules.
*/
get size(): number;
}
/**
* Returns the global registry, creating it on first call.
*/
declare const getGlobalRegistry: () => RuleRegistry;
/**
* Resets the global registry to a fresh empty instance.
*
* FOR TESTS ONLY — never call this in production code.
* Allows isolated unit tests that register their own rules without
* interfering with the global built-in rules.
*/
declare const resetGlobalRegistry: () => void;
/**
* Check if a rule exists in the global registry.
*/
declare const isKnownRule: (name: string) => boolean;
/**
* Get rule metadata by name from the global registry.
*/
declare const getRuleMetadata: (name: string) => RuleMetadata | undefined;
/**
* Get all registered rule names from the global registry.
*/
declare const getAllRuleNames: () => ReadonlyArray<string>;
/**
* Backward-compatible accessor for the legacy `ruleRegistry` constant.
* Returns a ReadonlyMap<string, RuleRegistryEntry> view of the global registry.
*/
declare const getRuleRegistryMap: () => ReadonlyMap<string, RuleRegistryEntry>;
/**
* Returns all registered rules as RuleListEntry objects.
* Used by the `compass rules` CLI command.
*/
declare function getRuleListEntries(): RuleListEntry[];

@@ -220,181 +99,29 @@

/**
* High-Performance Engine Adapter
*
* Bridges the RuleRegistry (plugin boundary) with the single-pass engine
* and the legacy orchestrator API. Maintains backward compatibility while
* enabling batched rule execution and external plugin registration.
*
* The mutable bare Map that previously lived here has been replaced by
* the global RuleRegistry singleton — see rules/registry/rule-registry.ts.
*/
/**
* Checks if a rule is implemented in the engine.
*/
declare const isNewEngineRule: (ruleName: string) => boolean;
/**
* Executes multiple rules in a single AST pass (optimal path).
*
* All handlers for the given rule names are collected from the global
* RuleRegistry (which includes both built-in rules and plugin rules) and
* passed to runSinglePassAnalysis() — the AST is walked exactly once.
*
* @param ruleNames - Rules to execute
* @param context - Rule execution context
* @returns Array of RuleResults, one per rule name
*/
declare const executeBatchedNewEngineRules: (ruleNames: ReadonlyArray<string>, context: RuleContext) => ReadonlyArray<RuleResult>;
/**
* Rule Resolution Pipeline
*
* Main entry point for resolving rules from config + presets
*/
/**
* Resolve rules from config
*
* Pipeline:
* 1. Load & resolve extends chain
* 2. Merge all preset rules (deepest first)
* 3. Apply user config rules (highest precedence)
* 4. Attach metadata from registry
* 5. Filter enabled rules
*/
declare const resolveRules: (config: NormalizedAnalyzerConfig, configDir?: string) => Promise<Result<RuleResolutionResult>>;
/**
* Get only enabled rules from resolution result
*
* Pure function: filters out disabled rules
*/
declare const resolveRules: (config: NormalizedAnalyzerConfig, configDir: string) => Promise<Result<RuleResolutionResult>>;
declare const getEnabledRules: (resolvedRules: ResolvedRulesMap) => ResolvedRulesMap;
/**
* Get rules by category
*
* Pure function: groups rules by category
*/
declare const getRulesByCategory: (resolvedRules: ResolvedRulesMap) => ReadonlyMap<string, ReadonlyArray<ResolvedRule>>;
/**
* Get rules by dependency type
*
* Pure function: groups rules by dependency type
*/
declare const getRulesByDependencyType: (resolvedRules: ResolvedRulesMap) => ReadonlyMap<string, ReadonlyArray<ResolvedRule>>;
/**
* Preset Loader
*
* Loads preset configurations from built-in presets or file system
*/
declare const loadPreset: (reference: PresetReference, configDir: string) => Promise<Result<PresetConfig>>;
declare const resolveExtendsChain: (extendsValue: string | ReadonlyArray<string> | undefined, configDir: string, inheritancePath?: ReadonlyArray<string>) => Promise<Result<ReadonlyArray<PresetConfig>>>;
/**
* Load a preset by reference
*
* Side effect: File I/O (isolated)
*/
declare const loadPreset: (reference: PresetReference, configDir?: string) => Promise<Result<PresetConfig>>;
/**
* Resolve extends chain recursively
*
* Handles: "extends": "recommended"
* Handles: "extends": ["recommended", "strict"]
* Handles: Nested extends in presets
*
* Returns presets in order (deepest first)
*/
declare const resolveExtendsChain: (extendsValue: string | ReadonlyArray<string> | undefined, configDir: string, path?: ReadonlyArray<string>) => Promise<Result<ReadonlyArray<PresetConfig>>>;
/**
* Rule Configuration Normalization
*
* Pure functions to normalize rule configurations
*/
/**
* Normalize rule config to full format
*
* Pure function: shorthand → full format
*/
declare const normalizeRuleConfig: (config: RuleConfig) => RuleConfigFull;
/**
* Check if a rule is enabled (severity !== 'off')
*/
declare const isRuleEnabled: (config: RuleConfig) => boolean;
/**
* Normalize all rules in a rules object
*
* Pure function: transforms all rule configs to full format
*/
declare const normalizeAllRules: (rules: Readonly<Record<string, RuleConfig>>) => ReadonlyMap<string, RuleConfigFull>;
/**
* Rule Configuration Merger
*
* Pure functions to merge rule configurations with proper precedence
*/
/**
* Merge two rule configurations
*
* Pure function: later config overrides earlier config
* Handles both shorthand and full format
*/
declare const mergeRuleConfig: (base: RuleConfig, override: RuleConfig) => RuleConfigFull;
/**
* Merge multiple rule configuration objects
*
* Pure function: later configs override earlier configs
* Precedence: rules[0] < rules[1] < ... < rules[n]
*/
declare const mergeRulesConfigs: (configs: ReadonlyArray<RulesConfig>) => ReadonlyMap<string, RuleConfigFull>;
/**
* Apply overrides to a base rules configuration
*
* Pure function: overrides have highest precedence
*/
declare const applyOverrides: (base: ReadonlyMap<string, RuleConfigFull>, overrides: RulesConfig) => ReadonlyMap<string, RuleConfigFull>;
/**
* Built-in Presets Registry
*/
/**
* Registry of built-in presets
*/
declare const builtinPresets: ReadonlyMap<BuiltinPreset, PresetConfig>;
/**
* Check if a preset name is a built-in preset
*/
declare const isBuiltinPreset: (name: string) => boolean;
/**
* Get a built-in preset by name
*/
declare const getBuiltinPreset: (name: string) => PresetConfig | undefined;
/**
* Returns all preset names that include the given rule.
*/
declare function getPresetsForRule(ruleName: string): string[];
/**
* Rule Recommendations
*
* Actionable, one-sentence fix recommendations surfaced in reporter output.
* Keys must match the ruleName field on RuleFailure exactly.
*/
declare const RECOMMENDATIONS: Readonly<Record<string, string>>;
/**
* Optional before/after code examples for rules that have no auto-fix.
*
* Keys must match the ruleName field on RuleFailure exactly.
* Values are plain multi-line TypeScript strings — no ANSI codes.
* The reporter renders them in a styled block below the fix recommendation.
*/
declare const CODE_EXAMPLES: Readonly<Record<string, string>>;
/**
* Loosely-typed AST node used by migration rules.
* Provides minimal structure while allowing dynamic property access
* that the oxc-parser AST requires.
*/
interface AstNode {

@@ -445,139 +172,30 @@ readonly type?: string;

type MaybeAstNode = AstNode | null | undefined;
/**
* Unwraps TS wrapper nodes, parentheses, chain expressions, and instantiation wrappers.
* Handles all known wrapper node types consistently.
*/
declare function unwrapNode(node: AstNode | null | undefined): AstNode | null;
/**
* Checks if a node is a member expression (static, computed, or optional).
*/
declare function isMemberExpressionLike(node: AstNode | null | undefined): boolean;
/**
* Gets the statically-resolvable property name from a member expression.
* Returns '' if the name cannot be determined.
*/
declare function getStaticPropertyName(member: AstNode | null | undefined): string;
/**
* Gets the start offset of a node, handling both oxc-parser span and estree start formats.
*/
declare function getNodeStart(node: AstNode | null | undefined): number;
/**
* Checks if a call expression's callee matches a given function name.
* Handles both direct calls (`fn()`) and member calls (`obj.fn()`).
*/
declare function isCalleeNamed(calleeRaw: AstNode | null | undefined, name: string): boolean;
/**
* Gets the name of a call expression's callee.
*/
declare function getCalleeName(callExprRaw: AstNode | null | undefined): string;
/**
* Checks if a call expression is a `.subscribe(...)` call.
*/
declare function isSubscribeCall(node: AstNode | null | undefined): boolean;
/**
* Gets a property from an ObjectExpression by key name.
*/
declare function getObjectProperty(objExpr: AstNode | null | undefined, name: string): AstNode | null;
/**
* Checks if a node is literal `true`.
*/
declare function isLiteralTrue(node: AstNode | null | undefined): boolean;
/**
* Checks if a node is literal `null` or `undefined`.
*/
declare function isLiteralNullOrUndefined(node: AstNode | null | undefined): boolean;
/**
* Yields all direct child AST nodes of a given node.
*
* Uses `for...in` instead of `Object.keys()` to avoid allocating an intermediate
* string array for every invocation. AST nodes are plain objects (POJOs) so
* inherited enumerable properties are not a concern in practice.
*
* Skips well-known non-child keys (parent, span, etc.) via a Set for O(1) lookup.
*/
declare function childNodes(node: AstNode | null | undefined): Iterable<AstNode>;
/**
* Checks if a method definition is a constructor.
*/
declare function isConstructorMethod(def: AstNode | null | undefined): boolean;
/**
* Checks if a member is a method definition.
*/
declare function isMethodDefinition(member: AstNode | null | undefined): boolean;
/**
* Gets the constructor member from a class body array.
*/
declare function getConstructorMember(classBody: AstNode[]): AstNode | null;
/**
* Gets the method body from a method definition.
*/
declare function getMethodBody(def: AstNode | null | undefined): AstNode | null;
/**
* Gets the method name from a method definition.
*/
declare function getMethodName(def: AstNode | null | undefined): string;
/**
* Gets the class body as an array from a class node.
*/
declare function getClassBody(classNode: AstNode | null | undefined): AstNode[];
/**
* Checks if an effect() call has allowed escape hatches ({ injector } or { manualCleanup: true }).
*/
declare function isAllowedEffectCall(callExprRaw: AstNode | null | undefined): boolean;
/**
* Finds all effect() calls in a subtree that are not allowed by escape hatches.
*/
declare function findEffectCalls(root: AstNode | null | undefined): AstNode[];
/**
* Gets the callback argument (first arg) from a computed() or effect() call,
* if it's an arrow or function expression.
*/
declare function getCallbackArg(callExpr: AstNode | null | undefined): AstNode | null;
/**
* Gets the body of a function expression.
*/
declare function getFunctionBody(fn: AstNode | null | undefined): AstNode | null;
/**
* Collects import aliases for a given exported name from rxjs imports.
* E.g., `import { BehaviorSubject as BS } from 'rxjs'` -> Set(['BehaviorSubject', 'BS'])
*
* @deprecated Use `collectAllRxjsAliases` instead for better performance — it scans the
* source text only once for all requested names instead of once per name.
*/
declare function collectRxjsAliases(sourceText: string | undefined, exportedName: string): Set<string>;
/**
* Batch version of collectRxjsAliases — scans source text ONCE for all requested export names.
*
* Use this instead of calling collectRxjsAliases() per name to avoid redundant regex work.
*
* @performance O(S × 2) instead of O(S × 2 × N) where N = number of requested names.
* Reduces 6 full-source regex sweeps (e.g. for Subject/ReplaySubject/AsyncSubject) down to 2.
*/
declare function collectAllRxjsAliases(sourceText: string | undefined, exportedNames: ReadonlySet<string>): Map<string, Set<string>>;
/**
* The canonical set of RxJS operators that properly scope subscription lifetime.
*
* Shared between rxjs-no-subscribe-in-component and rxjs-require-takeUntilDestroyed rules
* to guarantee consistent teardown detection without duplicating the operator list.
*/
declare const VALID_TEARDOWN_OPERATORS: Set<string>;
/**
* Extracts the operator name from a single pipe() argument node.
*/
declare function getOperatorNameFromPipeArg(arg: AstNode | null | undefined): string;
/**
* Returns true if the given pipe() call contains at least one valid teardown operator.
*/
declare function hasTeardownInPipeCall(pipeCall: AstNode): boolean;
/**
* Walks the receiver chain of a .subscribe() call looking for a .pipe() call that
* contains at least one valid teardown operator.
*
* @example `source$.pipe(takeUntilDestroyed(destroyRef)).subscribe(...)` → true
*/
declare function hasTeardownInReceiverChain(receiverExpr: AstNode | null | undefined): boolean;
/**
* Computes absolute offset for template expressions, accounting for inline template offset.
*/
declare function getTemplateAbsoluteOffset(context: {
declare function getTemplateAbsoluteOffset(_context: {
template?: {

@@ -587,54 +205,16 @@ templateStartOffset?: number;

}, nodeStart: number): number;
/**
* Walks a .subscribe() receiver chain past any .pipe() calls to the actual
* source observable call expression.
*
* @example
* this.svc.getUser(id).pipe(map(u => u.name)).subscribe(...)
* receiverExpr = pipe(map(...)) CallExpression
* returns = this.svc.getUser(id) CallExpression
*
* Returns null when the chain root is not a recognisable CallExpression.
*/
declare function findObservableSourceCall(receiverExpr: AstNode | null | undefined): AstNode | null;
/**
* Returns true if a call expression is a likely auto-completing HTTP observable.
*
* Detects two unambiguous patterns (conservative — avoids false negatives on
* legitimate long-lived streams):
*
* 1. Direct HttpClient verb call:
* `this.http.get(url)`, `this.httpClient.post(url, body)`
*
* 2. Service/API method with HTTP-action prefix AND at least one argument:
* `this.userSvc.getUser(id)`, `this.api.postComment(body)`,
* `this.repo.deleteItem(id)`, `this.gateway.fetchReport(params)`
*
* Both patterns emit once and complete — they do not need takeUntilDestroyed.
*/
declare function isLikelyHttpObservable(sourceCall: AstNode | null | undefined): boolean;
/**
* Gets parameters array from a function node, handling various AST formats.
*/
declare function getParamsArray(funcNode: AstNode | null | undefined): AstNode[];
/**
* Gets the identifier name from a parameter node (handles AssignmentPattern, RestElement, TSParameterProperty).
*/
declare function getParamIdentifierName(param: AstNode | null | undefined): string;
/**
* Gets the type name from a parameter's type annotation (handles TSParameterProperty).
*/
declare function getParamTypeName(param: AstNode | null | undefined): string;
/**
* Maps an Oxc AST node to a TypeScript AST node and fetches its symbol from the TypeChecker.
* Uses position-based lookup since Oxc and TS nodes do not share identity.
*/
declare function getTsSymbolAtNode(oxcNode: AstNode | null | undefined, context: RuleContext): typescript.Symbol | undefined;
/**
* Checks if a symbol belongs to a well-known Angular type or carries an @Injectable decorator.
*/
declare function isLikelyAngularInjectableSymbol(symbol: typescript.Symbol | undefined): boolean;
declare function ensureRuleSourceFile(context: RuleContext): typescript.SourceFile | undefined;
declare function isAngularComponentOrDirectiveFile(context: RuleContext): boolean;
declare function isTypeScriptLibSymbol(symbol: typescript.Symbol | undefined): boolean;
declare function isDomLibSymbol(symbol: typescript.Symbol | undefined): boolean;
declare const rules = "@ngcompass/rules";
export { type AstNode, CODE_EXAMPLES, type MaybeAstNode, RECOMMENDATIONS, type RegisterOptions, type RulePlugin, RuleRegistry, VALID_TEARDOWN_OPERATORS, applyOverrides, builtinPresets, childNodes, collectAllRxjsAliases, collectRxjsAliases, componentNoManualDetectChangesRule, executeBatchedNewEngineRules, findEffectCalls, findObservableSourceCall, getAllRuleNames, getBuiltinPreset, getCallbackArg, getCalleeName, getClassBody, getConstructorMember, getEnabledRules, getFunctionBody, getGlobalRegistry, getMethodBody, getMethodName, getNodeStart, getObjectProperty, getOperatorNameFromPipeArg, getParamIdentifierName, getParamTypeName, getParamsArray, getPresetsForRule, getRuleListEntries, getRuleMetadata, getRulesByCategory, getRulesByDependencyType, getStaticPropertyName, getTemplateAbsoluteOffset, getTsSymbolAtNode, hasManualTeardownInNgOnDestroy, hasTeardownInPipeCall, hasTeardownInReceiverChain, isAllowedEffectCall, isBuiltinPreset, isCalleeNamed, isConstructorMethod, isKnownRule, isLikelyAngularInjectableSymbol, isLikelyHttpObservable, isLiteralNullOrUndefined, isLiteralTrue, isMemberExpressionLike, isMethodDefinition, isNewEngineRule, isRuleEnabled, isSubscribeCall, loadPreset, mergeRuleConfig, mergeRulesConfigs, noBypassSanitizationRule, noDocumentAccessRule, normalizeAllRules, normalizeRuleConfig, preferAfterRenderOverAfterViewInitRule, preferInjectRule, preferOnPushRule, registerAllBuiltinRules, resetGlobalRegistry, resolveExtendsChain, resolveRules, getRuleRegistryMap as ruleRegistry, rules, rxjsAvoidSubjectRule, rxjsNoNestedSubscribeRule, rxjsNoSubscribeInComponentRule, rxjsPreferToSignalRule, rxjsRequireTakeUntilDestroyedRule, signalAvoidUntrackedRule, signalEffectDestroyScopedRule, signalNoSideEffectsInComputedRule, signalPreferComputedRule, signalPreferInputSignalRule, signalPreferModelRule, signalPreferOutputFunctionRule, specNoFocusedTestRule, templateNoArrayLiteralBindingRule, templateNoAsyncPipeDuplicationRule, templateNoCallExpressionRule, templateNoObjectLiteralBindingRule, templateNoUnsafeBindingsRule, templatePreferControlFlowRule, templateTrackByRequiredRule, toSignalRequireInitialValueRule, unwrapNode };
export { type AstNode, CODE_EXAMPLES, type MaybeAstNode, RECOMMENDATIONS, type RegisterOptions, type RulePlugin, RuleRegistry, VALID_TEARDOWN_OPERATORS, applyOverrides, builtinPresets, childNodes, collectAllRxjsAliases, collectRxjsAliases, componentNoManualDetectChangesRule, ensureRuleSourceFile, executeBatchedNewEngineRules, findEffectCalls, findObservableSourceCall, getAllRuleNames, getBuiltinPreset, getCallbackArg, getCalleeName, getClassBody, getConstructorMember, getEnabledRules, getFunctionBody, getGlobalRegistry, getMethodBody, getMethodName, getNodeStart, getObjectProperty, getOperatorNameFromPipeArg, getParamIdentifierName, getParamTypeName, getParamsArray, getPresetsForRule, getRuleListEntries, getRuleMetadata, getRulesByCategory, getRulesByDependencyType, getStaticPropertyName, getTemplateAbsoluteOffset, getTsSymbolAtNode, hasManualTeardownInNgOnDestroy, hasTeardownInPipeCall, hasTeardownInReceiverChain, isAllowedEffectCall, isAngularComponentOrDirectiveFile, isBuiltinPreset, isCalleeNamed, isConstructorMethod, isDomLibSymbol, isKnownRule, isLikelyAngularInjectableSymbol, isLikelyHttpObservable, isLiteralNullOrUndefined, isLiteralTrue, isMemberExpressionLike, isMethodDefinition, isNewEngineRule, isRuleEnabled, isSubscribeCall, isTypeScriptLibSymbol, loadPreset, mergeRuleConfig, mergeRulesConfigs, noBypassSanitizationRule, noDocumentAccessRule, normalizeAllRules, normalizeRuleConfig, preferAfterRenderOverAfterViewInitRule, preferInjectRule, preferOnPushRule, registerAllBuiltinRules, resetGlobalRegistry, resolveExtendsChain, resolveRules, getRuleRegistryMap as ruleRegistry, rules, rxjsAvoidSubjectRule, rxjsNoNestedSubscribeRule, rxjsNoSubscribeInComponentRule, rxjsPreferToSignalRule, rxjsRequireTakeUntilDestroyedRule, signalAvoidUntrackedRule, signalEffectDestroyScopedRule, signalNoSideEffectsInComputedRule, signalPreferComputedRule, signalPreferInputSignalRule, signalPreferModelRule, signalPreferOutputFunctionRule, specNoFocusedTestRule, templateNoArrayLiteralBindingRule, templateNoAsyncPipeDuplicationRule, templateNoCallExpressionRule, templateNoObjectLiteralBindingRule, templateNoUnsafeBindingsRule, templatePreferControlFlowRule, templateTrackByRequiredRule, toSignalRequireInitialValueRule, unwrapNode };

@@ -5,3 +5,3 @@ import * as _ngcompass_engine from '@ngcompass/engine';

import { AnyAngularClassNode, CallExpression, AngularClassNode, TemplateExpressionNode, TemplateAnalysis, TemplateAttributeNode } from '@ngcompass/ast';
import { RuleMetadata, PluginManifest, RuleRegistryEntry, RuleListEntry, RuleContext, RuleResult, ResolvedRulesMap, ResolvedRule, NormalizedAnalyzerConfig, Result, RuleResolutionResult, PresetReference, PresetConfig, RuleConfig, RuleConfigFull, RulesConfig, BuiltinPreset } from '@ngcompass/common';
import { RuleContext, RuleMetadata, PluginManifest, RuleRegistryEntry, RuleListEntry, RuleResult, ResolvedRulesMap, ResolvedRule, NormalizedAnalyzerConfig, Result, RuleResolutionResult, PresetReference, PresetConfig, RuleConfig, RuleConfigFull, RulesConfig, BuiltinPreset } from '@ngcompass/common';
import * as typescript from 'typescript';

@@ -37,3 +37,3 @@

declare function hasManualTeardownInNgOnDestroy(fileContent: string): boolean;
declare function hasManualTeardownInNgOnDestroy(context: RuleContext): boolean;
declare const rxjsRequireTakeUntilDestroyedRule: _ngcompass_engine.RuleHandler<CallExpression>;

@@ -65,152 +65,31 @@

/**
* RuleRegistry — Plugin Boundary
*
* Replaces the mutable bare Map in adapter.ts with a class that:
* - Throws on duplicate registration (prevents silent stomping)
* - Exposes a controlled surface for plugin authors
* - Provides a global singleton for CLI / built-in usage
* - Provides a reset helper for isolated test runs
*
* Plugin authors export an array of RulePlugin objects from their package.
* The plugin-loader reads the config `plugins` array and calls registry.register()
* for each plugin — no core files need to be modified.
*
* Example plugin package:
* ```ts
* // my-org-rules/src/index.ts
* import type { RulePlugin } from '@ngcompass/rules';
* import { createComponentRule } from '@ngcompass/engine';
*
* const noBareSelectorRule: RulePlugin = {
* name: 'my-org/no-bare-selectors',
* handler: createComponentRule('my-org/no-bare-selectors', (node, ctx) => { ... }),
* meta: { category: 'style', dependencyType: 'component' },
* };
*
* export default [noBareSelectorRule];
* ```
*
* ngcompass.config.ts:
* ```ts
* export default {
* plugins: ['my-org-rules'],
* rules: { 'my-org/no-bare-selectors': 'high' },
* };
* ```
*/
/**
* A plugin descriptor — the unit external rule authors export.
*/
interface RulePlugin {
/** Globally unique rule name. Use namespacing: 'my-org/rule-name' */
readonly name: string;
/** The rule handler (created via createComponentRule, createDecoratedPropertyRule, etc.) */
readonly handler: RuleHandler<unknown>;
/** Optional metadata overrides (category, description, dependencyType, etc.) */
readonly meta?: Partial<RuleMetadata>;
/** Optional manifest (RFC §7.6) */
readonly manifest?: PluginManifest;
}
/**
* Options controlling registration behaviour.
*/
interface RegisterOptions {
/**
* Allow overwriting an existing rule with the same name.
* Default: false — throws on duplicate to prevent silent errors.
*/
allowOverride?: boolean;
}
/**
* Central registry for rule handlers.
*
* Responsibilities:
* - Store handler instances keyed by rule name
* - Prevent accidental duplicate registration
* - Expose read-only views for the engine and adapter
*/
declare class RuleRegistry {
private readonly _handlers;
private readonly _meta;
/**
* Registers a rule plugin.
*
* @throws {Error} if the rule name is already registered and allowOverride is false
*/
register(plugin: RulePlugin, opts?: RegisterOptions): void;
/**
* Returns the handler for a rule name, or undefined if not registered.
*/
get(name: string): RuleHandler<unknown> | undefined;
/**
* Returns true if a rule with this name is registered.
*/
has(name: string): boolean;
/**
* Returns all registered rule names.
*/
getRuleNames(): ReadonlyArray<string>;
/**
* Returns the full handler map (read-only view).
* Used by the engine adapter for batched execution.
*/
getAll(): ReadonlyMap<string, RuleHandler<unknown>>;
/**
* Returns metadata overrides for a rule name, if any.
*/
getMeta(name: string): Partial<RuleMetadata> | undefined;
/**
* Returns resolved RuleMetadata for a rule name.
* Fills in defaults for fields not specified in the plugin's meta.
*/
getMetadata(name: string): RuleMetadata | undefined;
/**
* Returns a full RuleRegistryEntry (metadata + default config).
* Used for backward compatibility with the legacy registry API.
*/
getRegistryEntry(name: string): RuleRegistryEntry | undefined;
/**
* Returns a ReadonlyMap compatible with the legacy RuleRegistry type.
*/
toReadonlyMap(): ReadonlyMap<string, RuleRegistryEntry>;
/**
* Total number of registered rules.
*/
get size(): number;
}
/**
* Returns the global registry, creating it on first call.
*/
declare const getGlobalRegistry: () => RuleRegistry;
/**
* Resets the global registry to a fresh empty instance.
*
* FOR TESTS ONLY — never call this in production code.
* Allows isolated unit tests that register their own rules without
* interfering with the global built-in rules.
*/
declare const resetGlobalRegistry: () => void;
/**
* Check if a rule exists in the global registry.
*/
declare const isKnownRule: (name: string) => boolean;
/**
* Get rule metadata by name from the global registry.
*/
declare const getRuleMetadata: (name: string) => RuleMetadata | undefined;
/**
* Get all registered rule names from the global registry.
*/
declare const getAllRuleNames: () => ReadonlyArray<string>;
/**
* Backward-compatible accessor for the legacy `ruleRegistry` constant.
* Returns a ReadonlyMap<string, RuleRegistryEntry> view of the global registry.
*/
declare const getRuleRegistryMap: () => ReadonlyMap<string, RuleRegistryEntry>;
/**
* Returns all registered rules as RuleListEntry objects.
* Used by the `compass rules` CLI command.
*/
declare function getRuleListEntries(): RuleListEntry[];

@@ -220,181 +99,29 @@

/**
* High-Performance Engine Adapter
*
* Bridges the RuleRegistry (plugin boundary) with the single-pass engine
* and the legacy orchestrator API. Maintains backward compatibility while
* enabling batched rule execution and external plugin registration.
*
* The mutable bare Map that previously lived here has been replaced by
* the global RuleRegistry singleton — see rules/registry/rule-registry.ts.
*/
/**
* Checks if a rule is implemented in the engine.
*/
declare const isNewEngineRule: (ruleName: string) => boolean;
/**
* Executes multiple rules in a single AST pass (optimal path).
*
* All handlers for the given rule names are collected from the global
* RuleRegistry (which includes both built-in rules and plugin rules) and
* passed to runSinglePassAnalysis() — the AST is walked exactly once.
*
* @param ruleNames - Rules to execute
* @param context - Rule execution context
* @returns Array of RuleResults, one per rule name
*/
declare const executeBatchedNewEngineRules: (ruleNames: ReadonlyArray<string>, context: RuleContext) => ReadonlyArray<RuleResult>;
/**
* Rule Resolution Pipeline
*
* Main entry point for resolving rules from config + presets
*/
/**
* Resolve rules from config
*
* Pipeline:
* 1. Load & resolve extends chain
* 2. Merge all preset rules (deepest first)
* 3. Apply user config rules (highest precedence)
* 4. Attach metadata from registry
* 5. Filter enabled rules
*/
declare const resolveRules: (config: NormalizedAnalyzerConfig, configDir?: string) => Promise<Result<RuleResolutionResult>>;
/**
* Get only enabled rules from resolution result
*
* Pure function: filters out disabled rules
*/
declare const resolveRules: (config: NormalizedAnalyzerConfig, configDir: string) => Promise<Result<RuleResolutionResult>>;
declare const getEnabledRules: (resolvedRules: ResolvedRulesMap) => ResolvedRulesMap;
/**
* Get rules by category
*
* Pure function: groups rules by category
*/
declare const getRulesByCategory: (resolvedRules: ResolvedRulesMap) => ReadonlyMap<string, ReadonlyArray<ResolvedRule>>;
/**
* Get rules by dependency type
*
* Pure function: groups rules by dependency type
*/
declare const getRulesByDependencyType: (resolvedRules: ResolvedRulesMap) => ReadonlyMap<string, ReadonlyArray<ResolvedRule>>;
/**
* Preset Loader
*
* Loads preset configurations from built-in presets or file system
*/
declare const loadPreset: (reference: PresetReference, configDir: string) => Promise<Result<PresetConfig>>;
declare const resolveExtendsChain: (extendsValue: string | ReadonlyArray<string> | undefined, configDir: string, inheritancePath?: ReadonlyArray<string>) => Promise<Result<ReadonlyArray<PresetConfig>>>;
/**
* Load a preset by reference
*
* Side effect: File I/O (isolated)
*/
declare const loadPreset: (reference: PresetReference, configDir?: string) => Promise<Result<PresetConfig>>;
/**
* Resolve extends chain recursively
*
* Handles: "extends": "recommended"
* Handles: "extends": ["recommended", "strict"]
* Handles: Nested extends in presets
*
* Returns presets in order (deepest first)
*/
declare const resolveExtendsChain: (extendsValue: string | ReadonlyArray<string> | undefined, configDir: string, path?: ReadonlyArray<string>) => Promise<Result<ReadonlyArray<PresetConfig>>>;
/**
* Rule Configuration Normalization
*
* Pure functions to normalize rule configurations
*/
/**
* Normalize rule config to full format
*
* Pure function: shorthand → full format
*/
declare const normalizeRuleConfig: (config: RuleConfig) => RuleConfigFull;
/**
* Check if a rule is enabled (severity !== 'off')
*/
declare const isRuleEnabled: (config: RuleConfig) => boolean;
/**
* Normalize all rules in a rules object
*
* Pure function: transforms all rule configs to full format
*/
declare const normalizeAllRules: (rules: Readonly<Record<string, RuleConfig>>) => ReadonlyMap<string, RuleConfigFull>;
/**
* Rule Configuration Merger
*
* Pure functions to merge rule configurations with proper precedence
*/
/**
* Merge two rule configurations
*
* Pure function: later config overrides earlier config
* Handles both shorthand and full format
*/
declare const mergeRuleConfig: (base: RuleConfig, override: RuleConfig) => RuleConfigFull;
/**
* Merge multiple rule configuration objects
*
* Pure function: later configs override earlier configs
* Precedence: rules[0] < rules[1] < ... < rules[n]
*/
declare const mergeRulesConfigs: (configs: ReadonlyArray<RulesConfig>) => ReadonlyMap<string, RuleConfigFull>;
/**
* Apply overrides to a base rules configuration
*
* Pure function: overrides have highest precedence
*/
declare const applyOverrides: (base: ReadonlyMap<string, RuleConfigFull>, overrides: RulesConfig) => ReadonlyMap<string, RuleConfigFull>;
/**
* Built-in Presets Registry
*/
/**
* Registry of built-in presets
*/
declare const builtinPresets: ReadonlyMap<BuiltinPreset, PresetConfig>;
/**
* Check if a preset name is a built-in preset
*/
declare const isBuiltinPreset: (name: string) => boolean;
/**
* Get a built-in preset by name
*/
declare const getBuiltinPreset: (name: string) => PresetConfig | undefined;
/**
* Returns all preset names that include the given rule.
*/
declare function getPresetsForRule(ruleName: string): string[];
/**
* Rule Recommendations
*
* Actionable, one-sentence fix recommendations surfaced in reporter output.
* Keys must match the ruleName field on RuleFailure exactly.
*/
declare const RECOMMENDATIONS: Readonly<Record<string, string>>;
/**
* Optional before/after code examples for rules that have no auto-fix.
*
* Keys must match the ruleName field on RuleFailure exactly.
* Values are plain multi-line TypeScript strings — no ANSI codes.
* The reporter renders them in a styled block below the fix recommendation.
*/
declare const CODE_EXAMPLES: Readonly<Record<string, string>>;
/**
* Loosely-typed AST node used by migration rules.
* Provides minimal structure while allowing dynamic property access
* that the oxc-parser AST requires.
*/
interface AstNode {

@@ -445,139 +172,30 @@ readonly type?: string;

type MaybeAstNode = AstNode | null | undefined;
/**
* Unwraps TS wrapper nodes, parentheses, chain expressions, and instantiation wrappers.
* Handles all known wrapper node types consistently.
*/
declare function unwrapNode(node: AstNode | null | undefined): AstNode | null;
/**
* Checks if a node is a member expression (static, computed, or optional).
*/
declare function isMemberExpressionLike(node: AstNode | null | undefined): boolean;
/**
* Gets the statically-resolvable property name from a member expression.
* Returns '' if the name cannot be determined.
*/
declare function getStaticPropertyName(member: AstNode | null | undefined): string;
/**
* Gets the start offset of a node, handling both oxc-parser span and estree start formats.
*/
declare function getNodeStart(node: AstNode | null | undefined): number;
/**
* Checks if a call expression's callee matches a given function name.
* Handles both direct calls (`fn()`) and member calls (`obj.fn()`).
*/
declare function isCalleeNamed(calleeRaw: AstNode | null | undefined, name: string): boolean;
/**
* Gets the name of a call expression's callee.
*/
declare function getCalleeName(callExprRaw: AstNode | null | undefined): string;
/**
* Checks if a call expression is a `.subscribe(...)` call.
*/
declare function isSubscribeCall(node: AstNode | null | undefined): boolean;
/**
* Gets a property from an ObjectExpression by key name.
*/
declare function getObjectProperty(objExpr: AstNode | null | undefined, name: string): AstNode | null;
/**
* Checks if a node is literal `true`.
*/
declare function isLiteralTrue(node: AstNode | null | undefined): boolean;
/**
* Checks if a node is literal `null` or `undefined`.
*/
declare function isLiteralNullOrUndefined(node: AstNode | null | undefined): boolean;
/**
* Yields all direct child AST nodes of a given node.
*
* Uses `for...in` instead of `Object.keys()` to avoid allocating an intermediate
* string array for every invocation. AST nodes are plain objects (POJOs) so
* inherited enumerable properties are not a concern in practice.
*
* Skips well-known non-child keys (parent, span, etc.) via a Set for O(1) lookup.
*/
declare function childNodes(node: AstNode | null | undefined): Iterable<AstNode>;
/**
* Checks if a method definition is a constructor.
*/
declare function isConstructorMethod(def: AstNode | null | undefined): boolean;
/**
* Checks if a member is a method definition.
*/
declare function isMethodDefinition(member: AstNode | null | undefined): boolean;
/**
* Gets the constructor member from a class body array.
*/
declare function getConstructorMember(classBody: AstNode[]): AstNode | null;
/**
* Gets the method body from a method definition.
*/
declare function getMethodBody(def: AstNode | null | undefined): AstNode | null;
/**
* Gets the method name from a method definition.
*/
declare function getMethodName(def: AstNode | null | undefined): string;
/**
* Gets the class body as an array from a class node.
*/
declare function getClassBody(classNode: AstNode | null | undefined): AstNode[];
/**
* Checks if an effect() call has allowed escape hatches ({ injector } or { manualCleanup: true }).
*/
declare function isAllowedEffectCall(callExprRaw: AstNode | null | undefined): boolean;
/**
* Finds all effect() calls in a subtree that are not allowed by escape hatches.
*/
declare function findEffectCalls(root: AstNode | null | undefined): AstNode[];
/**
* Gets the callback argument (first arg) from a computed() or effect() call,
* if it's an arrow or function expression.
*/
declare function getCallbackArg(callExpr: AstNode | null | undefined): AstNode | null;
/**
* Gets the body of a function expression.
*/
declare function getFunctionBody(fn: AstNode | null | undefined): AstNode | null;
/**
* Collects import aliases for a given exported name from rxjs imports.
* E.g., `import { BehaviorSubject as BS } from 'rxjs'` -> Set(['BehaviorSubject', 'BS'])
*
* @deprecated Use `collectAllRxjsAliases` instead for better performance — it scans the
* source text only once for all requested names instead of once per name.
*/
declare function collectRxjsAliases(sourceText: string | undefined, exportedName: string): Set<string>;
/**
* Batch version of collectRxjsAliases — scans source text ONCE for all requested export names.
*
* Use this instead of calling collectRxjsAliases() per name to avoid redundant regex work.
*
* @performance O(S × 2) instead of O(S × 2 × N) where N = number of requested names.
* Reduces 6 full-source regex sweeps (e.g. for Subject/ReplaySubject/AsyncSubject) down to 2.
*/
declare function collectAllRxjsAliases(sourceText: string | undefined, exportedNames: ReadonlySet<string>): Map<string, Set<string>>;
/**
* The canonical set of RxJS operators that properly scope subscription lifetime.
*
* Shared between rxjs-no-subscribe-in-component and rxjs-require-takeUntilDestroyed rules
* to guarantee consistent teardown detection without duplicating the operator list.
*/
declare const VALID_TEARDOWN_OPERATORS: Set<string>;
/**
* Extracts the operator name from a single pipe() argument node.
*/
declare function getOperatorNameFromPipeArg(arg: AstNode | null | undefined): string;
/**
* Returns true if the given pipe() call contains at least one valid teardown operator.
*/
declare function hasTeardownInPipeCall(pipeCall: AstNode): boolean;
/**
* Walks the receiver chain of a .subscribe() call looking for a .pipe() call that
* contains at least one valid teardown operator.
*
* @example `source$.pipe(takeUntilDestroyed(destroyRef)).subscribe(...)` → true
*/
declare function hasTeardownInReceiverChain(receiverExpr: AstNode | null | undefined): boolean;
/**
* Computes absolute offset for template expressions, accounting for inline template offset.
*/
declare function getTemplateAbsoluteOffset(context: {
declare function getTemplateAbsoluteOffset(_context: {
template?: {

@@ -587,54 +205,16 @@ templateStartOffset?: number;

}, nodeStart: number): number;
/**
* Walks a .subscribe() receiver chain past any .pipe() calls to the actual
* source observable call expression.
*
* @example
* this.svc.getUser(id).pipe(map(u => u.name)).subscribe(...)
* receiverExpr = pipe(map(...)) CallExpression
* returns = this.svc.getUser(id) CallExpression
*
* Returns null when the chain root is not a recognisable CallExpression.
*/
declare function findObservableSourceCall(receiverExpr: AstNode | null | undefined): AstNode | null;
/**
* Returns true if a call expression is a likely auto-completing HTTP observable.
*
* Detects two unambiguous patterns (conservative — avoids false negatives on
* legitimate long-lived streams):
*
* 1. Direct HttpClient verb call:
* `this.http.get(url)`, `this.httpClient.post(url, body)`
*
* 2. Service/API method with HTTP-action prefix AND at least one argument:
* `this.userSvc.getUser(id)`, `this.api.postComment(body)`,
* `this.repo.deleteItem(id)`, `this.gateway.fetchReport(params)`
*
* Both patterns emit once and complete — they do not need takeUntilDestroyed.
*/
declare function isLikelyHttpObservable(sourceCall: AstNode | null | undefined): boolean;
/**
* Gets parameters array from a function node, handling various AST formats.
*/
declare function getParamsArray(funcNode: AstNode | null | undefined): AstNode[];
/**
* Gets the identifier name from a parameter node (handles AssignmentPattern, RestElement, TSParameterProperty).
*/
declare function getParamIdentifierName(param: AstNode | null | undefined): string;
/**
* Gets the type name from a parameter's type annotation (handles TSParameterProperty).
*/
declare function getParamTypeName(param: AstNode | null | undefined): string;
/**
* Maps an Oxc AST node to a TypeScript AST node and fetches its symbol from the TypeChecker.
* Uses position-based lookup since Oxc and TS nodes do not share identity.
*/
declare function getTsSymbolAtNode(oxcNode: AstNode | null | undefined, context: RuleContext): typescript.Symbol | undefined;
/**
* Checks if a symbol belongs to a well-known Angular type or carries an @Injectable decorator.
*/
declare function isLikelyAngularInjectableSymbol(symbol: typescript.Symbol | undefined): boolean;
declare function ensureRuleSourceFile(context: RuleContext): typescript.SourceFile | undefined;
declare function isAngularComponentOrDirectiveFile(context: RuleContext): boolean;
declare function isTypeScriptLibSymbol(symbol: typescript.Symbol | undefined): boolean;
declare function isDomLibSymbol(symbol: typescript.Symbol | undefined): boolean;
declare const rules = "@ngcompass/rules";
export { type AstNode, CODE_EXAMPLES, type MaybeAstNode, RECOMMENDATIONS, type RegisterOptions, type RulePlugin, RuleRegistry, VALID_TEARDOWN_OPERATORS, applyOverrides, builtinPresets, childNodes, collectAllRxjsAliases, collectRxjsAliases, componentNoManualDetectChangesRule, executeBatchedNewEngineRules, findEffectCalls, findObservableSourceCall, getAllRuleNames, getBuiltinPreset, getCallbackArg, getCalleeName, getClassBody, getConstructorMember, getEnabledRules, getFunctionBody, getGlobalRegistry, getMethodBody, getMethodName, getNodeStart, getObjectProperty, getOperatorNameFromPipeArg, getParamIdentifierName, getParamTypeName, getParamsArray, getPresetsForRule, getRuleListEntries, getRuleMetadata, getRulesByCategory, getRulesByDependencyType, getStaticPropertyName, getTemplateAbsoluteOffset, getTsSymbolAtNode, hasManualTeardownInNgOnDestroy, hasTeardownInPipeCall, hasTeardownInReceiverChain, isAllowedEffectCall, isBuiltinPreset, isCalleeNamed, isConstructorMethod, isKnownRule, isLikelyAngularInjectableSymbol, isLikelyHttpObservable, isLiteralNullOrUndefined, isLiteralTrue, isMemberExpressionLike, isMethodDefinition, isNewEngineRule, isRuleEnabled, isSubscribeCall, loadPreset, mergeRuleConfig, mergeRulesConfigs, noBypassSanitizationRule, noDocumentAccessRule, normalizeAllRules, normalizeRuleConfig, preferAfterRenderOverAfterViewInitRule, preferInjectRule, preferOnPushRule, registerAllBuiltinRules, resetGlobalRegistry, resolveExtendsChain, resolveRules, getRuleRegistryMap as ruleRegistry, rules, rxjsAvoidSubjectRule, rxjsNoNestedSubscribeRule, rxjsNoSubscribeInComponentRule, rxjsPreferToSignalRule, rxjsRequireTakeUntilDestroyedRule, signalAvoidUntrackedRule, signalEffectDestroyScopedRule, signalNoSideEffectsInComputedRule, signalPreferComputedRule, signalPreferInputSignalRule, signalPreferModelRule, signalPreferOutputFunctionRule, specNoFocusedTestRule, templateNoArrayLiteralBindingRule, templateNoAsyncPipeDuplicationRule, templateNoCallExpressionRule, templateNoObjectLiteralBindingRule, templateNoUnsafeBindingsRule, templatePreferControlFlowRule, templateTrackByRequiredRule, toSignalRequireInitialValueRule, unwrapNode };
export { type AstNode, CODE_EXAMPLES, type MaybeAstNode, RECOMMENDATIONS, type RegisterOptions, type RulePlugin, RuleRegistry, VALID_TEARDOWN_OPERATORS, applyOverrides, builtinPresets, childNodes, collectAllRxjsAliases, collectRxjsAliases, componentNoManualDetectChangesRule, ensureRuleSourceFile, executeBatchedNewEngineRules, findEffectCalls, findObservableSourceCall, getAllRuleNames, getBuiltinPreset, getCallbackArg, getCalleeName, getClassBody, getConstructorMember, getEnabledRules, getFunctionBody, getGlobalRegistry, getMethodBody, getMethodName, getNodeStart, getObjectProperty, getOperatorNameFromPipeArg, getParamIdentifierName, getParamTypeName, getParamsArray, getPresetsForRule, getRuleListEntries, getRuleMetadata, getRulesByCategory, getRulesByDependencyType, getStaticPropertyName, getTemplateAbsoluteOffset, getTsSymbolAtNode, hasManualTeardownInNgOnDestroy, hasTeardownInPipeCall, hasTeardownInReceiverChain, isAllowedEffectCall, isAngularComponentOrDirectiveFile, isBuiltinPreset, isCalleeNamed, isConstructorMethod, isDomLibSymbol, isKnownRule, isLikelyAngularInjectableSymbol, isLikelyHttpObservable, isLiteralNullOrUndefined, isLiteralTrue, isMemberExpressionLike, isMethodDefinition, isNewEngineRule, isRuleEnabled, isSubscribeCall, isTypeScriptLibSymbol, loadPreset, mergeRuleConfig, mergeRulesConfigs, noBypassSanitizationRule, noDocumentAccessRule, normalizeAllRules, normalizeRuleConfig, preferAfterRenderOverAfterViewInitRule, preferInjectRule, preferOnPushRule, registerAllBuiltinRules, resetGlobalRegistry, resolveExtendsChain, resolveRules, getRuleRegistryMap as ruleRegistry, rules, rxjsAvoidSubjectRule, rxjsNoNestedSubscribeRule, rxjsNoSubscribeInComponentRule, rxjsPreferToSignalRule, rxjsRequireTakeUntilDestroyedRule, signalAvoidUntrackedRule, signalEffectDestroyScopedRule, signalNoSideEffectsInComputedRule, signalPreferComputedRule, signalPreferInputSignalRule, signalPreferModelRule, signalPreferOutputFunctionRule, specNoFocusedTestRule, templateNoArrayLiteralBindingRule, templateNoAsyncPipeDuplicationRule, templateNoCallExpressionRule, templateNoObjectLiteralBindingRule, templateNoUnsafeBindingsRule, templatePreferControlFlowRule, templateTrackByRequiredRule, toSignalRequireInitialValueRule, unwrapNode };

@@ -1,2 +0,2 @@

'use strict';var planner=require('@ngcompass/planner'),engine=require('@ngcompass/engine'),common=require('@ngcompass/common'),ast=require('@ngcompass/ast'),Jt=require('typescript');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Jt__default=/*#__PURE__*/_interopDefault(Jt);var wt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var he=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description||`Rule: ${e}`,category:r.category||"general",dependencyType:r.dependencyType||"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:{severity:"warn",options:{}}}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let n=this.getRegistryEntry(r);n&&e.set(r,n);}return e}get size(){return this._handlers.size}},ye=null,X=()=>(ye||(ye=new he),ye);var C=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:{...t.meta?.requires}}};X().register(r),common.debug("engine",`Registered rule: ${t.name}`);},Ie=t=>X().has(t);var ke=(t,e)=>{let r=X(),n=[];for(let u of t){let a=r.get(u);a&&n.push(a);}if(n.length===0)return [];common.debug("engine",`Executing ${n.length} rules in single pass on ${e.filePath}`);let{results:o,performance:l}=engine.runSinglePassAnalysis(n,e);return common.debug("engine",`Single-pass complete: ${l.traversalMs.toFixed(2)}ms, ${l.nodesVisited} nodes`),common.debug("engine",`Cache hit rate: ${(l.cacheStats.hits/(l.cacheStats.hits+l.cacheStats.misses||1)*100).toFixed(1)}%`),l.budgetViolations.length>0&&common.debug("engine","Performance budget violations:",l.budgetViolations),o};var De;function s(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function x(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function v(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function O(t,e){let r=s(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!x(r)&&v(r)===e)}function j(t){let e=s(t);if(!e||e.type!=="CallExpression")return "";let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}function Y(t){let e=s(t?.callee);return !!x(e)&&v(e)==="subscribe"}function W(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let n of r){if(!n||n.type!=="Property")continue;let o=n.key;if((o?.type==="Identifier"?o.name:o?.type==="Literal"&&typeof o.value=="string"?o.value:"")===e)return n}return null}function ge(t){let e=s(t);return !!(e&&e.type==="Literal"&&e.value===true)}function Ee(t){let e=s(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Pt=new Set(["parent","span","loc","range","start","end","type"]);function*N(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Pt.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let n of r)n&&typeof n=="object"&&(yield n);else typeof r=="object"&&r.type&&(yield r);}}}function xe(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function B(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function U(t){for(let e of t)if(e&&B(e)&&xe(e))return e;return null}function L(t){return t?(t.value??t)?.body??null:null}function Le(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function w(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Ot(t){let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let n=s(r[1]);if(!n||n.type!=="ObjectExpression")return false;let o=W(n,"injector");if(o&&!Ee(o.value))return true;let l=W(n,"manualCleanup");return !!(l&&ge(l.value))}function $e(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let n=s(r.pop());if(n)for(let o of(n.type==="CallExpression"&&O(n.callee,"effect")&&!Ot(n)&&e.push(n),N(n)))r.push(o);}return e}function G(t){let e=t?.arguments;if(!Array.isArray(e)||e.length===0)return null;let r=s(e[0]);return r&&(r.type==="ArrowFunctionExpression"||r.type==="FunctionExpression")?r:null}function K(t){if(!t)return null;let e=t.body;return e?s(e):null}function _e(t,e){let r=new Map([...e].map(o=>[o,new Set([o])]));if(typeof t!="string"||t.length===0)return r;let n=new Map([...e].map(o=>[o,RegExp(`^${o}(?:\\s+as\\s+([A-Za-z_$][\\w$]*))?$`)]));for(let o of [/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs['"]/g,/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs\/[^'"]+['"]/g]){let l;for(;(l=o.exec(t))!==null;)for(let u of (l[1]??"").split(",").map(a=>a.trim()).filter(Boolean))for(let[a,c]of n){let p=c.exec(u);p&&r.get(a).add(p[1]??a);}}return r}var Tt=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function It(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}return x(e)?v(e):""}function kt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(Tt.has(It(r)))return true;return false}function Z(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let n=s(r.callee);if(!x(n))break;if(v(n)==="pipe"&&kt(r))return true;e=n?.object;}return false}function k(t,e){let r=t.template?.templateStartOffset;return typeof r=="number"&&Number.isFinite(r)?e+r:e}var Dt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),jt=new Set(["http","httpClient","_http","_httpClient"]),Lt=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function Q(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let n=s(r.callee);if(!x(n))break;if(v(n)!=="pipe")return r;e=n?.object;}return null}function J(t){if(!t)return false;let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=s(e.callee);if(!x(r))return false;let n=v(r);if(!n)return false;let o=s(r?.object),l=Array.isArray(e.arguments)?e.arguments:[];if(Dt.has(n)&&x(o)){let u=v(o);if(jt.has(u))return true}if(l.length>0){let u=n.toLowerCase();for(let a of Lt)if(u.startsWith(a)&&n.length>a.length)return true}return false}function ee(t){if(!t)return [];let e=t.params;if(Array.isArray(e))return e;if(e&&typeof e=="object"){if("items"in e&&Array.isArray(e.items))return e.items;if("elements"in e&&Array.isArray(e.elements))return e.elements}return []}function F(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="TSParameterProperty")return F(e.parameter);if(e.type==="AssignmentPattern"){let r=s(e.left);return r?.type==="Identifier"?r.name??"":""}if(e.type==="RestElement"){let r=s(e.argument);return r?.type==="Identifier"?r.name??"":""}return ""}function $(t){let e=s(t);if(!e)return "";if(e.type==="TSParameterProperty")return $(e.parameter);let r=e.typeAnnotation,n=s(r?.typeAnnotation??r);if(!n)return "";if(n.type==="TSTypeReference"||n.type==="TypeReference"){let o=n.typeName??n.name;if(o&&typeof o=="object"){if(o.type==="Identifier")return o.name??"";if(o.type==="TSQualifiedName")return o.right?.name??""}if(typeof o=="string")return o}return ""}var je=false;function Be(){if(!je){try{De=wt("typescript");}catch{}je=true;}return De}function q(t,e){if(!t||!e.typeChecker)return;let r=Be();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let n=e.sourceFile;if(!n)return;let o=(function(l,u,a){if(u<l.getStart()||u>=l.getEnd())return;let c=l;for(;;){let p=a.forEachChild(c,i=>{if(u>=i.getStart()&&u<i.getEnd())return i});if(!p)break;c=p;}return c})(n,b(t),r);return o?e.typeChecker.getSymbolAtLocation(o):void 0}catch{return}}var $t=["Service","Facade","Store","Client","Repository","Adapter","Controller","Provider","Registry","Logger","Router","Injector","Handler","Interceptor","Guard","Resolver","Validator"];function Ue(t){if(!t)return false;let e=Be();if(!e)return false;try{let r=t.getName();if($t.some(l=>r.endsWith(l)))return !0;let n=t.getDeclarations();if(!n||n.length===0)return !1;let o=n[0];if(!e.canHaveDecorators(o))return !1;for(let l of e.getDecorators(o)??[]){let u=l.expression;if(e.isCallExpression(u)&&e.isIdentifier(u.expression)&&u.expression.text==="Injectable")return !0}return !1}catch{return false}}var E={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},R={"prefer-on-push-component-change-detection":`// Before:
'use strict';var planner=require('@ngcompass/planner'),engine=require('@ngcompass/engine'),common=require('@ngcompass/common'),M=require('typescript'),ast=require('@ngcompass/ast');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var M__default=/*#__PURE__*/_interopDefault(M);var Ht=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var zt={severity:"warn",options:{}},ve=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description??`Rule: ${e}`,category:r.category??"general",dependencyType:r.dependencyType??"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:zt}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let n=this.getRegistryEntry(r);n&&e.set(r,n);}return e}get size(){return this._handlers.size}},Ce=null,J=()=>(Ce||(Ce=new ve),Ce);var R=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:t.meta?.requires??{}}};J().register(r),common.debug("engine",`Registered rule: ${t.name}`);},Ke=t=>J().has(t),Xe=(t,e)=>{let r=J(),n=[];for(let f of t){let d=r.get(f);d&&n.push(d);}if(n.length===0)return [];common.debug("engine",`Executing ${n.length} rules in single pass on ${e.filePath}`);let{results:a,performance:s}=engine.runSinglePassAnalysis(n,e);common.debug("engine",`Single-pass complete: ${s.traversalMs.toFixed(2)}ms, ${s.nodesVisited} nodes`);let c=s.cacheStats.hits+s.cacheStats.misses;if(c>0){let f=s.cacheStats.hits/c*100;common.debug("engine",`Component metadata cache hit rate: ${f.toFixed(1)}%`);}return s.budgetViolations.length>0&&common.debug("engine",`Performance budget violations: ${s.budgetViolations.join("; ")}`),a};var x={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},P={"prefer-on-push-component-change-detection":`// Before:
@Component({ selector: 'app-foo', template: '...' })

@@ -216,3 +216,3 @@ export class FooComponent { }

it('should render', () => { ... });
});`};var te="component-no-manual-detect-changes",Ut=new Set(["detectChanges","markForCheck"]),Ft=new Set(["cdr","cdref","changedetectorref","_cdr","_cdref","changedetector","_changedetector","changedetectionref","cd","_cd"]),qe=engine.createAnyAngularClassRule(te,(t,e)=>{var r,n;let o,l,u=t.node;if(n=u,ast.analyzeComponent(n)?.type!=="Component")return null;let a=(l=(r=(function(i){let f=new Set,m=w(i),d=U(m);if(d){for(let h of ee(d.value??d))if($(h)==="ChangeDetectorRef"){let y=F(h);y&&f.add(y);}}for(let h of m)if(h.type==="PropertyDefinition"&&h.value){let y=s(h.value);if(y&&(function(g){if(g.type!=="CallExpression")return false;let S=s(g.callee);if(S?.type!=="Identifier"||S.name!=="inject")return false;let[A]=g.arguments??[],M=s(A);return M?.type==="Identifier"&&M.name==="ChangeDetectorRef"})(y)){let g=h.key;g?.type==="Identifier"&&f.add(g.name);}}return f})(u)).size>0,i=>!!r.has(i)||!l&&Ft.has(i.toLowerCase())),c=(o=ast.analyzeComponent(u),o?.type==="Component"&&o.changeDetection?.kind==="literal"&&o.changeDetection.value===ast.ChangeDetectionStrategy.OnPush),p=(function(i,f,m,d){let h=[],y=[...w(i)];for(;y.length>0;){let g=s(y.pop());if(!g)continue;let S=(function(A){if(A.type!=="CallExpression")return null;let M=s(A.callee);if(!x(M))return null;let P=v(M);return P&&Ut.has(P)?P:null})(g);for(let A of(S&&(function(M,P){if(M.type!=="CallExpression")return false;let I=s(M.callee);if(!I||!x(I))return false;let T=s(I.object);if(!T)return false;if(T.type==="Identifier")return P(T.name);if(!x(T))return false;let D=s(T.object),_=v(T);return (D?.type==="ThisExpression"||D?.type==="Identifier"&&D.name==="this")&&!!_&&P(_)})(g,d)&&(m&&S==="markForCheck"||h.push((function(M,P,I,T){let D=b(M),{line:_,column:V}=P.locator.location(D);return {filePath:P.filePath,ruleName:te,message:T?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${I}) can hide state-flow bugs and make rendering harder to predict.`,line:_,column:V,severity:T?"warn":"error",fix:E[te],codeExample:R[te]}})(g,f,S,m))),N(g)))y.push(A);}return h})(u,e,c,a);return p.length>0?p:null});var be="signal-no-side-effects-in-computed",Ht=new Set(["post","put","patch","subscribe","unsubscribe","next","complete","setItem","removeItem","appendChild","removeChild","dispatch"]),zt=new Set(["set","update","mutate"]),Wt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]),He=engine.createCallExpressionRule(be,(t,e)=>{if(!O(t.callee,"computed"))return null;let r=G(t),n=r?K(r):null;if(!n)return null;let o=(function(l){let u=[l];for(;u.length>0;){var a;let c=s(u.pop());if(c){if(c!==l){if((function(p){let i=s(p);if(!i)return false;if(i.type==="AssignmentExpression"){let f=s(i.left);return !!f&&x(f)}if(i.type==="UpdateExpression"||i.type==="UnaryExpression"&&i.operator==="delete"){let f=s(i.argument);return !!f&&x(f)}return false})(c))return {node:c,type:"write"};if(c.type==="CallExpression"){let p=(function(i){let f=s(i);if(!f||f.type!=="CallExpression")return "";let m=s(f.callee);return x(m)&&v(m)||""})(c);if(zt.has(p))return {node:c,type:"write"};if(Ht.has(p))return {node:c,type:"effect"}}}if(!(c!==l&&(a=c).type&&Wt.has(a.type)))for(let p of N(c))u.push(p);}}return null})(n);return o?(function(l,u,a,c){let p=b(l)||b(u),{line:i,column:f}=a.locator.location(p);return {filePath:a.filePath,ruleName:be,message:c==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:i,column:f,severity:"error",fix:E[be]}})(o.node,t,e,o.type):null});var Se="signal-effect-must-be-destroy-scoped",ze=engine.createAnyAngularClassRule(Se,(t,e)=>{let r=w(t.node);if(r.length===0)return null;let n=[];for(let o of r)o&&B(o)&&!xe(o)&&n.push(...(function(l,u){let a=L(l);if(!a)return [];let c=Le(l),p=[];for(let i of $e(a))(function(f){if(f.type!=="CallExpression")return false;let m=s(f.callee);return !!m&&(m.type==="Identifier"?m.name==="effect":!!x(m)&&v(m)==="effect")})(i)&&!(function(f){let m=s((Array.isArray(f.arguments)?f.arguments:[])[1]);if(!m||m.type!=="ObjectExpression")return false;for(let d of Array.isArray(m.properties)?m.properties:[]){let h=s(d);if(h?.type==="Property"){let y=s(h.key),g=y?.type==="Identifier"?y.name:v(y)||"";if(g==="injector")return true;if(g==="manualCleanup"){let S=s(h.value);if(S?.type==="Literal"&&S.value===true)return true}}}return false})(i)&&p.push((function(f,m,d){let h=b(f),{line:y,column:g}=d.locator.location(h);return {filePath:d.filePath,ruleName:Se,message:`effect() inside "${m}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:g,severity:"error",fix:E[Se]}})(i,c,u));return p})(o,e));return n.length>0?n:null});var re="rxjs-no-nested-subscribe",Yt=new Set(["next","error","complete"]),Gt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function ve(t){if(t.type!=="CallExpression")return false;let e=s(t.callee);return !!x(e)&&v(e)==="subscribe"}function We(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var Ve=engine.createCallExpressionRule(re,(t,e)=>{if(!ve(t))return null;for(let r of (function(n){if(!ve(n))return [];let o=Array.isArray(n.arguments)?n.arguments:[];if(o.length===0)return [];let l=s(o[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let a=[];for(let c of Array.isArray(l.properties)?l.properties:[]){let p=s(c);if(p?.type==="Property"&&Yt.has((function(i){let f=s(i.key);return f?f.type==="Identifier"?f.name:v(f)||"":""})(p))){let i=s(p.value);We(i)&&a.push(i);}}return a}let u=[];for(let a=0;a<Math.min(o.length,3);a++){let c=s(o[a]);We(c)&&u.push(c);}return u})(t)){let n=s(r.body);if(n&&(function(o){let l=[o];for(;l.length>0;){var u;let a=s(l.pop());if(a){if(a!==o&&ve(a))return true;if(!(a!==o&&(u=a).type&&Gt.has(u.type)))for(let c of N(a))l.push(c);}}return false})(n))return (function(o,l){let u=b(o),{line:a,column:c}=l.locator.location(u);return {filePath:l.filePath,ruleName:re,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:a,column:c,severity:"error",fix:E[re],codeExample:R[re]}})(t,e)}return null});var ne="prefer-on-push-component-change-detection";function ie(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function oe(t){return t.replace(/\\/g,"/")}var Xe=engine.createComponentRule(ne,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(n){if(!n||typeof n!="object")return false;let{kind:o,value:l}=n;return o!=="non-literal"&&(o==="literal"?l!==ast.ChangeDetectionStrategy.OnPush:o==="missing")})(r.changeDetection)?null:(function(n,o){let l,u,a,c,p=(l=n.metadata??{},u=n.node,ie(l,"decoratorStart")??ie(l,"start")??ie(u,"start")??ie(n,"start")??0),{line:i,column:f}=o.locator.location(p),m=(a=n.metadata,typeof(c=a?.className)=="string"?c:"AnonymousComponent"),d=(function(h,y){if(!y.project)return null;let g=h.metadata,S=g?.className;if(typeof S!="string"||!S)return null;let A=oe(y.filePath),{ngModuleMap:M,classToFile:P}=y.project;for(let[T,D]of M){var I;if(D.isStandalone||!D.declarations.has(S))continue;let _=P.get(S);if(_&&oe(_)!==A)continue;let V=0;for(let Te of D.declarations)Te!==S&&(I=P.get(Te))&&oe(I).endsWith(".component.ts")&&V++;return {moduleName:(oe(T).split("/").pop()??T).replace(/\.ts$/,""),siblingComponentCount:V}}return null})(n,o);return {filePath:o.filePath,ruleName:ne,message:(function(h,y){if(!y)return `Component '${h}' uses default change detection, which can re-render more often than needed.`;let{moduleName:g,siblingComponentCount:S}=y,A=S>0?` ${S} other component${S===1?"":"s"} are declared in '${g}'.`:"";return `Component '${h}' uses default change detection, which can re-render more often than needed.${A}`})(m,d),line:i,column:f,severity:"error",fix:E[ne],codeExample:R[ne]}})(t,e)},{requires:{projectContext:true}});var Ae="template-no-call-expression",er=new Set(["translate","$localize","$any"]),tr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function Ye(t){let e=s(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var Ge=engine.createTemplateExpressionRule(Ae,(t,e)=>(function(r,n){let o=r?[r]:[];for(;o.length>0;){let l=s(o.pop());if(l){if(Ye(l)&&!(function(u){let a=s(u);if(!a||!Ye(a))return false;let c=s(a.callee);if(!c)return false;if(c.type==="Identifier")return er.has(c.name);if(!x(c))return false;let p=v(c);return !!p&&tr.has(p)})(l)){if((function(a){let c;return (c=s(a),Array.isArray(c?.arguments)?c.arguments:[]).length>0})(l))return true;let u=(function(a){let c=s(a);if(!c)return "";let p=s(c.callee);return p?p.type==="Identifier"?p.name??"":x(p)?v(p):"":""})(l);if(u&&!(function(a,c){let p=a.startsWith("get")||a.startsWith("is")||a.startsWith("has");if(c.crossRef?.signalMembers?.has(a))return true;if(c.typeChecker&&c.crossRef?.componentPath)try{let i=c.typeChecker,f=c.crossRef.componentPath,m=i.getProgram().getSourceFile(f);if(m){let d=m.statements.find(h=>Jt__default.default.isClassDeclaration(h));if(d&&d.name){let h=i.getTypeAtLocation(d),y=i.getPropertyOfType(h,a);if(y){if(!y)return !1;let g=y.valueDeclaration??y.declarations?.[0];if(!g)return !1;let S=i.getTypeOfSymbolAtLocation(y,g);if(!S)return !1;let A=i.typeToString(S);return A.includes("Signal")||A.includes("writable")||A.includes("computed")}}}}catch{}return !p})(u,n))return true}for(let u of N(l))o.push(u);}}return false})(t.expression,e)?[(function(r,n){let o=k(n,r.sourceSpan.start),{line:l,column:u}=n.locator.location(o);return {filePath:n.filePath,ruleName:Ae,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:u,severity:"error",fix:E[Ae]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function Ke(t,e,r,n){let o=k(t,e.sourceSpan.start),{line:l,column:u}=t.locator.location(o);return {filePath:t.filePath,ruleName:r,message:n,line:l,column:u,severity:"error",fix:E[r]}}var Ze=engine.createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let n of t.attributes)n.name==="*ngFor"&&!(function(o){return !!o.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(n.value??"")&&r.push(Ke(e,n,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let n of t.blocks)n.name!=="for"||n.parameters.some(o=>{let l=o.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(Ke(e,n,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Ce="template-no-object-literal-binding",Qe=engine.createTemplateExpressionRule(Ce,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let o=s(n.pop());if(o){if(o.type==="ObjectExpression")return true;for(let l of N(o))n.push(l);}}return false})(t.expression)?[(function(r,n){let o=k(n,r.sourceSpan.start),{line:l,column:u}=n.locator.location(o);return {filePath:n.filePath,ruleName:Ce,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ce]}})(t,e)]:null,{requires:{htmlAst:true}});var Ne="template-no-array-literal-binding",Je=engine.createTemplateExpressionRule(Ne,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let o=s(n.pop());if(o){if(o.type==="ArrayExpression")return true;for(let l of N(o))n.push(l);}}return false})(t.expression)?[(function(r,n){let o=k(n,r.sourceSpan.start),{line:l,column:u}=n.locator.location(o);return {filePath:n.filePath,ruleName:Ne,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ne]}})(t,e)]:null,{requires:{htmlAst:true}});var Re=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),et=engine.createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let u=s(l.callee);if(!u)return null;if(u.type==="Identifier"&&u.name)return Re.has(u.name)?u.name:null;if(x(u)){let a=v(u);return a&&Re.has(a)?a:null}return null})(t);if(!r)return null;let{line:n,column:o}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${Re.get(r)} sanitization, which can expose unsafe content.`,line:n,column:o,severity:"error",fix:E["no-bypass-sanitization"]}});var sr=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),lr=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,ur=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,tt=engine.createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=sr.get(t.name);if(!r)return null;let n=t.value??"";if(lr.test(n)||ur.test(n)||t.name==="[style]"&&!/[.(|?]/.test(n))return null;let{line:o,column:l}=e.locator.location(k(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:o,column:l,severity:r.severity,fix:E["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var pr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),rt=engine.createAnyAngularClassRule("no-document-access",(t,e)=>{let r=w(t.node);if(r.length===0)return null;let n=(function(a){let c=new Set,p=[...a];for(;p.length;){let i=s(p.pop());if(i){if(i.type==="VariableDeclarator"&&i.init){let f=s(i.init);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=i.id??i.key;m?.type==="Identifier"&&m.name&&c.add(m.name);}}if(i.type==="AssignmentExpression"&&i.right){let f=s(i.right);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=s(i.left);if(m&&x(m)&&s(m.object)?.type==="ThisExpression"){let d=m.property?.name;typeof d=="string"&&d&&c.add(d);}}}for(let f of N(i))p.push(f);}}return c})(r),o=[],l=new Set,u=[...r];for(;u.length;){let a=s(u.pop());if(a){if(a.type==="IfStatement"&&a.test){let c=s(a.test);if(c){let p=(function(i,f){let m=[i];for(;m.length;){let d=s(m.pop());if(d){if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformBrowser"))return "browser";if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformServer"))return "server";if(d.type==="UnaryExpression"&&d.operator==="!"&&d.argument){let h=s(d.argument);if(h?.type==="CallExpression"&&h.callee&&O(h.callee,"isPlatformServer"))return "browser"}if(d.type==="Identifier"&&f.has(d.name))return "browser";for(let h of N(d))m.push(h);}}return null})(c,n);if(p==="browser"){a.alternate&&u.push(a.alternate);continue}if(p==="server"){a.consequent&&u.push(a.consequent);continue}}}if(a.type==="CallExpression"&&a.callee){let c=s(a.callee);if(c&&(O(c,"afterNextRender")||O(c,"afterRender"))){let p=a.arguments??[];for(let i=1;i<p.length;i++)u.push(p[i]);continue}}if(x(a)){let c=(function(p){let i=p;for(;i&&x(i);)i=s(i.object);return i?.type==="Identifier"?i.name??null:null})(a);if(c&&pr.has(c)){let p=a;for(;p&&x(p);)p=s(p.object);let i=b(p);if(i!==void 0&&!l.has(i)){l.add(i);let{line:f,column:m}=e.locator.location(i);o.push({filePath:e.filePath,ruleName:"no-document-access",message:`Direct access to \`${c}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:E["no-document-access"],codeExample:R["no-document-access"]});}}}for(let c of N(a))u.push(c);}}return o.length?o:null});var mr=new Set(["nativeElement","getBoundingClientRect","querySelector","querySelectorAll","getElementById","createElement","scrollIntoView","focus","blur","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollTop","scrollLeft","innerHTML","outerHTML","textContent","parentElement","parentNode","firstChild","lastChild","nextSibling","previousSibling","children","ownerDocument","insertBefore","appendChild","removeChild","replaceChild","cloneNode","setAttribute","getAttribute","removeAttribute","hasAttribute","classList","dispatchEvent","contains","matches","closest","getClientRects","addEventListener","removeEventListener","requestAnimationFrame","cancelAnimationFrame"]),dr=["getElementsBy","offset","client","scroll"],nt=engine.createAnyAngularClassRule("prefer-after-render-over-after-view-init",(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=[];for(let o of ["ngAfterViewInit","ngAfterContentInit"]){let l=r.find(p=>p.key?.name===o),u=l?L(l):null;if(!u||!l||!(function(p){let i=[p];for(;i.length;){let f=s(i.pop());if(f){if((f.type==="MemberExpression"||f.type==="StaticMemberExpression"||f.type==="OptionalMemberExpression")&&!f.computed){let m=f.property?.name??"";if(mr.has(m))return true;for(let d of dr)if(m.startsWith(d))return true}if(f.type==="Identifier"&&(f.name==="document"||f.name==="window"))return true;for(let m of N(f))i.push(m);}}return false})(u))continue;let{line:a,column:c}=e.locator.location(b(l));n.push({filePath:e.filePath,ruleName:"prefer-after-render-over-after-view-init",message:`\`${o}\` contains DOM access that can run before browser-only APIs are safe.`,line:a,column:c,severity:"warn",fix:E["prefer-after-render-over-after-view-init"],codeExample:R["prefer-after-render-over-after-view-init"]});}return n.length?n:null});var ae=new Map;function we(t){return /ngOnDestroy\s*\([^)]*\)\s*\{[^}]*\.unsubscribe\s*\(\)/s.test(t)}var it=engine.createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{var r,n;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t))return null;let l=s(t.callee),u=x(l)?l?.object:null;if(u&&Z(u)||J(Q(u))||(r=e.filePath,n=e.fileContent,(o=ae.get(r))!==void 0||(o=we(n),ae.size>=500&&ae.clear(),ae.set(r,o)),o))return null;let a=b(t),{line:c,column:p}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:c,column:p,severity:"error",fix:E["rxjs-require-takeUntilDestroyed"]}});var se=new Map,le="rxjs-no-subscribe-in-component",ot=engine.createCallExpressionRule(le,(t,e)=>{var r,n;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t)||(function(i){let f=s(i.callee);if(!f||!x(f))return false;let m=s(f.object);if(!m)return false;if(m.type==="CallExpression"){let d=s(m.callee);if(x(d)&&v(d)==="pipe"&&(Array.isArray(m.arguments)?m.arguments:[]).some(h=>{let y=s(h);if(y?.type!=="CallExpression")return false;let g=s(y.callee)?.name;return g==="take"||g==="first"}))return true}return J(Q(m))})(t))return null;let l=s(t.callee),u=s(l?.object);if(u&&Z(u)||(r=e.filePath,n=e.fileContent,(o=se.get(r))!==void 0||(o=we(n),se.size>=500&&se.clear(),se.set(r,o)),o))return null;let a=b(t),{line:c,column:p}=e.locator.location(a);return {filePath:e.filePath,ruleName:le,message:(function(i,f){let m="Open-ended subscriptions in components can outlive the component and make state harder to track.",d=f.crossRef?.templateReferences;if(!d)return m;let h=s(i.callee),y=s(h?.object),g=y?v(y):null;if(!g)return m;let S=g.endsWith("$")?g.slice(0,-1):g;return d.has(g)||d.has(S)?`'${g}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:m})(t,e),line:c,column:p,severity:"error",fix:E[le],codeExample:R[le]}},{requires:{projectContext:true}});var ue="rxjs-avoid-subject-as-event-bus",at=new Set(["Subject","ReplaySubject","AsyncSubject","BehaviorSubject"]),Er=new Set(["destroy$","destroyed$","ondestroy$","ngondestroy$","unsubscribe$","unsub$","teardown$","dispose$","cleanup$","cleanupsubject$"]),xr=/state|loading|error|active|selected|open|visible|disabled|count|value|data|hidden|expanded|pending|success|failed/i;function H(t,e,r){let n=[t];for(;n.length;){let o=s(n.pop());if(!o)continue;let l=s(o.callee);if(o.type==="CallExpression"&&v(l)===e){let u=s(l?.object);if(u&&x(u)&&s(u.object)?.type==="ThisExpression"){let a=v(u);a&&r.add(a);}}for(let u of N(o))n.push(u);}}var st=engine.createAnyAngularClassRule(ue,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node);if(r.length===0)return null;let n=(function(a){let c=_e(a.sourceText,at),p=new Map;for(let[i,f]of c)for(let m of f)p.set(m,i);return p})(e),o=(function(a){let c=new Set,p=U(a);if(p){let i=L(p);i&&H(i,"next",c);}for(let i of a)if(B(i)){i.kind==="set"&&(function(m){let d=m.decorators;if(!Array.isArray(d))return false;for(let h of d){let y=s(h.expression);if(y?.name==="Input"||s(y?.callee)?.name==="Input")return true}return false})(i)&&H(i,"next",c);let f=i.key?.name;if(f==="ngOnChanges"){let m=L(i);m&&H(m,"next",c);}if(f==="ngOnDestroy"){let m=L(i);m&&H(m,"complete",c);}}else i.type==="PropertyDefinition"&&i.value&&H(i.value,"next",c);return c})(r),l=(function(a){let c=new Set;for(let p of a){let i=B(p)?L(p):p.type==="PropertyDefinition"?p.value:null;i&&H(i,"pipe",c);}return c})(r),u=[];for(let a of r){if(a.type!=="PropertyDefinition"||a.accessibility==="public")continue;let c=s(a.value??a.initializer);if(!c||c.type!=="NewExpression")continue;let p=(function(d,h){let y=s(d);if(!y)return null;if(y.type==="Identifier")return h.get(y.name)??null;if(x(y)){let g=v(y);return g&&at.has(g)?g:null}return null})(c.callee,n),i=a.key?.name??"";if(!p||!i||Er.has(i.toLowerCase())||o.has(i)||l.has(i))continue;let{line:f,column:m}=e.locator.location(b(a));u.push({filePath:e.filePath,ruleName:ue,message:xr.test(i)?`${p} '${i}' is used for component UI state, which adds stream overhead to local state updates.`:`${p} '${i}' is acting as a local event bus, which makes component interactions harder to trace.`,line:f,column:m,severity:"warn",fix:E[ue],codeExample:R[ue]});}return u.length?u:null});var Me="rxjs-prefer-toSignal-for-template-state",lt=new Set(["Observable","Subject","BehaviorSubject","ReplaySubject","AsyncSubject"]),Sr=new Set(["destroy$","destroyed$","unsub$","teardown$","dispose$"]),ut=engine.createAnyAngularClassRule(Me,(t,e)=>{if(t.metadata?.type!=="Component")return null;let n=e.crossRef?.templateReferences;if(n===void 0)return null;let o=w(t.node),l=[];for(let u of o){if(u.type!=="PropertyDefinition")continue;let a=u.key?.name??"";if(!a||!a.endsWith("$")||Sr.has(a.toLowerCase())||(function(f){let m=f.modifiers,d=f.decorators??(Array.isArray(m)?m.filter(h=>h.type==="Decorator"):void 0);return Array.isArray(d)&&d.some(h=>{let y=s(h.expression);return (y?.type==="CallExpression"?j(y):y?.type==="Identifier"?y.name:null)==="Output"})})(u))continue;let c=a.slice(0,-1);if(!n.has(a)&&!n.has(c)||!(function(f){if(lt.has((function(y){let g=y.typeAnnotation,S=s(g?.typeAnnotation);if(!S||S.type!=="TSTypeReference"&&S.type!=="TypeReference")return "";let A=S.typeName??S.name;if(typeof A=="string")return A;if(A&&typeof A=="object"){if(A.type==="Identifier")return A.name??"";if(A.type==="TSQualifiedName")return s(A.right)?.name??""}return ""})(f)))return true;let m=s(f.value??f.initializer);if(!m)return false;let d=j(m);if(d==="toSignal"||d==="signal"||d==="computed")return false;if(m.type==="NewExpression"){let y=s(m.callee),g=y?.type==="Identifier"?y.name:v(y);return !!g&&lt.has(g)}let h=[m];for(;h.length>0;){let y=s(h.pop());if(y){if(y.type==="CallExpression"&&j(y)==="pipe")return true;for(let g of N(y))h.push(g);}}return false})(u))continue;let{line:p,column:i}=e.locator.location(b(u));l.push({filePath:e.filePath,ruleName:Me,message:`Observable "${a}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:p,column:i,severity:"warn",fix:E[Me]});}return l.length?l:null},{requires:{projectContext:true,htmlAst:true}});var Pe="toSignal-require-initialValue",ct=engine.createCallExpressionRule(Pe,(t,e)=>{if(!O(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],n=r[1]?s(r[1]):null;if(!n||n.type!=="ObjectExpression"||!(function(o){let l=W(o,"initialValue");if(l&&!Ee(l.value))return true;let u=W(o,"requireSync");return !!u&&ge(u.value)})(n)){let{line:o,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:Pe,message:"toSignal() can emit undefined before the observable produces a value.",line:o,column:l,severity:"warn",fix:E[Pe]}}return null});var Cr=new Set(["set","update","mutate"]),Nr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame","then","catch","finally","subscribe"]),pt=engine.createCallExpressionRule("signal-prefer-computed-over-sync-effect",(t,e)=>{if(!O(t.callee,"effect"))return null;let r=G(t),n=r?K(r):null;if(!n)return null;let{hasRead:o,hasWrite:l,hasAsync:u,hasLinked:a,firstWrite:c}=(function(f,m){let d={hasRead:false,hasWrite:false,hasAsync:false,hasLinked:false,firstWrite:null},h=[f];for(;h.length;){let y=s(h.pop());if(y){if((y.type==="AwaitExpression"||y.type==="YieldExpression")&&(d.hasAsync=true),y.type==="CallExpression"){let g=j(y);g&&Nr.has(g)&&(d.hasAsync=true),g==="linkedSignal"&&(d.hasLinked=true),(function(S){let A=s(S);if(!A||A.type!=="CallExpression")return false;let M=s(A.callee);return x(M)&&Cr.has(v(M)||"")})(y)?(d.hasWrite=true,d.firstWrite||(d.firstWrite=y)):(function(S,A,M){let P=s(S);if(!P||P.type!=="CallExpression"||Array.isArray(P.arguments)&&P.arguments.length>0)return false;let I=s(P.callee);if(!I)return false;if(A.typeChecker)try{let T=q(I,A);if(T){let D=A.typeChecker.getTypeOfSymbolAtLocation(T,T.valueDeclaration);if(D&&A.typeChecker.typeToString(D).includes("Signal"))return !0}}catch{}return x(I)?s(I.object)?.type==="ThisExpression":M&&I.type==="Identifier"})(y,m,true)&&(d.hasRead=true);}for(let g of N(y))h.push(g);}}return d})(n,e);if(!l||!o||u||a)return null;let{line:p,column:i}=e.locator.location(b(c||t));return {filePath:e.filePath,ruleName:"signal-prefer-computed-over-sync-effect",message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:p,column:i,severity:"warn",fix:E["signal-prefer-computed-over-sync-effect"]}},{requires:{typeChecker:true}});var ft=new Set(["afterRender","afterNextRender"]),wr=/\bafterNextRender\s*\(|\bafterRender\s*\(/,ce=new Map,mt=engine.createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!O(t.callee,"untracked")||(function(o,l){let u=l.sourceText??l.fileContent;if(typeof u=="string"&&!wr.test(u))return false;let a=o.parent;for(;a;){if(a.type==="CallExpression"&&ft.has(j(a)))return true;a=a.parent;}let c=b(o);return (function(p){let i=ce.get(p.filePath);if(i!==void 0)return i;let f=p.program;return i=f?(function(m){let d=[],h=m.body,y=Array.isArray(h)?[...h]:[m];for(;y.length;){let g=s(y.pop());if(g){if(g.type==="CallExpression"&&ft.has(j(g))){let S=s(g.arguments?.[0]);if(S){let A=b(S),M=S.end??S.span?.end??b(S);M>A&&d.push([A,M]);}}for(let S of N(g))y.push(S);}}return d})(f):[],ce.size>=300&&ce.clear(),ce.set(p.filePath,i),i})(l).some(([p,i])=>c>=p&&c<i)})(t,e))return null;let{line:r,column:n}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:n,severity:"warn",fix:E["signal-avoid-untracked-overuse"]}});var pe="prefer-inject-over-constructor-di",Pr=new Set(["http","router","route","cdr","cdref","changedetectorref","injector","ngzone","zone","renderer","renderer2","elementref","el","document","platform","location","dialog","snack","toast","store","facade","logger","translate","i18n","auth","api","client","matdialog","overlay","breakpointobserver","snackbar","matsnackbar","bottomsheet","matbottomsheet","clipboard","directionality","focusmonitor","mediamatcher","viewportruler","scrolldispatcher","dragdrop","liveannouncer","activatedroute","fb","firestore","angularfire","formbuilder","titleservice","metaservice","title","meta","sanitizer","domsanitizer","compiler","applicationref","componentfactoryresolver","viewcontainerref","templateref","destroyref"]),Or=new Set(["data","config","options","opts","params","payload","input","value","values","items","item","context","ctx","model","vm","state","initialstate","result","name","id","label","text","title","message","url","path","index","count","size","length","width","height","color","type","key","mode","flag","enabled","disabled","visible","hidden"]),Tr=["Service","Facade","Store","Client","Repository","Adapter","Manager","Controller","Provider","Registry","Logger","Router","ActivatedRoute","ChangeDetectorRef","DestroyRef","Injector","NgZone","Renderer2","ElementRef","HttpClient","ViewContainerRef","TemplateRef","ComponentFactoryResolver","ApplicationRef","MatDialog","MatDialogRef","MatSnackBar","MatBottomSheet","Overlay","OverlayRef","BreakpointObserver","Clipboard","FocusMonitor","MediaMatcher","ScrollDispatcher","DragDrop","LiveAnnouncer","Directionality","ViewportRuler","FormBuilder","DomSanitizer","Title","Meta","Dispatcher","Gateway","Handler","Interceptor","Guard","Resolver","Factory","Strategy","Validator"],Ir=new Set(["string","number","boolean","symbol","bigint","any","unknown","void"]),dt=engine.createAnyAngularClassRule(pe,(t,e)=>{let r=U(w(t.node));if(!r)return null;let n=ee(r.value??r).filter(a=>(function(c,p){let i=s(c);if(!i)return false;if(Array.isArray(i.decorators)&&i.decorators.length>0||i.accessibility||i.readonly)return true;if(p.typeChecker){let d=q(c,p);if(d&&Ue(d))return true}let f=(F(c)||"").toLowerCase().trim();if(!f||Or.has(f))return false;if(Pr.has(f))return true;let m=($(c)||"").trim();return !(!m||Ir.has(m.toLowerCase()))&&Tr.some(d=>m.endsWith(d))})(a,e));if(n.length===0)return null;let{line:o,column:l}=e.locator.location(b(r)),u=n.map(a=>`${F(a)}: ${$(a)}`).join(", ");return {filePath:e.filePath,ruleName:pe,message:`Constructor dependency injection makes class setup less composable than inject().${u?` Offending params: ${u}.`:""}`,line:o,column:l,severity:"warn",fix:E[pe],codeExample:R[pe]}},{requires:{typeChecker:true}});var fe="signal-prefer-input-signal";function Dr(t){let e=s(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var yt=engine.createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=[],o=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let u=s(l);if(u&&(u.type==="PropertyDefinition"||u.type==="AccessorProperty")&&Array.isArray(u.decorators)&&u.decorators.some(Dr)){let a=b(u),{line:c,column:p}=e.locator.location(a),i=s(u.key),f=(i?.type==="Identifier"?i.name:i?.type==="Literal"?String(i.value):"")||"(unknown)",m=`'${f}' uses @Input(), which keeps this input outside Angular's signal graph.`;o&&(m+=" Standalone declarations benefit most from signal inputs."),n.push({filePath:e.filePath,ruleName:fe,message:m,line:c,column:p,severity:o?"error":"warn",fix:E[fe],codeExample:R[fe]});}}return n.length>0?n:null},{requires:{projectContext:true}});var me="signal-prefer-output-function",ht=engine.createAnyAngularClassRule(me,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=[];for(let o of r){let l=s(o);if(l&&(l.type==="PropertyDefinition"||l.type==="AccessorProperty")&&Array.isArray(l.decorators)&&l.decorators.some(u=>{let a=s(u.expression??u);if(!a)return false;if(a.type==="Identifier")return a.name==="Output";if(a.type==="CallExpression"){let c=s(a.callee);return c?.type==="Identifier"&&c.name==="Output"}return false})&&(function(u,a){let c=s(u.value);if(c?.type==="NewExpression"){let i=s(c.callee);if(i?.type==="Identifier"&&i.name==="EventEmitter")return true}let p=s(u.typeAnnotation);if(p&&$(p).includes("EventEmitter"))return true;if(a.typeChecker){let i=q(u,a);if(i&&(typeof i.getName=="function"?i.getName():"").includes("EventEmitter"))return true}return false})(l,e)){let u=b(l),{line:a,column:c}=e.locator.location(u),p=s(l.key),i=(p?.type==="Identifier"?p.name:p?.type==="Literal"?String(p.value):"")||"(unknown)";n.push({filePath:e.filePath,ruleName:me,message:`'${i}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:a,column:c,severity:"warn",fix:E[me],codeExample:R[me]});}}return n.length>0?n:null},{requires:{typeChecker:true}});var de="signal-prefer-model";function gt(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let n=s(r.expression??r);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(n.type==="CallExpression"){let o=s(n.callee);return o?.type==="Identifier"&&o.name===e}return false})}function Et(t,e){let r=s(t.value);if(!r||r.type!=="CallExpression")return false;let n=s(r.callee);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(x(n)){let o=s(n.object);return o?.type==="Identifier"&&o.name===e}return false}var xt=engine.createAnyAngularClassRule(de,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=new Map,o=new Map;for(let u of r){let a=s(u);if(!a||a.type!=="PropertyDefinition"&&a.type!=="AccessorProperty")continue;let c=(function(p){let i=s(p.key);return i?i.type==="Identifier"?i.name??null:i.type==="Literal"?String(i.value):null:null})(a);c&&((gt(a,"Input")||Et(a,"input"))&&n.set(c,a),(gt(a,"Output")||Et(a,"output"))&&o.set(c,a));}let l=[];for(let[u,a]of o){if(!u.endsWith("Change"))continue;let c=u.slice(0,-6),p=n.get(c);if(p){let i=b(p),{line:f,column:m}=e.locator.location(i);l.push({filePath:e.filePath,ruleName:de,message:`The \`${c}\` / \`${u}\` pair implements two-way binding with extra wiring that model() avoids.`,line:f,column:m,severity:"warn",fix:E[de],codeExample:R[de]});}}return l.length>0?l:null});var _r=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Oe="template-prefer-control-flow",bt=engine.createTemplateAttributeRule(Oe,(t,e)=>{var r;let n=(r=t.name,_r.get(r)??null);if(!n)return null;let o=k(e,t.sourceSpan.start),{line:l,column:u}=e.locator.location(o);return {filePath:e.filePath,ruleName:Oe,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${n}\` control flow benefits.`,line:l,column:u,severity:"error",fix:E[Oe]}},{requires:{htmlAst:true}});var St=new WeakMap,vt=engine.createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,n,o=(function p(i){let f=s(i);if(!f)return null;if(f.type==="BinaryExpression"&&f.operator==="|"){let m=s(f.right);return m?.type==="Identifier"&&m.name==="async"?s(f.left):p(f.left)}return null})(t.expression),l=o?(function p(i,f=0){if(!i||f>10)return null;if(i.type==="Identifier")return i.name;if(i.type==="ThisExpression")return "this";if(i.type==="Literal"){let m=i.value;return m===null?"null":typeof m=="string"||typeof m=="number"||typeof m=="boolean"||typeof m=="bigint"?String(m):null}if(i.type==="CallExpression"){let m=p(i.callee,f+1),d=(Array.isArray(i.arguments)?i.arguments:[]).map(h=>p(h,f+1)??"?");return `${m}(${d.join(",")})`}if(x(i)){let m=p(i.object,f+1),d=v(i);if(m&&d)return `${m}.${d}`}if(i.type==="UnaryExpression")return `${i.operator}${p(i.argument,f+1)}`;if(i.type==="ConditionalExpression")return `${p(i.test,f+1)}?${p(i.consequent,f+1)}:${p(i.alternate,f+1)}`;if(i.type==="OptionalExpression"||i.type==="ChainExpression")return p(i.expression,f+1);if(i.type==="LogicalExpression"){let m=p(i.left,f+1),d=p(i.right,f+1);if(m&&d)return `${m}${i.operator}${d}`}if(i.type==="BinaryExpression"&&i.operator!=="|"){let m=p(i.left,f+1),d=p(i.right,f+1);if(m&&d)return `${m}${i.operator}${d}`}if(i.type==="ArrayExpression")return `[${(i.elements??[]).map(d=>p(d,f+1)??"?").join(",")}]`;if(i.type==="ObjectExpression")return `{${(i.properties??[]).map(d=>{let h=d.key?p(d.key,f+1):"?",y=d.value?p(d.value,f+1):"?";return `${h}:${y}`}).join(",")}}`;if(i.type==="TemplateLiteral")return "`tmpl`";if(i.type==="AssignmentExpression"){let m=p(i.left,f+1),d=p(i.right,f+1);if(m&&d)return `${m}${i.operator}${d}`}return null})(o):null;if(!l)return null;let u=(r=e.template,n=r?.templateStartOffset,`${e.filePath}@${typeof n=="number"&&Number.isFinite(n)?n:0}`),a=St.get(e);a||(a=new Map,St.set(e,a));let c=a.get(u);if(c||(c=new Set,a.set(u,c)),c.has(l)){let p=k(e,t.sourceSpan.start),{line:i,column:f}=e.locator.location(p);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:i,column:f,severity:"warn",fix:E["template-no-async-pipe-duplication"]}}return c.add(l),null},{requires:{htmlAst:true}});var Fr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),qr=new Set(["xdescribe","xit","xtest","xcontext"]);function At(t){return t.type==="Identifier"?t.name??null:null}var Ct=engine.createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let n;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let o=s(t.callee);if(!o)return null;let l=(n=At(o)||(function(i){if(i.type==="MemberExpression"||i.type==="StaticMemberExpression"||i.type==="OptionalMemberExpression"){let f=s(i.object),m=i.property?.name??"",d=(f?.type==="Identifier"?f.name:"")??"";return d?`${d}.${m}`:null}return null})(o))&&Fr.has(n)?n:null;if(!l){if(At(o)==="pending"){let i=b(t),{line:f,column:m}=e.locator.location(i);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:f,column:m,severity:"error",fix:E["spec-no-focused-test"]}}return null}let u=b(t),{line:a,column:c}=e.locator.location(u),p=qr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:p,line:a,column:c,severity:"error",fix:E["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Nt(){C(qe,"correctness"),C(He,"correctness"),C(ze,"correctness"),C(Ve,"correctness"),C(Xe,"performance"),C(Ge,"performance"),C(Ze,"performance"),C(Qe,"performance"),C(Je,"performance"),C(et,"security"),C(tt,"security"),C(rt,"ssr"),C(nt,"ssr"),C(ot,"reactivity"),C(it,"reactivity"),C(st,"reactivity"),C(ut,"reactivity"),C(ct,"reactivity"),C(pt,"reactivity"),C(mt,"reactivity"),C(dt,"modern-api"),C(yt,"modern-api"),C(ht,"modern-api"),C(xt,"modern-api"),C(bt,"template"),C(vt,"template"),C(Ct,"testing");}Nt(),engine.configureRuleExecutor(ke,Ie),process.on("message",t=>{Xr(t);});var Xr=async t=>{let e=[],r=engine.createTypeAwareAnalysisContext(t.rootDir,t.files,t.parserOptions,{buildProjectContext:t.buildProjectContext,programRootFiles:t.programRootFiles});try{await r.warmup();let n=planner.groupTasksByFile(t.tasks),o=await Yr(Array.from(n),Math.max(1,t.fileConcurrency??1),async([l,u])=>{let a=performance.now();try{let c=await engine.executeBatchedTasks(u,r);return Rt(l,u.length,c,performance.now()-a),c}catch{return Rt(l,u.length,[],performance.now()-a),[]}finally{r.evict(l);}});e.push(...o.flat()),process.send?.({kind:"complete",results:e});}catch(n){process.send?.({kind:"error",error:n instanceof Error?n.message:String(n)});}finally{r.dispose(),process.disconnect?.();}};async function Yr(t,e,r){let n=Array(t.length),o=0,l=Math.min(e,t.length);return await Promise.all(Array.from({length:l},async()=>{for(;o<t.length;){let u=o++;n[u]=await r(t[u]);}})),n}var Rt=(t,e,r,n)=>{process.send?.(Gr(t,e,r,n));},Gr=(t,e,r,n)=>{let o=0,l=0;for(let u of r)for(let a of u.failures)a.severity==="error"?o++:a.severity==="warn"&&l++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:o+l,errorCount:o,warningCount:l,duration:n,typeAware:true}};//# sourceMappingURL=type-aware-worker.cjs.map
});`};var Ge;function g(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function C(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function N(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function T(t,e){let r=g(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!C(r)&&N(r)===e)}function Ne(t){let e=g(t);if(!e||e.type!=="CallExpression")return "";let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}function te(t){let e=g(t?.callee);return !!C(e)&&N(e)==="subscribe"}function Y(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let n of r){if(!n||n.type!=="Property")continue;let a=n.key;if((a?.type==="Identifier"?a.name:a?.type==="Literal"&&typeof a.value=="string"?a.value:"")===e)return n}return null}function Re(t){let e=g(t);return !!(e&&e.type==="Literal"&&e.value===true)}function we(t){let e=g(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Vt=new Set(["parent","span","loc","range","start","end","type"]);function*O(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Vt.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let n of r)n&&typeof n=="object"&&(yield n);else typeof r=="object"&&r.type&&(yield r);}}}function Me(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function H(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function Qe(t){for(let e of t)if(e&&H(e)&&Me(e))return e;return null}function z(t){return t?(t.value??t)?.body??null:null}function Ze(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function F(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Kt(t){let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let n=g(r[1]);if(!n||n.type!=="ObjectExpression")return false;let a=Y(n,"injector");if(a&&!we(a.value))return true;let s=Y(n,"manualCleanup");return !!(s&&Re(s.value))}function Je(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&T(n.callee,"effect")&&!Kt(n)&&e.push(n),O(n)))r.push(a);}return e}var Xt=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function Gt(t){let e=g(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}return C(e)?N(e):""}function Yt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(Xt.has(Gt(r)))return true;return false}function re(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)==="pipe"&&Yt(r))return true;e=n?.object;}return false}function I(t,e){return e}var Qt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),Zt=new Set(["http","httpClient","_http","_httpClient"]),Jt=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function ne(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)!=="pipe")return r;e=n?.object;}return null}function ie(t){if(!t)return false;let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=g(e.callee);if(!C(r))return false;let n=N(r);if(!n)return false;let a=g(r?.object),s=Array.isArray(e.arguments)?e.arguments:[];if(Qt.has(n)&&C(a)){let c=N(a);if(Zt.has(c))return true}if(s.length>0){let c=n.toLowerCase();for(let f of Jt)if(c.startsWith(f)&&n.length>f.length)return true}return false}var Ye=false;function Pe(){if(!Ye){try{Ge=Ht("typescript");}catch{}Ye=true;}return Ge}function et(t,e){if(!t||!e.typeChecker)return;let r=Pe();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let n=e.sourceFile;if(!n)return;let a=(function(s,c,f){if(c<s.getStart()||c>=s.getEnd())return;let d=s;for(;;){let p=f.forEachChild(d,i=>{if(c>=i.getStart()&&c<i.getEnd())return i});if(!p)break;d=p;}return d})(n,b(t),r);return a?e.typeChecker.getSymbolAtLocation(a):void 0}catch{return}}function D(t){if(t.sourceFile)return t.sourceFile;if(!t.fileContent)return;let e=Pe();if(e)return t.sourceFile=e.createSourceFile(t.filePath,t.fileContent,e.ScriptTarget.Latest,true),t.sourceFile}var ee=new Map;function oe(t){let e=ee.get(t.filePath);if(e!==void 0)return e;let r=(function(n){let{typeChecker:a,angularTypes:s}=n;if(!a||!s)return false;let c=Pe(),f=D(n);if(!c||!f)return false;for(let d of f.statements){if(!c.isClassDeclaration(d)||!c.canHaveDecorators(d))continue;let p=c.getDecorators(d);if(p)for(let i of p){let l=c.isCallExpression(i.expression)?i.expression.expression:i.expression;if(!c.isIdentifier(l)||l.text!=="Component"&&l.text!=="Directive")continue;let o=a.getSymbolAtLocation(l),u=o&&o.flags&c.SymbolFlags.Alias?a.getAliasedSymbol(o):o;if(s.isFromAngularCore(u))return true}}return false})(t);return ee.size>=1024&&ee.clear(),ee.set(t.filePath,r),r}function Q(t){if(!t)return false;let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib.dom"))return true;return false}var se="component-no-manual-detect-changes",nr=new Set(["detectChanges","markForCheck"]),tt=engine.createAnyAngularClassRule(se,(t,e)=>{let r,n=t.node,a=(r=ast.analyzeComponent(n),r?.type!=="Component"?{isComponent:false,isOnPush:false}:{isComponent:true,isOnPush:r.changeDetection?.kind==="literal"&&r.changeDetection.value===ast.ChangeDetectionStrategy.OnPush});if(!a.isComponent)return null;let{typeChecker:s,angularTypes:c}=e;if(!s||!c)return null;let f=(function(i,l){let o=D(l);if(!o)return;let u=b(i);for(let m of o.statements)if(M__default.default.isClassDeclaration(m)&&m.pos<=u&&u<=m.end)return m})(n,e);if(!f)return null;let d=[],p=i=>{if(M__default.default.isCallExpression(i)){let l=(function(o,u,m,y,h){if(!M__default.default.isPropertyAccessExpression(o.expression))return null;let E=o.expression.name.text;if(!nr.has(E)||y.isOnPush&&E==="markForCheck")return null;let S=u.getTypeAtLocation(o.expression.expression);if(!m.isChangeDetectorRef(S))return null;let{line:A,column:v}=h.locator.location(o.getStart());return {filePath:h.filePath,ruleName:se,message:y.isOnPush?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${E}) can hide state-flow bugs and make rendering harder to predict.`,line:A,column:v,severity:y.isOnPush?"warn":"error",fix:x[se],codeExample:P[se]}})(i,s,c,a,e);l&&d.push(l);}M__default.default.forEachChild(i,p);};return p(f),d.length>0?d:null});var Te="signal-no-side-effects-in-computed",or=new Set(["set","update","mutate"]),ar=new Set(["next","complete","error"]),rt=engine.createCallExpressionRule(Te,(t,e)=>{var r,n;let a,s;if(!T(t.callee,"computed"))return null;let{typeChecker:c,angularTypes:f}=e;if(!c||!f)return null;let d=(function(l,o){var u;let m,y=(u=l).sourceFile?u.sourceFile:u.fileContent?(u.sourceFile=M__default.default.createSourceFile(u.filePath,u.fileContent,M__default.default.ScriptTarget.Latest,true),u.sourceFile):void 0;if(!y)return;let h=E=>{if(!m){if(M__default.default.isCallExpression(E)&&E.getStart()===o){m=E;return}M__default.default.forEachChild(E,h);}};return h(y),m})(e,b(t));if(!d)return null;let p=d.arguments[0];if(!p||!(M__default.default.isArrowFunction(p)||M__default.default.isFunctionExpression(p)))return null;let i=(r=p.body,n={typeChecker:c,angularTypes:f},(s=l=>{var o,u,m,y;if(a)return;let h=(o=l,u=n,M__default.default.isBinaryExpression(o)&&(m=o.operatorToken.kind)>=M__default.default.SyntaxKind.FirstAssignment&&m<=M__default.default.SyntaxKind.LastAssignment?Oe(o.left)?{node:o,kind:"write"}:void 0:M__default.default.isPostfixUnaryExpression(o)||M__default.default.isPrefixUnaryExpression(o)?(o.operator===M__default.default.SyntaxKind.PlusPlusToken||o.operator===M__default.default.SyntaxKind.MinusMinusToken)&&Oe(o.operand)?{node:o,kind:"write"}:void 0:M__default.default.isDeleteExpression(o)&&Oe(o.expression)?{node:o,kind:"write"}:M__default.default.isCallExpression(o)?(function(E,S){if(!M__default.default.isPropertyAccessExpression(E.expression))return;let A=E.expression.name.text,v=E.expression.expression,w=S.typeChecker.getTypeAtLocation(v);return or.has(A)&&S.angularTypes.isWritableSignal(w)?{node:E,kind:"write"}:ar.has(A)&&S.angularTypes.isSubjectLike(w)||S.angularTypes.isHttpClient(w)?{node:E,kind:"effect"}:void 0})(o,u):void 0);if(h){a=h;return}y=l,M__default.default.isArrowFunction(y)||M__default.default.isFunctionExpression(y)||M__default.default.isFunctionDeclaration(y)||M__default.default.isMethodDeclaration(y)||M__default.default.isGetAccessorDeclaration(y)||M__default.default.isSetAccessorDeclaration(y)||M__default.default.forEachChild(l,s);})(r),a);return i?(function(l,o,u){let m=l.node.getStart(),{line:y,column:h}=u.locator.location(m||b(o));return {filePath:u.filePath,ruleName:Te,message:l.kind==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:y,column:h,severity:"error",fix:x[Te]}})(i,t,e):null},{requires:{typeChecker:true}});function Oe(t){return M__default.default.isPropertyAccessExpression(t)||M__default.default.isElementAccessExpression(t)}var ke="signal-effect-must-be-destroy-scoped",nt=engine.createAnyAngularClassRule(ke,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let n=[];for(let a of r)a&&H(a)&&!Me(a)&&n.push(...(function(s,c){let f=z(s);if(!f)return [];let d=Ze(s),p=[];for(let i of Je(f))(function(l){if(l.type!=="CallExpression")return false;let o=g(l.callee);return !!o&&(o.type==="Identifier"?o.name==="effect":!!C(o)&&N(o)==="effect")})(i)&&!(function(l){let o=g((Array.isArray(l.arguments)?l.arguments:[])[1]);if(!o||o.type!=="ObjectExpression")return false;for(let u of Array.isArray(o.properties)?o.properties:[]){let m=g(u);if(m?.type==="Property"){let y=g(m.key),h=y?.type==="Identifier"?y.name:N(y)||"";if(h==="injector")return true;if(h==="manualCleanup"){let E=g(m.value);if(E?.type==="Literal"&&E.value===true)return true}}}return false})(i)&&p.push((function(l,o,u){let m=b(l),{line:y,column:h}=u.locator.location(m);return {filePath:u.filePath,ruleName:ke,message:`effect() inside "${o}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:h,severity:"error",fix:x[ke]}})(i,d,c));return p})(a,e));return n.length>0?n:null});var le="rxjs-no-nested-subscribe",ur=new Set(["next","error","complete"]),cr=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function De(t){if(t.type!=="CallExpression")return false;let e=g(t.callee);return !!C(e)&&N(e)==="subscribe"}function it(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var ot=engine.createCallExpressionRule(le,(t,e)=>{if(!De(t))return null;for(let r of (function(n){if(!De(n))return [];let a=Array.isArray(n.arguments)?n.arguments:[];if(a.length===0)return [];let s=g(a[0]);if(s?.type==="ObjectExpression"){if(s.type!=="ObjectExpression")return [];let f=[];for(let d of Array.isArray(s.properties)?s.properties:[]){let p=g(d);if(p?.type==="Property"&&ur.has((function(i){let l=g(i.key);return l?l.type==="Identifier"?l.name:N(l)||"":""})(p))){let i=g(p.value);it(i)&&f.push(i);}}return f}let c=[];for(let f=0;f<Math.min(a.length,3);f++){let d=g(a[f]);it(d)&&c.push(d);}return c})(t)){let n=g(r.body);if(n&&(function(a){let s=[a];for(;s.length>0;){var c;let f=g(s.pop());if(f){if(f!==a&&De(f))return true;if(!(f!==a&&(c=f).type&&cr.has(c.type)))for(let d of O(f))s.push(d);}}return false})(n))return (function(a,s){let c=b(a),{line:f,column:d}=s.locator.location(c);return {filePath:s.filePath,ruleName:le,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:f,column:d,severity:"error",fix:x[le],codeExample:P[le]}})(t,e)}return null});var ue="prefer-on-push-component-change-detection";function ce(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function Ie(t){return t.replace(/\\/g,"/")}var at=engine.createComponentRule(ue,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(n){if(!n||typeof n!="object")return false;let{kind:a,value:s}=n;return a!=="non-literal"&&(a==="literal"?s!==ast.ChangeDetectionStrategy.OnPush:a==="missing")})(r.changeDetection)?null:(function(n,a){let s,c,f,d,p=(s=n.metadata??{},c=n.node,ce(s,"decoratorStart")??ce(s,"start")??ce(c,"start")??ce(n,"start")??0),{line:i,column:l}=a.locator.location(p),o=(f=n.metadata,typeof(d=f?.className)=="string"?d:"AnonymousComponent"),u=(function(m,y){if(!y.project)return null;let h=m.metadata,E=h?.className;if(typeof E!="string"||!E)return null;let S=Ie(y.filePath),{ngModuleMap:A,classToFile:v}=y.project;for(let[w,L]of A){if(L.isStandalone||!L.declarations.has(E))continue;let k=v.get(E);if(!k||Ie(k)===S)return {moduleName:(Ie(w).split("/").pop()??w).replace(/\.ts$/,""),siblingDeclarationCount:Math.max(0,L.declarations.size-1)}}return null})(n,a);return {filePath:a.filePath,ruleName:ue,message:(function(m,y){let h=`Component '${m}' uses default change detection, which can re-render more often than needed.`;if(!y)return h;let{moduleName:E,siblingDeclarationCount:S}=y;return S===0?`${h} It is declared in '${E}'.`:`${h} It is declared in '${E}' alongside ${S} other declaration${S===1?"":"s"}.`})(o,u),line:i,column:l,severity:"error",fix:x[ue],codeExample:P[ue]}})(t,e)},{requires:{projectContext:true}});var Le="template-no-call-expression",gr=new Set(["translate","$localize","$any"]),yr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function st(t){let e=g(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var lt=engine.createTemplateExpressionRule(Le,(t,e)=>(function(r,n){let a=r?[r]:[];for(;a.length>0;){let s=g(a.pop());if(s){if(st(s)&&!(function(c){let f=g(c);if(!f||!st(f))return false;let d=g(f.callee);if(!d)return false;if(d.type==="Identifier")return gr.has(d.name);if(!C(d))return false;let p=N(d);return !!p&&yr.has(p)})(s)){if((function(f){let d=g(f);return Array.isArray(d?.arguments)?d.arguments:[]})(s).length>0)return true;let c=(function(f){let d=g(f);if(!d)return "";let p=g(d.callee);return p?p.type==="Identifier"?p.name??"":C(p)?N(p):"":""})(s);if(c&&!(function(f,d){if(d.crossRef?.signalMembers?.has(f))return true;let{typeChecker:p,angularTypes:i,crossRef:l}=d;if(!p||!i||!l?.componentPath)return false;let o=(function(u,m,y){let h=y.getProgram?.(),E=h?.getSourceFile(m);if(!E)return;let S=E.statements.find(M__default.default.isClassDeclaration);if(!S)return;let A=y.getTypeAtLocation(S),v=y.getPropertyOfType(A,u);if(!v)return;let w=v.valueDeclaration??v.declarations?.[0];if(w)return y.getTypeOfSymbolAtLocation(v,w)})(f,l.componentPath,p);return !!o&&i.isSignal(o)})(c,n))return true}for(let c of O(s))a.push(c);}}return false})(t.expression,e)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:s,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:Le,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:s,column:c,severity:"error",fix:x[Le]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function ut(t,e,r,n){let a=I(t,e.sourceSpan.start),{line:s,column:c}=t.locator.location(a);return {filePath:t.filePath,ruleName:r,message:n,line:s,column:c,severity:"error",fix:x[r]}}var ct=engine.createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let n of t.attributes)n.name==="*ngFor"&&!(function(a){return !!a.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(n.value??"")&&r.push(ut(e,n,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let n of t.blocks)n.name!=="for"||n.parameters.some(a=>{let s=a.expression?.trim()??"";return !!s&&!!/^track\b/.test(s)&&s.replace(/^track\b/,"").trim().length>0})||r.push(ut(e,n,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var je="template-no-object-literal-binding",pt=engine.createTemplateExpressionRule(je,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ObjectExpression")return true;for(let s of O(a))n.push(s);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:s,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:je,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:s,column:c,severity:"warn",fix:x[je]}})(t,e)]:null,{requires:{htmlAst:true}});var Fe="template-no-array-literal-binding",ft=engine.createTemplateExpressionRule(Fe,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ArrayExpression")return true;for(let s of O(a))n.push(s);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:s,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:Fe,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:s,column:c,severity:"warn",fix:x[Fe]}})(t,e)]:null,{requires:{htmlAst:true}});var _e=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),mt=engine.createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(s){let c=g(s.callee);if(!c)return null;if(c.type==="Identifier"&&c.name)return _e.has(c.name)?c.name:null;if(C(c)){let f=N(c);return f&&_e.has(f)?f:null}return null})(t);if(!r)return null;let{line:n,column:a}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${_e.get(r)} sanitization, which can expose unsafe content.`,line:n,column:a,severity:"error",fix:x["no-bypass-sanitization"]}});var Ar=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),Cr=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,vr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,dt=engine.createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=Ar.get(t.name);if(!r)return null;let n=t.value??"";if(Cr.test(n)||vr.test(n)||t.name==="[style]"&&!/[.(|?]/.test(n))return null;let{line:a,column:s}=e.locator.location(I(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:a,column:s,severity:r.severity,fix:x["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var pe="no-document-access",Rr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),gt=engine.createAnyAngularClassRule(pe,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let{typeChecker:n}=e;if(!n)return null;let a=D(e);if(!a)return null;let s=(function(p){let i=new Set,l=[...p];for(;l.length;){let o=g(l.pop());if(o){if(o.type==="VariableDeclarator"&&o.init){let u=g(o.init);if(u?.type==="CallExpression"&&u.callee&&T(u.callee,"isPlatformBrowser")){let m=o.id??o.key;m?.type==="Identifier"&&m.name&&i.add(m.name);}}if(o.type==="AssignmentExpression"&&o.right){let u=g(o.right);if(u?.type==="CallExpression"&&u.callee&&T(u.callee,"isPlatformBrowser")){let m=g(o.left);if(m&&C(m)&&g(m.object)?.type==="ThisExpression"){let y=m.property?.name;typeof y=="string"&&y&&i.add(y);}}}for(let u of O(o))l.push(u);}}return i})(r),c=[],f=new Set,d=[...r];for(;d.length;){let p=g(d.pop());if(p){if(p.type==="IfStatement"&&p.test){let i=g(p.test);if(i){let l=(function(o,u){let m=[o];for(;m.length;){let y=g(m.pop());if(y){if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformBrowser"))return "browser";if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformServer"))return "server";if(y.type==="UnaryExpression"&&y.operator==="!"&&y.argument){let h=g(y.argument);if(h?.type==="CallExpression"&&h.callee&&T(h.callee,"isPlatformServer"))return "browser"}if(y.type==="Identifier"&&u.has(y.name))return "browser";for(let h of O(y))m.push(h);}}return null})(i,s);if(l==="browser"){p.alternate&&d.push(p.alternate);continue}if(l==="server"){p.consequent&&d.push(p.consequent);continue}}}if(p.type==="CallExpression"&&p.callee){let i=g(p.callee);if(i&&(T(i,"afterNextRender")||T(i,"afterRender"))){let l=p.arguments??[];for(let o=1;o<l.length;o++)d.push(l[o]);continue}}if(C(p)){let i=(function(o){let u=o;for(;u&&C(u);)u=g(u.object);return u?.type==="Identifier"?u:null})(p),l=i?.name;if(i&&l&&Rr.has(l)&&(function(o,u,m){let y=(function(E,S){let A,v=w=>{if(!A){if(M__default.default.isIdentifier(w)&&w.getStart()===S){A=w;return}M__default.default.forEachChild(w,v);}};return v(E),A})(u,b(o));if(!y)return false;let h=m.getSymbolAtLocation(y);return Q((h&&h.flags&M__default.default.SymbolFlags.Alias?m.getAliasedSymbol(h):h)??void 0)})(i,a,n)){let o=b(i);if(o!==void 0&&!f.has(o)){f.add(o);let{line:u,column:m}=e.locator.location(o);c.push({filePath:e.filePath,ruleName:pe,message:`Direct access to \`${l}\` can run during SSR where browser globals do not exist.`,line:u,column:m,severity:"error",fix:x[pe],codeExample:P[pe]});}}}for(let i of O(p))d.push(i);}}return c.length?c:null},{requires:{typeChecker:true}});var fe="prefer-after-render-over-after-view-init",Mr=new Set(["ngAfterViewInit","ngAfterContentInit"]),ht=engine.createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r}=e;if(!r)return null;let n=(function(s,c){let f=D(c);if(!f)return;let d=b(s);for(let p of f.statements)if(M__default.default.isClassDeclaration(p)&&p.pos<=d&&d<=p.end)return p})(t.node,e);if(!n)return null;let a=[];for(let s of n.members){if(!M__default.default.isMethodDeclaration(s)||!s.body||!M__default.default.isIdentifier(s.name))continue;let c=s.name.text;if(!Mr.has(c)||!(function(p,i){let l=false,o=u=>{if(!l){if(M__default.default.isPropertyAccessExpression(u)){if(yt(i.getTypeAtLocation(u.expression))){l=true;return}}else if(M__default.default.isElementAccessExpression(u)){if(yt(i.getTypeAtLocation(u.expression))){l=true;return}}else if(M__default.default.isIdentifier(u)&&!(function(m){let y=m.parent;return !!y&&!!(M__default.default.isPropertyAccessExpression(y)&&y.name===m||M__default.default.isQualifiedName(y)&&y.right===m)})(u)){let m=i.getSymbolAtLocation(u);if(Q((m&&m.flags&M__default.default.SymbolFlags.Alias?i.getAliasedSymbol(m):m)??void 0)){l=true;return}}M__default.default.forEachChild(u,o);}};return o(p),l})(s.body,r))continue;let{line:f,column:d}=e.locator.location(s.getStart());a.push({filePath:e.filePath,ruleName:fe,message:`\`${c}\` contains DOM access that can run before browser-only APIs are safe.`,line:f,column:d,severity:"warn",fix:x[fe],codeExample:P[fe]});}return a.length?a:null},{requires:{typeChecker:true}});function yt(t){let e=t.aliasSymbol??t.symbol;return !!e&&Q(e)}var me=new Map;function Be(t){let e=D(t);if(!e)return false;for(let r of e.statements)if(M__default.default.isClassDeclaration(r))for(let n of r.members){if(!M__default.default.isMethodDeclaration(n)||!n.name||!M__default.default.isIdentifier(n.name)||n.name.text!=="ngOnDestroy"||!n.body)continue;let a=false,s=c=>{if(!a){if(M__default.default.isCallExpression(c)&&M__default.default.isPropertyAccessExpression(c.expression)&&c.expression.name.text==="unsubscribe"&&c.arguments.length===0){a=true;return}M__default.default.forEachChild(c,s);}};if(s(n.body),a)return true}return false}var xt=engine.createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{if(!oe(e)||!te(t))return null;let r=g(t.callee),n=C(r)?r?.object:null;if(n&&re(n)||ie(ne(n))||(function(f){let d=me.get(f.filePath);if(d!==void 0)return d;let p=Be(f);return me.size>=500&&me.clear(),me.set(f.filePath,p),p})(e))return null;let a=b(t),{line:s,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:s,column:c,severity:"error",fix:x["rxjs-require-takeUntilDestroyed"]}},{requires:{typeChecker:true}});var de=new Map,ge="rxjs-no-subscribe-in-component",Et=engine.createCallExpressionRule(ge,(t,e)=>{if(!oe(e)||!te(t)||(function(f){let d=g(f.callee);if(!d||!C(d))return false;let p=g(d.object);if(!p)return false;if(p.type==="CallExpression"){let i=g(p.callee);if(C(i)&&N(i)==="pipe"&&(Array.isArray(p.arguments)?p.arguments:[]).some(l=>{let o=g(l);if(o?.type!=="CallExpression")return false;let u=g(o.callee)?.name;return u==="take"||u==="first"}))return true}return ie(ne(p))})(t))return null;let r=g(t.callee),n=g(r?.object);if(n&&re(n)||(function(f){let d=de.get(f.filePath);if(d!==void 0)return d;let p=Be(f);return de.size>=500&&de.clear(),de.set(f.filePath,p),p})(e))return null;let a=b(t),{line:s,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:ge,message:(function(f,d){let p="Open-ended subscriptions in components can outlive the component and make state harder to track.",i=d.crossRef?.templateReferences;if(!i)return p;let l=g(f.callee),o=g(l?.object),u=o?N(o):null;if(!u)return p;let m=u.endsWith("$")?u.slice(0,-1):u;return i.has(u)||i.has(m)?`'${u}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:p})(t,e),line:s,column:c,severity:"error",fix:x[ge],codeExample:P[ge]}},{requires:{typeChecker:true,projectContext:true}});var ye="rxjs-avoid-subject-as-event-bus",bt=engine.createAnyAngularClassRule(ye,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=F(t.node);if(a.length===0)return null;let s=(function(i){let l=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,u=>{let m=g(u.callee);if(m&&(m.type==="Identifier"?m.name:C(m)?N(m):"")==="takeUntil")for(let y of Array.isArray(u.arguments)?u.arguments:[]){let h=St(y);h&&l.add(h);}});return l})(a),c=(function(i){let l=new Set,o=m=>{he(m??null,y=>{let h=Ue(y,"next");h&&l.add(h);});},u=Qe(i);for(let m of(u&&o(z(u)),i))if(H(m)){let y=m.key?.name;m.kind==="set"&&(function(h){let E=h.decorators;if(!Array.isArray(E))return false;for(let S of E){let A=g(S.expression);if(A?.name==="Input"||g(A?.callee)?.name==="Input")return true}return false})(m)&&o(m),y==="ngOnChanges"&&o(z(m));}else m.type==="PropertyDefinition"&&m.value&&o(m.value);return l})(a),f=(function(i){let l=new Set;for(let o of i)H(o)&&o.key?.name==="ngOnDestroy"&&he(z(o),u=>{let m=Ue(u,"complete");m&&l.add(m);});return l})(a),d=(function(i){let l=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,u=>{let m=Ue(u,"pipe");m&&l.add(m);});return l})(a),p=[];for(let i of a){if(i.type!=="PropertyDefinition"||i.accessibility==="public")continue;let l=i.key?.name??"";if(!l||s.has(l)||c.has(l)||f.has(l)||d.has(l))continue;let o=et(i.key,e);if(!o)continue;let u=o.valueDeclaration??o.declarations?.[0];if(!u)continue;let m=r.getTypeOfSymbolAtLocation(o,u);if(!n.isSubjectLike(m))continue;let{line:y,column:h}=e.locator.location(b(i));p.push({filePath:e.filePath,ruleName:ye,message:`'${l}' is a Subject the class signals into without piping or external exposure \u2014 components are easier to follow when local state lives in fields or signals.`,line:y,column:h,severity:"warn",fix:x[ye],codeExample:P[ye]});}return p.length>0?p:null});function he(t,e){if(!t)return;let r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&e(n),O(n)))r.push(a);}}function St(t){let e=g(t);if(!e||!C(e))return null;let r=g(e.object),n=N(e);return n&&r?.type==="ThisExpression"?n:null}function Ue(t,e){let r=g(t.callee);return r&&C(r)&&N(r)===e?St(r.object):null}var qe="rxjs-prefer-toSignal-for-template-state",At=engine.createAnyAngularClassRule(qe,(t,e)=>{if(t.metadata?.type!=="Component")return null;let n=e.crossRef?.templateReferences;if(n===void 0)return null;let{typeChecker:a,angularTypes:s}=e;if(!a||!s)return null;let c=(function(p,i){let l=D(i);if(!l)return;let o=b(p);for(let u of l.statements)if(M__default.default.isClassDeclaration(u)&&u.pos<=o&&o<=u.end)return u})(t.node,e);if(!c)return null;let f=[];for(let p of c.members){var d;if(!M__default.default.isPropertyDeclaration(p))continue;let i=(function(m){if(M__default.default.isIdentifier(m.name)||M__default.default.isStringLiteral(m.name))return m.name.text})(p);if(!i||!n.has(i)&&!n.has((d=i).endsWith("$")?d.slice(0,-1):d)||(function(m,y,h){let E=M__default.default.getDecorators(m);if(!E)return false;for(let S of E){let A=M__default.default.isCallExpression(S.expression)?S.expression.expression:S.expression;if(!M__default.default.isIdentifier(A)||A.text!=="Output")continue;let v=y.getSymbolAtLocation(A),w=v&&v.flags&M__default.default.SymbolFlags.Alias?y.getAliasedSymbol(v):v;if(h.isFromAngularCore(w))return true}return false})(p,a,s))continue;let l=a.getTypeAtLocation(p);if(!s.isObservable(l)&&!s.isSubjectLike(l))continue;let{line:o,column:u}=e.locator.location(p.getStart());f.push({filePath:e.filePath,ruleName:qe,message:`Observable "${i}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:o,column:u,severity:"warn",fix:x[qe]});}return f.length?f:null},{requires:{projectContext:true,htmlAst:true,typeChecker:true}});var He="toSignal-require-initialValue",Ct=engine.createCallExpressionRule(He,(t,e)=>{if(!T(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],n=r[1]?g(r[1]):null;if(!n||n.type!=="ObjectExpression"||!(function(a){let s=Y(a,"initialValue");if(s&&!we(s.value))return true;let c=Y(a,"requireSync");return !!c&&Re(c.value)})(n)){let{line:a,column:s}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:He,message:"toSignal() can emit undefined before the observable produces a value.",line:a,column:s,severity:"warn",fix:x[He]}}return null});var ze="signal-prefer-computed-over-sync-effect",Lr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame"]),jr=new Set(["then","catch","finally"]),Fr=new Set(["set","update","mutate"]),Nt=engine.createCallExpressionRule(ze,(t,e)=>{var r,n;let a,s,c,f,d,p;if(!T(t.callee,"effect"))return null;let{typeChecker:i,angularTypes:l}=e;if(!i||!l)return null;let o=(function(S,A){let v,w=D(S);if(!w)return;let L=k=>{if(!v){if(M__default.default.isCallExpression(k)&&k.getStart()===A){v=k;return}M__default.default.forEachChild(k,L);}};return L(w),v})(e,b(t));if(!o)return null;let u=o.arguments[0];if(!u||!(M__default.default.isArrowFunction(u)||M__default.default.isFunctionExpression(u)))return null;let m=(r=u.body,n={typeChecker:i,angularTypes:l},s=false,c=false,f=false,d=false,(p=S=>{f&&d&&s&&c||((S.kind===M__default.default.SyntaxKind.AwaitExpression||S.kind===M__default.default.SyntaxKind.YieldExpression)&&(f=true),M__default.default.isCallExpression(S)&&(function(A,v,w){var L,k;if(M__default.default.isPropertyAccessExpression(A.expression)){let U,j=A.expression.name.text,K=A.expression.expression,q=v.typeChecker.getTypeAtLocation(K);return Fr.has(j)&&v.angularTypes.isWritableSignal(q)?w.onSignalWrite():(j==="subscribe"&&(v.angularTypes.isObservable(q)||v.angularTypes.isSubjectLike(q))||jr.has(j)&&(U=(L=q).aliasSymbol??L.symbol)&&U.name==="Promise"&&vt(U))&&w.onAsync()}if(M__default.default.isIdentifier(A.expression)){let U,j=A.expression.text;if(j==="linkedSignal")return w.onLinkedSignal();if(Lr.has(j)&&(k=A.expression,(U=v.typeChecker.getSymbolAtLocation(k))&&vt(U)))return w.onAsync();A.arguments.length===0&&(function(K,q){let Z=q.typeChecker.getSymbolAtLocation(K);if(!Z)return false;let Ve=Z.valueDeclaration??Z.declarations?.[0];if(!Ve)return false;let qt=q.typeChecker.getTypeOfSymbolAtLocation(Z,Ve);return q.angularTypes.isSignal(qt)})(A.expression,v)&&w.onSignalRead();}})(S,n,{onSignalRead:()=>{s=true;},onSignalWrite:()=>{c=true,a??=S;},onAsync:()=>{f=true;},onLinkedSignal:()=>{d=true;}}),M__default.default.forEachChild(S,p));})(r),{hasSignalRead:s,hasSignalWrite:c,hasAsync:f,hasLinkedSignal:d,firstWrite:a});if(!m.hasSignalRead||!m.hasSignalWrite||m.hasAsync||m.hasLinkedSignal)return null;let y=m.firstWrite??o,{line:h,column:E}=e.locator.location(y.getStart());return {filePath:e.filePath,ruleName:ze,message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:h,column:E,severity:"warn",fix:x[ze]}},{requires:{typeChecker:true}});function vt(t){let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib."))return true;return false}var Rt=new Set(["afterRender","afterNextRender"]),$r=/\bafterNextRender\s*\(|\bafterRender\s*\(/,xe=new Map,wt=engine.createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!T(t.callee,"untracked")||(function(a,s){let c=s.sourceText??s.fileContent;if(typeof c=="string"&&!$r.test(c))return false;let f=a.parent;for(;f;){if(f.type==="CallExpression"&&Rt.has(Ne(f)))return true;f=f.parent;}let d=b(a);return (function(p){let i=xe.get(p.filePath);if(i!==void 0)return i;let l=p.program;return i=l?(function(o){let u=[],m=o.body,y=Array.isArray(m)?[...m]:[o];for(;y.length;){let h=g(y.pop());if(h){if(h.type==="CallExpression"&&Rt.has(Ne(h))){let E=g(h.arguments?.[0]);if(E){let S=b(E),A=E.end??E.span?.end??b(E);A>S&&u.push([S,A]);}}for(let E of O(h))y.push(E);}}return u})(l):[],xe.size>=300&&xe.clear(),xe.set(p.filePath,i),i})(s).some(([p,i])=>d>=p&&d<i)})(t,e))return null;let{line:r,column:n}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:n,severity:"warn",fix:x["signal-avoid-untracked-overuse"]}});var Ee="prefer-inject-over-constructor-di",Ur=new Set(["Inject","Optional","Self","SkipSelf","Host"]),Mt=engine.createAnyAngularClassRule(Ee,(t,e)=>{let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(l,o){var u;let m=(u=o).sourceFile?u.sourceFile:u.fileContent?(u.sourceFile=M__default.default.createSourceFile(u.filePath,u.fileContent,M__default.default.ScriptTarget.Latest,true),u.sourceFile):void 0;if(!m)return;let y=b(l);for(let h of m.statements)if(M__default.default.isClassDeclaration(h)&&h.pos<=y&&y<=h.end)return h})(t.node,e);if(!a)return null;let s=a.members.find(M__default.default.isConstructorDeclaration);if(!s||s.parameters.length===0)return null;let c=[];for(let l of s.parameters){var f;(function(o,u,m){if((function(E,S,A){let v=M__default.default.getDecorators(E);if(!v||v.length===0)return false;for(let w of v){let L=(function(j){let K=M__default.default.isCallExpression(j.expression)?j.expression.expression:j.expression;return M__default.default.isIdentifier(K)?K:void 0})(w);if(!L||!Ur.has(L.text))continue;let k=S.getSymbolAtLocation(L),U=k&&k.flags&M__default.default.SymbolFlags.Alias?S.getAliasedSymbol(k):k;if(A.isFromAngularCore(U))return true}return false})(o,u,m))return true;if(!o.type)return false;let y=u.getTypeFromTypeNode(o.type);if(m.isInjectionToken(y))return true;let h=y.aliasSymbol??y.symbol;return !!h&&m.isInjectableClass(h)})(l,r,n)&&c.push((f=l,{name:M__default.default.isIdentifier(f.name)?f.name.text:"<binding>",typeText:f.type?f.type.getText():"<inferred>"}));}if(c.length===0)return null;let{line:d,column:p}=e.locator.location(b(s)),i=c.map(l=>`${l.name}: ${l.typeText}`).join(", ");return {filePath:e.filePath,ruleName:Ee,message:`Constructor dependency injection makes class setup less composable than inject(). Offending params: ${i}.`,line:d,column:p,severity:"warn",fix:x[Ee],codeExample:P[Ee]}},{requires:{typeChecker:true}});var be="signal-prefer-input-signal";function Hr(t){let e=g(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var Pt=engine.createAnyAngularClassRule(be,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=[],a=e.project?.standaloneComponents?.has(e.filePath)??false;for(let s of r){let c=g(s);if(c&&(c.type==="PropertyDefinition"||c.type==="AccessorProperty")&&Array.isArray(c.decorators)&&c.decorators.some(Hr)){let f=b(c),{line:d,column:p}=e.locator.location(f),i=g(c.key),l=(i?.type==="Identifier"?i.name:i?.type==="Literal"?String(i.value):"")||"(unknown)",o=`'${l}' uses @Input(), which keeps this input outside Angular's signal graph.`;a&&(o+=" Standalone declarations benefit most from signal inputs."),n.push({filePath:e.filePath,ruleName:be,message:o,line:d,column:p,severity:a?"error":"warn",fix:x[be],codeExample:P[be]});}}return n.length>0?n:null},{requires:{projectContext:true}});var Se="signal-prefer-output-function",Tt=engine.createAnyAngularClassRule(Se,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(c,f){let d=D(f);if(!d)return;let p=b(c);for(let i of d.statements)if(M__default.default.isClassDeclaration(i)&&i.pos<=p&&p<=i.end)return i})(t.node,e);if(!a)return null;let s=[];for(let c of a.members){if(!M__default.default.isPropertyDeclaration(c)||!(function(i,l,o){let u=M__default.default.getDecorators(i);if(!u)return false;for(let m of u){let y=M__default.default.isCallExpression(m.expression)?m.expression.expression:m.expression;if(!M__default.default.isIdentifier(y)||y.text!=="Output")continue;let h=l.getSymbolAtLocation(y),E=h&&h.flags&M__default.default.SymbolFlags.Alias?l.getAliasedSymbol(h):h;if(o.isFromAngularCore(E))return true}return false})(c,r,n)||!(function(i,l,o){if(i.type){let m=l.getTypeFromTypeNode(i.type);if(o.isEventEmitter(m))return true}if(i.initializer){let m=l.getTypeAtLocation(i.initializer);if(o.isEventEmitter(m))return true}let u=l.getSymbolAtLocation(i.name);if(u){let m=l.getTypeOfSymbolAtLocation(u,i);if(o.isEventEmitter(m))return true}return false})(c,r,n))continue;let f=(function(i){let l=i.name;if(M__default.default.isIdentifier(l)||M__default.default.isStringLiteral(l))return l.text})(c)??"(unknown)",{line:d,column:p}=e.locator.location(c.getStart());s.push({filePath:e.filePath,ruleName:Se,message:`'${f}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:d,column:p,severity:"warn",fix:x[Se],codeExample:P[Se]});}return s.length>0?s:null},{requires:{typeChecker:true}});var Ae="signal-prefer-model";function Ot(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let n=g(r.expression??r);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(n.type==="CallExpression"){let a=g(n.callee);return a?.type==="Identifier"&&a.name===e}return false})}function kt(t,e){let r=g(t.value);if(!r||r.type!=="CallExpression")return false;let n=g(r.callee);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(C(n)){let a=g(n.object);return a?.type==="Identifier"&&a.name===e}return false}var Dt=engine.createAnyAngularClassRule(Ae,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=new Map,a=new Map;for(let c of r){let f=g(c);if(!f||f.type!=="PropertyDefinition"&&f.type!=="AccessorProperty")continue;let d=(function(p){let i=g(p.key);return i?i.type==="Identifier"?i.name??null:i.type==="Literal"?String(i.value):null:null})(f);d&&((Ot(f,"Input")||kt(f,"input"))&&n.set(d,f),(Ot(f,"Output")||kt(f,"output"))&&a.set(d,f));}let s=[];for(let[c,f]of a){if(!c.endsWith("Change"))continue;let d=c.slice(0,-6),p=n.get(d);if(p){let i=b(p),{line:l,column:o}=e.locator.location(i);s.push({filePath:e.filePath,ruleName:Ae,message:`The \`${d}\` / \`${c}\` pair implements two-way binding with extra wiring that model() avoids.`,line:l,column:o,severity:"warn",fix:x[Ae],codeExample:P[Ae]});}}return s.length>0?s:null});var Kr=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),We="template-prefer-control-flow",It=engine.createTemplateAttributeRule(We,(t,e)=>{var r;let n=(r=t.name,Kr.get(r)??null);if(!n)return null;let a=I(e,t.sourceSpan.start),{line:s,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:We,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${n}\` control flow benefits.`,line:s,column:c,severity:"error",fix:x[We]}},{requires:{htmlAst:true}});var Lt=new WeakMap,jt=engine.createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,n,a=(function p(i){let l=g(i);if(!l)return null;if(l.type==="BinaryExpression"&&l.operator==="|"){let o=g(l.right);return o?.type==="Identifier"&&o.name==="async"?g(l.left):p(l.left)}return null})(t.expression),s=a?(function p(i,l=0){if(!i||l>10)return null;if(i.type==="Identifier")return i.name;if(i.type==="ThisExpression")return "this";if(i.type==="Literal"){let o=i.value;return o===null?"null":typeof o=="string"||typeof o=="number"||typeof o=="boolean"||typeof o=="bigint"?String(o):null}if(i.type==="CallExpression"){let o=p(i.callee,l+1),u=(Array.isArray(i.arguments)?i.arguments:[]).map(m=>p(m,l+1)??"?");return `${o}(${u.join(",")})`}if(C(i)){let o=p(i.object,l+1),u=N(i);if(o&&u)return `${o}.${u}`}if(i.type==="UnaryExpression")return `${i.operator}${p(i.argument,l+1)}`;if(i.type==="ConditionalExpression")return `${p(i.test,l+1)}?${p(i.consequent,l+1)}:${p(i.alternate,l+1)}`;if(i.type==="OptionalExpression"||i.type==="ChainExpression")return p(i.expression,l+1);if(i.type==="LogicalExpression"){let o=p(i.left,l+1),u=p(i.right,l+1);if(o&&u)return `${o}${i.operator}${u}`}if(i.type==="BinaryExpression"&&i.operator!=="|"){let o=p(i.left,l+1),u=p(i.right,l+1);if(o&&u)return `${o}${i.operator}${u}`}if(i.type==="ArrayExpression")return `[${(i.elements??[]).map(u=>p(u,l+1)??"?").join(",")}]`;if(i.type==="ObjectExpression")return `{${(i.properties??[]).map(u=>{let m=u.key?p(u.key,l+1):"?",y=u.value?p(u.value,l+1):"?";return `${m}:${y}`}).join(",")}}`;if(i.type==="TemplateLiteral")return "`tmpl`";if(i.type==="AssignmentExpression"){let o=p(i.left,l+1),u=p(i.right,l+1);if(o&&u)return `${o}${i.operator}${u}`}return null})(a):null;if(!s)return null;let c=(r=e.template,n=r?.templateStartOffset,`${e.filePath}@${typeof n=="number"&&Number.isFinite(n)?n:0}`),f=Lt.get(e);f||(f=new Map,Lt.set(e,f));let d=f.get(c);if(d||(d=new Set,f.set(c,d)),d.has(s)){let p=I(e,t.sourceSpan.start),{line:i,column:l}=e.locator.location(p);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${s}" can create repeated work and inconsistent loading states.`,line:i,column:l,severity:"warn",fix:x["template-no-async-pipe-duplication"]}}return d.add(s),null},{requires:{htmlAst:true}});var Yr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Qr=new Set(["xdescribe","xit","xtest","xcontext"]);function Ft(t){return t.type==="Identifier"?t.name??null:null}var _t=engine.createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let n;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let a=g(t.callee);if(!a)return null;let s=(n=Ft(a)||(function(i){if(i.type==="MemberExpression"||i.type==="StaticMemberExpression"||i.type==="OptionalMemberExpression"){let l=g(i.object),o=i.property?.name??"",u=(l?.type==="Identifier"?l.name:"")??"";return u?`${u}.${o}`:null}return null})(a))&&Yr.has(n)?n:null;if(!s){if(Ft(a)==="pending"){let i=b(t),{line:l,column:o}=e.locator.location(i);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:l,column:o,severity:"error",fix:x["spec-no-focused-test"]}}return null}let c=b(t),{line:f,column:d}=e.locator.location(c),p=Qr.has(s)?`\`${s}\` disables a test that may be forgotten.`:`\`${s}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:p,line:f,column:d,severity:"error",fix:x["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function $t(){R(tt,"correctness"),R(rt,"correctness"),R(nt,"correctness"),R(ot,"correctness"),R(at,"performance"),R(lt,"performance"),R(ct,"performance"),R(pt,"performance"),R(ft,"performance"),R(mt,"security"),R(dt,"security"),R(gt,"ssr"),R(ht,"ssr"),R(Et,"reactivity"),R(xt,"reactivity"),R(bt,"reactivity"),R(At,"reactivity"),R(Ct,"reactivity"),R(Nt,"reactivity"),R(wt,"reactivity"),R(Mt,"modern-api"),R(Pt,"modern-api"),R(Tt,"modern-api"),R(Dt,"modern-api"),R(It,"template"),R(jt,"template"),R(_t,"testing");}var Bt=(t,e,r,n,a)=>{let s=0,c=0;for(let f of r)for(let d of f.failures)d.severity==="error"?s++:d.severity==="warn"&&c++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:s+c,errorCount:s,warningCount:c,duration:n,typeAware:a}};$t(),engine.configureRuleExecutor(Xe,Ke),process.on("message",t=>{rn(t);});var rn=async t=>{let e=[],r=engine.createTypeAwareAnalysisContext(t.rootDir,t.files,t.parserOptions,{buildProjectContext:t.buildProjectContext,programRootFiles:t.programRootFiles});try{await r.warmup();let n=planner.groupTasksByFile(t.tasks),a=await nn(Array.from(n),Math.max(1,t.fileConcurrency??1),async([s,c])=>{let f=performance.now();try{let d=await engine.executeBatchedTasks(c,r);return Ut(s,c.length,d,performance.now()-f),d}catch{return Ut(s,c.length,[],performance.now()-f),[]}finally{r.evict(s);}});e.push(...a.flat()),process.send?.({kind:"complete",results:e});}catch(n){process.send?.({kind:"error",error:n instanceof Error?n.message:String(n)});}finally{r.dispose(),process.disconnect?.();}};async function nn(t,e,r){let n=Array(t.length),a=0,s=Math.min(e,t.length);return await Promise.all(Array.from({length:s},async()=>{for(;a<t.length;){let c=a++;n[c]=await r(t[c]);}})),n}var Ut=(t,e,r,n)=>{process.send?.(Bt(t,e,r,n,true));};//# sourceMappingURL=type-aware-worker.cjs.map
//# sourceMappingURL=type-aware-worker.cjs.map

@@ -1,2 +0,2 @@

import {groupTasksByFile}from'@ngcompass/planner';import {createAnyAngularClassRule,createCallExpressionRule,createComponentRule,createTemplateExpressionRule,createTemplateRule,createTemplateAttributeRule,configureRuleExecutor,createTypeAwareAnalysisContext,executeBatchedTasks,runSinglePassAnalysis}from'@ngcompass/engine';import {debug}from'@ngcompass/common';import {analyzeComponent,ChangeDetectionStrategy}from'@ngcompass/ast';import Jt from'typescript';var wt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var he=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description||`Rule: ${e}`,category:r.category||"general",dependencyType:r.dependencyType||"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:{severity:"warn",options:{}}}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let n=this.getRegistryEntry(r);n&&e.set(r,n);}return e}get size(){return this._handlers.size}},ye=null,X=()=>(ye||(ye=new he),ye);var C=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:{...t.meta?.requires}}};X().register(r),debug("engine",`Registered rule: ${t.name}`);},Ie=t=>X().has(t);var ke=(t,e)=>{let r=X(),n=[];for(let u of t){let a=r.get(u);a&&n.push(a);}if(n.length===0)return [];debug("engine",`Executing ${n.length} rules in single pass on ${e.filePath}`);let{results:o,performance:l}=runSinglePassAnalysis(n,e);return debug("engine",`Single-pass complete: ${l.traversalMs.toFixed(2)}ms, ${l.nodesVisited} nodes`),debug("engine",`Cache hit rate: ${(l.cacheStats.hits/(l.cacheStats.hits+l.cacheStats.misses||1)*100).toFixed(1)}%`),l.budgetViolations.length>0&&debug("engine","Performance budget violations:",l.budgetViolations),o};var De;function s(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function x(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function v(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function O(t,e){let r=s(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!x(r)&&v(r)===e)}function j(t){let e=s(t);if(!e||e.type!=="CallExpression")return "";let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}function Y(t){let e=s(t?.callee);return !!x(e)&&v(e)==="subscribe"}function W(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let n of r){if(!n||n.type!=="Property")continue;let o=n.key;if((o?.type==="Identifier"?o.name:o?.type==="Literal"&&typeof o.value=="string"?o.value:"")===e)return n}return null}function ge(t){let e=s(t);return !!(e&&e.type==="Literal"&&e.value===true)}function Ee(t){let e=s(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Pt=new Set(["parent","span","loc","range","start","end","type"]);function*N(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Pt.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let n of r)n&&typeof n=="object"&&(yield n);else typeof r=="object"&&r.type&&(yield r);}}}function xe(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function B(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function U(t){for(let e of t)if(e&&B(e)&&xe(e))return e;return null}function L(t){return t?(t.value??t)?.body??null:null}function Le(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function w(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Ot(t){let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let n=s(r[1]);if(!n||n.type!=="ObjectExpression")return false;let o=W(n,"injector");if(o&&!Ee(o.value))return true;let l=W(n,"manualCleanup");return !!(l&&ge(l.value))}function $e(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let n=s(r.pop());if(n)for(let o of(n.type==="CallExpression"&&O(n.callee,"effect")&&!Ot(n)&&e.push(n),N(n)))r.push(o);}return e}function G(t){let e=t?.arguments;if(!Array.isArray(e)||e.length===0)return null;let r=s(e[0]);return r&&(r.type==="ArrowFunctionExpression"||r.type==="FunctionExpression")?r:null}function K(t){if(!t)return null;let e=t.body;return e?s(e):null}function _e(t,e){let r=new Map([...e].map(o=>[o,new Set([o])]));if(typeof t!="string"||t.length===0)return r;let n=new Map([...e].map(o=>[o,RegExp(`^${o}(?:\\s+as\\s+([A-Za-z_$][\\w$]*))?$`)]));for(let o of [/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs['"]/g,/import\s*\{\s*([^}]+)\s*\}\s*from\s*['"]rxjs\/[^'"]+['"]/g]){let l;for(;(l=o.exec(t))!==null;)for(let u of (l[1]??"").split(",").map(a=>a.trim()).filter(Boolean))for(let[a,c]of n){let p=c.exec(u);p&&r.get(a).add(p[1]??a);}}return r}var Tt=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function It(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"?r.name??"":x(r)?v(r):""}return x(e)?v(e):""}function kt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(Tt.has(It(r)))return true;return false}function Z(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let n=s(r.callee);if(!x(n))break;if(v(n)==="pipe"&&kt(r))return true;e=n?.object;}return false}function k(t,e){let r=t.template?.templateStartOffset;return typeof r=="number"&&Number.isFinite(r)?e+r:e}var Dt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),jt=new Set(["http","httpClient","_http","_httpClient"]),Lt=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function Q(t){let e=t;for(;e;){let r=s(e);if(!r||r.type!=="CallExpression")break;let n=s(r.callee);if(!x(n))break;if(v(n)!=="pipe")return r;e=n?.object;}return null}function J(t){if(!t)return false;let e=s(t);if(!e||e.type!=="CallExpression")return false;let r=s(e.callee);if(!x(r))return false;let n=v(r);if(!n)return false;let o=s(r?.object),l=Array.isArray(e.arguments)?e.arguments:[];if(Dt.has(n)&&x(o)){let u=v(o);if(jt.has(u))return true}if(l.length>0){let u=n.toLowerCase();for(let a of Lt)if(u.startsWith(a)&&n.length>a.length)return true}return false}function ee(t){if(!t)return [];let e=t.params;if(Array.isArray(e))return e;if(e&&typeof e=="object"){if("items"in e&&Array.isArray(e.items))return e.items;if("elements"in e&&Array.isArray(e.elements))return e.elements}return []}function F(t){let e=s(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="TSParameterProperty")return F(e.parameter);if(e.type==="AssignmentPattern"){let r=s(e.left);return r?.type==="Identifier"?r.name??"":""}if(e.type==="RestElement"){let r=s(e.argument);return r?.type==="Identifier"?r.name??"":""}return ""}function $(t){let e=s(t);if(!e)return "";if(e.type==="TSParameterProperty")return $(e.parameter);let r=e.typeAnnotation,n=s(r?.typeAnnotation??r);if(!n)return "";if(n.type==="TSTypeReference"||n.type==="TypeReference"){let o=n.typeName??n.name;if(o&&typeof o=="object"){if(o.type==="Identifier")return o.name??"";if(o.type==="TSQualifiedName")return o.right?.name??""}if(typeof o=="string")return o}return ""}var je=false;function Be(){if(!je){try{De=wt("typescript");}catch{}je=true;}return De}function q(t,e){if(!t||!e.typeChecker)return;let r=Be();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let n=e.sourceFile;if(!n)return;let o=(function(l,u,a){if(u<l.getStart()||u>=l.getEnd())return;let c=l;for(;;){let p=a.forEachChild(c,i=>{if(u>=i.getStart()&&u<i.getEnd())return i});if(!p)break;c=p;}return c})(n,b(t),r);return o?e.typeChecker.getSymbolAtLocation(o):void 0}catch{return}}var $t=["Service","Facade","Store","Client","Repository","Adapter","Controller","Provider","Registry","Logger","Router","Injector","Handler","Interceptor","Guard","Resolver","Validator"];function Ue(t){if(!t)return false;let e=Be();if(!e)return false;try{let r=t.getName();if($t.some(l=>r.endsWith(l)))return !0;let n=t.getDeclarations();if(!n||n.length===0)return !1;let o=n[0];if(!e.canHaveDecorators(o))return !1;for(let l of e.getDecorators(o)??[]){let u=l.expression;if(e.isCallExpression(u)&&e.isIdentifier(u.expression)&&u.expression.text==="Injectable")return !0}return !1}catch{return false}}var E={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},R={"prefer-on-push-component-change-detection":`// Before:
import {groupTasksByFile}from'@ngcompass/planner';import {createAnyAngularClassRule,createCallExpressionRule,createComponentRule,createTemplateExpressionRule,createTemplateRule,createTemplateAttributeRule,configureRuleExecutor,createTypeAwareAnalysisContext,executeBatchedTasks,runSinglePassAnalysis}from'@ngcompass/engine';import {debug}from'@ngcompass/common';import M from'typescript';import {analyzeComponent,ChangeDetectionStrategy}from'@ngcompass/ast';var Ht=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var zt={severity:"warn",options:{}},ve=class{_handlers=new Map;_meta=new Map;register(e,r={}){if(this._handlers.has(e.name)&&!r.allowOverride)throw Error(`[ngcompass] Rule "${e.name}" is already registered. Use allowOverride: true to replace an existing rule intentionally.`);this._handlers.set(e.name,e.handler),e.meta&&this._meta.set(e.name,e.meta);}get(e){return this._handlers.get(e)}has(e){return this._handlers.has(e)}getRuleNames(){return Array.from(this._handlers.keys())}getAll(){return this._handlers}getMeta(e){return this._meta.get(e)}getMetadata(e){if(!this._handlers.has(e))return;let r=this._meta.get(e)??{};return {name:e,description:r.description??`Rule: ${e}`,category:r.category??"general",dependencyType:r.dependencyType??"standalone",requires:{tsAst:true,...r.requires},filePatterns:r.filePatterns}}getRegistryEntry(e){let r=this.getMetadata(e);if(r)return {name:e,metadata:r,defaultConfig:zt}}toReadonlyMap(){let e=new Map;for(let r of this._handlers.keys()){let n=this.getRegistryEntry(r);n&&e.set(r,n);}return e}get size(){return this._handlers.size}},Ce=null,J=()=>(Ce||(Ce=new ve),Ce);var R=(t,e)=>{let r={name:t.name,handler:t,meta:{dependencyType:"component",...t.meta,category:e??t.meta?.category??"best-practice",requires:t.meta?.requires??{}}};J().register(r),debug("engine",`Registered rule: ${t.name}`);},Ke=t=>J().has(t),Xe=(t,e)=>{let r=J(),n=[];for(let f of t){let d=r.get(f);d&&n.push(d);}if(n.length===0)return [];debug("engine",`Executing ${n.length} rules in single pass on ${e.filePath}`);let{results:a,performance:s}=runSinglePassAnalysis(n,e);debug("engine",`Single-pass complete: ${s.traversalMs.toFixed(2)}ms, ${s.nodesVisited} nodes`);let c=s.cacheStats.hits+s.cacheStats.misses;if(c>0){let f=s.cacheStats.hits/c*100;debug("engine",`Component metadata cache hit rate: ${f.toFixed(1)}%`);}return s.budgetViolations.length>0&&debug("engine",`Performance budget violations: ${s.budgetViolations.join("; ")}`),a};var x={"prefer-on-push-component-change-detection":"Add `changeDetection: ChangeDetectionStrategy.OnPush` to the component metadata.","template-no-call-expression":"Move the value to a pipe, computed signal, or cached component property.","rxjs-no-subscribe-in-component":"Use `toSignal()` or the `async` pipe for view state; add `takeUntilDestroyed()` for long-lived imperative subscriptions.","template-trackby-required":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-trackby-required-for-ngfor":"Add `trackBy` to `*ngFor`, or use `track` when migrating to `@for`.","template-no-object-literal-binding":"Move the object to a component property, signal, computed value, or pure pipe.","template-no-array-literal-binding":"Move the array to a component property, signal, computed value, or pure pipe.","toSignal-require-initialValue":"Pass `{ initialValue }` or `{ requireSync: true }` so the signal has a stable type.","rxjs-avoid-subject-as-event-bus":"Use `signal()` for component UI state; move complex async pipelines into a service.","signal-no-side-effects-in-computed":"Move side effects to an `effect()` or method, and keep `computed()` pure.","signal-no-writes-in-computed":"Move `.set()` or `.update()` calls to an `effect()` or event handler.","prefer-inject-over-constructor-di":"Replace constructor parameters with field initializers that call `inject()`.","component-no-manual-detect-changes":"Use signals, `async` pipe, or input-driven state instead of calling `detectChanges()` or `markForCheck()`.","rxjs-require-takeUntilDestroyed":"Add `takeUntilDestroyed()` or another teardown operator before `subscribe()`.","template-no-async-pipe-duplication":"Store the async value once with `@if (... | async; as value)` or a view-model signal.","rxjs-prefer-toSignal-for-template-state":"Convert template-used observables to `toSignal()` and read them as signals in the template.","signal-effect-must-be-destroy-scoped":"Create the effect in an injection context or pass an explicit `{ injector }`.","signal-no-effect-in-constructor":"Move the `effect()` call to a field initializer.","signal-prefer-computed-over-sync-effect":"Replace the write-producing `effect()` with a `computed()` signal.","signal-avoid-untracked-overuse":"Remove `untracked()` unless the dependency must be intentionally ignored.","template-prefer-control-flow":"Replace the legacy directive with the matching `@if`, `@for`, or `@switch` block.","signal-prefer-input-signal":"Replace `@Input()` with `input()` or `input.required()`.","signal-prefer-output-function":"Replace `@Output() EventEmitter` with `output<T>()`.","no-bypass-sanitization":"Use Angular sanitization or a trusted server-side sanitizer instead of `bypassSecurityTrust*`.","rxjs-no-nested-subscribe":"Flatten the stream with `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.","no-document-access":"Inject `DOCUMENT` or move browser-only DOM work into `afterNextRender()`.","template-no-unsafe-bindings":"Sanitize the value before binding, or replace the raw HTML binding with structured template content.","signal-prefer-model":"Replace the `@Input()` / `@Output()Change` pair with `model()`.","prefer-after-render-over-after-view-init":"Move browser-only DOM access into `afterNextRender()`.","spec-no-focused-test":"Replace focused or disabled test helpers with normal `describe` and `it` calls."},P={"prefer-on-push-component-change-detection":`// Before:
@Component({ selector: 'app-foo', template: '...' })

@@ -216,3 +216,3 @@ export class FooComponent { }

it('should render', () => { ... });
});`};var te="component-no-manual-detect-changes",Ut=new Set(["detectChanges","markForCheck"]),Ft=new Set(["cdr","cdref","changedetectorref","_cdr","_cdref","changedetector","_changedetector","changedetectionref","cd","_cd"]),qe=createAnyAngularClassRule(te,(t,e)=>{var r,n;let o,l,u=t.node;if(n=u,analyzeComponent(n)?.type!=="Component")return null;let a=(l=(r=(function(i){let f=new Set,m=w(i),d=U(m);if(d){for(let h of ee(d.value??d))if($(h)==="ChangeDetectorRef"){let y=F(h);y&&f.add(y);}}for(let h of m)if(h.type==="PropertyDefinition"&&h.value){let y=s(h.value);if(y&&(function(g){if(g.type!=="CallExpression")return false;let S=s(g.callee);if(S?.type!=="Identifier"||S.name!=="inject")return false;let[A]=g.arguments??[],M=s(A);return M?.type==="Identifier"&&M.name==="ChangeDetectorRef"})(y)){let g=h.key;g?.type==="Identifier"&&f.add(g.name);}}return f})(u)).size>0,i=>!!r.has(i)||!l&&Ft.has(i.toLowerCase())),c=(o=analyzeComponent(u),o?.type==="Component"&&o.changeDetection?.kind==="literal"&&o.changeDetection.value===ChangeDetectionStrategy.OnPush),p=(function(i,f,m,d){let h=[],y=[...w(i)];for(;y.length>0;){let g=s(y.pop());if(!g)continue;let S=(function(A){if(A.type!=="CallExpression")return null;let M=s(A.callee);if(!x(M))return null;let P=v(M);return P&&Ut.has(P)?P:null})(g);for(let A of(S&&(function(M,P){if(M.type!=="CallExpression")return false;let I=s(M.callee);if(!I||!x(I))return false;let T=s(I.object);if(!T)return false;if(T.type==="Identifier")return P(T.name);if(!x(T))return false;let D=s(T.object),_=v(T);return (D?.type==="ThisExpression"||D?.type==="Identifier"&&D.name==="this")&&!!_&&P(_)})(g,d)&&(m&&S==="markForCheck"||h.push((function(M,P,I,T){let D=b(M),{line:_,column:V}=P.locator.location(D);return {filePath:P.filePath,ruleName:te,message:T?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${I}) can hide state-flow bugs and make rendering harder to predict.`,line:_,column:V,severity:T?"warn":"error",fix:E[te],codeExample:R[te]}})(g,f,S,m))),N(g)))y.push(A);}return h})(u,e,c,a);return p.length>0?p:null});var be="signal-no-side-effects-in-computed",Ht=new Set(["post","put","patch","subscribe","unsubscribe","next","complete","setItem","removeItem","appendChild","removeChild","dispatch"]),zt=new Set(["set","update","mutate"]),Wt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]),He=createCallExpressionRule(be,(t,e)=>{if(!O(t.callee,"computed"))return null;let r=G(t),n=r?K(r):null;if(!n)return null;let o=(function(l){let u=[l];for(;u.length>0;){var a;let c=s(u.pop());if(c){if(c!==l){if((function(p){let i=s(p);if(!i)return false;if(i.type==="AssignmentExpression"){let f=s(i.left);return !!f&&x(f)}if(i.type==="UpdateExpression"||i.type==="UnaryExpression"&&i.operator==="delete"){let f=s(i.argument);return !!f&&x(f)}return false})(c))return {node:c,type:"write"};if(c.type==="CallExpression"){let p=(function(i){let f=s(i);if(!f||f.type!=="CallExpression")return "";let m=s(f.callee);return x(m)&&v(m)||""})(c);if(zt.has(p))return {node:c,type:"write"};if(Ht.has(p))return {node:c,type:"effect"}}}if(!(c!==l&&(a=c).type&&Wt.has(a.type)))for(let p of N(c))u.push(p);}}return null})(n);return o?(function(l,u,a,c){let p=b(l)||b(u),{line:i,column:f}=a.locator.location(p);return {filePath:a.filePath,ruleName:be,message:c==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:i,column:f,severity:"error",fix:E[be]}})(o.node,t,e,o.type):null});var Se="signal-effect-must-be-destroy-scoped",ze=createAnyAngularClassRule(Se,(t,e)=>{let r=w(t.node);if(r.length===0)return null;let n=[];for(let o of r)o&&B(o)&&!xe(o)&&n.push(...(function(l,u){let a=L(l);if(!a)return [];let c=Le(l),p=[];for(let i of $e(a))(function(f){if(f.type!=="CallExpression")return false;let m=s(f.callee);return !!m&&(m.type==="Identifier"?m.name==="effect":!!x(m)&&v(m)==="effect")})(i)&&!(function(f){let m=s((Array.isArray(f.arguments)?f.arguments:[])[1]);if(!m||m.type!=="ObjectExpression")return false;for(let d of Array.isArray(m.properties)?m.properties:[]){let h=s(d);if(h?.type==="Property"){let y=s(h.key),g=y?.type==="Identifier"?y.name:v(y)||"";if(g==="injector")return true;if(g==="manualCleanup"){let S=s(h.value);if(S?.type==="Literal"&&S.value===true)return true}}}return false})(i)&&p.push((function(f,m,d){let h=b(f),{line:y,column:g}=d.locator.location(h);return {filePath:d.filePath,ruleName:Se,message:`effect() inside "${m}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:g,severity:"error",fix:E[Se]}})(i,c,u));return p})(o,e));return n.length>0?n:null});var re="rxjs-no-nested-subscribe",Yt=new Set(["next","error","complete"]),Gt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function ve(t){if(t.type!=="CallExpression")return false;let e=s(t.callee);return !!x(e)&&v(e)==="subscribe"}function We(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var Ve=createCallExpressionRule(re,(t,e)=>{if(!ve(t))return null;for(let r of (function(n){if(!ve(n))return [];let o=Array.isArray(n.arguments)?n.arguments:[];if(o.length===0)return [];let l=s(o[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let a=[];for(let c of Array.isArray(l.properties)?l.properties:[]){let p=s(c);if(p?.type==="Property"&&Yt.has((function(i){let f=s(i.key);return f?f.type==="Identifier"?f.name:v(f)||"":""})(p))){let i=s(p.value);We(i)&&a.push(i);}}return a}let u=[];for(let a=0;a<Math.min(o.length,3);a++){let c=s(o[a]);We(c)&&u.push(c);}return u})(t)){let n=s(r.body);if(n&&(function(o){let l=[o];for(;l.length>0;){var u;let a=s(l.pop());if(a){if(a!==o&&ve(a))return true;if(!(a!==o&&(u=a).type&&Gt.has(u.type)))for(let c of N(a))l.push(c);}}return false})(n))return (function(o,l){let u=b(o),{line:a,column:c}=l.locator.location(u);return {filePath:l.filePath,ruleName:re,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:a,column:c,severity:"error",fix:E[re],codeExample:R[re]}})(t,e)}return null});var ne="prefer-on-push-component-change-detection";function ie(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function oe(t){return t.replace(/\\/g,"/")}var Xe=createComponentRule(ne,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(n){if(!n||typeof n!="object")return false;let{kind:o,value:l}=n;return o!=="non-literal"&&(o==="literal"?l!==ChangeDetectionStrategy.OnPush:o==="missing")})(r.changeDetection)?null:(function(n,o){let l,u,a,c,p=(l=n.metadata??{},u=n.node,ie(l,"decoratorStart")??ie(l,"start")??ie(u,"start")??ie(n,"start")??0),{line:i,column:f}=o.locator.location(p),m=(a=n.metadata,typeof(c=a?.className)=="string"?c:"AnonymousComponent"),d=(function(h,y){if(!y.project)return null;let g=h.metadata,S=g?.className;if(typeof S!="string"||!S)return null;let A=oe(y.filePath),{ngModuleMap:M,classToFile:P}=y.project;for(let[T,D]of M){var I;if(D.isStandalone||!D.declarations.has(S))continue;let _=P.get(S);if(_&&oe(_)!==A)continue;let V=0;for(let Te of D.declarations)Te!==S&&(I=P.get(Te))&&oe(I).endsWith(".component.ts")&&V++;return {moduleName:(oe(T).split("/").pop()??T).replace(/\.ts$/,""),siblingComponentCount:V}}return null})(n,o);return {filePath:o.filePath,ruleName:ne,message:(function(h,y){if(!y)return `Component '${h}' uses default change detection, which can re-render more often than needed.`;let{moduleName:g,siblingComponentCount:S}=y,A=S>0?` ${S} other component${S===1?"":"s"} are declared in '${g}'.`:"";return `Component '${h}' uses default change detection, which can re-render more often than needed.${A}`})(m,d),line:i,column:f,severity:"error",fix:E[ne],codeExample:R[ne]}})(t,e)},{requires:{projectContext:true}});var Ae="template-no-call-expression",er=new Set(["translate","$localize","$any"]),tr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function Ye(t){let e=s(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var Ge=createTemplateExpressionRule(Ae,(t,e)=>(function(r,n){let o=r?[r]:[];for(;o.length>0;){let l=s(o.pop());if(l){if(Ye(l)&&!(function(u){let a=s(u);if(!a||!Ye(a))return false;let c=s(a.callee);if(!c)return false;if(c.type==="Identifier")return er.has(c.name);if(!x(c))return false;let p=v(c);return !!p&&tr.has(p)})(l)){if((function(a){let c;return (c=s(a),Array.isArray(c?.arguments)?c.arguments:[]).length>0})(l))return true;let u=(function(a){let c=s(a);if(!c)return "";let p=s(c.callee);return p?p.type==="Identifier"?p.name??"":x(p)?v(p):"":""})(l);if(u&&!(function(a,c){let p=a.startsWith("get")||a.startsWith("is")||a.startsWith("has");if(c.crossRef?.signalMembers?.has(a))return true;if(c.typeChecker&&c.crossRef?.componentPath)try{let i=c.typeChecker,f=c.crossRef.componentPath,m=i.getProgram().getSourceFile(f);if(m){let d=m.statements.find(h=>Jt.isClassDeclaration(h));if(d&&d.name){let h=i.getTypeAtLocation(d),y=i.getPropertyOfType(h,a);if(y){if(!y)return !1;let g=y.valueDeclaration??y.declarations?.[0];if(!g)return !1;let S=i.getTypeOfSymbolAtLocation(y,g);if(!S)return !1;let A=i.typeToString(S);return A.includes("Signal")||A.includes("writable")||A.includes("computed")}}}}catch{}return !p})(u,n))return true}for(let u of N(l))o.push(u);}}return false})(t.expression,e)?[(function(r,n){let o=k(n,r.sourceSpan.start),{line:l,column:u}=n.locator.location(o);return {filePath:n.filePath,ruleName:Ae,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:u,severity:"error",fix:E[Ae]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function Ke(t,e,r,n){let o=k(t,e.sourceSpan.start),{line:l,column:u}=t.locator.location(o);return {filePath:t.filePath,ruleName:r,message:n,line:l,column:u,severity:"error",fix:E[r]}}var Ze=createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let n of t.attributes)n.name==="*ngFor"&&!(function(o){return !!o.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(n.value??"")&&r.push(Ke(e,n,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let n of t.blocks)n.name!=="for"||n.parameters.some(o=>{let l=o.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(Ke(e,n,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Ce="template-no-object-literal-binding",Qe=createTemplateExpressionRule(Ce,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let o=s(n.pop());if(o){if(o.type==="ObjectExpression")return true;for(let l of N(o))n.push(l);}}return false})(t.expression)?[(function(r,n){let o=k(n,r.sourceSpan.start),{line:l,column:u}=n.locator.location(o);return {filePath:n.filePath,ruleName:Ce,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ce]}})(t,e)]:null,{requires:{htmlAst:true}});var Ne="template-no-array-literal-binding",Je=createTemplateExpressionRule(Ne,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let o=s(n.pop());if(o){if(o.type==="ArrayExpression")return true;for(let l of N(o))n.push(l);}}return false})(t.expression)?[(function(r,n){let o=k(n,r.sourceSpan.start),{line:l,column:u}=n.locator.location(o);return {filePath:n.filePath,ruleName:Ne,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ne]}})(t,e)]:null,{requires:{htmlAst:true}});var Re=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),et=createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let u=s(l.callee);if(!u)return null;if(u.type==="Identifier"&&u.name)return Re.has(u.name)?u.name:null;if(x(u)){let a=v(u);return a&&Re.has(a)?a:null}return null})(t);if(!r)return null;let{line:n,column:o}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${Re.get(r)} sanitization, which can expose unsafe content.`,line:n,column:o,severity:"error",fix:E["no-bypass-sanitization"]}});var sr=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),lr=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,ur=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,tt=createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=sr.get(t.name);if(!r)return null;let n=t.value??"";if(lr.test(n)||ur.test(n)||t.name==="[style]"&&!/[.(|?]/.test(n))return null;let{line:o,column:l}=e.locator.location(k(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:o,column:l,severity:r.severity,fix:E["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var pr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),rt=createAnyAngularClassRule("no-document-access",(t,e)=>{let r=w(t.node);if(r.length===0)return null;let n=(function(a){let c=new Set,p=[...a];for(;p.length;){let i=s(p.pop());if(i){if(i.type==="VariableDeclarator"&&i.init){let f=s(i.init);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=i.id??i.key;m?.type==="Identifier"&&m.name&&c.add(m.name);}}if(i.type==="AssignmentExpression"&&i.right){let f=s(i.right);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=s(i.left);if(m&&x(m)&&s(m.object)?.type==="ThisExpression"){let d=m.property?.name;typeof d=="string"&&d&&c.add(d);}}}for(let f of N(i))p.push(f);}}return c})(r),o=[],l=new Set,u=[...r];for(;u.length;){let a=s(u.pop());if(a){if(a.type==="IfStatement"&&a.test){let c=s(a.test);if(c){let p=(function(i,f){let m=[i];for(;m.length;){let d=s(m.pop());if(d){if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformBrowser"))return "browser";if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformServer"))return "server";if(d.type==="UnaryExpression"&&d.operator==="!"&&d.argument){let h=s(d.argument);if(h?.type==="CallExpression"&&h.callee&&O(h.callee,"isPlatformServer"))return "browser"}if(d.type==="Identifier"&&f.has(d.name))return "browser";for(let h of N(d))m.push(h);}}return null})(c,n);if(p==="browser"){a.alternate&&u.push(a.alternate);continue}if(p==="server"){a.consequent&&u.push(a.consequent);continue}}}if(a.type==="CallExpression"&&a.callee){let c=s(a.callee);if(c&&(O(c,"afterNextRender")||O(c,"afterRender"))){let p=a.arguments??[];for(let i=1;i<p.length;i++)u.push(p[i]);continue}}if(x(a)){let c=(function(p){let i=p;for(;i&&x(i);)i=s(i.object);return i?.type==="Identifier"?i.name??null:null})(a);if(c&&pr.has(c)){let p=a;for(;p&&x(p);)p=s(p.object);let i=b(p);if(i!==void 0&&!l.has(i)){l.add(i);let{line:f,column:m}=e.locator.location(i);o.push({filePath:e.filePath,ruleName:"no-document-access",message:`Direct access to \`${c}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:E["no-document-access"],codeExample:R["no-document-access"]});}}}for(let c of N(a))u.push(c);}}return o.length?o:null});var mr=new Set(["nativeElement","getBoundingClientRect","querySelector","querySelectorAll","getElementById","createElement","scrollIntoView","focus","blur","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollTop","scrollLeft","innerHTML","outerHTML","textContent","parentElement","parentNode","firstChild","lastChild","nextSibling","previousSibling","children","ownerDocument","insertBefore","appendChild","removeChild","replaceChild","cloneNode","setAttribute","getAttribute","removeAttribute","hasAttribute","classList","dispatchEvent","contains","matches","closest","getClientRects","addEventListener","removeEventListener","requestAnimationFrame","cancelAnimationFrame"]),dr=["getElementsBy","offset","client","scroll"],nt=createAnyAngularClassRule("prefer-after-render-over-after-view-init",(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=[];for(let o of ["ngAfterViewInit","ngAfterContentInit"]){let l=r.find(p=>p.key?.name===o),u=l?L(l):null;if(!u||!l||!(function(p){let i=[p];for(;i.length;){let f=s(i.pop());if(f){if((f.type==="MemberExpression"||f.type==="StaticMemberExpression"||f.type==="OptionalMemberExpression")&&!f.computed){let m=f.property?.name??"";if(mr.has(m))return true;for(let d of dr)if(m.startsWith(d))return true}if(f.type==="Identifier"&&(f.name==="document"||f.name==="window"))return true;for(let m of N(f))i.push(m);}}return false})(u))continue;let{line:a,column:c}=e.locator.location(b(l));n.push({filePath:e.filePath,ruleName:"prefer-after-render-over-after-view-init",message:`\`${o}\` contains DOM access that can run before browser-only APIs are safe.`,line:a,column:c,severity:"warn",fix:E["prefer-after-render-over-after-view-init"],codeExample:R["prefer-after-render-over-after-view-init"]});}return n.length?n:null});var ae=new Map;function we(t){return /ngOnDestroy\s*\([^)]*\)\s*\{[^}]*\.unsubscribe\s*\(\)/s.test(t)}var it=createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{var r,n;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t))return null;let l=s(t.callee),u=x(l)?l?.object:null;if(u&&Z(u)||J(Q(u))||(r=e.filePath,n=e.fileContent,(o=ae.get(r))!==void 0||(o=we(n),ae.size>=500&&ae.clear(),ae.set(r,o)),o))return null;let a=b(t),{line:c,column:p}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:c,column:p,severity:"error",fix:E["rxjs-require-takeUntilDestroyed"]}});var se=new Map,le="rxjs-no-subscribe-in-component",ot=createCallExpressionRule(le,(t,e)=>{var r,n;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t)||(function(i){let f=s(i.callee);if(!f||!x(f))return false;let m=s(f.object);if(!m)return false;if(m.type==="CallExpression"){let d=s(m.callee);if(x(d)&&v(d)==="pipe"&&(Array.isArray(m.arguments)?m.arguments:[]).some(h=>{let y=s(h);if(y?.type!=="CallExpression")return false;let g=s(y.callee)?.name;return g==="take"||g==="first"}))return true}return J(Q(m))})(t))return null;let l=s(t.callee),u=s(l?.object);if(u&&Z(u)||(r=e.filePath,n=e.fileContent,(o=se.get(r))!==void 0||(o=we(n),se.size>=500&&se.clear(),se.set(r,o)),o))return null;let a=b(t),{line:c,column:p}=e.locator.location(a);return {filePath:e.filePath,ruleName:le,message:(function(i,f){let m="Open-ended subscriptions in components can outlive the component and make state harder to track.",d=f.crossRef?.templateReferences;if(!d)return m;let h=s(i.callee),y=s(h?.object),g=y?v(y):null;if(!g)return m;let S=g.endsWith("$")?g.slice(0,-1):g;return d.has(g)||d.has(S)?`'${g}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:m})(t,e),line:c,column:p,severity:"error",fix:E[le],codeExample:R[le]}},{requires:{projectContext:true}});var ue="rxjs-avoid-subject-as-event-bus",at=new Set(["Subject","ReplaySubject","AsyncSubject","BehaviorSubject"]),Er=new Set(["destroy$","destroyed$","ondestroy$","ngondestroy$","unsubscribe$","unsub$","teardown$","dispose$","cleanup$","cleanupsubject$"]),xr=/state|loading|error|active|selected|open|visible|disabled|count|value|data|hidden|expanded|pending|success|failed/i;function H(t,e,r){let n=[t];for(;n.length;){let o=s(n.pop());if(!o)continue;let l=s(o.callee);if(o.type==="CallExpression"&&v(l)===e){let u=s(l?.object);if(u&&x(u)&&s(u.object)?.type==="ThisExpression"){let a=v(u);a&&r.add(a);}}for(let u of N(o))n.push(u);}}var st=createAnyAngularClassRule(ue,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node);if(r.length===0)return null;let n=(function(a){let c=_e(a.sourceText,at),p=new Map;for(let[i,f]of c)for(let m of f)p.set(m,i);return p})(e),o=(function(a){let c=new Set,p=U(a);if(p){let i=L(p);i&&H(i,"next",c);}for(let i of a)if(B(i)){i.kind==="set"&&(function(m){let d=m.decorators;if(!Array.isArray(d))return false;for(let h of d){let y=s(h.expression);if(y?.name==="Input"||s(y?.callee)?.name==="Input")return true}return false})(i)&&H(i,"next",c);let f=i.key?.name;if(f==="ngOnChanges"){let m=L(i);m&&H(m,"next",c);}if(f==="ngOnDestroy"){let m=L(i);m&&H(m,"complete",c);}}else i.type==="PropertyDefinition"&&i.value&&H(i.value,"next",c);return c})(r),l=(function(a){let c=new Set;for(let p of a){let i=B(p)?L(p):p.type==="PropertyDefinition"?p.value:null;i&&H(i,"pipe",c);}return c})(r),u=[];for(let a of r){if(a.type!=="PropertyDefinition"||a.accessibility==="public")continue;let c=s(a.value??a.initializer);if(!c||c.type!=="NewExpression")continue;let p=(function(d,h){let y=s(d);if(!y)return null;if(y.type==="Identifier")return h.get(y.name)??null;if(x(y)){let g=v(y);return g&&at.has(g)?g:null}return null})(c.callee,n),i=a.key?.name??"";if(!p||!i||Er.has(i.toLowerCase())||o.has(i)||l.has(i))continue;let{line:f,column:m}=e.locator.location(b(a));u.push({filePath:e.filePath,ruleName:ue,message:xr.test(i)?`${p} '${i}' is used for component UI state, which adds stream overhead to local state updates.`:`${p} '${i}' is acting as a local event bus, which makes component interactions harder to trace.`,line:f,column:m,severity:"warn",fix:E[ue],codeExample:R[ue]});}return u.length?u:null});var Me="rxjs-prefer-toSignal-for-template-state",lt=new Set(["Observable","Subject","BehaviorSubject","ReplaySubject","AsyncSubject"]),Sr=new Set(["destroy$","destroyed$","unsub$","teardown$","dispose$"]),ut=createAnyAngularClassRule(Me,(t,e)=>{if(t.metadata?.type!=="Component")return null;let n=e.crossRef?.templateReferences;if(n===void 0)return null;let o=w(t.node),l=[];for(let u of o){if(u.type!=="PropertyDefinition")continue;let a=u.key?.name??"";if(!a||!a.endsWith("$")||Sr.has(a.toLowerCase())||(function(f){let m=f.modifiers,d=f.decorators??(Array.isArray(m)?m.filter(h=>h.type==="Decorator"):void 0);return Array.isArray(d)&&d.some(h=>{let y=s(h.expression);return (y?.type==="CallExpression"?j(y):y?.type==="Identifier"?y.name:null)==="Output"})})(u))continue;let c=a.slice(0,-1);if(!n.has(a)&&!n.has(c)||!(function(f){if(lt.has((function(y){let g=y.typeAnnotation,S=s(g?.typeAnnotation);if(!S||S.type!=="TSTypeReference"&&S.type!=="TypeReference")return "";let A=S.typeName??S.name;if(typeof A=="string")return A;if(A&&typeof A=="object"){if(A.type==="Identifier")return A.name??"";if(A.type==="TSQualifiedName")return s(A.right)?.name??""}return ""})(f)))return true;let m=s(f.value??f.initializer);if(!m)return false;let d=j(m);if(d==="toSignal"||d==="signal"||d==="computed")return false;if(m.type==="NewExpression"){let y=s(m.callee),g=y?.type==="Identifier"?y.name:v(y);return !!g&&lt.has(g)}let h=[m];for(;h.length>0;){let y=s(h.pop());if(y){if(y.type==="CallExpression"&&j(y)==="pipe")return true;for(let g of N(y))h.push(g);}}return false})(u))continue;let{line:p,column:i}=e.locator.location(b(u));l.push({filePath:e.filePath,ruleName:Me,message:`Observable "${a}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:p,column:i,severity:"warn",fix:E[Me]});}return l.length?l:null},{requires:{projectContext:true,htmlAst:true}});var Pe="toSignal-require-initialValue",ct=createCallExpressionRule(Pe,(t,e)=>{if(!O(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],n=r[1]?s(r[1]):null;if(!n||n.type!=="ObjectExpression"||!(function(o){let l=W(o,"initialValue");if(l&&!Ee(l.value))return true;let u=W(o,"requireSync");return !!u&&ge(u.value)})(n)){let{line:o,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:Pe,message:"toSignal() can emit undefined before the observable produces a value.",line:o,column:l,severity:"warn",fix:E[Pe]}}return null});var Cr=new Set(["set","update","mutate"]),Nr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame","then","catch","finally","subscribe"]),pt=createCallExpressionRule("signal-prefer-computed-over-sync-effect",(t,e)=>{if(!O(t.callee,"effect"))return null;let r=G(t),n=r?K(r):null;if(!n)return null;let{hasRead:o,hasWrite:l,hasAsync:u,hasLinked:a,firstWrite:c}=(function(f,m){let d={hasRead:false,hasWrite:false,hasAsync:false,hasLinked:false,firstWrite:null},h=[f];for(;h.length;){let y=s(h.pop());if(y){if((y.type==="AwaitExpression"||y.type==="YieldExpression")&&(d.hasAsync=true),y.type==="CallExpression"){let g=j(y);g&&Nr.has(g)&&(d.hasAsync=true),g==="linkedSignal"&&(d.hasLinked=true),(function(S){let A=s(S);if(!A||A.type!=="CallExpression")return false;let M=s(A.callee);return x(M)&&Cr.has(v(M)||"")})(y)?(d.hasWrite=true,d.firstWrite||(d.firstWrite=y)):(function(S,A,M){let P=s(S);if(!P||P.type!=="CallExpression"||Array.isArray(P.arguments)&&P.arguments.length>0)return false;let I=s(P.callee);if(!I)return false;if(A.typeChecker)try{let T=q(I,A);if(T){let D=A.typeChecker.getTypeOfSymbolAtLocation(T,T.valueDeclaration);if(D&&A.typeChecker.typeToString(D).includes("Signal"))return !0}}catch{}return x(I)?s(I.object)?.type==="ThisExpression":M&&I.type==="Identifier"})(y,m,true)&&(d.hasRead=true);}for(let g of N(y))h.push(g);}}return d})(n,e);if(!l||!o||u||a)return null;let{line:p,column:i}=e.locator.location(b(c||t));return {filePath:e.filePath,ruleName:"signal-prefer-computed-over-sync-effect",message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:p,column:i,severity:"warn",fix:E["signal-prefer-computed-over-sync-effect"]}},{requires:{typeChecker:true}});var ft=new Set(["afterRender","afterNextRender"]),wr=/\bafterNextRender\s*\(|\bafterRender\s*\(/,ce=new Map,mt=createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!O(t.callee,"untracked")||(function(o,l){let u=l.sourceText??l.fileContent;if(typeof u=="string"&&!wr.test(u))return false;let a=o.parent;for(;a;){if(a.type==="CallExpression"&&ft.has(j(a)))return true;a=a.parent;}let c=b(o);return (function(p){let i=ce.get(p.filePath);if(i!==void 0)return i;let f=p.program;return i=f?(function(m){let d=[],h=m.body,y=Array.isArray(h)?[...h]:[m];for(;y.length;){let g=s(y.pop());if(g){if(g.type==="CallExpression"&&ft.has(j(g))){let S=s(g.arguments?.[0]);if(S){let A=b(S),M=S.end??S.span?.end??b(S);M>A&&d.push([A,M]);}}for(let S of N(g))y.push(S);}}return d})(f):[],ce.size>=300&&ce.clear(),ce.set(p.filePath,i),i})(l).some(([p,i])=>c>=p&&c<i)})(t,e))return null;let{line:r,column:n}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:n,severity:"warn",fix:E["signal-avoid-untracked-overuse"]}});var pe="prefer-inject-over-constructor-di",Pr=new Set(["http","router","route","cdr","cdref","changedetectorref","injector","ngzone","zone","renderer","renderer2","elementref","el","document","platform","location","dialog","snack","toast","store","facade","logger","translate","i18n","auth","api","client","matdialog","overlay","breakpointobserver","snackbar","matsnackbar","bottomsheet","matbottomsheet","clipboard","directionality","focusmonitor","mediamatcher","viewportruler","scrolldispatcher","dragdrop","liveannouncer","activatedroute","fb","firestore","angularfire","formbuilder","titleservice","metaservice","title","meta","sanitizer","domsanitizer","compiler","applicationref","componentfactoryresolver","viewcontainerref","templateref","destroyref"]),Or=new Set(["data","config","options","opts","params","payload","input","value","values","items","item","context","ctx","model","vm","state","initialstate","result","name","id","label","text","title","message","url","path","index","count","size","length","width","height","color","type","key","mode","flag","enabled","disabled","visible","hidden"]),Tr=["Service","Facade","Store","Client","Repository","Adapter","Manager","Controller","Provider","Registry","Logger","Router","ActivatedRoute","ChangeDetectorRef","DestroyRef","Injector","NgZone","Renderer2","ElementRef","HttpClient","ViewContainerRef","TemplateRef","ComponentFactoryResolver","ApplicationRef","MatDialog","MatDialogRef","MatSnackBar","MatBottomSheet","Overlay","OverlayRef","BreakpointObserver","Clipboard","FocusMonitor","MediaMatcher","ScrollDispatcher","DragDrop","LiveAnnouncer","Directionality","ViewportRuler","FormBuilder","DomSanitizer","Title","Meta","Dispatcher","Gateway","Handler","Interceptor","Guard","Resolver","Factory","Strategy","Validator"],Ir=new Set(["string","number","boolean","symbol","bigint","any","unknown","void"]),dt=createAnyAngularClassRule(pe,(t,e)=>{let r=U(w(t.node));if(!r)return null;let n=ee(r.value??r).filter(a=>(function(c,p){let i=s(c);if(!i)return false;if(Array.isArray(i.decorators)&&i.decorators.length>0||i.accessibility||i.readonly)return true;if(p.typeChecker){let d=q(c,p);if(d&&Ue(d))return true}let f=(F(c)||"").toLowerCase().trim();if(!f||Or.has(f))return false;if(Pr.has(f))return true;let m=($(c)||"").trim();return !(!m||Ir.has(m.toLowerCase()))&&Tr.some(d=>m.endsWith(d))})(a,e));if(n.length===0)return null;let{line:o,column:l}=e.locator.location(b(r)),u=n.map(a=>`${F(a)}: ${$(a)}`).join(", ");return {filePath:e.filePath,ruleName:pe,message:`Constructor dependency injection makes class setup less composable than inject().${u?` Offending params: ${u}.`:""}`,line:o,column:l,severity:"warn",fix:E[pe],codeExample:R[pe]}},{requires:{typeChecker:true}});var fe="signal-prefer-input-signal";function Dr(t){let e=s(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var yt=createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=[],o=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let u=s(l);if(u&&(u.type==="PropertyDefinition"||u.type==="AccessorProperty")&&Array.isArray(u.decorators)&&u.decorators.some(Dr)){let a=b(u),{line:c,column:p}=e.locator.location(a),i=s(u.key),f=(i?.type==="Identifier"?i.name:i?.type==="Literal"?String(i.value):"")||"(unknown)",m=`'${f}' uses @Input(), which keeps this input outside Angular's signal graph.`;o&&(m+=" Standalone declarations benefit most from signal inputs."),n.push({filePath:e.filePath,ruleName:fe,message:m,line:c,column:p,severity:o?"error":"warn",fix:E[fe],codeExample:R[fe]});}}return n.length>0?n:null},{requires:{projectContext:true}});var me="signal-prefer-output-function",ht=createAnyAngularClassRule(me,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=[];for(let o of r){let l=s(o);if(l&&(l.type==="PropertyDefinition"||l.type==="AccessorProperty")&&Array.isArray(l.decorators)&&l.decorators.some(u=>{let a=s(u.expression??u);if(!a)return false;if(a.type==="Identifier")return a.name==="Output";if(a.type==="CallExpression"){let c=s(a.callee);return c?.type==="Identifier"&&c.name==="Output"}return false})&&(function(u,a){let c=s(u.value);if(c?.type==="NewExpression"){let i=s(c.callee);if(i?.type==="Identifier"&&i.name==="EventEmitter")return true}let p=s(u.typeAnnotation);if(p&&$(p).includes("EventEmitter"))return true;if(a.typeChecker){let i=q(u,a);if(i&&(typeof i.getName=="function"?i.getName():"").includes("EventEmitter"))return true}return false})(l,e)){let u=b(l),{line:a,column:c}=e.locator.location(u),p=s(l.key),i=(p?.type==="Identifier"?p.name:p?.type==="Literal"?String(p.value):"")||"(unknown)";n.push({filePath:e.filePath,ruleName:me,message:`'${i}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:a,column:c,severity:"warn",fix:E[me],codeExample:R[me]});}}return n.length>0?n:null},{requires:{typeChecker:true}});var de="signal-prefer-model";function gt(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let n=s(r.expression??r);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(n.type==="CallExpression"){let o=s(n.callee);return o?.type==="Identifier"&&o.name===e}return false})}function Et(t,e){let r=s(t.value);if(!r||r.type!=="CallExpression")return false;let n=s(r.callee);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(x(n)){let o=s(n.object);return o?.type==="Identifier"&&o.name===e}return false}var xt=createAnyAngularClassRule(de,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),n=new Map,o=new Map;for(let u of r){let a=s(u);if(!a||a.type!=="PropertyDefinition"&&a.type!=="AccessorProperty")continue;let c=(function(p){let i=s(p.key);return i?i.type==="Identifier"?i.name??null:i.type==="Literal"?String(i.value):null:null})(a);c&&((gt(a,"Input")||Et(a,"input"))&&n.set(c,a),(gt(a,"Output")||Et(a,"output"))&&o.set(c,a));}let l=[];for(let[u,a]of o){if(!u.endsWith("Change"))continue;let c=u.slice(0,-6),p=n.get(c);if(p){let i=b(p),{line:f,column:m}=e.locator.location(i);l.push({filePath:e.filePath,ruleName:de,message:`The \`${c}\` / \`${u}\` pair implements two-way binding with extra wiring that model() avoids.`,line:f,column:m,severity:"warn",fix:E[de],codeExample:R[de]});}}return l.length>0?l:null});var _r=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Oe="template-prefer-control-flow",bt=createTemplateAttributeRule(Oe,(t,e)=>{var r;let n=(r=t.name,_r.get(r)??null);if(!n)return null;let o=k(e,t.sourceSpan.start),{line:l,column:u}=e.locator.location(o);return {filePath:e.filePath,ruleName:Oe,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${n}\` control flow benefits.`,line:l,column:u,severity:"error",fix:E[Oe]}},{requires:{htmlAst:true}});var St=new WeakMap,vt=createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,n,o=(function p(i){let f=s(i);if(!f)return null;if(f.type==="BinaryExpression"&&f.operator==="|"){let m=s(f.right);return m?.type==="Identifier"&&m.name==="async"?s(f.left):p(f.left)}return null})(t.expression),l=o?(function p(i,f=0){if(!i||f>10)return null;if(i.type==="Identifier")return i.name;if(i.type==="ThisExpression")return "this";if(i.type==="Literal"){let m=i.value;return m===null?"null":typeof m=="string"||typeof m=="number"||typeof m=="boolean"||typeof m=="bigint"?String(m):null}if(i.type==="CallExpression"){let m=p(i.callee,f+1),d=(Array.isArray(i.arguments)?i.arguments:[]).map(h=>p(h,f+1)??"?");return `${m}(${d.join(",")})`}if(x(i)){let m=p(i.object,f+1),d=v(i);if(m&&d)return `${m}.${d}`}if(i.type==="UnaryExpression")return `${i.operator}${p(i.argument,f+1)}`;if(i.type==="ConditionalExpression")return `${p(i.test,f+1)}?${p(i.consequent,f+1)}:${p(i.alternate,f+1)}`;if(i.type==="OptionalExpression"||i.type==="ChainExpression")return p(i.expression,f+1);if(i.type==="LogicalExpression"){let m=p(i.left,f+1),d=p(i.right,f+1);if(m&&d)return `${m}${i.operator}${d}`}if(i.type==="BinaryExpression"&&i.operator!=="|"){let m=p(i.left,f+1),d=p(i.right,f+1);if(m&&d)return `${m}${i.operator}${d}`}if(i.type==="ArrayExpression")return `[${(i.elements??[]).map(d=>p(d,f+1)??"?").join(",")}]`;if(i.type==="ObjectExpression")return `{${(i.properties??[]).map(d=>{let h=d.key?p(d.key,f+1):"?",y=d.value?p(d.value,f+1):"?";return `${h}:${y}`}).join(",")}}`;if(i.type==="TemplateLiteral")return "`tmpl`";if(i.type==="AssignmentExpression"){let m=p(i.left,f+1),d=p(i.right,f+1);if(m&&d)return `${m}${i.operator}${d}`}return null})(o):null;if(!l)return null;let u=(r=e.template,n=r?.templateStartOffset,`${e.filePath}@${typeof n=="number"&&Number.isFinite(n)?n:0}`),a=St.get(e);a||(a=new Map,St.set(e,a));let c=a.get(u);if(c||(c=new Set,a.set(u,c)),c.has(l)){let p=k(e,t.sourceSpan.start),{line:i,column:f}=e.locator.location(p);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:i,column:f,severity:"warn",fix:E["template-no-async-pipe-duplication"]}}return c.add(l),null},{requires:{htmlAst:true}});var Fr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),qr=new Set(["xdescribe","xit","xtest","xcontext"]);function At(t){return t.type==="Identifier"?t.name??null:null}var Ct=createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let n;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let o=s(t.callee);if(!o)return null;let l=(n=At(o)||(function(i){if(i.type==="MemberExpression"||i.type==="StaticMemberExpression"||i.type==="OptionalMemberExpression"){let f=s(i.object),m=i.property?.name??"",d=(f?.type==="Identifier"?f.name:"")??"";return d?`${d}.${m}`:null}return null})(o))&&Fr.has(n)?n:null;if(!l){if(At(o)==="pending"){let i=b(t),{line:f,column:m}=e.locator.location(i);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:f,column:m,severity:"error",fix:E["spec-no-focused-test"]}}return null}let u=b(t),{line:a,column:c}=e.locator.location(u),p=qr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:p,line:a,column:c,severity:"error",fix:E["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Nt(){C(qe,"correctness"),C(He,"correctness"),C(ze,"correctness"),C(Ve,"correctness"),C(Xe,"performance"),C(Ge,"performance"),C(Ze,"performance"),C(Qe,"performance"),C(Je,"performance"),C(et,"security"),C(tt,"security"),C(rt,"ssr"),C(nt,"ssr"),C(ot,"reactivity"),C(it,"reactivity"),C(st,"reactivity"),C(ut,"reactivity"),C(ct,"reactivity"),C(pt,"reactivity"),C(mt,"reactivity"),C(dt,"modern-api"),C(yt,"modern-api"),C(ht,"modern-api"),C(xt,"modern-api"),C(bt,"template"),C(vt,"template"),C(Ct,"testing");}Nt(),configureRuleExecutor(ke,Ie),process.on("message",t=>{Xr(t);});var Xr=async t=>{let e=[],r=createTypeAwareAnalysisContext(t.rootDir,t.files,t.parserOptions,{buildProjectContext:t.buildProjectContext,programRootFiles:t.programRootFiles});try{await r.warmup();let n=groupTasksByFile(t.tasks),o=await Yr(Array.from(n),Math.max(1,t.fileConcurrency??1),async([l,u])=>{let a=performance.now();try{let c=await executeBatchedTasks(u,r);return Rt(l,u.length,c,performance.now()-a),c}catch{return Rt(l,u.length,[],performance.now()-a),[]}finally{r.evict(l);}});e.push(...o.flat()),process.send?.({kind:"complete",results:e});}catch(n){process.send?.({kind:"error",error:n instanceof Error?n.message:String(n)});}finally{r.dispose(),process.disconnect?.();}};async function Yr(t,e,r){let n=Array(t.length),o=0,l=Math.min(e,t.length);return await Promise.all(Array.from({length:l},async()=>{for(;o<t.length;){let u=o++;n[u]=await r(t[u]);}})),n}var Rt=(t,e,r,n)=>{process.send?.(Gr(t,e,r,n));},Gr=(t,e,r,n)=>{let o=0,l=0;for(let u of r)for(let a of u.failures)a.severity==="error"?o++:a.severity==="warn"&&l++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:o+l,errorCount:o,warningCount:l,duration:n,typeAware:true}};//# sourceMappingURL=type-aware-worker.js.map
});`};var Ge;function g(t){let e=t;for(;e;){let r=e.type;if(r==="ChainExpression"||r==="TSNonNullExpression"||r==="TSAsExpression"||r==="ParenthesizedExpression"||r==="TSInstantiationExpression"||r==="TSSatisfiesExpression"){e=e.expression;continue}break}return e??null}function C(t){let e=t?.type;return e==="MemberExpression"||e==="StaticMemberExpression"||e==="OptionalMemberExpression"}function N(t){if(!t)return "";let e=t.property;return e?t.computed?e.type==="Literal"&&typeof e.value=="string"?e.value:"":e.name??"":""}function b(t){return t?t.start??t.span?.start??0:0}function T(t,e){let r=g(t);return !!r&&(r.type==="Identifier"?(r.name??"")===e:!!C(r)&&N(r)===e)}function Ne(t){let e=g(t);if(!e||e.type!=="CallExpression")return "";let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}function te(t){let e=g(t?.callee);return !!C(e)&&N(e)==="subscribe"}function Y(t,e){if(!t||t.type!=="ObjectExpression")return null;let r=t.properties;if(!Array.isArray(r))return null;for(let n of r){if(!n||n.type!=="Property")continue;let a=n.key;if((a?.type==="Identifier"?a.name:a?.type==="Literal"&&typeof a.value=="string"?a.value:"")===e)return n}return null}function Re(t){let e=g(t);return !!(e&&e.type==="Literal"&&e.value===true)}function we(t){let e=g(t);return !e||e.type==="Literal"&&e.value===null||e.type==="Identifier"&&e.name==="undefined"}var Vt=new Set(["parent","span","loc","range","start","end","type"]);function*O(t){if(t&&typeof t=="object"){if(Array.isArray(t)){for(let e of t)e&&typeof e=="object"&&(yield e);return}for(let e in t){if(Vt.has(e))continue;let r=t[e];if(r)if(Array.isArray(r))for(let n of r)n&&typeof n=="object"&&(yield n);else typeof r=="object"&&r.type&&(yield r);}}}function Me(t){if(!t)return false;if(t.kind==="constructor")return true;let e=t.key;return e?.type==="Identifier"&&e.name==="constructor"||e?.type==="Literal"&&e.value==="constructor"}function H(t){if(!t)return false;let e=t.type;return e==="MethodDefinition"||e==="TSAbstractMethodDefinition"||e==="ClassMethod"||e==="MethodDeclaration"}function Qe(t){for(let e of t)if(e&&H(e)&&Me(e))return e;return null}function z(t){return t?(t.value??t)?.body??null:null}function Ze(t){let e=t?.key;return e?e.type==="Identifier"?e.name??"<method>":e.type==="Literal"&&typeof e.value=="string"?e.value:"<method>":"<method>"}function F(t){if(!t)return [];let e=t.body;if(Array.isArray(e))return e;if(e&&typeof e=="object"&&"body"in e){let r=e.body;if(Array.isArray(r))return r}return []}function Kt(t){let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=e.arguments;if(!Array.isArray(r)||r.length<2)return false;let n=g(r[1]);if(!n||n.type!=="ObjectExpression")return false;let a=Y(n,"injector");if(a&&!we(a.value))return true;let s=Y(n,"manualCleanup");return !!(s&&Re(s.value))}function Je(t){if(!t)return [];let e=[],r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&T(n.callee,"effect")&&!Kt(n)&&e.push(n),O(n)))r.push(a);}return e}var Xt=new Set(["takeUntilDestroyed","takeUntil","take","first","takeWhile"]);function Gt(t){let e=g(t);if(!e)return "";if(e.type==="Identifier")return e.name??"";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"?r.name??"":C(r)?N(r):""}return C(e)?N(e):""}function Yt(t){let e=t.arguments;if(!Array.isArray(e))return false;for(let r of e)if(Xt.has(Gt(r)))return true;return false}function re(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)==="pipe"&&Yt(r))return true;e=n?.object;}return false}function I(t,e){return e}var Qt=new Set(["get","post","put","patch","delete","head","options","jsonp","request"]),Zt=new Set(["http","httpClient","_http","_httpClient"]),Jt=["get","fetch","load","save","create","update","delete","remove","submit","send","post","put","patch","upload","download"];function ne(t){let e=t;for(;e;){let r=g(e);if(!r||r.type!=="CallExpression")break;let n=g(r.callee);if(!C(n))break;if(N(n)!=="pipe")return r;e=n?.object;}return null}function ie(t){if(!t)return false;let e=g(t);if(!e||e.type!=="CallExpression")return false;let r=g(e.callee);if(!C(r))return false;let n=N(r);if(!n)return false;let a=g(r?.object),s=Array.isArray(e.arguments)?e.arguments:[];if(Qt.has(n)&&C(a)){let c=N(a);if(Zt.has(c))return true}if(s.length>0){let c=n.toLowerCase();for(let f of Jt)if(c.startsWith(f)&&n.length>f.length)return true}return false}var Ye=false;function Pe(){if(!Ye){try{Ge=Ht("typescript");}catch{}Ye=true;}return Ge}function et(t,e){if(!t||!e.typeChecker)return;let r=Pe();if(r)try{!e.sourceFile&&e.fileContent&&(e.sourceFile=r.createSourceFile(e.filePath,e.fileContent,r.ScriptTarget.Latest,!0));let n=e.sourceFile;if(!n)return;let a=(function(s,c,f){if(c<s.getStart()||c>=s.getEnd())return;let d=s;for(;;){let p=f.forEachChild(d,i=>{if(c>=i.getStart()&&c<i.getEnd())return i});if(!p)break;d=p;}return d})(n,b(t),r);return a?e.typeChecker.getSymbolAtLocation(a):void 0}catch{return}}function D(t){if(t.sourceFile)return t.sourceFile;if(!t.fileContent)return;let e=Pe();if(e)return t.sourceFile=e.createSourceFile(t.filePath,t.fileContent,e.ScriptTarget.Latest,true),t.sourceFile}var ee=new Map;function oe(t){let e=ee.get(t.filePath);if(e!==void 0)return e;let r=(function(n){let{typeChecker:a,angularTypes:s}=n;if(!a||!s)return false;let c=Pe(),f=D(n);if(!c||!f)return false;for(let d of f.statements){if(!c.isClassDeclaration(d)||!c.canHaveDecorators(d))continue;let p=c.getDecorators(d);if(p)for(let i of p){let l=c.isCallExpression(i.expression)?i.expression.expression:i.expression;if(!c.isIdentifier(l)||l.text!=="Component"&&l.text!=="Directive")continue;let o=a.getSymbolAtLocation(l),u=o&&o.flags&c.SymbolFlags.Alias?a.getAliasedSymbol(o):o;if(s.isFromAngularCore(u))return true}}return false})(t);return ee.size>=1024&&ee.clear(),ee.set(t.filePath,r),r}function Q(t){if(!t)return false;let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib.dom"))return true;return false}var se="component-no-manual-detect-changes",nr=new Set(["detectChanges","markForCheck"]),tt=createAnyAngularClassRule(se,(t,e)=>{let r,n=t.node,a=(r=analyzeComponent(n),r?.type!=="Component"?{isComponent:false,isOnPush:false}:{isComponent:true,isOnPush:r.changeDetection?.kind==="literal"&&r.changeDetection.value===ChangeDetectionStrategy.OnPush});if(!a.isComponent)return null;let{typeChecker:s,angularTypes:c}=e;if(!s||!c)return null;let f=(function(i,l){let o=D(l);if(!o)return;let u=b(i);for(let m of o.statements)if(M.isClassDeclaration(m)&&m.pos<=u&&u<=m.end)return m})(n,e);if(!f)return null;let d=[],p=i=>{if(M.isCallExpression(i)){let l=(function(o,u,m,y,h){if(!M.isPropertyAccessExpression(o.expression))return null;let E=o.expression.name.text;if(!nr.has(E)||y.isOnPush&&E==="markForCheck")return null;let S=u.getTypeAtLocation(o.expression.expression);if(!m.isChangeDetectorRef(S))return null;let{line:A,column:v}=h.locator.location(o.getStart());return {filePath:h.filePath,ruleName:se,message:y.isOnPush?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${E}) can hide state-flow bugs and make rendering harder to predict.`,line:A,column:v,severity:y.isOnPush?"warn":"error",fix:x[se],codeExample:P[se]}})(i,s,c,a,e);l&&d.push(l);}M.forEachChild(i,p);};return p(f),d.length>0?d:null});var Te="signal-no-side-effects-in-computed",or=new Set(["set","update","mutate"]),ar=new Set(["next","complete","error"]),rt=createCallExpressionRule(Te,(t,e)=>{var r,n;let a,s;if(!T(t.callee,"computed"))return null;let{typeChecker:c,angularTypes:f}=e;if(!c||!f)return null;let d=(function(l,o){var u;let m,y=(u=l).sourceFile?u.sourceFile:u.fileContent?(u.sourceFile=M.createSourceFile(u.filePath,u.fileContent,M.ScriptTarget.Latest,true),u.sourceFile):void 0;if(!y)return;let h=E=>{if(!m){if(M.isCallExpression(E)&&E.getStart()===o){m=E;return}M.forEachChild(E,h);}};return h(y),m})(e,b(t));if(!d)return null;let p=d.arguments[0];if(!p||!(M.isArrowFunction(p)||M.isFunctionExpression(p)))return null;let i=(r=p.body,n={typeChecker:c,angularTypes:f},(s=l=>{var o,u,m,y;if(a)return;let h=(o=l,u=n,M.isBinaryExpression(o)&&(m=o.operatorToken.kind)>=M.SyntaxKind.FirstAssignment&&m<=M.SyntaxKind.LastAssignment?Oe(o.left)?{node:o,kind:"write"}:void 0:M.isPostfixUnaryExpression(o)||M.isPrefixUnaryExpression(o)?(o.operator===M.SyntaxKind.PlusPlusToken||o.operator===M.SyntaxKind.MinusMinusToken)&&Oe(o.operand)?{node:o,kind:"write"}:void 0:M.isDeleteExpression(o)&&Oe(o.expression)?{node:o,kind:"write"}:M.isCallExpression(o)?(function(E,S){if(!M.isPropertyAccessExpression(E.expression))return;let A=E.expression.name.text,v=E.expression.expression,w=S.typeChecker.getTypeAtLocation(v);return or.has(A)&&S.angularTypes.isWritableSignal(w)?{node:E,kind:"write"}:ar.has(A)&&S.angularTypes.isSubjectLike(w)||S.angularTypes.isHttpClient(w)?{node:E,kind:"effect"}:void 0})(o,u):void 0);if(h){a=h;return}y=l,M.isArrowFunction(y)||M.isFunctionExpression(y)||M.isFunctionDeclaration(y)||M.isMethodDeclaration(y)||M.isGetAccessorDeclaration(y)||M.isSetAccessorDeclaration(y)||M.forEachChild(l,s);})(r),a);return i?(function(l,o,u){let m=l.node.getStart(),{line:y,column:h}=u.locator.location(m||b(o));return {filePath:u.filePath,ruleName:Te,message:l.kind==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:y,column:h,severity:"error",fix:x[Te]}})(i,t,e):null},{requires:{typeChecker:true}});function Oe(t){return M.isPropertyAccessExpression(t)||M.isElementAccessExpression(t)}var ke="signal-effect-must-be-destroy-scoped",nt=createAnyAngularClassRule(ke,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let n=[];for(let a of r)a&&H(a)&&!Me(a)&&n.push(...(function(s,c){let f=z(s);if(!f)return [];let d=Ze(s),p=[];for(let i of Je(f))(function(l){if(l.type!=="CallExpression")return false;let o=g(l.callee);return !!o&&(o.type==="Identifier"?o.name==="effect":!!C(o)&&N(o)==="effect")})(i)&&!(function(l){let o=g((Array.isArray(l.arguments)?l.arguments:[])[1]);if(!o||o.type!=="ObjectExpression")return false;for(let u of Array.isArray(o.properties)?o.properties:[]){let m=g(u);if(m?.type==="Property"){let y=g(m.key),h=y?.type==="Identifier"?y.name:N(y)||"";if(h==="injector")return true;if(h==="manualCleanup"){let E=g(m.value);if(E?.type==="Literal"&&E.value===true)return true}}}return false})(i)&&p.push((function(l,o,u){let m=b(l),{line:y,column:h}=u.locator.location(m);return {filePath:u.filePath,ruleName:ke,message:`effect() inside "${o}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:h,severity:"error",fix:x[ke]}})(i,d,c));return p})(a,e));return n.length>0?n:null});var le="rxjs-no-nested-subscribe",ur=new Set(["next","error","complete"]),cr=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function De(t){if(t.type!=="CallExpression")return false;let e=g(t.callee);return !!C(e)&&N(e)==="subscribe"}function it(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var ot=createCallExpressionRule(le,(t,e)=>{if(!De(t))return null;for(let r of (function(n){if(!De(n))return [];let a=Array.isArray(n.arguments)?n.arguments:[];if(a.length===0)return [];let s=g(a[0]);if(s?.type==="ObjectExpression"){if(s.type!=="ObjectExpression")return [];let f=[];for(let d of Array.isArray(s.properties)?s.properties:[]){let p=g(d);if(p?.type==="Property"&&ur.has((function(i){let l=g(i.key);return l?l.type==="Identifier"?l.name:N(l)||"":""})(p))){let i=g(p.value);it(i)&&f.push(i);}}return f}let c=[];for(let f=0;f<Math.min(a.length,3);f++){let d=g(a[f]);it(d)&&c.push(d);}return c})(t)){let n=g(r.body);if(n&&(function(a){let s=[a];for(;s.length>0;){var c;let f=g(s.pop());if(f){if(f!==a&&De(f))return true;if(!(f!==a&&(c=f).type&&cr.has(c.type)))for(let d of O(f))s.push(d);}}return false})(n))return (function(a,s){let c=b(a),{line:f,column:d}=s.locator.location(c);return {filePath:s.filePath,ruleName:le,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:f,column:d,severity:"error",fix:x[le],codeExample:P[le]}})(t,e)}return null});var ue="prefer-on-push-component-change-detection";function ce(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function Ie(t){return t.replace(/\\/g,"/")}var at=createComponentRule(ue,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(n){if(!n||typeof n!="object")return false;let{kind:a,value:s}=n;return a!=="non-literal"&&(a==="literal"?s!==ChangeDetectionStrategy.OnPush:a==="missing")})(r.changeDetection)?null:(function(n,a){let s,c,f,d,p=(s=n.metadata??{},c=n.node,ce(s,"decoratorStart")??ce(s,"start")??ce(c,"start")??ce(n,"start")??0),{line:i,column:l}=a.locator.location(p),o=(f=n.metadata,typeof(d=f?.className)=="string"?d:"AnonymousComponent"),u=(function(m,y){if(!y.project)return null;let h=m.metadata,E=h?.className;if(typeof E!="string"||!E)return null;let S=Ie(y.filePath),{ngModuleMap:A,classToFile:v}=y.project;for(let[w,L]of A){if(L.isStandalone||!L.declarations.has(E))continue;let k=v.get(E);if(!k||Ie(k)===S)return {moduleName:(Ie(w).split("/").pop()??w).replace(/\.ts$/,""),siblingDeclarationCount:Math.max(0,L.declarations.size-1)}}return null})(n,a);return {filePath:a.filePath,ruleName:ue,message:(function(m,y){let h=`Component '${m}' uses default change detection, which can re-render more often than needed.`;if(!y)return h;let{moduleName:E,siblingDeclarationCount:S}=y;return S===0?`${h} It is declared in '${E}'.`:`${h} It is declared in '${E}' alongside ${S} other declaration${S===1?"":"s"}.`})(o,u),line:i,column:l,severity:"error",fix:x[ue],codeExample:P[ue]}})(t,e)},{requires:{projectContext:true}});var Le="template-no-call-expression",gr=new Set(["translate","$localize","$any"]),yr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function st(t){let e=g(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var lt=createTemplateExpressionRule(Le,(t,e)=>(function(r,n){let a=r?[r]:[];for(;a.length>0;){let s=g(a.pop());if(s){if(st(s)&&!(function(c){let f=g(c);if(!f||!st(f))return false;let d=g(f.callee);if(!d)return false;if(d.type==="Identifier")return gr.has(d.name);if(!C(d))return false;let p=N(d);return !!p&&yr.has(p)})(s)){if((function(f){let d=g(f);return Array.isArray(d?.arguments)?d.arguments:[]})(s).length>0)return true;let c=(function(f){let d=g(f);if(!d)return "";let p=g(d.callee);return p?p.type==="Identifier"?p.name??"":C(p)?N(p):"":""})(s);if(c&&!(function(f,d){if(d.crossRef?.signalMembers?.has(f))return true;let{typeChecker:p,angularTypes:i,crossRef:l}=d;if(!p||!i||!l?.componentPath)return false;let o=(function(u,m,y){let h=y.getProgram?.(),E=h?.getSourceFile(m);if(!E)return;let S=E.statements.find(M.isClassDeclaration);if(!S)return;let A=y.getTypeAtLocation(S),v=y.getPropertyOfType(A,u);if(!v)return;let w=v.valueDeclaration??v.declarations?.[0];if(w)return y.getTypeOfSymbolAtLocation(v,w)})(f,l.componentPath,p);return !!o&&i.isSignal(o)})(c,n))return true}for(let c of O(s))a.push(c);}}return false})(t.expression,e)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:s,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:Le,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:s,column:c,severity:"error",fix:x[Le]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function ut(t,e,r,n){let a=I(t,e.sourceSpan.start),{line:s,column:c}=t.locator.location(a);return {filePath:t.filePath,ruleName:r,message:n,line:s,column:c,severity:"error",fix:x[r]}}var ct=createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let n of t.attributes)n.name==="*ngFor"&&!(function(a){return !!a.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(n.value??"")&&r.push(ut(e,n,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let n of t.blocks)n.name!=="for"||n.parameters.some(a=>{let s=a.expression?.trim()??"";return !!s&&!!/^track\b/.test(s)&&s.replace(/^track\b/,"").trim().length>0})||r.push(ut(e,n,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var je="template-no-object-literal-binding",pt=createTemplateExpressionRule(je,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ObjectExpression")return true;for(let s of O(a))n.push(s);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:s,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:je,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:s,column:c,severity:"warn",fix:x[je]}})(t,e)]:null,{requires:{htmlAst:true}});var Fe="template-no-array-literal-binding",ft=createTemplateExpressionRule(Fe,(t,e)=>(function(r){let n=r?[r]:[];for(;n.length>0;){let a=g(n.pop());if(a){if(a.type==="ArrayExpression")return true;for(let s of O(a))n.push(s);}}return false})(t.expression)?[(function(r,n){let a=I(n,r.sourceSpan.start),{line:s,column:c}=n.locator.location(a);return {filePath:n.filePath,ruleName:Fe,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:s,column:c,severity:"warn",fix:x[Fe]}})(t,e)]:null,{requires:{htmlAst:true}});var _e=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),mt=createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(s){let c=g(s.callee);if(!c)return null;if(c.type==="Identifier"&&c.name)return _e.has(c.name)?c.name:null;if(C(c)){let f=N(c);return f&&_e.has(f)?f:null}return null})(t);if(!r)return null;let{line:n,column:a}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${_e.get(r)} sanitization, which can expose unsafe content.`,line:n,column:a,severity:"error",fix:x["no-bypass-sanitization"]}});var Ar=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),Cr=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,vr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,dt=createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=Ar.get(t.name);if(!r)return null;let n=t.value??"";if(Cr.test(n)||vr.test(n)||t.name==="[style]"&&!/[.(|?]/.test(n))return null;let{line:a,column:s}=e.locator.location(I(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:a,column:s,severity:r.severity,fix:x["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var pe="no-document-access",Rr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),gt=createAnyAngularClassRule(pe,(t,e)=>{let r=F(t.node);if(r.length===0)return null;let{typeChecker:n}=e;if(!n)return null;let a=D(e);if(!a)return null;let s=(function(p){let i=new Set,l=[...p];for(;l.length;){let o=g(l.pop());if(o){if(o.type==="VariableDeclarator"&&o.init){let u=g(o.init);if(u?.type==="CallExpression"&&u.callee&&T(u.callee,"isPlatformBrowser")){let m=o.id??o.key;m?.type==="Identifier"&&m.name&&i.add(m.name);}}if(o.type==="AssignmentExpression"&&o.right){let u=g(o.right);if(u?.type==="CallExpression"&&u.callee&&T(u.callee,"isPlatformBrowser")){let m=g(o.left);if(m&&C(m)&&g(m.object)?.type==="ThisExpression"){let y=m.property?.name;typeof y=="string"&&y&&i.add(y);}}}for(let u of O(o))l.push(u);}}return i})(r),c=[],f=new Set,d=[...r];for(;d.length;){let p=g(d.pop());if(p){if(p.type==="IfStatement"&&p.test){let i=g(p.test);if(i){let l=(function(o,u){let m=[o];for(;m.length;){let y=g(m.pop());if(y){if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformBrowser"))return "browser";if(y.type==="CallExpression"&&y.callee&&T(y.callee,"isPlatformServer"))return "server";if(y.type==="UnaryExpression"&&y.operator==="!"&&y.argument){let h=g(y.argument);if(h?.type==="CallExpression"&&h.callee&&T(h.callee,"isPlatformServer"))return "browser"}if(y.type==="Identifier"&&u.has(y.name))return "browser";for(let h of O(y))m.push(h);}}return null})(i,s);if(l==="browser"){p.alternate&&d.push(p.alternate);continue}if(l==="server"){p.consequent&&d.push(p.consequent);continue}}}if(p.type==="CallExpression"&&p.callee){let i=g(p.callee);if(i&&(T(i,"afterNextRender")||T(i,"afterRender"))){let l=p.arguments??[];for(let o=1;o<l.length;o++)d.push(l[o]);continue}}if(C(p)){let i=(function(o){let u=o;for(;u&&C(u);)u=g(u.object);return u?.type==="Identifier"?u:null})(p),l=i?.name;if(i&&l&&Rr.has(l)&&(function(o,u,m){let y=(function(E,S){let A,v=w=>{if(!A){if(M.isIdentifier(w)&&w.getStart()===S){A=w;return}M.forEachChild(w,v);}};return v(E),A})(u,b(o));if(!y)return false;let h=m.getSymbolAtLocation(y);return Q((h&&h.flags&M.SymbolFlags.Alias?m.getAliasedSymbol(h):h)??void 0)})(i,a,n)){let o=b(i);if(o!==void 0&&!f.has(o)){f.add(o);let{line:u,column:m}=e.locator.location(o);c.push({filePath:e.filePath,ruleName:pe,message:`Direct access to \`${l}\` can run during SSR where browser globals do not exist.`,line:u,column:m,severity:"error",fix:x[pe],codeExample:P[pe]});}}}for(let i of O(p))d.push(i);}}return c.length?c:null},{requires:{typeChecker:true}});var fe="prefer-after-render-over-after-view-init",Mr=new Set(["ngAfterViewInit","ngAfterContentInit"]),ht=createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r}=e;if(!r)return null;let n=(function(s,c){let f=D(c);if(!f)return;let d=b(s);for(let p of f.statements)if(M.isClassDeclaration(p)&&p.pos<=d&&d<=p.end)return p})(t.node,e);if(!n)return null;let a=[];for(let s of n.members){if(!M.isMethodDeclaration(s)||!s.body||!M.isIdentifier(s.name))continue;let c=s.name.text;if(!Mr.has(c)||!(function(p,i){let l=false,o=u=>{if(!l){if(M.isPropertyAccessExpression(u)){if(yt(i.getTypeAtLocation(u.expression))){l=true;return}}else if(M.isElementAccessExpression(u)){if(yt(i.getTypeAtLocation(u.expression))){l=true;return}}else if(M.isIdentifier(u)&&!(function(m){let y=m.parent;return !!y&&!!(M.isPropertyAccessExpression(y)&&y.name===m||M.isQualifiedName(y)&&y.right===m)})(u)){let m=i.getSymbolAtLocation(u);if(Q((m&&m.flags&M.SymbolFlags.Alias?i.getAliasedSymbol(m):m)??void 0)){l=true;return}}M.forEachChild(u,o);}};return o(p),l})(s.body,r))continue;let{line:f,column:d}=e.locator.location(s.getStart());a.push({filePath:e.filePath,ruleName:fe,message:`\`${c}\` contains DOM access that can run before browser-only APIs are safe.`,line:f,column:d,severity:"warn",fix:x[fe],codeExample:P[fe]});}return a.length?a:null},{requires:{typeChecker:true}});function yt(t){let e=t.aliasSymbol??t.symbol;return !!e&&Q(e)}var me=new Map;function Be(t){let e=D(t);if(!e)return false;for(let r of e.statements)if(M.isClassDeclaration(r))for(let n of r.members){if(!M.isMethodDeclaration(n)||!n.name||!M.isIdentifier(n.name)||n.name.text!=="ngOnDestroy"||!n.body)continue;let a=false,s=c=>{if(!a){if(M.isCallExpression(c)&&M.isPropertyAccessExpression(c.expression)&&c.expression.name.text==="unsubscribe"&&c.arguments.length===0){a=true;return}M.forEachChild(c,s);}};if(s(n.body),a)return true}return false}var xt=createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{if(!oe(e)||!te(t))return null;let r=g(t.callee),n=C(r)?r?.object:null;if(n&&re(n)||ie(ne(n))||(function(f){let d=me.get(f.filePath);if(d!==void 0)return d;let p=Be(f);return me.size>=500&&me.clear(),me.set(f.filePath,p),p})(e))return null;let a=b(t),{line:s,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:s,column:c,severity:"error",fix:x["rxjs-require-takeUntilDestroyed"]}},{requires:{typeChecker:true}});var de=new Map,ge="rxjs-no-subscribe-in-component",Et=createCallExpressionRule(ge,(t,e)=>{if(!oe(e)||!te(t)||(function(f){let d=g(f.callee);if(!d||!C(d))return false;let p=g(d.object);if(!p)return false;if(p.type==="CallExpression"){let i=g(p.callee);if(C(i)&&N(i)==="pipe"&&(Array.isArray(p.arguments)?p.arguments:[]).some(l=>{let o=g(l);if(o?.type!=="CallExpression")return false;let u=g(o.callee)?.name;return u==="take"||u==="first"}))return true}return ie(ne(p))})(t))return null;let r=g(t.callee),n=g(r?.object);if(n&&re(n)||(function(f){let d=de.get(f.filePath);if(d!==void 0)return d;let p=Be(f);return de.size>=500&&de.clear(),de.set(f.filePath,p),p})(e))return null;let a=b(t),{line:s,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:ge,message:(function(f,d){let p="Open-ended subscriptions in components can outlive the component and make state harder to track.",i=d.crossRef?.templateReferences;if(!i)return p;let l=g(f.callee),o=g(l?.object),u=o?N(o):null;if(!u)return p;let m=u.endsWith("$")?u.slice(0,-1):u;return i.has(u)||i.has(m)?`'${u}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:p})(t,e),line:s,column:c,severity:"error",fix:x[ge],codeExample:P[ge]}},{requires:{typeChecker:true,projectContext:true}});var ye="rxjs-avoid-subject-as-event-bus",bt=createAnyAngularClassRule(ye,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=F(t.node);if(a.length===0)return null;let s=(function(i){let l=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,u=>{let m=g(u.callee);if(m&&(m.type==="Identifier"?m.name:C(m)?N(m):"")==="takeUntil")for(let y of Array.isArray(u.arguments)?u.arguments:[]){let h=St(y);h&&l.add(h);}});return l})(a),c=(function(i){let l=new Set,o=m=>{he(m??null,y=>{let h=Ue(y,"next");h&&l.add(h);});},u=Qe(i);for(let m of(u&&o(z(u)),i))if(H(m)){let y=m.key?.name;m.kind==="set"&&(function(h){let E=h.decorators;if(!Array.isArray(E))return false;for(let S of E){let A=g(S.expression);if(A?.name==="Input"||g(A?.callee)?.name==="Input")return true}return false})(m)&&o(m),y==="ngOnChanges"&&o(z(m));}else m.type==="PropertyDefinition"&&m.value&&o(m.value);return l})(a),f=(function(i){let l=new Set;for(let o of i)H(o)&&o.key?.name==="ngOnDestroy"&&he(z(o),u=>{let m=Ue(u,"complete");m&&l.add(m);});return l})(a),d=(function(i){let l=new Set;for(let o of i)he((H(o)?z(o):o.type==="PropertyDefinition"?o.value:void 0)??null,u=>{let m=Ue(u,"pipe");m&&l.add(m);});return l})(a),p=[];for(let i of a){if(i.type!=="PropertyDefinition"||i.accessibility==="public")continue;let l=i.key?.name??"";if(!l||s.has(l)||c.has(l)||f.has(l)||d.has(l))continue;let o=et(i.key,e);if(!o)continue;let u=o.valueDeclaration??o.declarations?.[0];if(!u)continue;let m=r.getTypeOfSymbolAtLocation(o,u);if(!n.isSubjectLike(m))continue;let{line:y,column:h}=e.locator.location(b(i));p.push({filePath:e.filePath,ruleName:ye,message:`'${l}' is a Subject the class signals into without piping or external exposure \u2014 components are easier to follow when local state lives in fields or signals.`,line:y,column:h,severity:"warn",fix:x[ye],codeExample:P[ye]});}return p.length>0?p:null});function he(t,e){if(!t)return;let r=[t];for(;r.length;){let n=g(r.pop());if(n)for(let a of(n.type==="CallExpression"&&e(n),O(n)))r.push(a);}}function St(t){let e=g(t);if(!e||!C(e))return null;let r=g(e.object),n=N(e);return n&&r?.type==="ThisExpression"?n:null}function Ue(t,e){let r=g(t.callee);return r&&C(r)&&N(r)===e?St(r.object):null}var qe="rxjs-prefer-toSignal-for-template-state",At=createAnyAngularClassRule(qe,(t,e)=>{if(t.metadata?.type!=="Component")return null;let n=e.crossRef?.templateReferences;if(n===void 0)return null;let{typeChecker:a,angularTypes:s}=e;if(!a||!s)return null;let c=(function(p,i){let l=D(i);if(!l)return;let o=b(p);for(let u of l.statements)if(M.isClassDeclaration(u)&&u.pos<=o&&o<=u.end)return u})(t.node,e);if(!c)return null;let f=[];for(let p of c.members){var d;if(!M.isPropertyDeclaration(p))continue;let i=(function(m){if(M.isIdentifier(m.name)||M.isStringLiteral(m.name))return m.name.text})(p);if(!i||!n.has(i)&&!n.has((d=i).endsWith("$")?d.slice(0,-1):d)||(function(m,y,h){let E=M.getDecorators(m);if(!E)return false;for(let S of E){let A=M.isCallExpression(S.expression)?S.expression.expression:S.expression;if(!M.isIdentifier(A)||A.text!=="Output")continue;let v=y.getSymbolAtLocation(A),w=v&&v.flags&M.SymbolFlags.Alias?y.getAliasedSymbol(v):v;if(h.isFromAngularCore(w))return true}return false})(p,a,s))continue;let l=a.getTypeAtLocation(p);if(!s.isObservable(l)&&!s.isSubjectLike(l))continue;let{line:o,column:u}=e.locator.location(p.getStart());f.push({filePath:e.filePath,ruleName:qe,message:`Observable "${i}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:o,column:u,severity:"warn",fix:x[qe]});}return f.length?f:null},{requires:{projectContext:true,htmlAst:true,typeChecker:true}});var He="toSignal-require-initialValue",Ct=createCallExpressionRule(He,(t,e)=>{if(!T(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],n=r[1]?g(r[1]):null;if(!n||n.type!=="ObjectExpression"||!(function(a){let s=Y(a,"initialValue");if(s&&!we(s.value))return true;let c=Y(a,"requireSync");return !!c&&Re(c.value)})(n)){let{line:a,column:s}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:He,message:"toSignal() can emit undefined before the observable produces a value.",line:a,column:s,severity:"warn",fix:x[He]}}return null});var ze="signal-prefer-computed-over-sync-effect",Lr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame"]),jr=new Set(["then","catch","finally"]),Fr=new Set(["set","update","mutate"]),Nt=createCallExpressionRule(ze,(t,e)=>{var r,n;let a,s,c,f,d,p;if(!T(t.callee,"effect"))return null;let{typeChecker:i,angularTypes:l}=e;if(!i||!l)return null;let o=(function(S,A){let v,w=D(S);if(!w)return;let L=k=>{if(!v){if(M.isCallExpression(k)&&k.getStart()===A){v=k;return}M.forEachChild(k,L);}};return L(w),v})(e,b(t));if(!o)return null;let u=o.arguments[0];if(!u||!(M.isArrowFunction(u)||M.isFunctionExpression(u)))return null;let m=(r=u.body,n={typeChecker:i,angularTypes:l},s=false,c=false,f=false,d=false,(p=S=>{f&&d&&s&&c||((S.kind===M.SyntaxKind.AwaitExpression||S.kind===M.SyntaxKind.YieldExpression)&&(f=true),M.isCallExpression(S)&&(function(A,v,w){var L,k;if(M.isPropertyAccessExpression(A.expression)){let U,j=A.expression.name.text,K=A.expression.expression,q=v.typeChecker.getTypeAtLocation(K);return Fr.has(j)&&v.angularTypes.isWritableSignal(q)?w.onSignalWrite():(j==="subscribe"&&(v.angularTypes.isObservable(q)||v.angularTypes.isSubjectLike(q))||jr.has(j)&&(U=(L=q).aliasSymbol??L.symbol)&&U.name==="Promise"&&vt(U))&&w.onAsync()}if(M.isIdentifier(A.expression)){let U,j=A.expression.text;if(j==="linkedSignal")return w.onLinkedSignal();if(Lr.has(j)&&(k=A.expression,(U=v.typeChecker.getSymbolAtLocation(k))&&vt(U)))return w.onAsync();A.arguments.length===0&&(function(K,q){let Z=q.typeChecker.getSymbolAtLocation(K);if(!Z)return false;let Ve=Z.valueDeclaration??Z.declarations?.[0];if(!Ve)return false;let qt=q.typeChecker.getTypeOfSymbolAtLocation(Z,Ve);return q.angularTypes.isSignal(qt)})(A.expression,v)&&w.onSignalRead();}})(S,n,{onSignalRead:()=>{s=true;},onSignalWrite:()=>{c=true,a??=S;},onAsync:()=>{f=true;},onLinkedSignal:()=>{d=true;}}),M.forEachChild(S,p));})(r),{hasSignalRead:s,hasSignalWrite:c,hasAsync:f,hasLinkedSignal:d,firstWrite:a});if(!m.hasSignalRead||!m.hasSignalWrite||m.hasAsync||m.hasLinkedSignal)return null;let y=m.firstWrite??o,{line:h,column:E}=e.locator.location(y.getStart());return {filePath:e.filePath,ruleName:ze,message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:h,column:E,severity:"warn",fix:x[ze]}},{requires:{typeChecker:true}});function vt(t){let e=t.getDeclarations();if(!e)return false;for(let r of e)if(r.getSourceFile().fileName.replace(/\\/g,"/").includes("/typescript/lib/lib."))return true;return false}var Rt=new Set(["afterRender","afterNextRender"]),$r=/\bafterNextRender\s*\(|\bafterRender\s*\(/,xe=new Map,wt=createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!T(t.callee,"untracked")||(function(a,s){let c=s.sourceText??s.fileContent;if(typeof c=="string"&&!$r.test(c))return false;let f=a.parent;for(;f;){if(f.type==="CallExpression"&&Rt.has(Ne(f)))return true;f=f.parent;}let d=b(a);return (function(p){let i=xe.get(p.filePath);if(i!==void 0)return i;let l=p.program;return i=l?(function(o){let u=[],m=o.body,y=Array.isArray(m)?[...m]:[o];for(;y.length;){let h=g(y.pop());if(h){if(h.type==="CallExpression"&&Rt.has(Ne(h))){let E=g(h.arguments?.[0]);if(E){let S=b(E),A=E.end??E.span?.end??b(E);A>S&&u.push([S,A]);}}for(let E of O(h))y.push(E);}}return u})(l):[],xe.size>=300&&xe.clear(),xe.set(p.filePath,i),i})(s).some(([p,i])=>d>=p&&d<i)})(t,e))return null;let{line:r,column:n}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:n,severity:"warn",fix:x["signal-avoid-untracked-overuse"]}});var Ee="prefer-inject-over-constructor-di",Ur=new Set(["Inject","Optional","Self","SkipSelf","Host"]),Mt=createAnyAngularClassRule(Ee,(t,e)=>{let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(l,o){var u;let m=(u=o).sourceFile?u.sourceFile:u.fileContent?(u.sourceFile=M.createSourceFile(u.filePath,u.fileContent,M.ScriptTarget.Latest,true),u.sourceFile):void 0;if(!m)return;let y=b(l);for(let h of m.statements)if(M.isClassDeclaration(h)&&h.pos<=y&&y<=h.end)return h})(t.node,e);if(!a)return null;let s=a.members.find(M.isConstructorDeclaration);if(!s||s.parameters.length===0)return null;let c=[];for(let l of s.parameters){var f;(function(o,u,m){if((function(E,S,A){let v=M.getDecorators(E);if(!v||v.length===0)return false;for(let w of v){let L=(function(j){let K=M.isCallExpression(j.expression)?j.expression.expression:j.expression;return M.isIdentifier(K)?K:void 0})(w);if(!L||!Ur.has(L.text))continue;let k=S.getSymbolAtLocation(L),U=k&&k.flags&M.SymbolFlags.Alias?S.getAliasedSymbol(k):k;if(A.isFromAngularCore(U))return true}return false})(o,u,m))return true;if(!o.type)return false;let y=u.getTypeFromTypeNode(o.type);if(m.isInjectionToken(y))return true;let h=y.aliasSymbol??y.symbol;return !!h&&m.isInjectableClass(h)})(l,r,n)&&c.push((f=l,{name:M.isIdentifier(f.name)?f.name.text:"<binding>",typeText:f.type?f.type.getText():"<inferred>"}));}if(c.length===0)return null;let{line:d,column:p}=e.locator.location(b(s)),i=c.map(l=>`${l.name}: ${l.typeText}`).join(", ");return {filePath:e.filePath,ruleName:Ee,message:`Constructor dependency injection makes class setup less composable than inject(). Offending params: ${i}.`,line:d,column:p,severity:"warn",fix:x[Ee],codeExample:P[Ee]}},{requires:{typeChecker:true}});var be="signal-prefer-input-signal";function Hr(t){let e=g(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=g(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var Pt=createAnyAngularClassRule(be,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=[],a=e.project?.standaloneComponents?.has(e.filePath)??false;for(let s of r){let c=g(s);if(c&&(c.type==="PropertyDefinition"||c.type==="AccessorProperty")&&Array.isArray(c.decorators)&&c.decorators.some(Hr)){let f=b(c),{line:d,column:p}=e.locator.location(f),i=g(c.key),l=(i?.type==="Identifier"?i.name:i?.type==="Literal"?String(i.value):"")||"(unknown)",o=`'${l}' uses @Input(), which keeps this input outside Angular's signal graph.`;a&&(o+=" Standalone declarations benefit most from signal inputs."),n.push({filePath:e.filePath,ruleName:be,message:o,line:d,column:p,severity:a?"error":"warn",fix:x[be],codeExample:P[be]});}}return n.length>0?n:null},{requires:{projectContext:true}});var Se="signal-prefer-output-function",Tt=createAnyAngularClassRule(Se,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let{typeChecker:r,angularTypes:n}=e;if(!r||!n)return null;let a=(function(c,f){let d=D(f);if(!d)return;let p=b(c);for(let i of d.statements)if(M.isClassDeclaration(i)&&i.pos<=p&&p<=i.end)return i})(t.node,e);if(!a)return null;let s=[];for(let c of a.members){if(!M.isPropertyDeclaration(c)||!(function(i,l,o){let u=M.getDecorators(i);if(!u)return false;for(let m of u){let y=M.isCallExpression(m.expression)?m.expression.expression:m.expression;if(!M.isIdentifier(y)||y.text!=="Output")continue;let h=l.getSymbolAtLocation(y),E=h&&h.flags&M.SymbolFlags.Alias?l.getAliasedSymbol(h):h;if(o.isFromAngularCore(E))return true}return false})(c,r,n)||!(function(i,l,o){if(i.type){let m=l.getTypeFromTypeNode(i.type);if(o.isEventEmitter(m))return true}if(i.initializer){let m=l.getTypeAtLocation(i.initializer);if(o.isEventEmitter(m))return true}let u=l.getSymbolAtLocation(i.name);if(u){let m=l.getTypeOfSymbolAtLocation(u,i);if(o.isEventEmitter(m))return true}return false})(c,r,n))continue;let f=(function(i){let l=i.name;if(M.isIdentifier(l)||M.isStringLiteral(l))return l.text})(c)??"(unknown)",{line:d,column:p}=e.locator.location(c.getStart());s.push({filePath:e.filePath,ruleName:Se,message:`'${f}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:d,column:p,severity:"warn",fix:x[Se],codeExample:P[Se]});}return s.length>0?s:null},{requires:{typeChecker:true}});var Ae="signal-prefer-model";function Ot(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let n=g(r.expression??r);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(n.type==="CallExpression"){let a=g(n.callee);return a?.type==="Identifier"&&a.name===e}return false})}function kt(t,e){let r=g(t.value);if(!r||r.type!=="CallExpression")return false;let n=g(r.callee);if(!n)return false;if(n.type==="Identifier")return n.name===e;if(C(n)){let a=g(n.object);return a?.type==="Identifier"&&a.name===e}return false}var Dt=createAnyAngularClassRule(Ae,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=F(t.node),n=new Map,a=new Map;for(let c of r){let f=g(c);if(!f||f.type!=="PropertyDefinition"&&f.type!=="AccessorProperty")continue;let d=(function(p){let i=g(p.key);return i?i.type==="Identifier"?i.name??null:i.type==="Literal"?String(i.value):null:null})(f);d&&((Ot(f,"Input")||kt(f,"input"))&&n.set(d,f),(Ot(f,"Output")||kt(f,"output"))&&a.set(d,f));}let s=[];for(let[c,f]of a){if(!c.endsWith("Change"))continue;let d=c.slice(0,-6),p=n.get(d);if(p){let i=b(p),{line:l,column:o}=e.locator.location(i);s.push({filePath:e.filePath,ruleName:Ae,message:`The \`${d}\` / \`${c}\` pair implements two-way binding with extra wiring that model() avoids.`,line:l,column:o,severity:"warn",fix:x[Ae],codeExample:P[Ae]});}}return s.length>0?s:null});var Kr=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),We="template-prefer-control-flow",It=createTemplateAttributeRule(We,(t,e)=>{var r;let n=(r=t.name,Kr.get(r)??null);if(!n)return null;let a=I(e,t.sourceSpan.start),{line:s,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:We,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${n}\` control flow benefits.`,line:s,column:c,severity:"error",fix:x[We]}},{requires:{htmlAst:true}});var Lt=new WeakMap,jt=createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,n,a=(function p(i){let l=g(i);if(!l)return null;if(l.type==="BinaryExpression"&&l.operator==="|"){let o=g(l.right);return o?.type==="Identifier"&&o.name==="async"?g(l.left):p(l.left)}return null})(t.expression),s=a?(function p(i,l=0){if(!i||l>10)return null;if(i.type==="Identifier")return i.name;if(i.type==="ThisExpression")return "this";if(i.type==="Literal"){let o=i.value;return o===null?"null":typeof o=="string"||typeof o=="number"||typeof o=="boolean"||typeof o=="bigint"?String(o):null}if(i.type==="CallExpression"){let o=p(i.callee,l+1),u=(Array.isArray(i.arguments)?i.arguments:[]).map(m=>p(m,l+1)??"?");return `${o}(${u.join(",")})`}if(C(i)){let o=p(i.object,l+1),u=N(i);if(o&&u)return `${o}.${u}`}if(i.type==="UnaryExpression")return `${i.operator}${p(i.argument,l+1)}`;if(i.type==="ConditionalExpression")return `${p(i.test,l+1)}?${p(i.consequent,l+1)}:${p(i.alternate,l+1)}`;if(i.type==="OptionalExpression"||i.type==="ChainExpression")return p(i.expression,l+1);if(i.type==="LogicalExpression"){let o=p(i.left,l+1),u=p(i.right,l+1);if(o&&u)return `${o}${i.operator}${u}`}if(i.type==="BinaryExpression"&&i.operator!=="|"){let o=p(i.left,l+1),u=p(i.right,l+1);if(o&&u)return `${o}${i.operator}${u}`}if(i.type==="ArrayExpression")return `[${(i.elements??[]).map(u=>p(u,l+1)??"?").join(",")}]`;if(i.type==="ObjectExpression")return `{${(i.properties??[]).map(u=>{let m=u.key?p(u.key,l+1):"?",y=u.value?p(u.value,l+1):"?";return `${m}:${y}`}).join(",")}}`;if(i.type==="TemplateLiteral")return "`tmpl`";if(i.type==="AssignmentExpression"){let o=p(i.left,l+1),u=p(i.right,l+1);if(o&&u)return `${o}${i.operator}${u}`}return null})(a):null;if(!s)return null;let c=(r=e.template,n=r?.templateStartOffset,`${e.filePath}@${typeof n=="number"&&Number.isFinite(n)?n:0}`),f=Lt.get(e);f||(f=new Map,Lt.set(e,f));let d=f.get(c);if(d||(d=new Set,f.set(c,d)),d.has(s)){let p=I(e,t.sourceSpan.start),{line:i,column:l}=e.locator.location(p);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${s}" can create repeated work and inconsistent loading states.`,line:i,column:l,severity:"warn",fix:x["template-no-async-pipe-duplication"]}}return d.add(s),null},{requires:{htmlAst:true}});var Yr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Qr=new Set(["xdescribe","xit","xtest","xcontext"]);function Ft(t){return t.type==="Identifier"?t.name??null:null}var _t=createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let n;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let a=g(t.callee);if(!a)return null;let s=(n=Ft(a)||(function(i){if(i.type==="MemberExpression"||i.type==="StaticMemberExpression"||i.type==="OptionalMemberExpression"){let l=g(i.object),o=i.property?.name??"",u=(l?.type==="Identifier"?l.name:"")??"";return u?`${u}.${o}`:null}return null})(a))&&Yr.has(n)?n:null;if(!s){if(Ft(a)==="pending"){let i=b(t),{line:l,column:o}=e.locator.location(i);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:l,column:o,severity:"error",fix:x["spec-no-focused-test"]}}return null}let c=b(t),{line:f,column:d}=e.locator.location(c),p=Qr.has(s)?`\`${s}\` disables a test that may be forgotten.`:`\`${s}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:p,line:f,column:d,severity:"error",fix:x["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function $t(){R(tt,"correctness"),R(rt,"correctness"),R(nt,"correctness"),R(ot,"correctness"),R(at,"performance"),R(lt,"performance"),R(ct,"performance"),R(pt,"performance"),R(ft,"performance"),R(mt,"security"),R(dt,"security"),R(gt,"ssr"),R(ht,"ssr"),R(Et,"reactivity"),R(xt,"reactivity"),R(bt,"reactivity"),R(At,"reactivity"),R(Ct,"reactivity"),R(Nt,"reactivity"),R(wt,"reactivity"),R(Mt,"modern-api"),R(Pt,"modern-api"),R(Tt,"modern-api"),R(Dt,"modern-api"),R(It,"template"),R(jt,"template"),R(_t,"testing");}var Bt=(t,e,r,n,a)=>{let s=0,c=0;for(let f of r)for(let d of f.failures)d.severity==="error"?s++:d.severity==="warn"&&c++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:s+c,errorCount:s,warningCount:c,duration:n,typeAware:a}};$t(),configureRuleExecutor(Xe,Ke),process.on("message",t=>{rn(t);});var rn=async t=>{let e=[],r=createTypeAwareAnalysisContext(t.rootDir,t.files,t.parserOptions,{buildProjectContext:t.buildProjectContext,programRootFiles:t.programRootFiles});try{await r.warmup();let n=groupTasksByFile(t.tasks),a=await nn(Array.from(n),Math.max(1,t.fileConcurrency??1),async([s,c])=>{let f=performance.now();try{let d=await executeBatchedTasks(c,r);return Ut(s,c.length,d,performance.now()-f),d}catch{return Ut(s,c.length,[],performance.now()-f),[]}finally{r.evict(s);}});e.push(...a.flat()),process.send?.({kind:"complete",results:e});}catch(n){process.send?.({kind:"error",error:n instanceof Error?n.message:String(n)});}finally{r.dispose(),process.disconnect?.();}};async function nn(t,e,r){let n=Array(t.length),a=0,s=Math.min(e,t.length);return await Promise.all(Array.from({length:s},async()=>{for(;a<t.length;){let c=a++;n[c]=await r(t[c]);}})),n}var Ut=(t,e,r,n)=>{process.send?.(Bt(t,e,r,n,true));};//# sourceMappingURL=type-aware-worker.js.map
//# sourceMappingURL=type-aware-worker.js.map
{
"name": "@ngcompass/rules",
"version": "0.1.6-beta",
"version": "0.1.7-beta",
"description": "Rules collection for ngcompass",

@@ -32,6 +32,6 @@ "sideEffects": false,

"dependencies": {
"@ngcompass/common": "0.1.6-beta",
"@ngcompass/ast": "0.1.6-beta",
"@ngcompass/planner": "0.1.6-beta",
"@ngcompass/engine": "0.1.6-beta"
"@ngcompass/engine": "0.1.7-beta",
"@ngcompass/ast": "0.1.7-beta",
"@ngcompass/common": "0.1.7-beta",
"@ngcompass/planner": "0.1.7-beta"
},

@@ -38,0 +38,0 @@ "keywords": [

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display