/** * An isomorphic library for detecting and classifying changes between TypeScript declaration files. * * @remarks * This package analyzes TypeScript source code to identify API changes and classify them * according to semantic versioning impact (major, minor, patch, or none). * * This core package is designed to work in both Node.js and browser environments. * It does not use any Node.js-specific APIs like `fs`. * * @example * ```ts * import * as ts from 'typescript'; * import { analyzeChanges } from '@api-extractor-tools/change-detector-core'; * * const result = analyzeChanges(oldSource, newSource, ts); * console.log(`Release type: ${result.releaseType}`); * * for (const { change, releaseType, matchedRule } of result.results) { * console.log(`[${releaseType}] ${change.explanation}`); * } * ``` * * @packageDocumentation */ import type * as ts from 'typescript'; import type { TSESTree } from '@typescript-eslint/typescript-estree'; /** * Adapts a legacy InputProcessorPlugin to the unified plugin format. * * @remarks * Use this function to convert existing legacy plugins to the new unified format * without requiring changes to the plugin itself. * * @param legacy - The legacy plugin to adapt * @returns A unified ChangeDetectorPlugin * * @example * ```typescript * import legacyPlugin from 'some-legacy-plugin'; * import { adaptLegacyInputProcessorPlugin } from '@api-extractor-tools/change-detector-core'; * * const unifiedPlugin = adaptLegacyInputProcessorPlugin(legacyPlugin); * registry.register(unifiedPlugin); * ``` * * @alpha */ export declare function adaptLegacyInputProcessorPlugin(legacy: InputProcessorPlugin): ChangeDetectorPlugin; /** * Descriptor for 'added' actions. * * @alpha */ export declare interface AddedDescriptor extends ChangeDescriptorBase { action: 'added'; aspect?: never; impact?: never; } /** * A normalized AST node ready for comparison. * This is the primary unit of analysis in the AST-based system. * * @alpha */ export declare interface AnalyzableNode { /** * Unique identifier within the module. * Uses dot notation for nesting (e.g., "User", "User.id", "MyNamespace.MyClass.method") */ path: string; /** The export name (may differ from path for nested items) */ name: string; /** The kind of construct */ kind: NodeKind; /** Location in source */ location: SourceRange; /** Parent node path, if this is a nested member */ parent?: string; /** Type information resolved by TypeChecker */ typeInfo: TypeInfo; /** Modifiers applied to this declaration */ modifiers: Set; /** TSDoc metadata if present */ metadata?: NodeMetadata; /** Child nodes (members, parameters, etc.) */ children: Map; /** Heritage clause - types that this class/interface extends */ extends?: string[]; /** Heritage clause - types that this class implements */ implements?: string[]; /** * Raw AST node for advanced analysis. * Note: This should not be serialized; use for runtime analysis only. */ astNode?: TSESTree.Node; } /** * Convenience function that combines parsing, diffing, and classification. * * This is the recommended entry point for change analysis. It handles the * full workflow of: * 1. Parsing both source files into AST analyses with TypeChecker * 2. Computing structural changes between them * 3. Classifying changes according to the policy * 4. Determining the overall release type * * @param oldSource - The old (baseline) source code * @param newSource - The new source code to compare * @param tsModule - The TypeScript module to use for type checking * @param options - Optional configuration for parsing, diffing, and policy * @returns Analysis results including changes, classifications, and release type * * @example * ```ts * import * as ts from 'typescript'; * import { analyzeChanges } from '@api-extractor-tools/change-detector-core'; * * const result = analyzeChanges(oldSource, newSource, ts); * console.log(`Release type: ${result.releaseType}`); * * for (const { change, releaseType, matchedRule } of result.results) { * console.log(`[${releaseType}] ${change.explanation}`); * if (matchedRule) { * console.log(` Rule: ${matchedRule.name}`); * } * } * ``` * * @alpha */ export declare function analyzeChanges(oldSource: string, newSource: string, tsModule: typeof ts, options?: AnalyzeChangesOptions): AnalyzeChangesResult; /** * Options for the analyzeChanges convenience function. * * @alpha */ export declare interface AnalyzeChangesOptions { /** Policy to use for classification (defaults to semverDefaultPolicy) */ policy?: Policy; /** Options for parsing source code */ parseOptions?: ParseOptions; /** Options for comparing modules */ diffOptions?: DiffOptions; } /** * Result of analyzing changes between two source files. * * @alpha */ export declare interface AnalyzeChangesResult { /** All detected API changes */ changes: ApiChange[]; /** Classification results with matched rules */ results: ClassificationResult[]; /** The overall release type (highest severity) */ releaseType: ReleaseType; } /** * A raw detected change before policy application. * * @alpha */ export declare interface AnalyzedChange { /** The name of the symbol that changed */ symbolName: string; /** The kind of symbol */ symbolKind: SymbolKind; /** What kind of change occurred */ category: ChangeCategory; /** Human-readable explanation of the change */ explanation: string; /** Old signature (for modified/removed symbols) */ before?: string; /** New signature (for modified/added symbols) */ after?: string; /** Additional details for policy decisions */ details?: ChangeDetails; } /** * An API change detected between two versions. * Uses multi-dimensional classification for precise policy matching. * * @alpha */ export declare interface ApiChange { /** Multi-dimensional change classification */ descriptor: ChangeDescriptor; /** The affected node path (e.g., "MyInterface.myProperty") */ path: string; /** The kind of AST node affected */ nodeKind: NodeKind; /** Location in old source (for modifications/removals) */ oldLocation?: SourceRange; /** Location in new source (for modifications/additions) */ newLocation?: SourceRange; /** The old node (for modifications/removals) */ oldNode?: AnalyzableNode; /** The new node (for modifications/additions) */ newNode?: AnalyzableNode; /** Nested changes within this node (hierarchical view) */ nestedChanges: ApiChange[]; /** Additional context for this change */ context: ChangeContext; /** Human-readable explanation */ explanation: string; } /** * An input processor that produces AST analysis instead of symbol maps. * * @alpha */ export declare interface ASTAwareInputProcessor { /** * Process input content and return AST analysis. * * @param content - The input content to process * @param filename - Optional filename for context * @returns AST process result with module analysis */ processAST(content: string, filename?: string): Promise | ASTProcessResult; } /** * Definition of an AST-aware policy capability. * * This extends the base PolicyDefinition to create policies that can * leverage the full structural context from AST analysis. * * @alpha */ export declare interface ASTAwarePolicyDefinition extends Omit, 'createPolicy'> { /** * Whether this policy requires AST context. * If true, the policy will only be used when AST analysis is available. */ readonly requiresAST: true; /** * Creates an AST-aware policy instance. * * @param options - Optional configuration for the policy * @returns A rule-based policy instance */ createPolicy(options?: TOptions): Policy; } /** * Options for AST-aware policies that extend the base policy options. * * @alpha */ export declare interface ASTAwarePolicyOptions extends PolicyOptions { /** Whether to treat nested changes differently */ treatNestedChangesAsMinor?: boolean; /** Custom severity overrides by descriptor key (e.g., "export:removed") */ severityOverrides?: Partial>; /** Whether renames should be treated as breaking */ renamesAreBreaking?: boolean; /** Maximum depth to report nested changes */ maxNestedDepth?: number; } /** * An AST-aware reporter instance that can format structural changes. * * @alpha */ export declare interface ASTAwareReporter { /** * Formats an AST comparison report. * * @param report - The AST comparison report to format * @param options - Formatting options * @returns Formatted output */ formatAST(report: ASTComparisonReport, options?: ASTAwareReporterOptions): Promise | string; } /** * Definition of an AST-aware reporter capability. * * @alpha */ export declare interface ASTAwareReporterDefinition extends Omit, 'createReporter'> { /** * Whether this reporter supports AST-aware output. */ readonly supportsAST: true; /** * Creates a reporter that can format AST comparison reports. */ createReporter(options?: TOptions): ASTAwareReporter; } /** * Extended reporter options that include AST-specific options. * * @alpha */ export declare interface ASTAwareReporterOptions extends ReporterOptions { /** AST-specific reporter options */ ast?: ASTReporterOptions; } /** * Capability object for AST-based analysis. * * Plugins can implement this to provide AST-aware functionality. * * @alpha */ export declare interface ASTCapability { /** * Compares two module analyses and returns structural changes. * * @param oldAnalysis - The old module analysis * @param newAnalysis - The new module analysis * @returns Array of API changes */ compareModules(oldAnalysis: ModuleAnalysis, newAnalysis: ModuleAnalysis): ApiChange[]; /** * Applies a policy to classify API changes. * * @param changes - The API changes to classify * @param policy - The policy to apply * @returns Classified changes with release types */ applyPolicy(changes: ApiChange[], policy: Policy): ClassifiedChange[]; } /** * JSON-serializable change representation. * * @alpha */ export declare interface ASTChangeJSON { path: string; /** Descriptor key in format "target:action" or "target:action:aspect" */ changeKind: string; /** The target of the change (export, parameter, property, etc.) */ target: string; /** The action performed (added, removed, modified, etc.) */ action: string; /** The aspect that changed (for modified actions) */ aspect?: string; /** The semantic impact (widening, narrowing, etc.) */ impact?: string; nodeKind: string; releaseType: ReleaseType; explanation: string; oldLocation?: { start: { line: number; column: number; }; end: { line: number; column: number; }; }; newLocation?: { start: { line: number; column: number; }; end: { line: number; column: number; }; }; oldSignature?: string; newSignature?: string; nestedChanges?: ASTChangeJSON[]; } /** * A report grouping changes by release type. * * @alpha */ export declare interface ASTComparisonReport { /** The overall release type */ releaseType: ReleaseType; /** All classified changes */ changes: ClassifiedChange[]; /** Changes grouped by release type */ byReleaseType: Record; /** Summary statistics */ stats: { total: number; forbidden: number; major: number; minor: number; patch: number; none: number; }; } /** * Information about a function/method parameter. * * @alpha */ export declare interface ASTParameterInfo { /** Name of the parameter */ name: string; /** Normalized name (arg0, arg1, etc.) for comparison */ normalizedName: string; /** Type annotation as string */ type: string; /** Whether the parameter is optional */ optional: boolean; /** Whether the parameter is a rest parameter (...args) */ rest: boolean; /** Default value expression, if any */ defaultValue?: string; /** Source location of the parameter */ location: SourceRange; } /** * Extended process result that includes AST analysis. * * @alpha */ export declare interface ASTProcessResult { /** The parsed module analysis */ analysis: ModuleAnalysis; /** Any parse errors encountered */ errors: string[]; } /** * Options for AST-aware reporters. * * @alpha */ export declare interface ASTReporterOptions { /** Whether to include source locations */ includeLocations?: boolean; /** Whether to show nested changes inline or flat */ flattenNested?: boolean; /** Maximum depth of nested changes to show */ maxDepth?: number; /** Whether to include unchanged items (releaseType: 'none') */ includeUnchanged?: boolean; /** File path prefix for source locations (e.g., 'src/api.d.ts') */ oldFilePath?: string; newFilePath?: string; /** Whether to use colors (for terminal output) */ useColors?: boolean; /** Whether to show diff-style before/after */ showDiff?: boolean; } /** * JSON-serializable report representation. * * @alpha */ export declare interface ASTReportJSON { releaseType: ReleaseType; stats: { total: number; forbidden: number; major: number; minor: number; patch: number; none: number; }; changes: { forbidden: ASTChangeJSON[]; major: ASTChangeJSON[]; minor: ASTChangeJSON[]; patch: ASTChangeJSON[]; none: ASTChangeJSON[]; }; } /** * Reporter that supports async operations. * * @remarks * Use this interface for reporters that need to perform I/O, * such as writing to files or making network requests. * * @alpha */ export declare interface AsyncReporter { /** * Formats a complete comparison report asynchronously. */ format(report: ComparisonReport): Promise; /** * Formats a single change asynchronously. */ formatChange?(change: Change): Promise; /** * Async setup hook. */ begin?(): Promise; /** * Async teardown hook. */ end?(): Promise; } /** * Calculate confidence score for how well a pattern captures a dimensional rule. * * This function measures information preservation by comparing: * - Action preservation (weighted 3x) * - Aspect preservation (weighted 2.5x) * - Target preservation (weighted 2x) * - Impact preservation (weighted 2x) * - Node kind preservation (weighted 1.5x) * - Nested flag preservation (weighted 1x) * - Release type match (weighted 2x) * - Description preservation (weighted 0.5x) * * Useful for validating roundtrip transformations or choosing between * alternative pattern representations. * * @param dimensional - The original dimensional rule * @param pattern - The proposed pattern representation * @returns Confidence score between 0 and 1 * * @example * ```typescript * const dimensional: DimensionalRule = { * type: 'dimensional', * action: ['removed'], * target: ['export'], * returns: 'major' * } * * const pattern: PatternRule = { * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major' * } * * const confidence = calculatePatternConfidence(dimensional, pattern) * // Returns: ~0.9 (high - action, target, and returns all match) * ``` * * @alpha */ export declare function calculatePatternConfidence(dimensional: DimensionalRule, pattern: PatternRule): number; /** * A detected change between old and new API, classified with a release type. * * @alpha */ export declare interface Change extends AnalyzedChange { /** Semver impact of this change */ releaseType: ReleaseType; } /** * What happened to the target construct. * * @alpha */ export declare type ChangeAction = 'added' | 'removed' | 'modified' | 'renamed' | 'reordered'; /** * What aspect of the target changed (for 'modified' actions). * * @alpha */ export declare type ChangeAspect = 'type' | 'optionality' | 'readonly' | 'visibility' | 'abstractness' | 'staticness' | 'deprecation' | 'default-value' | 'constraint' | 'default-type' | 'enum-value' | 'extends-clause' | 'implements-clause'; /** * Categories of API changes detected by the comparator. * The versioning impact of each category is determined by the policy. * * @alpha */ export declare type ChangeCategory = 'symbol-removed' | 'symbol-added' | 'type-narrowed' | 'type-widened' | 'param-added-required' | 'param-added-optional' | 'param-removed' | 'param-order-changed' | 'return-type-changed' | 'signature-identical' | 'field-deprecated' | 'field-undeprecated' | 'field-renamed' | 'default-added' | 'default-removed' | 'default-changed' | 'optionality-loosened' | 'optionality-tightened' | 'enum-member-added' | 'enum-type-opened' | 'enum-type-closed'; /** * Additional context for a detected change. * * @alpha */ export declare interface ChangeContext { /** Is this a nested change within another change? */ isNested: boolean; /** Depth of nesting (0 = top-level export) */ depth: number; /** Parent change paths that contain this change */ ancestors: string[]; /** For renames: confidence score (0-1) */ renameConfidence?: number; /** For modifier changes: which modifier changed */ modifierChange?: { modifier: Modifier; direction: 'added' | 'removed'; }; /** Old type signature (for type changes) */ oldType?: string; /** New type signature (for type changes) */ newType?: string; } /** * Multi-dimensional change classification. * Uses a discriminated union to enforce that 'modified' actions * include both aspect and impact. * * @alpha */ export declare type ChangeDescriptor = AddedDescriptor | RemovedDescriptor | ModifiedDescriptor | RenamedDescriptor | ReorderedDescriptor; /** * Base properties shared by all change descriptors. */ declare interface ChangeDescriptorBase { /** What construct was affected */ target: ChangeTarget; /** Additional metadata tags for fine-grained policy matching */ tags: Set; } /** * Detailed analysis data that might be useful for policy decisions. * * @alpha */ declare interface ChangeDetails { /** * For 'param-order-changed', this contains the detailed analysis of the reordering. */ parameterAnalysis?: ParameterOrderAnalysis; } /** * A unified plugin that can provide any combination of change-detector capabilities. * * @remarks * Plugins are discovered via npm package.json keywords: * - `"change-detector:plugin"` - Unified plugins (preferred) * - `"change-detector:input-processor-plugin"` - Legacy input processor plugins * * Plugins should export a default export conforming to this interface, * or a factory function that returns this interface. * * @example * ```typescript * // Simple plugin with static configuration * const plugin: ChangeDetectorPlugin = { * metadata: { * id: 'my-custom-plugin', * name: 'My Custom Plugin', * version: '1.0.0', * }, * policies: [{ * id: 'relaxed', * name: 'Relaxed Policy', * createPolicy: () => ({ name: 'relaxed', classify: () => 'patch' }) * }] * }; * export default plugin; * ``` * * @example * ```typescript * // Multi-capability plugin * const plugin: ChangeDetectorPlugin = { * metadata: { * id: 'graphql', * name: 'GraphQL Plugin', * version: '1.0.0', * }, * inputProcessors: [{ * id: 'schema', * name: 'GraphQL Schema Processor', * extensions: ['.graphql', '.gql'], * createProcessor: () => new GraphQLSchemaProcessor(), * }], * policies: [{ * id: 'strict', * name: 'GraphQL Strict Policy', * createPolicy: () => graphqlStrictPolicy, * }], * reporters: [{ * id: 'diff', * name: 'GraphQL Diff Reporter', * format: 'text', * createReporter: () => new GraphQLDiffReporter(), * }], * }; * export default plugin; * ``` * * @alpha */ export declare interface ChangeDetectorPlugin { /** * Plugin metadata for identification and display. */ readonly metadata: PluginMetadata; /** * Input processors provided by this plugin. * These transform various file formats into the normalized symbol map. */ readonly inputProcessors?: readonly InputProcessorDefinition[]; /** * Versioning policies provided by this plugin. * These classify changes into semantic versioning impact levels. */ readonly policies?: readonly PolicyDefinition[]; /** * Reporters provided by this plugin. * These format comparison reports for various output targets. */ readonly reporters?: readonly ReporterDefinition[]; /** * Validators provided by this plugin. * These perform pre-comparison validation checks. */ readonly validators?: readonly ValidatorDefinition[]; } /** * Extended plugin interface with lifecycle support. * * @alpha */ export declare interface ChangeDetectorPluginWithLifecycle extends ChangeDetectorPlugin, PluginLifecycle { } /** * The semantic effect of the change. * Critical for variance-aware policies (read-only vs write-only APIs). * Required for all 'modified' actions. * * @alpha */ export declare type ChangeImpact = 'widening' | 'narrowing' | 'equivalent' | 'unrelated' | 'undetermined'; /** * A predicate that matches changes based on their descriptor. * * @alpha */ export declare type ChangeMatcher = (change: ApiChange) => boolean; /** * Changes grouped by their semver impact. * * @alpha */ export declare interface ChangesByImpact { /** Changes that are never allowed, even in major releases */ forbidden: Change[]; /** Changes requiring a major version bump (breaking changes) */ breaking: Change[]; /** Changes requiring a minor version bump (additions/compatible changes) */ nonBreaking: Change[]; /** Changes with no version impact (patch or none) */ unchanged: Change[]; } /** * Metadata tags for fine-grained policy matching. * Use for secondary characteristics that don't warrant a full dimension. * * @alpha */ export declare type ChangeTag = 'was-required' | 'now-required' | 'was-optional' | 'now-optional' | 'is-rest-parameter' | 'was-rest-parameter' | 'has-default' | 'had-default' | 'is-nested-change' | 'has-nested-changes' | 'affects-type-parameter'; /** * What API construct was affected by the change. * Fine-grained to allow precise policy matching. * * @alpha */ export declare type ChangeTarget = 'export' | 'parameter' | 'return-type' | 'type-parameter' | 'property' | 'method' | 'enum-member' | 'index-signature' | 'constructor' | 'accessor'; /** * Result of classifying a change with a policy. * * @remarks * This type extends ClassifiedChange which contains the full change data * plus the release type and matched rule info. The `change` property is * provided for backward compatibility but is effectively the same as `this`. * * New code should use ClassifiedChange directly. * * @alpha */ export declare interface ClassificationResult extends ClassifiedChange { /** * The original change (for backward compatibility). * @deprecated Access properties directly on the result instead. */ change: ApiChange; } /** * An API change with its release type classification. * This is the output of applying a policy to an ApiChange. * * @alpha */ export declare interface ClassifiedChange extends ApiChange { /** The semver release type determined by the policy */ releaseType: ReleaseType; /** The policy rule that matched this change (undefined if default was used) */ matchedRule?: { /** Name of the matching rule */ name?: string; /** Description of why the rule matched */ description?: string; }; } /** * Applies a policy to classify a single change. * * @param change - The change to classify * @param policy - The policy to apply * @returns Classification result with release type and matched rule * * @alpha */ export declare function classifyChange(change: ApiChange, policy: Policy): ClassificationResult; /** * Applies a policy to classify multiple changes. * * @param changes - The changes to classify * @param policy - The policy to apply * @returns Array of classification results * * @alpha */ export declare function classifyChanges(changes: ApiChange[], policy: Policy): ClassificationResult[]; /** * Additional context passed to policy classify() for informed decisions. * * @alpha */ export declare interface ClassifyContext { /** Metadata from the old (baseline) symbol */ oldMetadata?: SymbolMetadata; /** Metadata from the new symbol */ newMetadata?: SymbolMetadata; } /** * Pre-defined common intent expressions * * @alpha */ export declare const COMMON_INTENTS: { readonly BREAKING_REMOVAL: IntentExpression; readonly BREAKING_RENAME: IntentExpression; readonly BREAKING_REQUIRED: IntentExpression; readonly BREAKING_NARROWING: IntentExpression; readonly SAFE_ADDITION: IntentExpression; readonly SAFE_OPTIONAL: IntentExpression; readonly SAFE_WIDENING: IntentExpression; readonly PATCH_DEPRECATION: IntentExpression; }; /** * Pre-defined common patterns for quick rule creation * * @alpha */ export declare const COMMON_PATTERNS: { readonly EXPORT_REMOVAL: PatternTemplate; readonly MEMBER_REMOVAL: PatternTemplate; readonly REQUIRED_ADDITION: PatternTemplate; readonly OPTIONAL_ADDITION: PatternTemplate; readonly TYPE_NARROWING: PatternTemplate; readonly TYPE_WIDENING: PatternTemplate; readonly MADE_OPTIONAL: PatternTemplate; readonly MADE_REQUIRED: PatternTemplate; readonly DEPRECATION: PatternTemplate; readonly RENAME: PatternTemplate; readonly REORDER: PatternTemplate; }; /** * The complete comparison report. * * @alpha */ export declare interface ComparisonReport { /** Overall release type classification based on all changes */ releaseType: ReleaseType; /** All changes grouped by impact */ changes: ChangesByImpact; /** Numeric statistics about the comparison */ stats: ComparisonStats; /** Identifier for the old declaration source (file path or label) */ oldFile: string; /** Identifier for the new declaration source (file path or label) */ newFile: string; } /** * Statistics about the comparison. * * @alpha */ export declare interface ComparisonStats { /** Total number of symbols in the old declaration file */ totalSymbolsOld: number; /** Total number of symbols in the new declaration file */ totalSymbolsNew: number; /** Number of symbols added */ added: number; /** Number of symbols removed */ removed: number; /** Number of symbols modified */ modified: number; /** Number of symbols unchanged */ unchanged: number; } /** * Compile a pattern rule into dimensional representation. * * This function transforms template-based pattern rules into the lowest-level * dimensional representation, extracting all dimensional components: * * - **Actions**: From template prefixes (added, removed, renamed, etc.) * - **Aspects**: From template suffixes (type narrowed, deprecated, etc.) * - **Targets**: From variable substitutions with type='target' * - **Impacts**: Inferred from the combination of action, aspect, and release type * - **Node kinds**: From variables with type='nodeKind' * - **Nested flag**: Set for conditional patterns ('when', 'unless') * * The compilation will fail if the pattern doesn't specify at least one * dimension (action, aspect, or target). * * @param pattern - The pattern rule to compile * @returns Compilation result with dimensional rule (on success) or errors (on failure) * * @example Basic compilation * ```typescript * const result = compilePattern({ * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major' * }) * * if (result.success) { * // result.dimensional contains the compiled rule * console.log(result.dimensional.action) // ['removed'] * console.log(result.dimensional.target) // ['export'] * } * ``` * * @example Type change pattern * ```typescript * const result = compilePattern({ * type: 'pattern', * template: '{target} type narrowed', * variables: [{ name: 'target', value: 'return-type', type: 'target' }], * returns: 'major' * }) * // result.dimensional.aspect = ['type'] * // result.dimensional.impact = ['narrowing'] * ``` * * @alpha */ export declare function compilePattern(pattern: PatternRule): PatternCompileResult; /** * Creates an AST-aware policy definition. * * @example * ```ts * import { rule, createPolicy } from '@api-extractor-tools/change-detector-core/ast'; * * const myPolicy = createASTAwarePolicyDefinition({ * id: 'my-custom-policy', * name: 'My Custom Policy', * description: 'A policy with custom classification logic', * createPolicy: (options) => createPolicy('my-custom-policy', 'major') * .addRule(rule('deprecation').aspect('deprecation').returns('patch')) * .addRule(rule('removal').action('removed').returns('major')) * .build(), * }) * ``` * * @alpha */ export declare function createASTAwarePolicyDefinition(definition: Omit, 'requiresAST'>): ASTAwarePolicyDefinition; /** * Creates an AST-aware reporter definition. * * @example * ```ts * const myReporter = createASTAwareReporterDefinition({ * id: 'my-custom-reporter', * name: 'My Custom Reporter', * formats: ['text'], * createReporter: (options) => ({ * formatAST: (report) => { * // Custom formatting logic * return `Changes: ${report.stats.total}` * }, * }), * }) * ``` * * @alpha */ export declare function createASTAwareReporterDefinition(definition: Omit, 'supportsAST'>): ASTAwareReporterDefinition; /** * Creates a comparison report from classified changes. * * @alpha */ export declare function createASTComparisonReport(changes: ClassifiedChange[]): ASTComparisonReport; /** * Creates a new plugin registry. * * @param options - Registry options * @returns A new plugin registry instance * * @example * ```typescript * const registry = createPluginRegistry(); * * registry.register(myPlugin); * * const processor = registry.getInputProcessor('typescript:default'); * const processors = registry.findInputProcessorsForExtension('.ts'); * ``` * * @alpha */ export declare function createPluginRegistry(options?: PluginRegistryOptions): PluginRegistry; /** * Creates a new policy builder. * * @param name - Human-readable name for the policy * @param defaultReleaseType - Release type when no rule matches * * @example * ```ts * const policy = createPolicy('semver-strict', 'major') * .addRule(rule('removal').action('removed').returns('major')) * .addRule(rule('addition').action('added').returns('minor')) * .build(); * ``` * * @alpha */ export declare function createPolicy(name: string, defaultReleaseType: ReleaseType): PolicyBuilder; /** * Create a new progressive rule builder. * * This is the main entry point for building Progressive DSL policies. * * @returns A new ProgressiveRuleBuilder instance * * @example * ```typescript * const policy = createProgressivePolicy() * .intent('export removal is breaking', 'major') * .pattern('added optional {target}', { target: 'parameter' }, 'none') * .build('my-policy', 'patch') * ``` * * @alpha */ export declare function createProgressivePolicy(): ProgressiveRuleBuilder; /** * Create a policy with common, pre-configured patterns. * * This is a convenience function for quickly creating policies with * standard semantic versioning rules. * * @param name - Unique name identifying this policy * @param config - Configuration object with feature toggles: * - `breakingRemovals` - Include rules for breaking removals (default: true) * - `safeAdditions` - Include rules for safe additions (default: true) * - `deprecations` - Include rules for deprecation handling (default: true) * - `typeNarrowing` - Include rules for type changes (default: true) * - `defaultReleaseType` - Default release type for unmatched changes (default: 'none') * @returns A complete DSLPolicy ready for use * * @example * ```typescript * const standardPolicy = createStandardPolicy('my-standard-policy', { * breakingRemovals: true, * safeAdditions: true, * deprecations: true, * typeNarrowing: true, * defaultReleaseType: 'patch' * }) * ``` * * @example Minimal configuration * ```typescript * // Use all defaults * const policy = createStandardPolicy('standard') * ``` * * @alpha */ export declare function createStandardPolicy(name: string, config?: { breakingRemovals?: boolean; safeAdditions?: boolean; deprecations?: boolean; typeNarrowing?: boolean; defaultReleaseType?: ReleaseType; }): DSLPolicy; /** * Decompile a dimensional rule into pattern representation. * * This function transforms low-level dimensional rules back into readable * pattern templates. It uses a catalog of pattern mappings with confidence * scoring to find the best representation. * * The decompilation process: * 1. Validates the input dimensional rule * 2. Finds all pattern mappings that match the dimensions * 3. Calculates confidence scores for each match * 4. Returns the best match with alternatives * * If no patterns match, it falls back to creating a generic pattern based * on the action (e.g., "modified \{target\}"). * * @param dimensional - The dimensional rule to decompile * @returns Decompilation result with pattern, confidence, and alternatives * * @example Basic decompilation * ```typescript * const result = decompileToPattern({ * type: 'dimensional', * action: ['removed'], * target: ['export'], * impact: ['narrowing'], * returns: 'major' * }) * * if (result.success) { * console.log(result.pattern?.template) // 'removed {target}' * console.log(result.confidence) // ~0.8 * console.log(result.alternatives?.length) // 0-3 alternatives * } * ``` * * @example Type change decompilation * ```typescript * const result = decompileToPattern({ * type: 'dimensional', * action: ['modified'], * aspect: ['type'], * impact: ['narrowing'], * target: ['return-type'], * returns: 'major' * }) * // result.pattern.template = '{target} type narrowed' * // result.confidence ≈ 0.9 (high due to aspect + impact match) * ``` * * @example Fallback for unrecognized dimensions * ```typescript * const result = decompileToPattern({ * type: 'dimensional', * returns: 'patch' * // No action, aspect, or target specified * }) * // Falls back to 'modified {target}' with low confidence (0.2) * ``` * * @alpha */ export declare function decompileToPattern(dimensional: DimensionalRule): PatternDecompileResult; /** * Built-in AST-aware default policy definition. * * @alpha */ export declare const defaultASTPolicy: ASTAwarePolicyDefinition; /** * Detect common pattern categories that map to natural language. * * This function categorizes patterns into semantic groups, which can be * useful for reporting, grouping, or documentation purposes. * * @param pattern - The pattern rule to analyze * @returns Pattern category name or null if not recognized * * ## Pattern Categories * * - `'removal-pattern'` - Patterns involving removal of elements * - `'addition-pattern'` - Patterns involving addition of elements * - `'type-change-pattern'` - Patterns involving type modifications * - `'optionality-pattern'` - Patterns involving optional/required changes * - `'deprecation-pattern'` - Patterns involving deprecation * - `'rename-pattern'` - Patterns involving renaming * - `'reorder-pattern'` - Patterns involving reordering * - `'conditional-when-pattern'` - Patterns with 'when' conditions * - `'conditional-unless-pattern'` - Patterns with 'unless' conditions * - `'compound-and-pattern'` - Patterns with AND logic * - `'compound-or-pattern'` - Patterns with OR logic * * @example * ```typescript * const category = detectCommonPattern({ * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major' * }) * // Returns: 'removal-pattern' * ``` * * @alpha */ export declare function detectCommonPattern(pattern: PatternRule): string | null; /** * Detects if parameters have been reordered between two signatures. * * This provides rich analysis including: * - Whether reordering is detected * - Confidence level based on the evidence * - Detailed per-position analysis with similarity scores * - Human-readable interpretations for user feedback * * @param oldParams - Parameter info from the old signature * @param newParams - Parameter info from the new signature * @returns Detailed analysis result * * @alpha */ export declare function detectParameterReordering(oldParams: ParameterInfo[], newParams: ParameterInfo[]): ParameterOrderAnalysis; /** * Determines the overall release type from classification results. * Returns the highest severity: forbidden \> major \> minor \> patch \> none. * * @param results - Array of classified changes or classification results * @returns The highest severity release type * * @alpha */ export declare function determineOverallRelease(results: ReadonlyArray>): ReleaseType; /** * Compares two module analyses and produces API changes. * * Requires TypeChecker for accurate semantic analysis. Use `parseModuleWithTypes()` * to create the input analyses. * * @param oldAnalysis - The old (baseline) module analysis with TypeChecker * @param newAnalysis - The new module analysis with TypeChecker * @param options - Comparison options * @returns Array of API changes with multi-dimensional descriptors * * @alpha */ export declare function diffModules(oldAnalysis: ModuleAnalysisWithTypes, newAnalysis: ModuleAnalysisWithTypes, options?: DiffOptions): ApiChange[]; /** * Options for comparing two module analyses. * * @alpha */ export declare interface DiffOptions { /** Threshold for rename detection (0-1, default 0.8) */ renameThreshold?: number; /** Whether to include nested member changes */ includeNestedChanges?: boolean; /** Whether to resolve type relationships */ resolveTypeRelationships?: boolean; /** Maximum depth for nested change detection */ maxNestingDepth?: number; /** Whether to detect parameter reordering (default: true) */ detectParameterReordering?: boolean; } /** * Full dimensional rule using the existing multi-dimensional system. * * The Dimensional DSL provides the most precise control by directly specifying * multi-dimensional change characteristics. This level is compatible with the * legacy RuleBuilder system. * * ## When to Use Direct Dimensions * * Use the dimensional DSL when you need: * - **Maximum Precision**: Complex rules that can't be expressed naturally in higher levels * - **Legacy Compatibility**: Migrating from existing RuleBuilder-based policies * - **Performance**: Direct dimensional matching without transformation overhead * - **Complex Conditions**: Rules with multiple intersecting dimensions * * ## Complete Dimension Reference * * **Targets** (`ChangeTarget`): * - `'export'` - Public API exports * - `'parameter'` - Function/method parameters * - `'property'` - Object/class properties * - `'return-type'` - Function return types * - `'type-parameter'` - Generic type parameters * - `'method'` - Class methods * - `'constructor'` - Class constructors * * **Actions** (`ChangeAction`): * - `'added'` - Something was added * - `'removed'` - Something was removed * - `'renamed'` - Something was renamed * - `'reordered'` - Order was changed * - `'modified'` - Something was modified * * **Aspects** (`ChangeAspect`): * - `'type'` - Type-related changes * - `'optionality'` - Optional/required changes * - `'deprecation'` - Deprecation status changes * - `'visibility'` - Access level changes * - `'inheritance'` - Inheritance hierarchy changes * * **Impacts** (`ChangeImpact`): * - `'narrowing'` - Restricts possible values/usage * - `'widening'` - Expands possible values/usage * - `'equivalent'` - No semantic impact * - `'unrelated'` - Impact is context-dependent * - `'undetermined'` - Impact cannot be determined * * **Tags** (`ChangeTag`): * - `'optional'` - Marked as optional * - `'deprecated'` - Marked as deprecated * - `'internal'` - Internal/private API * - `'experimental'` - Experimental API * - `'breaking'` - Explicitly marked breaking * * **Node Kinds** (`NodeKind`): * - `'function'` - Function declarations * - `'class'` - Class declarations * - `'interface'` - Interface declarations * - `'enum'` - Enum declarations * - `'type-alias'` - Type alias declarations * - `'variable'` - Variable declarations * - `'namespace'` - Namespace declarations * * @example * ```typescript * const dimensionalPolicy = createProgressivePolicy() * .dimensional('export-removal') * .action('removed') * .target('export') * .impact('narrowing') * .returns('major') * * .dimensional('optional-param-addition') * .action('added') * .target('parameter') * .hasTag('optional') * .impact('widening') * .returns('none') * * .dimensional('deprecation') * .aspect('deprecation') * .impact('equivalent') * .returns('patch') * * .build('dimensional-policy', 'none') * ``` * * @alpha */ export declare interface DimensionalRule { /** Discriminator for the rule type */ type: 'dimensional'; /** Targets that this rule applies to (e.g., 'export', 'parameter') */ target?: ChangeTarget[]; /** Actions that this rule matches (e.g., 'added', 'removed') */ action?: ChangeAction[]; /** Aspects of the change (e.g., 'type', 'optionality') */ aspect?: ChangeAspect[]; /** Impact classification (e.g., 'narrowing', 'widening') */ impact?: ChangeImpact[]; /** Tags that must be present for the rule to match */ tags?: ChangeTag[]; /** Tags that must NOT be present for the rule to match */ notTags?: ChangeTag[]; /** Node kinds this rule applies to (e.g., 'function', 'class') */ nodeKind?: NodeKind[]; /** Whether this rule applies to nested changes */ nested?: boolean; /** The release type to use when this rule matches */ returns: ReleaseType; /** Optional human-readable description */ description?: string; } /** * Fluent builder for dimensional rules. * * This class provides a chainable API for building dimensional rules * with maximum precision. It's returned by {@link ProgressiveRuleBuilder.dimensional} * and allows specifying all dimensional constraints before returning to the * main builder. * * @example * ```typescript * builder * .dimensional('nested-interface-modification') * .action('modified') * .target('property') * .aspect('type') * .impact('narrowing') * .hasTag('breaking') * .nested(true) * .returns('major') * ``` */ declare class DimensionalRuleBuilder { private progressiveBuilder; private currentRule; constructor(name: string, progressiveBuilder: T); /** * Specify change actions to match. * * @param actions - One or more actions ('added', 'removed', 'renamed', 'reordered', 'modified') * @returns This builder for chaining * * @example * ```typescript * .action('added', 'removed') * ``` */ action(...actions: ChangeAction[]): this; /** * Specify change targets to match. * * @param targets - One or more targets ('export', 'parameter', 'property', etc.) * @returns This builder for chaining * * @example * ```typescript * .target('export', 'parameter') * ``` */ target(...targets: ChangeTarget[]): this; /** * Specify change aspects to match. * * @param aspects - One or more aspects ('type', 'optionality', 'deprecation', etc.) * @returns This builder for chaining * * @example * ```typescript * .aspect('type', 'optionality') * ``` */ aspect(...aspects: ChangeAspect[]): this; /** * Specify change impacts to match. * * @param impacts - One or more impacts ('narrowing', 'widening', 'equivalent', etc.) * @returns This builder for chaining * * @example * ```typescript * .impact('narrowing', 'unrelated') * ``` */ impact(...impacts: ChangeImpact[]): this; /** * Specify tags that must be present for the rule to match. * * @param tags - One or more tags ('optional', 'deprecated', 'internal', etc.) * @returns This builder for chaining * * @example * ```typescript * .hasTag('optional', 'deprecated') * ``` */ hasTag(...tags: ChangeTag[]): this; /** * Mark this rule as applying to nested changes. * * @param value - Whether to match nested changes (default: true) * @returns This builder for chaining * * @example * ```typescript * .nested(true) * ``` */ nested(value?: boolean): this; /** * Complete the dimensional rule and return to the main builder. * * @param releaseType - The release type for this rule ('major', 'minor', 'patch', 'none') * @returns The parent ProgressiveRuleBuilder for continued chaining * * @example * ```typescript * .returns('major') * ``` */ returns(releaseType: ReleaseType): T; } /** * Represents a discovered plugin before it's loaded. * * @remarks * Used by the plugin discovery system in Node.js environments. * * @alpha */ export declare interface DiscoveredPlugin { /** * npm package name. */ readonly packageName: string; /** * Package version. */ readonly packageVersion: string; /** * Absolute path to the package. */ readonly packagePath: string; /** * Keywords found in package.json. */ readonly keywords: readonly string[]; /** * Whether this is a legacy input processor plugin. */ readonly isLegacy: boolean; } /** * Fluent builder state for progressive rule creation * * @alpha */ export declare interface DSLBuilderState { currentLevel: 'intent' | 'pattern' | 'dimensional'; partialRule: Partial; validationErrors: DSLValidationError[]; } /** * A collection of rules forming a complete API change policy. * * Policies are the top-level construct that groups related rules together * with a default behavior for unmatched changes. * * @example * ```typescript * const policy: DSLPolicy = { * name: 'strict-library', * description: 'Policy for stable libraries', * rules: [ * { type: 'intent', expression: 'export removal is breaking', returns: 'major' }, * { type: 'intent', expression: 'deprecation is patch', returns: 'patch' } * ], * defaultReleaseType: 'major' // Conservative default * } * ``` * * @alpha */ export declare interface DSLPolicy { /** Unique name identifying this policy */ name: string; /** Optional human-readable description */ description?: string; /** The rules that make up this policy */ rules: DSLRule[]; /** Release type to use when no rule matches */ defaultReleaseType: ReleaseType; } /** * A rule can be expressed at any of the three DSL levels. * * This union type enables seamless mixing of rules at different abstraction levels * within a single policy. Each rule type can be transformed to any other level * using the transformation functions. * * @see {@link IntentRule} for natural language rules * @see {@link PatternRule} for template-based rules * @see {@link DimensionalRule} for multi-dimensional rules * * @alpha */ export declare type DSLRule = IntentRule | PatternRule | DimensionalRule; /** * Validation error details * * @alpha */ export declare interface DSLValidationError { level: 'intent' | 'pattern' | 'dimensional'; code: string; message: string; location?: { line?: number; column?: number; expression?: string; }; } /** * Validation result for a DSL rule * * @alpha */ export declare interface DSLValidationResult { valid: boolean; errors: DSLValidationError[]; warnings: DSLValidationWarning[]; } /** * Validation warning details * * @alpha */ export declare interface DSLValidationWarning { level: 'intent' | 'pattern' | 'dimensional'; code: string; message: string; suggestion?: string; } /** * Calculates the Levenshtein edit distance between two strings. * This measures the minimum number of single-character edits * (insertions, deletions, substitutions) needed to transform one string into another. * * @alpha */ export declare function editDistance(a: string, b: string): number; /** * Information about an enum member. * * @alpha */ export declare interface EnumMemberInfo { /** Name of the enum member */ name: string; /** Value of the enum member (string or number) */ value: string | number | undefined; /** Whether the value is explicitly assigned */ hasExplicitValue: boolean; /** Source location of the enum member */ location: SourceRange; } /** * Information about a single exported symbol extracted from a declaration file. * * @alpha */ export declare interface ExportedSymbol { /** The name of the exported symbol */ name: string; /** The kind of symbol (function, class, interface, etc.) */ kind: SymbolKind; /** Human-readable type signature */ signature: string; /** Metadata extracted from TSDoc comments */ metadata?: SymbolMetadata; /** Source location of this symbol's declaration (optional) */ sourceLocation?: SourceLocation; } /** * Extended versioning policy interface with optional context support. * * @remarks * Backward compatible with existing VersioningPolicy implementations. * The classify method signature matches the existing interface. * If classifyWithContext is implemented, it is preferred when context is available. * * @alpha */ export declare interface ExtendedVersioningPolicy extends VersioningPolicy { /** * Optional context-aware classification. * * @remarks * If implemented, this method is preferred over `classify` when context is available. * Falls back to `classify` if not implemented. * * @param change - The change to classify * @param context - Additional context for the classification decision * @returns The release type classification */ classifyWithContext?(change: AnalyzedChange, context: PolicyContext): ReleaseType; } /** * Extracts parameter information from a TypeScript signature. * * @alpha */ export declare function extractParameterInfo(sig: ts.Signature, checker: ts.TypeChecker, tsModule: typeof ts): ParameterInfo[]; /** * Find the best matching pattern template for a dimensional rule. * * This is a convenience function that returns just the template string * without the full decompilation result. Useful for quick lookups or * when you only need the template. * * @param dimensional - The dimensional rule to match * @returns Best matching pattern template string, or null if invalid input * * @example * ```typescript * const template = findBestPattern({ * type: 'dimensional', * action: ['removed'], * target: ['export'], * returns: 'major' * }) * // Returns: 'removed {target}' * ``` * * @example With confidence threshold * ```typescript * const template = findBestPattern(rule) * // Returns fallback template if no match has confidence >= 0.3 * ``` * * @alpha */ export declare function findBestPattern(dimensional: DimensionalRule): string | null; /** * Flattens nested changes into a single array. * Useful for reporting or counting total changes. * Adds 'is-nested-change' tag to nested changes. * * Note: This function does NOT mutate the input changes. * Each nested change gets a new descriptor with the tag added. * * @alpha */ export declare function flattenChanges(changes: ApiChange[]): ApiChange[]; /** * Converts an AST comparison report to JSON format. * * @alpha */ export declare function formatASTReportAsJSON(report: ASTComparisonReport, options?: ASTReporterOptions): ASTReportJSON; /** * Formats an AST comparison report as markdown. * * @alpha */ export declare function formatASTReportAsMarkdown(report: ASTComparisonReport, options?: ASTReporterOptions): string; /** * Formats an AST comparison report as plain text. * * @alpha */ export declare function formatASTReportAsText(report: ASTComparisonReport, options?: ASTReporterOptions): string; /** * Formats a source location as a string. * * @alpha */ export declare function formatSourceLocation(location: SourceRange | undefined, filePath?: string): string; /** * Formats validation errors into a human-readable string. * * @param result - The validation result * @param packageName - Optional package name for context * @returns Formatted error message * * @alpha */ export declare function formatValidationErrors(result: PluginValidationResult, packageName?: string): string; /** * Generate a readable natural language expression from a pattern. * * This function creates human-readable text by: * 1. Looking up direct intent mappings * 2. Substituting variables with readable values * 3. Adding severity context from the release type * * Unlike `synthesizeIntent`, this function always returns a string, * using fallback generation for unknown patterns. * * @param pattern - The pattern rule to convert * @returns Natural language expression string * * @example * ```typescript * const expression = generateIntentExpression({ * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major' * }) * // Returns: 'export removal is breaking' * ``` * * @example Generated fallback * ```typescript * const expression = generateIntentExpression({ * type: 'pattern', * template: 'custom {thing}', * variables: [{ name: 'thing', value: 'widget', type: 'target' }], * returns: 'minor' * }) * // Returns: 'minor custom widget' * ``` * * @alpha */ export declare function generateIntentExpression(pattern: PatternRule): string; /** * Groups changes by their descriptor key. * * @alpha */ export declare function groupChangesByDescriptor(changes: ApiChange[]): Map; /** * Helper type for creating policy definitions that work with both * legacy and AST-aware modes. * * @alpha */ export declare type HybridPolicyDefinition = PolicyDefinition | ASTAwarePolicyDefinition; /** * Infer dimensional constraints from a pattern without full compilation. * * This is a lighter-weight alternative to `compilePattern` that returns * a partial dimensional rule with only the constraints that can be * directly inferred from the pattern. Useful for analysis or validation. * * @param pattern - The pattern rule to analyze * @returns Partial dimensional rule with inferred constraints * * @example * ```typescript * const constraints = inferConstraints({ * type: 'pattern', * template: '{target} type narrowed', * variables: [{ name: 'target', value: 'parameter', type: 'target' }], * returns: 'major' * }) * * console.log(constraints.aspect) // ['type'] * console.log(constraints.target) // ['parameter'] * console.log(constraints.impact) // ['narrowing'] * ``` * * @alpha */ export declare function inferConstraints(pattern: PatternRule): Partial; /** * An input processor instance that can process content. * * @remarks * Input processors convert various input formats (TypeScript, GraphQL, OpenAPI, etc.) * into the normalized `Map` representation used by the change detector. * * @alpha */ export declare interface InputProcessor { /** * Process input content and return exported symbols. * * @param content - The input content to process * @param filename - Optional filename for context (used in error messages) * @returns Process result with symbols and any errors */ process(content: string, filename?: string): Promise | ProcessResult; } /** * Definition of an input processor capability. * * @remarks * Input processors transform various file formats into the normalized symbol map * used by the change detector for comparison. * * @example * ```typescript * const processor: InputProcessorDefinition = { * id: 'schema', * name: 'GraphQL Schema Processor', * extensions: ['.graphql', '.gql'], * mimeTypes: ['application/graphql'], * createProcessor: (options) => new GraphQLSchemaProcessor(options), * }; * ``` * * @alpha */ export declare interface InputProcessorDefinition { /** * Identifier for this processor within the plugin. * Combined with plugin ID to form `{pluginId}:{processorId}`. */ readonly id: string; /** * Human-readable name. */ readonly name: string; /** * File extensions this processor handles (including dot). * * @example ['.d.ts', '.ts'] * @example ['.graphql', '.gql'] */ readonly extensions: readonly string[]; /** * Optional description. */ readonly description?: string; /** * MIME types this processor can handle (for browser environments). * * @example ['text/typescript', 'application/typescript'] */ readonly mimeTypes?: readonly string[]; /** * JSON Schema for validating options (optional). * Can be used by tooling for configuration validation. */ readonly optionsSchema?: Record; /** * Creates a processor instance. * * @param options - Optional configuration for the processor * @returns A processor instance, or a Promise resolving to one */ createProcessor(options?: TOptions): InputProcessor | Promise; } /** * Options that can be passed to input processor factories. * * @remarks * Plugin authors should extend this interface for type-safe options. * * @alpha */ export declare interface InputProcessorOptions { /** * Index signature allows plugin-specific options. * Plugin authors should define specific option types and validate at runtime. */ [key: string]: unknown; } /** * Legacy input processor plugin interface. * * @deprecated Use {@link ChangeDetectorPlugin} with inputProcessors array instead. * This interface is provided for backward compatibility during migration. * * @example * ```ts * // Legacy format (deprecated) * const legacyPlugin: InputProcessorPlugin = { * id: 'typescript', * name: 'TypeScript Processor', * version: '1.0.0', * extensions: ['.d.ts'], * createProcessor: () => ({ process: (content) => ({ symbols: new Map(), errors: [] }) }) * }; * * // New unified format (preferred) * const newPlugin: ChangeDetectorPlugin = { * metadata: { id: 'typescript', name: 'TypeScript Processor', version: '1.0.0' }, * inputProcessors: [{ * id: 'default', * name: 'TypeScript Processor', * extensions: ['.d.ts'], * createProcessor: () => ({ process: (content) => ({ symbols: new Map(), errors: [] }) }) * }] * }; * ``` * * @alpha */ export declare interface InputProcessorPlugin { /** Plugin identifier */ id: string; /** Human-readable plugin name */ name: string; /** Plugin version */ version: string; /** File extensions this plugin handles */ extensions: string[]; /** Creates a processor instance */ createProcessor(options?: unknown): InputProcessor; } /** * Natural language expressions that capture user intent directly. * These are the simplest, most readable forms of rules. * * The Intent DSL allows you to express change rules using natural language expressions * that capture your intent directly. * * ## Supported Expression Categories * * **Removal Patterns:** * - `'breaking removal'` - Any removal that breaks the API * - `'safe removal'` - Removals that don't break compatibility * - `'export removal is breaking'` - Specifically export removals * - `'member removal is breaking'` - Specifically member removals * * **Addition Patterns:** * - `'safe addition'` - Additions that don't break compatibility * - `'required addition is breaking'` - Required additions that break compatibility * - `'optional addition is safe'` - Optional additions that are safe * * **Type Change Patterns:** * - `'type narrowing is breaking'` - Type changes that narrow possibilities * - `'type widening is safe'` - Type changes that widen possibilities * - `'type change is breaking'` - Any type change is breaking * * **Optionality Patterns:** * - `'making optional is breaking'` - Making required things optional * - `'making required is breaking'` - Making optional things required * * **Common Patterns:** * - `'deprecation is patch'` - Deprecations result in patch releases * - `'rename is breaking'` - Renames are breaking changes * - `'reorder is breaking'` - Reordering parameters is breaking * * **Conditional Patterns:** * - `'breaking removal when nested'` - Conditional expressions using "when" * - `'safe addition unless required'` - Conditional expressions using "unless" * * @example * ```typescript * const intentPolicy = createProgressivePolicy() * .intent('export removal is breaking', 'major') * .intent('rename is breaking', 'major') * .intent('optional addition is safe', 'none') * .intent('deprecation is patch', 'patch') * .intent('breaking removal when nested', 'major') * .build('intent-based-policy', 'none') * ``` * * @alpha */ export declare type IntentExpression = 'breaking removal' | 'safe removal' | 'export removal is breaking' | 'member removal is breaking' | 'safe addition' | 'required addition is breaking' | 'optional addition is safe' | 'type narrowing is breaking' | 'type widening is safe' | 'type change is breaking' | 'making optional is breaking' | 'making required is breaking' | 'deprecation is patch' | 'rename is breaking' | 'reorder is breaking' | `${string} when ${string}` | `${string} unless ${string}`; /** * Result of parsing an intent expression into a pattern rule. * * When parsing fails, `errors` contains the reasons and `suggestions` * may contain corrected expressions based on Levenshtein distance matching. * * @see {@link parseIntent} for the parsing function * * @example * ```typescript * const result = parseIntent({ * type: 'intent', * expression: 'breaking removal', * returns: 'major' * }) * * if (result.success) { * console.log('Pattern:', result.pattern) * } else { * console.log('Errors:', result.errors) * console.log('Suggestions:', result.suggestions) * } * ``` * * @alpha */ export declare interface IntentParseResult { /** Whether the parse was successful */ success: boolean; /** The parsed pattern rule (when successful) */ pattern?: PatternRule; /** Error messages (when unsuccessful) */ errors?: string[]; /** Suggested corrections for typos or invalid expressions */ suggestions?: string[]; } /** * Intent-based rule definition. * * An intent rule captures a natural language expression that describes * the semantic meaning of a change pattern and its impact. * * @example * ```typescript * const rule: IntentRule = { * type: 'intent', * expression: 'export removal is breaking', * returns: 'major', * description: 'Removing exports breaks dependent code' * } * ``` * * @alpha */ export declare interface IntentRule { /** Discriminator for the rule type */ type: 'intent'; /** The natural language expression describing the rule */ expression: IntentExpression; /** The release type to use when this rule matches */ returns: ReleaseType; /** Optional human-readable description */ description?: string; } /** * Result of synthesizing an intent expression from a pattern rule. * * Includes a confidence score indicating how natural the resulting * intent expression is. * * @see {@link synthesizeIntent} for the synthesis function * * @alpha */ export declare interface IntentSynthesisResult { /** Whether the synthesis was successful */ success: boolean; /** The synthesized intent rule (when successful) */ intent?: IntentRule; /** Confidence score (0-1) indicating how natural the intent expression is */ confidence: number; /** Alternative intent expressions with lower confidence */ alternatives?: IntentRule[]; } /** * Generates a human-readable interpretation of a name change based on similarity. * * @param oldName - The original parameter name * @param newName - The new parameter name * @param similarity - Pre-computed similarity score * @returns Human-readable interpretation * * @alpha */ export declare function interpretNameChange(oldName: string, newName: string, similarity: number): string; /** * Type guard to check if an input processor is AST-aware. * * @alpha */ export declare function isASTAwareInputProcessor(processor: unknown): processor is ASTAwareInputProcessor; /** * Type guard to check if a policy definition is AST-aware. * * @alpha */ export declare function isASTAwarePolicyDefinition(def: HybridPolicyDefinition): def is ASTAwarePolicyDefinition; /** * Type guard to check if a reporter definition is AST-aware. * * @alpha */ export declare function isASTAwareReporterDefinition(def: ReporterDefinition | ASTAwareReporterDefinition): def is ASTAwareReporterDefinition; /** * Type guard to check if a rule is a DimensionalRule. * * @alpha */ export declare function isDimensionalRule(rule: DSLRule): rule is DimensionalRule; /** * Type guard to check if a rule is an IntentRule. * * @alpha */ export declare function isIntentRule(rule: DSLRule): rule is IntentRule; /** * Type guard to check if a rule is a PatternRule. * * @alpha */ export declare function isPatternRule(rule: DSLRule): rule is PatternRule; /** * Validate whether a string is a valid intent expression. * * This function checks if the expression: * 1. Matches a known intent expression in the mapping * 2. Is a valid conditional pattern (contains 'when' or 'unless') * * Use this to validate user input before constructing intent rules. * * @param expression - The expression string to validate * @returns True if the expression is valid, false otherwise (also acts as type guard) * * @example * ```typescript * if (isValidIntentExpression('breaking removal')) { * // TypeScript now knows this is IntentExpression * const rule: IntentRule = { * type: 'intent', * expression: expression, // type-safe * returns: 'major' * } * } * ``` * * @example Validating user input * ```typescript * function createRuleFromInput(userInput: string): IntentRule | null { * if (isValidIntentExpression(userInput)) { * return { type: 'intent', expression: userInput, returns: 'major' } * } * return null * } * ``` * * @alpha */ export declare function isValidIntentExpression(expression: string): expression is IntentExpression; /** * Validate whether a string is a valid pattern template. * * A valid pattern template must match at least one of: * - Action prefix (added, removed, renamed, reordered, modified) * - Aspect suffix (type narrowed, type widened, made optional, etc.) * - Placeholder syntax (`\{...\}`) * - Conditional clause (`when \{...\}`, `unless \{...\}`) * * @param template - The template string to validate * @returns True if the template is valid, false otherwise * * @example * ```typescript * isValidPatternTemplate('removed {target}') // true * isValidPatternTemplate('{target} type narrowed') // true * isValidPatternTemplate('some random text') // false * ``` * * @alpha */ export declare function isValidPatternTemplate(template: string): boolean; /** * Type guard to check if a value is a valid ChangeDetectorPlugin. * * @remarks * This is a convenience function that combines validation with type narrowing. * For detailed error information, use `validatePlugin()` directly. * * @param plugin - The value to check * @returns True if the value is a valid plugin * * @example * ```typescript * if (isValidPlugin(loadedModule)) { * // loadedModule is typed as ChangeDetectorPlugin * registry.register(loadedModule); * } * ``` * * @alpha */ export declare function isValidPlugin(plugin: unknown): plugin is ChangeDetectorPlugin; /** * Built-in AST-aware JSON reporter definition. * * @alpha */ export declare const jsonASTReporter: ASTAwareReporterDefinition; /** * Result of loading a discovered plugin. * * @alpha */ export declare interface LoadedPlugin { /** * Package information. */ readonly package: PluginPackageInfo; /** * The loaded and validated plugin instance. */ readonly plugin: ChangeDetectorPlugin; /** * Whether this was a legacy plugin that was normalized. */ readonly isLegacy: boolean; } /** * Built-in AST-aware markdown reporter definition. * * @alpha */ export declare const markdownASTReporter: ASTAwareReporterDefinition; /** * Descriptor for 'modified' actions. * Requires aspect and impact to be specified. * * @alpha */ export declare interface ModifiedDescriptor extends ChangeDescriptorBase { action: 'modified'; /** What aspect changed (required for 'modified' actions) */ aspect: ChangeAspect; /** The semantic direction of the change (required for 'modified' actions) */ impact: ChangeImpact; } /** * Modifiers that can be applied to declarations. * * @alpha */ export declare type Modifier = 'exported' | 'default-export' | 'readonly' | 'optional' | 'abstract' | 'static' | 'private' | 'protected' | 'public' | 'const' | 'declare' | 'async'; /** * Complete analysis of a module/file. * * @alpha */ export declare interface ModuleAnalysis { /** The source filename */ filename: string; /** Original source code */ source: string; /** All analyzable nodes indexed by path */ nodes: Map; /** Top-level exports (subset of nodes that are exported) */ exports: Map; /** Any errors encountered during analysis */ errors: string[]; } /** * Module analysis with TypeScript program access for deep type queries. * * @alpha */ export declare interface ModuleAnalysisWithTypes extends ModuleAnalysis { /** TypeScript program */ program: ts.Program; /** TypeScript type checker */ checker: ts.TypeChecker; /** Map from node path to TypeScript Symbol */ symbols: Map; } /** * Calculates a normalized similarity score between two strings (0-1). * 1 means identical, 0 means completely different. * * @alpha */ export declare function nameSimilarity(a: string, b: string): number; /** * The kind of AST construct being analyzed. * * @alpha */ export declare type NodeKind = 'function' | 'class' | 'interface' | 'type-alias' | 'enum' | 'namespace' | 'variable' | 'property' | 'method' | 'parameter' | 'type-parameter' | 'enum-member' | 'call-signature' | 'construct-signature' | 'index-signature' | 'getter' | 'setter'; /** * Metadata extracted from TSDoc comments. * * @alpha */ export declare interface NodeMetadata { /** Whether the symbol is marked \@deprecated */ deprecated: boolean; /** Deprecation message if provided */ deprecationMessage?: string; /** Default value from \@default or \@defaultValue tag */ defaultValue?: string; /** Full TSDoc comment text */ rawComment?: string; } /** * Information about a single parameter in a function signature. * * @alpha */ export declare interface ParameterInfo { /** Original parameter name from source */ name: string; /** Type as a string */ type: string; /** Position in the parameter list (0-indexed) */ position: number; /** Whether the parameter is optional */ isOptional: boolean; /** Whether the parameter is a rest parameter */ isRest: boolean; } /** * Result of analyzing parameter order changes between two function signatures. * * @alpha */ export declare interface ParameterOrderAnalysis { /** Whether parameters appear to have been reordered */ hasReordering: boolean; /** Confidence level of the reordering detection */ confidence: ReorderingConfidence; /** Human-readable summary of the analysis */ summary: string; /** Detailed analysis of each parameter position */ positionAnalysis: ParameterPositionAnalysis[]; /** The old parameter order */ oldParams: ParameterInfo[]; /** The new parameter order */ newParams: ParameterInfo[]; } /** * Analysis of a single parameter position change. * * @alpha */ export declare interface ParameterPositionAnalysis { /** Position in the parameter list */ position: number; /** Old parameter name */ oldName: string; /** New parameter name */ newName: string; /** Type at this position (same in both if types match) */ type: string; /** Similarity score between old and new names (0-1) */ similarity: number; /** Human-readable interpretation of the change */ interpretation: string; } /** * Result of parsing a declaration string. * * @alpha */ export declare interface ParseDeclarationResult { /** Map of symbol names to their information */ symbols: Map; /** Any errors encountered during parsing */ errors: string[]; } /** * Parse a TypeScript declaration string and extract exported symbols. * * @remarks * This is a compatibility function that wraps the AST parser to provide * the legacy ExportedSymbol format used by input processors. * * @param content - TypeScript source code to parse * @param tsModule - The TypeScript module to use * @param filename - Optional filename for error messages * @returns Parse result with symbols and errors * * @example * ```ts * import * as ts from 'typescript'; * import { parseDeclarationString } from '@api-extractor-tools/change-detector-core'; * * const result = parseDeclarationString( * 'export declare function greet(name: string): string;', * ts * ); * console.log(result.symbols.get('greet')); * ``` * * @alpha */ export declare function parseDeclarationString(content: string, _tsModule: typeof ts, _filename?: string): ParseDeclarationResult; /** * Parse an intent expression into a pattern rule. * * This function transforms natural language intent expressions into structured * pattern rules. It handles both direct mappings and conditional patterns * (expressions with 'when' or 'unless' clauses). * * When parsing fails, the result includes error messages and suggestions for * similar valid expressions (based on Levenshtein distance matching). * * @param intent - The intent rule to parse * @returns Parse result with pattern rule (on success) or errors and suggestions (on failure) * * @example Successful parse * ```typescript * const result = parseIntent({ * type: 'intent', * expression: 'breaking removal', * returns: 'major' * }) * * if (result.success && result.pattern) { * console.log('Template:', result.pattern.template) * // Output: "removed {target}" * } * ``` * * @example Conditional expression * ```typescript * const result = parseIntent({ * type: 'intent', * expression: 'breaking removal when nested', * returns: 'major' * }) * // Parses to pattern with 'when' clause * ``` * * @example Failed parse with suggestions * ```typescript * const result = parseIntent({ * type: 'intent', * expression: 'braking removal', // typo * returns: 'major' * }) * * if (!result.success) { * console.log('Errors:', result.errors) * console.log('Did you mean:', result.suggestions) * // suggestions: ['breaking removal'] * } * ``` * * @alpha */ export declare function parseIntent(intent: IntentRule): IntentParseResult; /** * Parses a TypeScript declaration string into a ModuleAnalysis. * * This uses \@typescript-eslint/typescript-estree for parsing and produces * an AST-based analysis without type resolution. For type resolution, * use parseWithTypes(). * * @param source - The source code to parse * @param options - Parse options * @returns ModuleAnalysis with all extracted nodes * * @alpha */ export declare function parseModule(source: string, options?: ParseOptions): ModuleAnalysis; /** * Parses a TypeScript declaration string with type resolution. * * This uses both \@typescript-eslint/typescript-estree for AST parsing * and TypeScript's type checker for type resolution. * * @param source - The source code to parse * @param tsModule - The TypeScript module * @param options - Parse options * @returns ModuleAnalysisWithTypes with TypeScript program access * * @alpha */ export declare function parseModuleWithTypes(source: string, tsModule: typeof ts, options?: ParseOptions): ModuleAnalysisWithTypes; /** * Options for parsing source code. * * @alpha */ export declare interface ParseOptions { /** Filename for the source (defaults to 'input.d.ts') */ filename?: string; /** Whether to resolve types via TypeChecker (requires tsModule) */ resolveTypes?: boolean; /** Whether to extract TSDoc metadata */ extractMetadata?: boolean; } /** * Result of compiling a pattern rule to dimensional representation. * * @see {@link compilePattern} for the compilation function * * @example * ```typescript * const result = compilePattern({ * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major' * }) * * if (result.success) { * console.log('Dimensional:', result.dimensional) * } * ``` * * @alpha */ export declare interface PatternCompileResult { /** Whether the compilation was successful */ success: boolean; /** The compiled dimensional rule (when successful) */ dimensional?: DimensionalRule; /** Error messages (when unsuccessful) */ errors?: string[]; /** Warnings about potential issues or information loss */ warnings?: string[]; } /** * Result of decompiling a dimensional rule back to pattern representation. * * Includes a confidence score indicating how well the pattern captures * the original dimensional semantics. * * @see {@link decompileToPattern} for the decompilation function * * @alpha */ export declare interface PatternDecompileResult { /** Whether the decompilation was successful */ success: boolean; /** The decompiled pattern rule (when successful) */ pattern?: PatternRule; /** Confidence score (0-1) indicating how well the pattern captures the dimensions */ confidence: number; /** Alternative pattern representations with lower confidence */ alternatives?: PatternRule[]; } /** * Pattern-based rule definition. * * A pattern rule uses a template with placeholders that get substituted * with concrete values during evaluation. * * @example * ```typescript * const rule: PatternRule = { * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major', * description: 'Export removal rule' * } * ``` * * @alpha */ export declare interface PatternRule { /** Discriminator for the rule type */ type: 'pattern'; /** The pattern template with placeholders */ template: PatternTemplate; /** Variables to substitute into the template */ variables: PatternVariable[]; /** The release type to use when this rule matches */ returns: ReleaseType; /** Optional human-readable description */ description?: string; } /** * Pattern templates with placeholders for structured rule definitions. * * The Pattern DSL provides template-based rules with `{placeholder}` syntax for * variable substitution, offering more flexibility than intent expressions while * remaining readable. * * ## Template Categories * * **Action Templates:** * - `'added {target}'` - Something was added * - `'removed {target}'` - Something was removed * - `'renamed {target}'` - Something was renamed * - `'reordered {target}'` - Something was reordered * - `'modified {target}'` - Something was modified * * **Action + Modifier Templates:** * - `'added required {target}'` - Required addition * - `'added optional {target}'` - Optional addition * - `'removed optional {target}'` - Optional removal * * **Aspect Templates:** * - `'{target} type narrowed'` - Type became more restrictive * - `'{target} type widened'` - Type became less restrictive * - `'{target} made optional'` - Became optional * - `'{target} made required'` - Became required * - `'{target} deprecated'` - Marked as deprecated * - `'{target} undeprecated'` - Removed deprecation * * **Conditional Templates:** * - `'{pattern} when {condition}'` - Pattern with condition * - `'{pattern} unless {condition}'` - Pattern with negated condition * - `'{pattern} for {nodeKind}'` - Pattern for specific node types * * **Compound Templates:** * - `'{pattern} and {pattern}'` - Multiple patterns (AND) * - `'{pattern} or {pattern}'` - Alternative patterns (OR) * * @example * ```typescript * const patternPolicy = createProgressivePolicy() * .pattern('removed {target}', { target: 'export' }, 'major') * .pattern('added optional {target}', { target: 'parameter' }, 'none') * .pattern('{target} type narrowed', { target: 'return-type' }, 'major') * .pattern('removed {target} when {condition}', { * target: 'property', * condition: 'not inherited' * }, 'major') * .build('pattern-based-policy', 'none') * ``` * * @alpha */ export declare type PatternTemplate = 'added {target}' | 'removed {target}' | 'renamed {target}' | 'reordered {target}' | 'modified {target}' | 'added required {target}' | 'added optional {target}' | 'removed optional {target}' | '{target} type narrowed' | '{target} type widened' | '{target} made optional' | '{target} made required' | '{target} deprecated' | '{target} undeprecated' | '{pattern} when {condition}' | '{pattern} unless {condition}' | '{pattern} for {nodeKind}' | '{pattern} and {pattern}' | '{pattern} or {pattern}'; /** * Variable that can be substituted in pattern templates. * * Variables in patterns have specific types that determine their allowed values: * - `'target'` - Targets of changes (`'export'`, `'parameter'`, `'property'`, etc.) * - `'nodeKind'` - Types of AST nodes (`'function'`, `'class'`, `'interface'`, etc.) * - `'condition'` - Conditional expressions (strings describing conditions) * - `'pattern'` - Nested pattern expressions * * @example * ```typescript * const variables: PatternVariable[] = [ * { name: 'target', value: 'export', type: 'target' }, * { name: 'condition', value: 'not deprecated', type: 'condition' } * ] * ``` * * @alpha */ export declare interface PatternVariable { /** Name of the variable (matches placeholder in template) */ name: string; /** Value to substitute for this variable */ value: ChangeTarget | NodeKind; /** Type of the variable, which determines allowed values */ type: 'target' | 'nodeKind' | 'condition' | 'pattern'; } /** * Keywords used for npm-based plugin discovery. * * @alpha */ export declare const PLUGIN_KEYWORDS: { /** Unified plugin keyword (preferred) */ readonly UNIFIED: "change-detector:plugin"; /** Legacy input processor plugin keyword */ readonly INPUT_PROCESSOR_LEGACY: "change-detector:input-processor-plugin"; }; /** * Error that occurred during plugin discovery or loading. * * @alpha */ export declare interface PluginDiscoveryError { /** * Package name (if known). */ readonly packageName?: string; /** * Package path (if known). */ readonly packagePath?: string; /** * Error message. */ readonly message: string; /** * Original error (if any). */ readonly cause?: Error; } /** * Logger interface for discovery operations. * * @alpha */ export declare interface PluginDiscoveryLogger { /** * Log debug information. */ debug?(message: string): void; /** * Log warnings (non-fatal issues). */ warn(message: string): void; /** * Log errors (fatal issues for individual plugins). */ error(message: string): void; } /** * Options for plugin discovery. * * @alpha */ export declare interface PluginDiscoveryOptions { /** * Directories to scan for node_modules. * Defaults to current working directory. */ readonly searchPaths?: readonly string[]; /** * Include legacy input-processor-plugin keyword in search. * Defaults to true for backward compatibility. */ readonly includeLegacy?: boolean; /** * Optional filter to include only specific plugin package names. * If provided, only packages matching these names will be loaded. */ readonly packageNames?: readonly string[]; /** * Whether to validate plugins after loading. * Defaults to true. */ readonly validate?: boolean; /** * Custom logger for discovery progress and errors. * Defaults to console.warn for errors. */ readonly logger?: PluginDiscoveryLogger; } /** * Result of plugin discovery operation. * * @alpha */ export declare interface PluginDiscoveryResult { /** * Successfully loaded plugins. */ readonly plugins: readonly LoadedPlugin[]; /** * Errors that occurred during discovery (non-fatal). */ readonly errors: readonly PluginDiscoveryError[]; /** * Package info for packages that were found but not loaded. */ readonly skipped: readonly PluginPackageInfo[]; } /** * Structured error from plugin operations. * * @alpha */ export declare class PluginError extends Error { /** * Error code for programmatic handling. */ readonly code: PluginErrorCode; /** * Plugin ID where the error originated, if known. */ readonly pluginId?: string; /** * Capability ID where the error originated, if known. */ readonly capabilityId?: string; /** * Original error that caused this error, if any. */ readonly cause?: Error; constructor(code: PluginErrorCode, message: string, options?: { pluginId?: string; capabilityId?: string; cause?: Error; }); } /** * Plugin error types. */ /** * Error codes for plugin-related errors. * * @alpha */ export declare type PluginErrorCode = 'PLUGIN_LOAD_FAILED' | 'PLUGIN_INVALID_METADATA' | 'PLUGIN_CAPABILITY_NOT_FOUND' | 'PLUGIN_OPTIONS_INVALID' | 'PROCESSOR_PARSE_ERROR' | 'POLICY_CLASSIFICATION_ERROR' | 'REPORTER_FORMAT_ERROR' | 'VALIDATOR_ERROR'; /** * Lifecycle hooks for plugins that need initialization or cleanup. * * @remarks * These are optional and only implemented by plugins that need them. * Most plugins can rely on the factory pattern for initialization. * * @alpha */ export declare interface PluginLifecycle { /** * Called when the plugin is first loaded. * * @remarks * Async initialization should happen here, not in capability factories. * This allows the host to control when initialization occurs. * * @returns Promise that resolves when initialization is complete */ initialize?(): Promise; /** * Called when the plugin is being unloaded. * * @remarks * Use this to clean up resources like file handles, connections, etc. */ dispose?(): Promise; } /** * Metadata identifying a plugin. * * @alpha */ export declare interface PluginMetadata { /** * Unique identifier for this plugin. * * @remarks * Should be a valid npm package name fragment (lowercase, hyphens allowed). * Used to construct fully-qualified capability IDs like `{pluginId}:{capabilityId}`. * * @example 'typescript', 'graphql', 'openapi' */ readonly id: string; /** * Human-readable display name. */ readonly name: string; /** * Semantic version string. */ readonly version: string; /** * Optional description of the plugin's purpose. */ readonly description?: string; /** * Optional URL for documentation or homepage. */ readonly homepage?: string; } /** * Information about a discovered plugin package before loading. * * @alpha */ export declare interface PluginPackageInfo { /** * Package name from package.json. */ readonly packageName: string; /** * Package version from package.json. */ readonly packageVersion: string; /** * Absolute path to the package directory. */ readonly packagePath: string; /** * Keywords from package.json that matched our search. */ readonly keywords: readonly string[]; /** * Whether this package uses the legacy keyword. */ readonly isLegacy: boolean; /** * Main entry point from package.json (resolved). */ readonly main?: string; } /** * A registry for indexing and retrieving plugin capabilities. * * @remarks * The registry indexes capabilities by: * - Fully-qualified ID (`pluginId:capabilityId`) * - File extension (for input processors) * - Output format (for reporters) * * Shorthand IDs are supported when unambiguous (e.g., `typescript` instead of `typescript:default`). * * @alpha */ export declare interface PluginRegistry { /** * All registered plugins. */ readonly plugins: ReadonlyMap; /** * Register a plugin and index its capabilities. * * @param plugin - The plugin to register * @param options - Registration options * @throws If plugin ID is already registered (unless force is true) */ register(plugin: ChangeDetectorPlugin, options?: RegisterOptions): void; /** * Unregister a plugin and remove its capabilities from the index. * * @param pluginId - The ID of the plugin to unregister * @returns True if the plugin was found and removed */ unregister(pluginId: string): boolean; /** * Get an input processor by ID. * * @remarks * Supports both fully-qualified IDs (`graphql:schema`) and shorthand IDs (`graphql`) * when the plugin has only one input processor. * * @param id - Fully-qualified or shorthand ID * @returns The resolved capability or undefined if not found */ getInputProcessor(id: string): ResolvedCapability | undefined; /** * Get a policy by ID. * * @param id - Fully-qualified or shorthand ID * @returns The resolved capability or undefined if not found */ getPolicy(id: string): ResolvedCapability | undefined; /** * Get a reporter by ID. * * @param id - Fully-qualified or shorthand ID * @returns The resolved capability or undefined if not found */ getReporter(id: string): ResolvedCapability | undefined; /** * Get a validator by ID. * * @param id - Fully-qualified or shorthand ID * @returns The resolved capability or undefined if not found */ getValidator(id: string): ResolvedCapability | undefined; /** * Find input processors that handle a specific file extension. * * @param extension - File extension including dot (e.g., '.ts', '.graphql') * @returns Array of resolved capabilities that handle this extension */ findInputProcessorsForExtension(extension: string): ReadonlyArray>; /** * Find reporters that produce a specific output format. * * @param format - Output format ('text', 'markdown', 'json', 'html', 'custom') * @returns Array of resolved capabilities that produce this format */ findReportersForFormat(format: string): ReadonlyArray>; /** * List all registered input processors. * * @returns Array of all input processor capabilities with plugin context */ listInputProcessors(): ReadonlyArray>; /** * List all registered policies. * * @returns Array of all policy capabilities with plugin context */ listPolicies(): ReadonlyArray>; /** * List all registered reporters. * * @returns Array of all reporter capabilities with plugin context */ listReporters(): ReadonlyArray>; /** * List all registered validators. * * @returns Array of all validator capabilities with plugin context */ listValidators(): ReadonlyArray>; /** * Clear all registered plugins and capabilities. */ clear(): void; } /** * Options for creating a plugin registry. * * @alpha */ export declare interface PluginRegistryOptions { /** * Custom logger for registry operations. */ readonly logger?: RegistryLogger; } /** * Result type for operations that can fail gracefully. * * @alpha */ export declare type PluginResult = { readonly success: true; readonly value: T; } | { readonly success: false; readonly error: PluginError; }; /** * A single validation error with location context. * * @alpha */ export declare interface PluginValidationError { /** * Dot-notation path to the invalid field. * * @example 'metadata.id', 'inputProcessors[0].extensions' */ readonly path: string; /** * Human-readable error message. */ readonly message: string; /** * Plugin ID if known (may not be available if metadata is invalid). */ readonly pluginId?: string; } /** * Options for plugin validation. * * @alpha */ export declare interface PluginValidationOptions { /** * Package name for error context (e.g., npm package name). */ readonly packageName?: string; /** * Whether to validate that factory functions are callable. * Defaults to true. */ readonly validateFactories?: boolean; /** * Whether to allow plugins with no capabilities. * Defaults to false (at least one capability required). */ readonly allowEmptyCapabilities?: boolean; } /** * Result of validating a plugin. * * @alpha */ export declare interface PluginValidationResult { /** * Whether the plugin passed all validation checks. */ readonly valid: boolean; /** * List of validation errors (empty if valid). */ readonly errors: readonly PluginValidationError[]; /** * List of validation warnings (non-fatal issues). */ readonly warnings: readonly PluginValidationError[]; } /** * A complete policy consisting of ordered rules. * * @alpha */ export declare interface Policy { /** Human-readable name for the policy */ name: string; /** Ordered list of rules (first match wins) */ rules: PolicyRule[]; /** Release type when no rule matches */ defaultReleaseType: ReleaseType; } /** * Builder for creating complete policies. * * @alpha */ export declare class PolicyBuilder { private readonly policyName; private readonly defaultRelease; private readonly policyRules; constructor(name: string, defaultReleaseType: ReleaseType); /** * Adds a rule to the policy. * Rules are evaluated in order; first match wins. */ addRule(policyRule: PolicyRule): this; /** * Adds multiple rules to the policy. */ addRules(...rules: PolicyRule[]): this; /** * Builds the final policy. */ build(): Policy; } /** * Context provided to policies for context-aware classification. * * @remarks * This allows policies to make decisions based on more than just the change category. * For example, a policy might allow one breaking change per release but flag multiple * breaking changes as requiring special approval. * * @alpha */ export declare interface PolicyContext { /** * The full list of changes being classified. * Useful for policies that consider the overall change set. */ readonly allChanges: readonly AnalyzedChange[]; /** * Index of the current change within allChanges. */ readonly changeIndex: number; /** * Optional metadata about the comparison context. */ readonly metadata?: Readonly>; } /** * Definition of a versioning policy capability. * * @remarks * Policies classify changes into semantic versioning impact levels (major, minor, patch, none). * They can be used to customize how different types of changes affect version bumps. * * @example * ```typescript * const policy: PolicyDefinition = { * id: 'strict', * name: 'Strict Policy', * description: 'Treats all changes as breaking', * createPolicy: () => ({ * name: 'strict', * classify: () => 'major' * }) * }; * ``` * * @alpha */ export declare interface PolicyDefinition { /** * Identifier for this policy within the plugin. */ readonly id: string; /** * Human-readable name. */ readonly name: string; /** * Optional description explaining when to use this policy. */ readonly description?: string; /** * JSON Schema for validating options. */ readonly optionsSchema?: Record; /** * Creates a policy instance. * * @param options - Optional configuration for the policy * @returns A policy instance (extended or base interface) */ createPolicy(options?: TOptions): VersioningPolicy | ExtendedVersioningPolicy; } /** * Options that can be passed to policy factories. * * @alpha */ export declare interface PolicyOptions { [key: string]: unknown; } /** * A single rule in a policy that matches changes and assigns release types. * * @alpha */ export declare interface PolicyRule { /** Human-readable name for the rule */ name: string; /** Predicate that determines if this rule matches a change */ matches: ChangeMatcher; /** The release type to assign when this rule matches */ releaseType: ReleaseType; /** Optional explanation of why this rule exists */ rationale?: string; } /** * Result of processing input content through an input processor. * * @alpha */ export declare interface ProcessResult { /** Extracted exported symbols */ symbols: Map; /** Any errors encountered during processing */ errors: string[]; /** * Optional source mapping for diagnostic positioning. * If provided, enables precise source locations in language server diagnostics. */ sourceMapping?: SourceMapping; } /** * Progressive rule builder supporting all three DSL levels. * * The main entry point for building Progressive DSL policies. Supports mixing * rules at all three levels (intent, pattern, dimensional) with fluent API. * * ## Real-World Policy Examples * * ### Strict Library Policy * For stable libraries where any breaking change should be carefully considered: * * ```typescript * const strictLibraryPolicy = createProgressivePolicy() * .intent('export removal is breaking', 'major') * .intent('member removal is breaking', 'major') * .intent('type narrowing is breaking', 'major') * .intent('required addition is breaking', 'major') * .intent('optional addition is safe', 'none') * .intent('deprecation is patch', 'patch') * .build('strict-library', 'major') * ``` * * ### Agile Development Policy * For rapidly evolving APIs where some changes are acceptable in minor versions: * * ```typescript * const agilePolicy = createProgressivePolicy() * .intent('export removal is breaking', 'major') * .pattern('renamed {target}', { target: 'property' }, 'minor') * .intent('type widening is safe', 'minor') * .intent('deprecation is patch', 'patch') * .dimensional('internal-changes') * .hasTag('internal') * .returns('patch') * .build('agile-development', 'patch') * ``` * * @see {@link createProgressivePolicy} - Factory function to create a new builder * @see {@link createStandardPolicy} - Factory for pre-configured common policies * * @alpha */ export declare class ProgressiveRuleBuilder implements ProgressiveRuleBuilderInterface { private rules; private pendingDimensionalRules; /** * Add a rule using natural language intent. * * Intent rules are the highest-level, most readable way to express change rules. * They use natural language expressions that capture semantic meaning directly. * * @param expression - Natural language expression (e.g., 'export removal is breaking') * @param returns - Release type for this rule ('major', 'minor', 'patch', 'none') * @param description - Optional human-readable description * @returns This builder for chaining * * @example * ```typescript * builder * .intent('export removal is breaking', 'major', 'Public API removal') * .intent('optional addition is safe', 'none') * .intent('deprecation is patch', 'patch') * ``` */ intent(expression: IntentExpression, returns: ReleaseType, description?: string): this; /** * Add a rule using pattern template. * * Pattern rules use `\{placeholder\}` syntax for variable substitution, offering * more flexibility than intent expressions while remaining readable. * * @param template - Pattern template with placeholders (e.g., `'removed \{target\}'`) * @param variables - Object mapping placeholder names to values * @param returns - Release type for this rule ('major', 'minor', 'patch', 'none') * @param description - Optional human-readable description * @returns This builder for chaining * * @example Basic patterns * ```typescript * builder * .pattern('removed {target}', { target: 'export' }, 'major') * .pattern('added optional {target}', { target: 'parameter' }, 'none') * .pattern('{target} type narrowed', { target: 'return-type' }, 'major') * ``` * * @example Conditional patterns * ```typescript * builder.pattern('removed {target} when {condition}', { * target: 'property', * condition: 'not inherited' * }, 'major') * ``` * * @example Node-specific patterns * ```typescript * builder.pattern('{pattern} for {nodeKind}', { * pattern: 'modified', * nodeKind: 'interface' * }, 'major') * ``` */ pattern(template: PatternTemplate, variables: Record, returns: ReleaseType, description?: string): this; /** * Start building a dimensional rule with the fluent API. * * Dimensional rules provide the most precise control by directly specifying * multi-dimensional change characteristics. Use this when you need: * - Maximum precision for complex rules * - Legacy compatibility with RuleBuilder-based policies * - Rules with multiple intersecting dimensions * * @param name - Rule name (used as description) * @returns A DimensionalRuleBuilder for specifying dimensions * * @example * ```typescript * builder * .dimensional('complex-rule') * .action('modified') * .target('export') * .aspect('type') * .impact('narrowing') * .returns('major') * ``` * * @example With tags and nested flag * ```typescript * builder * .dimensional('internal-api-changes') * .hasTag('internal') * .nested(true) * .returns('patch') * ``` */ dimensional(name: string): DimensionalRuleBuilder; /** * Internal method to add a dimensional rule (called by proxy) */ addDimensionalRule(rule: DimensionalRule): void; /** * Transform existing rules to a different DSL level. * * This enables converting rules between the three abstraction levels: * - `'intent'` - Natural language expressions (highest level) * - `'pattern'` - Template-based rules (middle level) * - `'dimensional'` - Multi-dimensional specifications (lowest level) * * **Note:** Transforming to higher levels (dimensional \> pattern \> intent) may * result in some information loss, as higher levels are less expressive. * * @param options - Transformation options including target level * @returns This builder for chaining * * @example * ```typescript * // Transform all rules to dimensional representation * builder.transform({ targetLevel: 'dimensional' }) * * // Transform to pattern level for better readability * builder.transform({ * targetLevel: 'pattern', * preserveMetadata: true, * validate: true * }) * ``` */ transform(options: TransformOptions): this; /** * Build the final policy from all configured rules. * * This method finalizes the builder, processing all rules and creating * a complete DSLPolicy that can be used for change classification. * * @param name - Unique name identifying this policy * @param defaultReleaseType - Release type to use when no rule matches * @param description - Optional human-readable description * @returns The finalized DSLPolicy * * @example * ```typescript * const policy = builder.build('my-policy', 'patch', 'My API policy') * ``` * * @example Conservative default (unmatched changes are breaking) * ```typescript * const strictPolicy = builder.build('strict-library', 'major') * ``` */ build(name: string, defaultReleaseType: ReleaseType, description?: string): DSLPolicy; /** * Add a custom DSL rule directly. * * This is useful when you have a pre-constructed rule object, or when * programmatically generating rules. * * @param rule - The DSL rule to add (IntentRule, PatternRule, or DimensionalRule) * @returns This builder for chaining * * @example * ```typescript * builder.addRule({ * type: 'intent', * expression: 'breaking removal', * returns: 'major' * }) * ``` */ addRule(rule: DSLRule): this; /** * Get the current rules for inspection or debugging. * * @returns Read-only array of all configured rules * * @example * ```typescript * const rules = builder.getRules() * console.log(`Policy has ${rules.length} rules`) * ``` */ getRules(): ReadonlyArray; /** * Clear all rules from the builder. * * Useful when creating variations of a policy or resetting the builder. * * @returns This builder for chaining * * @example * ```typescript * builder.clear() * ``` */ clear(): this; /** * Clone the builder with all current rules. * * Useful for creating policy variations without modifying the original. * * @returns A new ProgressiveRuleBuilder with copies of all rules * * @example Multi-stage policy with variations * ```typescript * const basePolicy = createProgressivePolicy() * .intent('export removal is breaking', 'major') * .intent('deprecation is patch', 'patch') * * // Create stricter variation * const stricterPolicy = basePolicy.clone() * .intent('rename is breaking', 'major') * .build('stricter-policy', 'major') * ``` */ clone(): ProgressiveRuleBuilder; } declare interface ProgressiveRuleBuilderInterface { addDimensionalRule(rule: DimensionalRule): void; } /** * Information about an object property or interface member. * * @alpha */ export declare interface PropertyInfo { /** Name of the property */ name: string; /** Type of the property */ type: string; /** Whether the property is optional */ optional: boolean; /** Whether the property is readonly */ readonly: boolean; /** Source location of the property */ location: SourceRange; } /** * Built-in AST-aware read-only (consumer/covariant) policy definition. * * @alpha */ export declare const readOnlyASTPolicy: ASTAwarePolicyDefinition; /** * Options for registering a plugin. * * @alpha */ export declare interface RegisterOptions { /** * If true, overwrites existing capabilities with the same fully-qualified ID. * Defaults to false (first-registered wins). */ readonly force?: boolean; } /** * Logger interface for registry operations. * * @alpha */ export declare interface RegistryLogger { /** * Log warning messages (e.g., ID conflicts). */ warn(message: string): void; /** * Log debug messages. */ debug?(message: string): void; } /** * The release type this delta represents according to semantic versioning. * - "forbidden": Changes that are never allowed, even in major releases * - "major": Breaking changes that require a major version bump * - "minor": New features/additions that are backwards compatible * - "patch": Bug fixes or internal changes with no API impact * - "none": No changes detected * * @alpha */ export declare type ReleaseType = 'forbidden' | 'major' | 'minor' | 'patch' | 'none'; /** * Descriptor for 'removed' actions. * * @alpha */ export declare interface RemovedDescriptor extends ChangeDescriptorBase { action: 'removed'; aspect?: never; impact?: never; } /** * Descriptor for 'renamed' actions. * * @alpha */ export declare interface RenamedDescriptor extends ChangeDescriptorBase { action: 'renamed'; aspect?: never; impact?: never; } /** * Descriptor for 'reordered' actions. * * @alpha */ export declare interface ReorderedDescriptor extends ChangeDescriptorBase { action: 'reordered'; aspect?: never; impact?: never; } /** * Confidence level for parameter reordering detection. * * @alpha */ export declare type ReorderingConfidence = 'high' | 'medium' | 'low'; /** * Reporter instance that formats comparison reports. * * @remarks * Reporters transform comparison reports into human-readable or machine-readable formats. * The `format` method is required; other methods are optional lifecycle hooks. * * @alpha */ export declare interface Reporter { /** * Formats a complete comparison report. * * @param report - The comparison report to format * @returns Formatted output with type information */ format(report: ComparisonReport): ReportOutput; /** * Formats a single change (for streaming/incremental output). * * @remarks * Optional. If not implemented, the full report must be formatted at once. * * @param change - A single change to format * @returns Formatted output for this change */ formatChange?(change: Change): ReportOutput; /** * Called before formatting begins (for reporters that need setup). * * @remarks * Optional lifecycle hook. Useful for HTML reporters that need * to emit document headers, or JSON reporters starting an array. */ begin?(): ReportOutput | void; /** * Called after all formatting is complete. * * @remarks * Optional lifecycle hook. Useful for closing tags or finalizing output. */ end?(): ReportOutput | void; } /** * Definition of a reporter capability. * * @remarks * Reporters format comparison reports for various output targets (terminal, files, CI systems). * * @example * ```typescript * const reporter: ReporterDefinition = { * id: 'markdown', * name: 'Markdown Reporter', * format: 'markdown', * fileExtension: 'md', * createReporter: () => ({ * format: (report) => ({ * format: 'markdown', * content: `# API Changes\n...` * }) * }) * }; * ``` * * @alpha */ export declare interface ReporterDefinition { /** * Identifier for this reporter within the plugin. */ readonly id: string; /** * Human-readable name. */ readonly name: string; /** * The output format category this reporter produces. */ readonly format: ReportOutputFormat; /** * Suggested file extension for the output (without dot). * * @remarks * Used by CLI tools to determine output filename. * Ignored in browser environments. * * @example 'md', 'json', 'html' */ readonly fileExtension?: string; /** * Optional description. */ readonly description?: string; /** * JSON Schema for validating options. */ readonly optionsSchema?: Record; /** * Whether this reporter requires async operations. * * @remarks * Helps consumers know whether to expect sync or async behavior. * Defaults to false. */ readonly isAsync?: boolean; /** * Creates a reporter instance. * * @param options - Optional configuration * @returns A reporter instance (sync or async based on isAsync flag) */ createReporter(options?: TOptions): Reporter | AsyncReporter | Promise; } /** * Options for reporter factories. * * @alpha */ export declare interface ReporterOptions { [key: string]: unknown; } /** * Result of formatting a report. * * @remarks * Discriminated union based on format type for type-safe handling. * Consumers can switch on the `format` property to get the correct content type. * * @alpha */ export declare type ReportOutput = { readonly format: 'text'; readonly content: string; } | { readonly format: 'markdown'; readonly content: string; } | { readonly format: 'json'; readonly content: object; } | { readonly format: 'html'; readonly content: string; } | { readonly format: 'custom'; readonly content: string | object; }; /** * Supported output format categories. * * @alpha */ export declare type ReportOutputFormat = 'text' | 'markdown' | 'json' | 'html' | 'custom'; /** * Result of looking up a capability with its plugin context. * * @alpha */ export declare interface ResolvedCapability { /** * The plugin ID that provides this capability. */ readonly pluginId: string; /** * The capability definition. */ readonly definition: T; /** * The fully-qualified ID (`pluginId:capabilityId`). */ readonly qualifiedId: string; } /** * A loaded and resolved plugin with fully-qualified capability IDs. * * @alpha */ export declare interface ResolvedPlugin { /** * The loaded plugin instance. */ readonly plugin: ChangeDetectorPlugin | ChangeDetectorPluginWithLifecycle; /** * Source package information. */ readonly source: DiscoveredPlugin; /** * Map of fully-qualified IDs to input processors. * Keys are in the format `{pluginId}:{processorId}`. */ readonly inputProcessors: ReadonlyMap; /** * Map of fully-qualified IDs to policies. */ readonly policies: ReadonlyMap; /** * Map of fully-qualified IDs to reporters. */ readonly reporters: ReadonlyMap; /** * Map of fully-qualified IDs to validators. */ readonly validators: ReadonlyMap; } /** * Creates a new rule builder with the given name. * * @example * ```ts * rule('export-removal') * .target('export') * .action('removed') * .returns('major') * ``` * * @alpha */ export declare function rule(name: string): RuleBuilder; /** * Fluent builder for creating policy rules. * * Rules match changes based on descriptor dimensions. All conditions * are combined with AND logic - a change must match all specified * conditions for the rule to apply. * * @alpha */ export declare class RuleBuilder { private readonly ruleName; private targetConditions; private actionConditions; private aspectConditions; private impactConditions; private tagConditions; private anyTagConditions; private notTagConditions; private nodeKindConditions; private nestedCondition?; private customMatchers; private ruleRationale?; constructor(name: string); /** * Matches changes targeting specific constructs. * Multiple targets are OR'd together. */ target(...targets: ChangeTarget[]): this; /** * Matches changes with specific actions. * Multiple actions are OR'd together. */ action(...actions: ChangeAction[]): this; /** * Matches changes affecting specific aspects. * Multiple aspects are OR'd together. */ aspect(...aspects: ChangeAspect[]): this; /** * Matches changes with specific semantic impacts. * Multiple impacts are OR'd together. */ impact(...impacts: ChangeImpact[]): this; /** * Matches changes affecting specific AST node kinds. * Multiple kinds are OR'd together. * * Use this to distinguish between different types of constructs * with the same target, e.g., function vs interface removals. * * @example * ```ts * // Only match function removals (not interface or class) * rule('function-removed').action('removed').nodeKind('function').returns('major') * * // Match interface or type-alias changes * rule('type-def-changed').nodeKind('interface', 'type-alias').returns('minor') * ``` */ nodeKind(...kinds: NodeKind[]): this; /** * Matches changes that have ALL specified tags (AND logic). * * Note: Unlike target(), action(), aspect(), and impact() which use OR logic * for multiple values, hasTag() uses AND logic - the change must have * every specified tag to match. * * @example * ```ts * // Must have BOTH 'was-required' AND 'now-optional' * rule('required-to-optional').hasTag('was-required', 'now-optional') * ``` */ hasTag(...tags: ChangeTag[]): this; /** * Matches changes that have ANY of the specified tags (OR logic). * * Use this when you want to match changes with at least one of several tags. * * @example * ```ts * // Must have 'now-optional' OR 'has-default' * rule('optional-or-default').hasAnyTag('now-optional', 'has-default') * ``` */ hasAnyTag(...tags: ChangeTag[]): this; /** * Matches changes that don't have any of the specified tags. */ notTag(...tags: ChangeTag[]): this; /** * Matches only nested changes (changes within other constructs). */ nested(isNested?: boolean): this; /** * Adds a custom matcher function. * Multiple custom matchers are AND'd together. */ when(matcher: ChangeMatcher): this; /** * Adds a rationale explaining why this rule exists. */ rationale(text: string): this; /** * Completes the rule with the specified release type. */ returns(releaseType: ReleaseType): PolicyRule; /** * Builds the composite matcher from all conditions. */ private buildMatcher; } /** * Standard semver policy for general API compatibility. * * Rules: * - Removals are always breaking (major) * - Required parameter additions are breaking (major) * - Type narrowing is breaking (major) * - Optionality changes are breaking (major) * - Optional additions are non-breaking (minor) * - Type widening is non-breaking (minor) * - Deprecations are patch-level * - Equivalent changes have no impact * * @alpha */ export declare const semverDefaultPolicy: Policy; /** * Policy for read-only/consumer APIs (covariant position). * * Optimized for consumers who READ from the API: * - Type widening is safe (more values to receive) * - Type narrowing is breaking (might not handle all values) * - Adding members is safe (more data available) * - Removing members is breaking (expected data missing) * * @alpha */ export declare const semverReadOnlyPolicy: Policy; /** * Policy for write-only/producer APIs (contravariant position). * * Optimized for producers who WRITE to the API: * - Type narrowing is safe (stricter requirements, existing code still valid) * - Type widening is breaking (must handle new value types) * - Removing optional members is safe (don't need to provide) * - Adding required members is breaking (must provide new values) * * @alpha */ export declare const semverWriteOnlyPolicy: Policy; /** * Information about a call/construct signature. * * @alpha */ export declare interface SignatureInfo { /** Type parameters for the signature */ typeParameters: TypeParameterInfo[]; /** Parameters of the signature */ parameters: ASTParameterInfo[]; /** Return type as string */ returnType: string; /** Normalized signature string for comparison */ normalized: string; /** Source location of the signature */ location: SourceRange; } /** * Represents a location in a source file. * Line numbers are 1-based (matching most editors). * Column numbers are 0-based (matching LSP specification). * * @alpha */ export declare interface SourceLocation { /** 1-based line number */ line: number; /** 0-based column (character position) */ column: number; /** 1-based end line (optional, for ranges) */ endLine?: number; /** 0-based end column (optional, for ranges) */ endColumn?: number; } /** * Source mapping information from an input processor. * Maps symbol names to their source locations for diagnostic positioning. * * @alpha */ export declare interface SourceMapping { /** * Maps symbol name to its source location in the input file. * The key should match the symbol name in the ProcessResult.symbols map. */ symbolLocations: Map; /** * The source filename that was processed. * Used for diagnostic reporting. */ sourceFile: string; } /** * Represents a position in source code. * Line numbers are 1-based (matching most editors). * Column numbers are 0-based (matching LSP specification). * * @alpha */ export declare interface SourcePosition { /** 1-based line number */ line: number; /** 0-based column (character position) */ column: number; /** Byte offset from start of source */ offset: number; } /** * Represents a range in source code. * * @alpha */ export declare interface SourceRange { /** Start position of the range */ start: SourcePosition; /** End position of the range */ end: SourcePosition; } /** * Suggest corrections for typos or invalid intent expressions. * * This function uses Levenshtein distance to find similar valid expressions * and returns up to 3 suggestions sorted by similarity. * * Only expressions with distance less than 40% of the input length are suggested, * ensuring suggestions are meaningfully similar. * * @param expression - The invalid or misspelled expression * @returns Array of up to 3 suggested valid expressions, sorted by similarity * * @example * ```typescript * const suggestions = suggestIntentCorrections('braking removal') * // Returns: ['breaking removal'] * * const suggestions2 = suggestIntentCorrections('type narrwing') * // Returns: ['type narrowing is breaking'] * ``` * * @example Integration with validation * ```typescript * function validateWithSuggestions(input: string): { * valid: boolean * suggestions?: string[] * } { * if (isValidIntentExpression(input)) { * return { valid: true } * } * return { * valid: false, * suggestions: suggestIntentCorrections(input) * } * } * ``` * * @alpha */ export declare function suggestIntentCorrections(expression: string): string[]; /** * Kinds of exported symbols we track. * * @alpha */ export declare type SymbolKind = 'function' | 'class' | 'interface' | 'type' | 'variable' | 'enum' | 'namespace'; /** * Metadata extracted from TSDoc comments for a symbol. * * @alpha */ export declare interface SymbolMetadata { /** Whether the symbol is marked with \@deprecated */ isDeprecated?: boolean; /** Deprecation message if provided in \@deprecated tag */ deprecationMessage?: string; /** Default value from \@default or \@defaultValue tag */ defaultValue?: string; /** Whether this symbol's type is a reference to another type */ isReference?: boolean; /** The referenced type name if isReference is true */ referencedType?: string; /** * Whether this enum or string literal union type is open or closed for exhaustive consumption. * - 'open': New members may be added at any time; consumers should handle unknown values * - 'closed': Intended to be consumed exhaustively; adding a member is breaking * - undefined: Unmarked, defaults to 'closed' behavior */ enumType?: 'open' | 'closed'; } /** * Synthesize an intent expression from a pattern rule. * * This function transforms template-based pattern rules back into natural * language intent expressions. It uses inverse mapping with confidence scoring * to find the most natural expression. * * The synthesis process: * 1. Checks for conditional patterns (when/unless) and handles them specially * 2. Looks up the pattern template in the inverse mapping * 3. Matches variable constraints to find the best intent * 4. Falls back to generated expressions if no mapping exists * * Results include a confidence score: * - **1.0**: Exact match with variable constraints * - **0.7-0.9**: Partial match or generic fallback * - **0.3**: Generated expression (low confidence) * * @param pattern - The pattern rule to synthesize from * @returns Synthesis result with intent, confidence, and alternatives * * @example High-confidence synthesis * ```typescript * const result = synthesizeIntent({ * type: 'pattern', * template: 'removed {target}', * variables: [{ name: 'target', value: 'export', type: 'target' }], * returns: 'major' * }) * * console.log(result.intent?.expression) // 'export removal is breaking' * console.log(result.confidence) // 1.0 * console.log(result.alternatives) // ['breaking removal', ...] * ``` * * @example Conditional pattern synthesis * ```typescript * const result = synthesizeIntent({ * type: 'pattern', * template: '{pattern} when {condition}', * variables: [ * { name: 'pattern', value: 'removed {target}', type: 'pattern' }, * { name: 'condition', value: 'nested', type: 'condition' } * ], * returns: 'major' * }) * // result.intent.expression = 'breaking removal when nested' * ``` * * @alpha */ export declare function synthesizeIntent(pattern: PatternRule): IntentSynthesisResult; /** * Built-in AST-aware text reporter definition. * * @alpha */ export declare const textASTReporter: ASTAwareReporterDefinition; /** * Result of a complete bidirectional transformation * * @alpha */ export declare interface TransformationChain { /** Original rule */ source: DSLRule; /** Intermediate representations */ intermediates: DSLRule[]; /** Final rule */ target: DSLRule; /** Confidence of the complete transformation (0-1) */ confidence: number; /** Any information loss during transformation */ lossyTransformations: string[]; } /** * Options for rule transformation between DSL levels. * * @example * ```typescript * builder.transform({ * targetLevel: 'dimensional', * preserveMetadata: true, * validate: true, * preference: 'precise' * }) * ``` * * @alpha */ export declare interface TransformOptions { /** Target DSL level to transform rules to */ targetLevel: 'intent' | 'pattern' | 'dimensional'; /** Whether to preserve original metadata (descriptions, etc.) */ preserveMetadata?: boolean; /** Whether to validate rules during transformation */ validate?: boolean; /** * Preference for handling ambiguous transformation cases: * - `'readable'`: Prefer more human-readable output * - `'precise'`: Prefer more precise/detailed output * - `'compact'`: Prefer shorter output */ preference?: 'readable' | 'precise' | 'compact'; } /** * Comprehensive type information resolved from the TypeChecker. * * @alpha */ export declare interface TypeInfo { /** Normalized string representation for comparison */ signature: string; /** Raw type string from TypeScript */ raw: string; /** For union types */ unionMembers?: string[]; /** For intersection types */ intersectionMembers?: string[]; /** For callable types */ callSignatures?: SignatureInfo[]; /** For constructable types */ constructSignatures?: SignatureInfo[]; /** For object/interface types */ properties?: PropertyInfo[]; /** For generic types */ typeParameters?: TypeParameterInfo[]; /** For index signatures */ stringIndexType?: string; numberIndexType?: string; } /** * Information about a type parameter (generic). * * @alpha */ export declare interface TypeParameterInfo { /** Name of the type parameter */ name: string; /** Normalized name (T0, T1, etc.) for comparison */ normalizedName: string; /** Constraint type, if any */ constraint?: string; /** Default type, if any */ default?: string; /** Source location of the type parameter */ location: SourceRange; } /** * Validates a plugin conforms to the expected structure. * * @remarks * This function performs comprehensive validation including: * - Metadata validation (id, name, version) * - Capability validation (inputProcessors, policies, reporters, validators) * - Unique ID checks within each capability type * - Factory function validation (optional) * * @param plugin - The plugin to validate (can be any value) * @param options - Validation options * @returns Validation result with errors and warnings * * @example * ```typescript * import { validatePlugin } from '@api-extractor-tools/change-detector-core'; * * const result = validatePlugin(myPlugin, { packageName: 'my-plugin' }); * if (!result.valid) { * console.error('Plugin validation failed:', result.errors); * } * ``` * * @alpha */ export declare function validatePlugin(plugin: unknown, options?: PluginValidationOptions): PluginValidationResult; /** * Result of validation. * * @alpha */ export declare interface ValidationResult { /** Whether validation passed */ readonly valid: boolean; /** Warning messages (validation passes but with concerns) */ readonly warnings: readonly string[]; /** Error messages (validation failed) */ readonly errors: readonly string[]; } /** * Validator for pre-comparison checks. * * @remarks * Validators can check input before comparison to ensure quality * or enforce custom rules (e.g., required exports, naming conventions). * * @alpha */ export declare interface Validator { /** * Validates input before comparison. * * @param symbols - The parsed symbol map * @param source - Source identifier (filename) * @returns Validation result with any warnings/errors */ validate(symbols: ReadonlyMap, source: string): ValidationResult; } /** * Validator definition for plugins. * * @example * ```typescript * const validator: ValidatorDefinition = { * id: 'required-exports', * name: 'Required Exports Validator', * description: 'Ensures certain symbols are always exported', * createValidator: (options) => ({ * validate: (symbols, source) => { * const required = options?.required ?? []; * const missing = required.filter(r => !symbols.has(r)); * return { * valid: missing.length === 0, * warnings: [], * errors: missing.map(m => `Missing required export: ${m}`) * }; * } * }) * }; * ``` * * @alpha */ export declare interface ValidatorDefinition = Record> { /** * Identifier for this validator within the plugin. */ readonly id: string; /** * Human-readable name. */ readonly name: string; /** * Optional description. */ readonly description?: string; /** * Creates a validator instance. * * @param options - Optional configuration * @returns A validator instance */ createValidator(options?: TOptions): Validator; } /** * A policy that maps analyzed changes to release types. * * @alpha */ export declare interface VersioningPolicy { /** The name of the policy */ readonly name: string; /** * Classifies a change to determine its release type. * @param change - The raw analyzed change * @param context - Optional additional context including symbol metadata * @returns The release type (major, minor, patch, or none) */ classify(change: AnalyzedChange, context?: ClassifyContext): ReleaseType; } /** * Built-in AST-aware write-only (producer/contravariant) policy definition. * * @alpha */ export declare const writeOnlyASTPolicy: ASTAwarePolicyDefinition; export { }