/** * Auto-Source Assignment Service * * Automatically matches scanned plugins to the curated registry * and assigns download sources/URLs. Only assigns to plugins that * don't already have a configured source. * * @since v2.2.0 */ import type { RegistryService } from '../registry/registry-service.js'; import type { RegistryPlugin } from '../registry/registry-types.js'; import type { Plugin, ScannedPlugin } from '../types/plugin.js'; import type { AutoAssignOptions, AutoAssignResult, SourceAssignment } from './auto-source-types.js'; import type { IdentificationEvidence } from './identification-types.js'; /** * Does a piece of identification evidence belong to this scanned plugin? * Prefers exact jarPath equality (rungs emit per-JAR); falls back to a * case-insensitive name match so directly-injected evidence (tests, stub * call sites with empty jarPath) still applies. */ export declare function evidenceMatchesScanned(evidence: IdentificationEvidence, scanned: ScannedPlugin): boolean; /** * Auto-Source Assignment Service * * Matches scanned plugins against the curated registry and assigns * download sources. Respects manual overrides and confidence thresholds. */ export declare class AutoSourceAssigner { private readonly registryService; constructor(registryService: RegistryService); /** * Assign sources to scanned plugins by matching against the registry. * * @param scannedPlugins - Plugins discovered from JAR scanning * @param existingPlugins - Already-configured plugins (from plugins.json) * @param options - Assignment configuration * @returns Summary of assignments, suggestions, skips, and failures */ assignSources(scannedPlugins: ScannedPlugin[], existingPlugins: Plugin[], options?: AutoAssignOptions): AutoAssignResult; /** * Check if a plugin already has a configured (non-manual) source */ private hasConfiguredSource; /** * Check if a plugin already has the same source type and identifiers * as the proposed assignment (i.e., re-assigning would be a no-op). * Public since Phase 2: registry-correction propagation (identify.ts) * uses it to detect drift between registry and configured sources. */ isSameSource(plugin: Plugin, assignment: SourceAssignment): boolean; /** * Get an identifier value from a plugin by key name */ private getPluginIdentifier; /** * Try to find a source assignment for a scanned plugin. * * Precedence (Phase 2 identification ladder): * 1. Hash evidence (byte-exact, confidence 1.0) — with the registry * consulted for confirmation/conflict (see below) * 2. Registry match (by name) * 3. Embedded watermark evidence (store-injected, in-JAR) * 4. Embedded URL evidence (author-embedded, in-JAR) * 5. Website URL hint (plugin.yml website field, or injected evidence) * 6. pom.properties Maven-coordinate evidence * * Hash-vs-registry interplay: hash WINS for channel+identifier. When the * registry name-match lists that same channel/identifier among its * sources, that's confirmation — the registryId linkage (and that * source's manualDownload/legacy flags) ride along. When they genuinely * disagree, the assignment is flagged requiresReview (suggested tier) — * a contradiction is never silently auto-applied. */ private findAssignment; /** * Pick the highest-confidence evidence record whose method matches. * Stable for ties (first wins) so rung output order is deterministic. */ private bestEvidence; /** * Convert an identification-evidence record into a source assignment. * Returns null for channels that cannot be represented as a Plugin source. * * Channels without a checkable built-in source (curseforge after the * June 2026 BukkitSource removal; the BuiltByBit/Polymart stores) come * back flagged requiresReview so they land in the suggested tier with an * honest explanation instead of being silently dropped. */ private assignmentFromEvidence; /** * Find a registry source entry matching an evidence record's * channel+identifier (case-insensitive). Used to distinguish hash-registry * CONFIRMATION (registry lists the same source) from genuine conflict. */ private registrySourceMatchingEvidence; /** * Identity-change guard (Phase 2): compare byte-exact hash evidence * against an EXISTING plugin's configured source. A contradiction yields a * suggested re-assignment carrying previousType/previousIdentifier — * callers surface it for review; it is never auto-applied. */ private detectIdentityCorrection; /** * Match a plugin name to the curated registry. * Uses exact name match first, then fuzzy search. * * @returns Registry plugin and confidence, or null if no good match */ matchToRegistry(pluginName: string): { plugin: RegistryPlugin; confidence: number; } | null; /** * Extract a source assignment from a registry plugin entry. * Uses the preferred source from the registry. * * Registry entries whose preferred source is type 'manual' (premium * stores with no API: chatcontrol, cmieinjector, protectionlib, ...) * yield an honest type:'manual' assignment carrying the registryId — so * the plugin is REGISTRY-IDENTIFIED (notes/page reachable downstream) * instead of invisible-unidentified. getSourceIdentifier('manual') * returns null and the update checker skips manual-type plugins, so the * downstream path stays graceful. */ extractSourceFromRegistry(registryPlugin: RegistryPlugin, pluginName: string, confidence: number): SourceAssignment | null; /** * Map registry source fields to Plugin identifier fields */ private mapSourceIdentifiers; /** * Try to extract a source assignment from a website URL. * Parses known URL patterns for Spigot, Modrinth, GitHub, Hangar, * dev.bukkit.org, BuiltByBit, and Polymart/Voxel. * * Scheme-less URLs (~14% of real plugin.yml website fields, e.g. * `www.spigotmc.org/resources/selection-visualizer.22631/`) are * normalized with an https:// prefix before parsing — previously * `new URL()` threw and the hint was silently dropped. */ extractSourceFromWebsite(website: string, pluginName: string): SourceAssignment | null; /** * Apply source assignments to plugins, creating/updating Plugin entries. * * @param assignments - Source assignments to apply * @param existingPlugins - Current plugins list (mutated in place) * @param scannedPlugins - Scanned plugin data for version info * @returns Updated plugins list */ applyAssignments(assignments: SourceAssignment[], existingPlugins: Plugin[], scannedPlugins: ScannedPlugin[]): Plugin[]; /** * Apply identifier fields from an assignment to a Plugin object */ private applyIdentifiers; } //# sourceMappingURL=auto-assigner.d.ts.map