@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.
- package/LICENSE +21 -0
- package/dist/execution-worker.cjs +217 -0
- package/dist/execution-worker.cjs.map +1 -0
- package/dist/execution-worker.d.cts +22 -0
- package/dist/execution-worker.d.ts +22 -0
- package/dist/execution-worker.js +217 -0
- package/dist/execution-worker.js.map +1 -0
- package/dist/index.cjs +432 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +634 -0
- package/dist/index.d.ts +634 -0
- package/dist/index.js +432 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
package/dist/index.d.ts
ADDED
|
@@ -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 };
|