@ngcompass/rules 0.1.1-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,634 @@
1
+ import * as _ngcompass_engine from '@ngcompass/engine';
2
+ import { RuleHandler } from '@ngcompass/engine';
3
+ export { RuleContextFactory, RuleHandler } from '@ngcompass/engine';
4
+ import { AnyAngularClassNode, CallExpression, AngularClassNode, TemplateExpressionNode, TemplateAnalysis, TemplateAttributeNode } from '@ngcompass/ast';
5
+ import { RuleMetadata, PluginManifest, RuleRegistryEntry, RuleListEntry, RuleContext, RuleResult, ResolvedRulesMap, ResolvedRule, NormalizedAnalyzerConfig, Result, RuleResolutionResult, PresetReference, PresetConfig, RuleConfig, RuleConfigFull, RulesConfig, BuiltinPreset } from '@ngcompass/common';
6
+ import * as typescript from 'typescript';
7
+
8
+ declare const componentNoManualDetectChangesRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
9
+
10
+ declare const signalNoSideEffectsInComputedRule: _ngcompass_engine.RuleHandler<CallExpression>;
11
+
12
+ declare const signalEffectDestroyScopedRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
13
+
14
+ declare const rxjsNoNestedSubscribeRule: _ngcompass_engine.RuleHandler<CallExpression>;
15
+
16
+ declare const preferOnPushRule: _ngcompass_engine.RuleHandler<AngularClassNode>;
17
+
18
+ declare const templateNoCallExpressionRule: _ngcompass_engine.RuleHandler<TemplateExpressionNode>;
19
+
20
+ declare const templateTrackByRequiredRule: _ngcompass_engine.RuleHandler<TemplateAnalysis>;
21
+
22
+ declare const templateNoObjectLiteralBindingRule: _ngcompass_engine.RuleHandler<TemplateExpressionNode>;
23
+
24
+ declare const templateNoArrayLiteralBindingRule: _ngcompass_engine.RuleHandler<TemplateExpressionNode>;
25
+
26
+ declare const noBypassSanitizationRule: _ngcompass_engine.RuleHandler<CallExpression>;
27
+
28
+ declare const templateNoUnsafeBindingsRule: _ngcompass_engine.RuleHandler<TemplateAttributeNode>;
29
+
30
+ declare const noDocumentAccessRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
31
+
32
+ declare const preferAfterRenderOverAfterViewInitRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
33
+
34
+ declare const rxjsNoSubscribeInComponentRule: _ngcompass_engine.RuleHandler<CallExpression>;
35
+
36
+ declare function hasManualTeardownInNgOnDestroy(fileContent: string): boolean;
37
+ declare const rxjsRequireTakeUntilDestroyedRule: _ngcompass_engine.RuleHandler<CallExpression>;
38
+
39
+ declare const rxjsAvoidSubjectRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
40
+
41
+ declare const rxjsPreferToSignalRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
42
+
43
+ declare const toSignalRequireInitialValueRule: _ngcompass_engine.RuleHandler<CallExpression>;
44
+
45
+ declare const signalPreferComputedRule: _ngcompass_engine.RuleHandler<CallExpression>;
46
+
47
+ declare const signalAvoidUntrackedRule: _ngcompass_engine.RuleHandler<CallExpression>;
48
+
49
+ declare const preferInjectRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
50
+
51
+ declare const signalPreferInputSignalRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
52
+
53
+ declare const signalPreferOutputFunctionRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
54
+
55
+ declare const signalPreferModelRule: _ngcompass_engine.RuleHandler<AnyAngularClassNode>;
56
+
57
+ declare const templatePreferControlFlowRule: _ngcompass_engine.RuleHandler<TemplateAttributeNode>;
58
+
59
+ declare const templateNoAsyncPipeDuplicationRule: _ngcompass_engine.RuleHandler<TemplateExpressionNode>;
60
+
61
+ declare const specNoFocusedTestRule: _ngcompass_engine.RuleHandler<CallExpression>;
62
+
63
+ /**
64
+ * RuleRegistry — Plugin Boundary
65
+ *
66
+ * Replaces the mutable bare Map in adapter.ts with a class that:
67
+ * - Throws on duplicate registration (prevents silent stomping)
68
+ * - Exposes a controlled surface for plugin authors
69
+ * - Provides a global singleton for CLI / built-in usage
70
+ * - Provides a reset helper for isolated test runs
71
+ *
72
+ * Plugin authors export an array of RulePlugin objects from their package.
73
+ * The plugin-loader reads the config `plugins` array and calls registry.register()
74
+ * for each plugin — no core files need to be modified.
75
+ *
76
+ * Example plugin package:
77
+ * ```ts
78
+ * // my-org-rules/src/index.ts
79
+ * import type { RulePlugin } from '@ngcompass/rules';
80
+ * import { createComponentRule } from '@ngcompass/engine';
81
+ *
82
+ * const noBareSelectorRule: RulePlugin = {
83
+ * name: 'my-org/no-bare-selectors',
84
+ * handler: createComponentRule('my-org/no-bare-selectors', (node, ctx) => { ... }),
85
+ * meta: { category: 'style', dependencyType: 'component' },
86
+ * };
87
+ *
88
+ * export default [noBareSelectorRule];
89
+ * ```
90
+ *
91
+ * ngcompass.config.ts:
92
+ * ```ts
93
+ * export default {
94
+ * plugins: ['my-org-rules'],
95
+ * rules: { 'my-org/no-bare-selectors': 'high' },
96
+ * };
97
+ * ```
98
+ */
99
+
100
+ /**
101
+ * A plugin descriptor — the unit external rule authors export.
102
+ */
103
+ interface RulePlugin {
104
+ /** Globally unique rule name. Use namespacing: 'my-org/rule-name' */
105
+ readonly name: string;
106
+ /** The rule handler (created via createComponentRule, createDecoratedPropertyRule, etc.) */
107
+ readonly handler: RuleHandler<unknown>;
108
+ /** Optional metadata overrides (category, description, dependencyType, etc.) */
109
+ readonly meta?: Partial<RuleMetadata>;
110
+ /** Optional manifest (RFC §7.6) */
111
+ readonly manifest?: PluginManifest;
112
+ }
113
+ /**
114
+ * Options controlling registration behaviour.
115
+ */
116
+ interface RegisterOptions {
117
+ /**
118
+ * Allow overwriting an existing rule with the same name.
119
+ * Default: false — throws on duplicate to prevent silent errors.
120
+ */
121
+ allowOverride?: boolean;
122
+ }
123
+ /**
124
+ * Central registry for rule handlers.
125
+ *
126
+ * Responsibilities:
127
+ * - Store handler instances keyed by rule name
128
+ * - Prevent accidental duplicate registration
129
+ * - Expose read-only views for the engine and adapter
130
+ */
131
+ declare class RuleRegistry {
132
+ private readonly _handlers;
133
+ private readonly _meta;
134
+ /**
135
+ * Registers a rule plugin.
136
+ *
137
+ * @throws {Error} if the rule name is already registered and allowOverride is false
138
+ */
139
+ register(plugin: RulePlugin, opts?: RegisterOptions): void;
140
+ /**
141
+ * Returns the handler for a rule name, or undefined if not registered.
142
+ */
143
+ get(name: string): RuleHandler<unknown> | undefined;
144
+ /**
145
+ * Returns true if a rule with this name is registered.
146
+ */
147
+ has(name: string): boolean;
148
+ /**
149
+ * Returns all registered rule names.
150
+ */
151
+ getRuleNames(): ReadonlyArray<string>;
152
+ /**
153
+ * Returns the full handler map (read-only view).
154
+ * Used by the engine adapter for batched execution.
155
+ */
156
+ getAll(): ReadonlyMap<string, RuleHandler<unknown>>;
157
+ /**
158
+ * Returns metadata overrides for a rule name, if any.
159
+ */
160
+ getMeta(name: string): Partial<RuleMetadata> | undefined;
161
+ /**
162
+ * Returns resolved RuleMetadata for a rule name.
163
+ * Fills in defaults for fields not specified in the plugin's meta.
164
+ */
165
+ getMetadata(name: string): RuleMetadata | undefined;
166
+ /**
167
+ * Returns a full RuleRegistryEntry (metadata + default config).
168
+ * Used for backward compatibility with the legacy registry API.
169
+ */
170
+ getRegistryEntry(name: string): RuleRegistryEntry | undefined;
171
+ /**
172
+ * Returns a ReadonlyMap compatible with the legacy RuleRegistry type.
173
+ */
174
+ toReadonlyMap(): ReadonlyMap<string, RuleRegistryEntry>;
175
+ /**
176
+ * Total number of registered rules.
177
+ */
178
+ get size(): number;
179
+ }
180
+ /**
181
+ * Returns the global registry, creating it on first call.
182
+ */
183
+ declare const getGlobalRegistry: () => RuleRegistry;
184
+ /**
185
+ * Resets the global registry to a fresh empty instance.
186
+ *
187
+ * FOR TESTS ONLY — never call this in production code.
188
+ * Allows isolated unit tests that register their own rules without
189
+ * interfering with the global built-in rules.
190
+ */
191
+ declare const resetGlobalRegistry: () => void;
192
+ /**
193
+ * Check if a rule exists in the global registry.
194
+ */
195
+ declare const isKnownRule: (name: string) => boolean;
196
+ /**
197
+ * Get rule metadata by name from the global registry.
198
+ */
199
+ declare const getRuleMetadata: (name: string) => RuleMetadata | undefined;
200
+ /**
201
+ * Get all registered rule names from the global registry.
202
+ */
203
+ declare const getAllRuleNames: () => ReadonlyArray<string>;
204
+ /**
205
+ * Backward-compatible accessor for the legacy `ruleRegistry` constant.
206
+ * Returns a ReadonlyMap<string, RuleRegistryEntry> view of the global registry.
207
+ */
208
+ declare const getRuleRegistryMap: () => ReadonlyMap<string, RuleRegistryEntry>;
209
+ /**
210
+ * Returns all registered rules as RuleListEntry objects.
211
+ * Used by the `compass rules` CLI command.
212
+ */
213
+ declare function getRuleListEntries(): RuleListEntry[];
214
+
215
+ declare function registerAllBuiltinRules(): void;
216
+
217
+ /**
218
+ * High-Performance Engine Adapter
219
+ *
220
+ * Bridges the RuleRegistry (plugin boundary) with the single-pass engine
221
+ * and the legacy orchestrator API. Maintains backward compatibility while
222
+ * enabling batched rule execution and external plugin registration.
223
+ *
224
+ * The mutable bare Map that previously lived here has been replaced by
225
+ * the global RuleRegistry singleton — see rules/registry/rule-registry.ts.
226
+ */
227
+
228
+ /**
229
+ * Checks if a rule is implemented in the engine.
230
+ */
231
+ declare const isNewEngineRule: (ruleName: string) => boolean;
232
+ /**
233
+ * Executes multiple rules in a single AST pass (optimal path).
234
+ *
235
+ * All handlers for the given rule names are collected from the global
236
+ * RuleRegistry (which includes both built-in rules and plugin rules) and
237
+ * passed to runSinglePassAnalysis() — the AST is walked exactly once.
238
+ *
239
+ * @param ruleNames - Rules to execute
240
+ * @param context - Rule execution context
241
+ * @returns Array of RuleResults, one per rule name
242
+ */
243
+ declare const executeBatchedNewEngineRules: (ruleNames: ReadonlyArray<string>, context: RuleContext) => ReadonlyArray<RuleResult>;
244
+
245
+ /**
246
+ * Rule Resolution Pipeline
247
+ *
248
+ * Main entry point for resolving rules from config + presets
249
+ */
250
+
251
+ /**
252
+ * Resolve rules from config
253
+ *
254
+ * Pipeline:
255
+ * 1. Load & resolve extends chain
256
+ * 2. Merge all preset rules (deepest first)
257
+ * 3. Apply user config rules (highest precedence)
258
+ * 4. Attach metadata from registry
259
+ * 5. Filter enabled rules
260
+ */
261
+ declare const resolveRules: (config: NormalizedAnalyzerConfig, configDir?: string) => Promise<Result<RuleResolutionResult>>;
262
+ /**
263
+ * Get only enabled rules from resolution result
264
+ *
265
+ * Pure function: filters out disabled rules
266
+ */
267
+ declare const getEnabledRules: (resolvedRules: ResolvedRulesMap) => ResolvedRulesMap;
268
+ /**
269
+ * Get rules by category
270
+ *
271
+ * Pure function: groups rules by category
272
+ */
273
+ declare const getRulesByCategory: (resolvedRules: ResolvedRulesMap) => ReadonlyMap<string, ReadonlyArray<ResolvedRule>>;
274
+ /**
275
+ * Get rules by dependency type
276
+ *
277
+ * Pure function: groups rules by dependency type
278
+ */
279
+ declare const getRulesByDependencyType: (resolvedRules: ResolvedRulesMap) => ReadonlyMap<string, ReadonlyArray<ResolvedRule>>;
280
+
281
+ /**
282
+ * Preset Loader
283
+ *
284
+ * Loads preset configurations from built-in presets or file system
285
+ */
286
+
287
+ /**
288
+ * Load a preset by reference
289
+ *
290
+ * Side effect: File I/O (isolated)
291
+ */
292
+ declare const loadPreset: (reference: PresetReference, configDir?: string) => Promise<Result<PresetConfig>>;
293
+ /**
294
+ * Resolve extends chain recursively
295
+ *
296
+ * Handles: "extends": "recommended"
297
+ * Handles: "extends": ["recommended", "strict"]
298
+ * Handles: Nested extends in presets
299
+ *
300
+ * Returns presets in order (deepest first)
301
+ */
302
+ declare const resolveExtendsChain: (extendsValue: string | ReadonlyArray<string> | undefined, configDir: string, path?: ReadonlyArray<string>) => Promise<Result<ReadonlyArray<PresetConfig>>>;
303
+
304
+ /**
305
+ * Rule Configuration Normalization
306
+ *
307
+ * Pure functions to normalize rule configurations
308
+ */
309
+
310
+ /**
311
+ * Normalize rule config to full format
312
+ *
313
+ * Pure function: shorthand → full format
314
+ */
315
+ declare const normalizeRuleConfig: (config: RuleConfig) => RuleConfigFull;
316
+ /**
317
+ * Check if a rule is enabled (severity !== 'off')
318
+ */
319
+ declare const isRuleEnabled: (config: RuleConfig) => boolean;
320
+ /**
321
+ * Normalize all rules in a rules object
322
+ *
323
+ * Pure function: transforms all rule configs to full format
324
+ */
325
+ declare const normalizeAllRules: (rules: Readonly<Record<string, RuleConfig>>) => ReadonlyMap<string, RuleConfigFull>;
326
+
327
+ /**
328
+ * Rule Configuration Merger
329
+ *
330
+ * Pure functions to merge rule configurations with proper precedence
331
+ */
332
+
333
+ /**
334
+ * Merge two rule configurations
335
+ *
336
+ * Pure function: later config overrides earlier config
337
+ * Handles both shorthand and full format
338
+ */
339
+ declare const mergeRuleConfig: (base: RuleConfig, override: RuleConfig) => RuleConfigFull;
340
+ /**
341
+ * Merge multiple rule configuration objects
342
+ *
343
+ * Pure function: later configs override earlier configs
344
+ * Precedence: rules[0] < rules[1] < ... < rules[n]
345
+ */
346
+ declare const mergeRulesConfigs: (configs: ReadonlyArray<RulesConfig>) => ReadonlyMap<string, RuleConfigFull>;
347
+ /**
348
+ * Apply overrides to a base rules configuration
349
+ *
350
+ * Pure function: overrides have highest precedence
351
+ */
352
+ declare const applyOverrides: (base: ReadonlyMap<string, RuleConfigFull>, overrides: RulesConfig) => ReadonlyMap<string, RuleConfigFull>;
353
+
354
+ /**
355
+ * Built-in Presets Registry
356
+ */
357
+
358
+ /**
359
+ * Registry of built-in presets
360
+ */
361
+ declare const builtinPresets: ReadonlyMap<BuiltinPreset, PresetConfig>;
362
+ /**
363
+ * Check if a preset name is a built-in preset
364
+ */
365
+ declare const isBuiltinPreset: (name: string) => boolean;
366
+ /**
367
+ * Get a built-in preset by name
368
+ */
369
+ declare const getBuiltinPreset: (name: string) => PresetConfig | undefined;
370
+ /**
371
+ * Returns all preset names that include the given rule.
372
+ */
373
+ declare function getPresetsForRule(ruleName: string): string[];
374
+
375
+ /**
376
+ * Rule Recommendations
377
+ *
378
+ * Actionable, one-sentence fix recommendations surfaced in reporter output.
379
+ * Keys must match the ruleName field on RuleFailure exactly.
380
+ */
381
+ declare const RECOMMENDATIONS: Readonly<Record<string, string>>;
382
+ /**
383
+ * Optional before/after code examples for rules that have no auto-fix.
384
+ *
385
+ * Keys must match the ruleName field on RuleFailure exactly.
386
+ * Values are plain multi-line TypeScript strings — no ANSI codes.
387
+ * The reporter renders them in a styled block below the fix recommendation.
388
+ */
389
+ declare const CODE_EXAMPLES: Readonly<Record<string, string>>;
390
+
391
+ /**
392
+ * Loosely-typed AST node used by migration rules.
393
+ * Provides minimal structure while allowing dynamic property access
394
+ * that the oxc-parser AST requires.
395
+ */
396
+ interface AstNode {
397
+ readonly type?: string;
398
+ readonly start?: number;
399
+ readonly end?: number;
400
+ readonly span?: {
401
+ start: number;
402
+ end: number;
403
+ };
404
+ readonly name?: string;
405
+ readonly value?: unknown;
406
+ readonly computed?: boolean;
407
+ readonly operator?: string;
408
+ readonly accessibility?: string;
409
+ readonly readonly?: boolean;
410
+ readonly static?: boolean;
411
+ readonly kind?: string;
412
+ readonly expression?: AstNode;
413
+ readonly callee?: AstNode;
414
+ readonly object?: AstNode;
415
+ readonly property?: AstNode;
416
+ readonly arguments?: AstNode[];
417
+ readonly properties?: AstNode[];
418
+ readonly elements?: AstNode[];
419
+ readonly body?: AstNode | AstNode[] | {
420
+ body?: AstNode[];
421
+ };
422
+ readonly params?: AstNode[] | {
423
+ items?: AstNode[];
424
+ elements?: AstNode[];
425
+ };
426
+ readonly key?: AstNode;
427
+ readonly left?: AstNode;
428
+ readonly right?: AstNode;
429
+ readonly test?: AstNode;
430
+ readonly consequent?: AstNode;
431
+ readonly alternate?: AstNode;
432
+ readonly argument?: AstNode;
433
+ readonly decorators?: AstNode[];
434
+ readonly typeAnnotation?: AstNode;
435
+ readonly typeName?: AstNode;
436
+ readonly initializer?: AstNode;
437
+ readonly parent?: AstNode;
438
+ [key: string]: unknown;
439
+ }
440
+ type MaybeAstNode = AstNode | null | undefined;
441
+ /**
442
+ * Unwraps TS wrapper nodes, parentheses, chain expressions, and instantiation wrappers.
443
+ * Handles all known wrapper node types consistently.
444
+ */
445
+ declare function unwrapNode(node: AstNode | null | undefined): AstNode | null;
446
+ /**
447
+ * Checks if a node is a member expression (static, computed, or optional).
448
+ */
449
+ declare function isMemberExpressionLike(node: AstNode | null | undefined): boolean;
450
+ /**
451
+ * Gets the statically-resolvable property name from a member expression.
452
+ * Returns '' if the name cannot be determined.
453
+ */
454
+ declare function getStaticPropertyName(member: AstNode | null | undefined): string;
455
+ /**
456
+ * Gets the start offset of a node, handling both oxc-parser span and estree start formats.
457
+ */
458
+ declare function getNodeStart(node: AstNode | null | undefined): number;
459
+ /**
460
+ * Checks if a call expression's callee matches a given function name.
461
+ * Handles both direct calls (`fn()`) and member calls (`obj.fn()`).
462
+ */
463
+ declare function isCalleeNamed(calleeRaw: AstNode | null | undefined, name: string): boolean;
464
+ /**
465
+ * Gets the name of a call expression's callee.
466
+ */
467
+ declare function getCalleeName(callExprRaw: AstNode | null | undefined): string;
468
+ /**
469
+ * Checks if a call expression is a `.subscribe(...)` call.
470
+ */
471
+ declare function isSubscribeCall(node: AstNode | null | undefined): boolean;
472
+ /**
473
+ * Gets a property from an ObjectExpression by key name.
474
+ */
475
+ declare function getObjectProperty(objExpr: AstNode | null | undefined, name: string): AstNode | null;
476
+ /**
477
+ * Checks if a node is literal `true`.
478
+ */
479
+ declare function isLiteralTrue(node: AstNode | null | undefined): boolean;
480
+ /**
481
+ * Checks if a node is literal `null` or `undefined`.
482
+ */
483
+ declare function isLiteralNullOrUndefined(node: AstNode | null | undefined): boolean;
484
+ /**
485
+ * Yields all direct child AST nodes of a given node.
486
+ *
487
+ * Uses `for...in` instead of `Object.keys()` to avoid allocating an intermediate
488
+ * string array for every invocation. AST nodes are plain objects (POJOs) so
489
+ * inherited enumerable properties are not a concern in practice.
490
+ *
491
+ * Skips well-known non-child keys (parent, span, etc.) via a Set for O(1) lookup.
492
+ */
493
+ declare function childNodes(node: AstNode | null | undefined): Iterable<AstNode>;
494
+ /**
495
+ * Checks if a method definition is a constructor.
496
+ */
497
+ declare function isConstructorMethod(def: AstNode | null | undefined): boolean;
498
+ /**
499
+ * Checks if a member is a method definition.
500
+ */
501
+ declare function isMethodDefinition(member: AstNode | null | undefined): boolean;
502
+ /**
503
+ * Gets the constructor member from a class body array.
504
+ */
505
+ declare function getConstructorMember(classBody: AstNode[]): AstNode | null;
506
+ /**
507
+ * Gets the method body from a method definition.
508
+ */
509
+ declare function getMethodBody(def: AstNode | null | undefined): AstNode | null;
510
+ /**
511
+ * Gets the method name from a method definition.
512
+ */
513
+ declare function getMethodName(def: AstNode | null | undefined): string;
514
+ /**
515
+ * Gets the class body as an array from a class node.
516
+ */
517
+ declare function getClassBody(classNode: AstNode | null | undefined): AstNode[];
518
+ /**
519
+ * Checks if an effect() call has allowed escape hatches ({ injector } or { manualCleanup: true }).
520
+ */
521
+ declare function isAllowedEffectCall(callExprRaw: AstNode | null | undefined): boolean;
522
+ /**
523
+ * Finds all effect() calls in a subtree that are not allowed by escape hatches.
524
+ */
525
+ declare function findEffectCalls(root: AstNode | null | undefined): AstNode[];
526
+ /**
527
+ * Gets the callback argument (first arg) from a computed() or effect() call,
528
+ * if it's an arrow or function expression.
529
+ */
530
+ declare function getCallbackArg(callExpr: AstNode | null | undefined): AstNode | null;
531
+ /**
532
+ * Gets the body of a function expression.
533
+ */
534
+ declare function getFunctionBody(fn: AstNode | null | undefined): AstNode | null;
535
+ /**
536
+ * Collects import aliases for a given exported name from rxjs imports.
537
+ * E.g., `import { BehaviorSubject as BS } from 'rxjs'` -> Set(['BehaviorSubject', 'BS'])
538
+ *
539
+ * @deprecated Use `collectAllRxjsAliases` instead for better performance — it scans the
540
+ * source text only once for all requested names instead of once per name.
541
+ */
542
+ declare function collectRxjsAliases(sourceText: string | undefined, exportedName: string): Set<string>;
543
+ /**
544
+ * Batch version of collectRxjsAliases — scans source text ONCE for all requested export names.
545
+ *
546
+ * Use this instead of calling collectRxjsAliases() per name to avoid redundant regex work.
547
+ *
548
+ * @performance O(S × 2) instead of O(S × 2 × N) where N = number of requested names.
549
+ * Reduces 6 full-source regex sweeps (e.g. for Subject/ReplaySubject/AsyncSubject) down to 2.
550
+ */
551
+ declare function collectAllRxjsAliases(sourceText: string | undefined, exportedNames: ReadonlySet<string>): Map<string, Set<string>>;
552
+ /**
553
+ * The canonical set of RxJS operators that properly scope subscription lifetime.
554
+ *
555
+ * Shared between rxjs-no-subscribe-in-component and rxjs-require-takeUntilDestroyed rules
556
+ * to guarantee consistent teardown detection without duplicating the operator list.
557
+ */
558
+ declare const VALID_TEARDOWN_OPERATORS: Set<string>;
559
+ /**
560
+ * Extracts the operator name from a single pipe() argument node.
561
+ */
562
+ declare function getOperatorNameFromPipeArg(arg: AstNode | null | undefined): string;
563
+ /**
564
+ * Returns true if the given pipe() call contains at least one valid teardown operator.
565
+ */
566
+ declare function hasTeardownInPipeCall(pipeCall: AstNode): boolean;
567
+ /**
568
+ * Walks the receiver chain of a .subscribe() call looking for a .pipe() call that
569
+ * contains at least one valid teardown operator.
570
+ *
571
+ * @example `source$.pipe(takeUntilDestroyed(destroyRef)).subscribe(...)` → true
572
+ */
573
+ declare function hasTeardownInReceiverChain(receiverExpr: AstNode | null | undefined): boolean;
574
+ /**
575
+ * Computes absolute offset for template expressions, accounting for inline template offset.
576
+ */
577
+ declare function getTemplateAbsoluteOffset(context: {
578
+ template?: {
579
+ templateStartOffset?: number;
580
+ };
581
+ }, nodeStart: number): number;
582
+ /**
583
+ * Walks a .subscribe() receiver chain past any .pipe() calls to the actual
584
+ * source observable call expression.
585
+ *
586
+ * @example
587
+ * this.svc.getUser(id).pipe(map(u => u.name)).subscribe(...)
588
+ * receiverExpr = pipe(map(...)) CallExpression
589
+ * returns = this.svc.getUser(id) CallExpression
590
+ *
591
+ * Returns null when the chain root is not a recognisable CallExpression.
592
+ */
593
+ declare function findObservableSourceCall(receiverExpr: AstNode | null | undefined): AstNode | null;
594
+ /**
595
+ * Returns true if a call expression is a likely auto-completing HTTP observable.
596
+ *
597
+ * Detects two unambiguous patterns (conservative — avoids false negatives on
598
+ * legitimate long-lived streams):
599
+ *
600
+ * 1. Direct HttpClient verb call:
601
+ * `this.http.get(url)`, `this.httpClient.post(url, body)`
602
+ *
603
+ * 2. Service/API method with HTTP-action prefix AND at least one argument:
604
+ * `this.userSvc.getUser(id)`, `this.api.postComment(body)`,
605
+ * `this.repo.deleteItem(id)`, `this.gateway.fetchReport(params)`
606
+ *
607
+ * Both patterns emit once and complete — they do not need takeUntilDestroyed.
608
+ */
609
+ declare function isLikelyHttpObservable(sourceCall: AstNode | null | undefined): boolean;
610
+ /**
611
+ * Gets parameters array from a function node, handling various AST formats.
612
+ */
613
+ declare function getParamsArray(funcNode: AstNode | null | undefined): AstNode[];
614
+ /**
615
+ * Gets the identifier name from a parameter node (handles AssignmentPattern, RestElement, TSParameterProperty).
616
+ */
617
+ declare function getParamIdentifierName(param: AstNode | null | undefined): string;
618
+ /**
619
+ * Gets the type name from a parameter's type annotation (handles TSParameterProperty).
620
+ */
621
+ declare function getParamTypeName(param: AstNode | null | undefined): string;
622
+ /**
623
+ * Maps an Oxc AST node to a TypeScript AST node and fetches its symbol from the TypeChecker.
624
+ * Uses position-based lookup since Oxc and TS nodes do not share identity.
625
+ */
626
+ declare function getTsSymbolAtNode(oxcNode: AstNode | null | undefined, context: RuleContext): typescript.Symbol | undefined;
627
+ /**
628
+ * Checks if a symbol belongs to a well-known Angular type or carries an @Injectable decorator.
629
+ */
630
+ declare function isLikelyAngularInjectableSymbol(symbol: typescript.Symbol | undefined): boolean;
631
+
632
+ declare const rules = "@ngcompass/rules";
633
+
634
+ 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 };