/** * @fileoverview Generic marker-based plugin discovery. * * Walks ancestor `node_modules/` directories from a project root, looking * for packages whose `package.json` declares an `opensipTools.kind` value * matching the requested kind. Returns the deduplicated list (first * occurrence walking outward wins, matching Node's nearest-ancestor * module resolution). * * Four marker kinds are recognised today: `'tool'`, `'fit-pack'`, * `'sim-pack'`, and `'graph-adapter'`. New kinds get added to `MarkerKind` * explicitly — keeping the union closed lets the type system catch typos at * call sites, and makes `MARKER_KINDS` the single source of truth for the * plugin-kind vocabulary (the workspace-invariant test asserts every * package.json marker against it). * * Why a marker rather than a name pattern: a name-prefix rule (e.g. * anything matching `@opensip-tools/*`) breaks down once organisations * publish their own scoped packs (`@my-company/checks-acme`). Marker- * based discovery decouples publication scope from plugin shape, so * customers can ship under any scope they own. * * Tool plugins, fit packs, and sim packs all share this walker. The * domain-typed wrappers (`tool-package-discovery.ts`, * fitness `cli/fit.ts`, simulation `cli/sim.ts`) call this with their * respective kinds and adapt the return type. */ /** * The closed vocabulary of `opensipTools.kind` markers. Exported as the * single source of truth: discovery wrappers narrow to it, and the * workspace-invariant test validates every package.json marker against it. */ export declare const MARKER_KINDS: readonly ["tool", "fit-pack", "sim-pack", "graph-adapter"]; export type MarkerKind = (typeof MARKER_KINDS)[number]; export interface MarkerDiscoveryOptions { /** Absolute path to the project root. */ readonly projectDir: string; /** Which marker kind to discover. */ readonly kind: MarkerKind; } export interface DiscoveredMarkerPackage { /** npm package name, e.g. '@opensip-tools/fitness' or '@my-co/fit'. */ readonly name: string; /** Absolute path to the package's directory inside node_modules. */ readonly packageDir: string; /** Echoed back so callers consuming multiple kinds can multiplex. */ readonly kind: MarkerKind; } /** * Narrow an unknown string to MarkerKind. Used by readMarkerKind below * and re-exported for callers that need to validate dynamic input. */ export declare function isMarkerKind(value: unknown): value is MarkerKind; /** * Walk up from `projectDir` looking for `node_modules/` directories. * For each one, scan top-level entries (and one level into scoped * directories like `@opensip-tools/`) for packages declaring * `opensipTools.kind === options.kind`. Return the deduplicated list. * * Same-named packages are returned once — the first occurrence walking * from `projectDir` outward wins, matching Node's nearest-ancestor * resolution behavior. */ export declare function discoverPackagesByMarker(options: MarkerDiscoveryOptions): DiscoveredMarkerPackage[]; /** * Scan EXACTLY ONE `node_modules` directory for packages declaring * `opensipTools.kind === kind` — no ancestor walk. Used for fixed plugin * host dirs (`~/.opensip-tools/plugins/tool/node_modules`, * `/.runtime/plugins/tool/node_modules`) where walking up would * wrongly pull in `$HOME/node_modules` or unrelated ancestor trees. */ export declare function discoverPackagesInNodeModules(nodeModulesDir: string, kind: MarkerKind): DiscoveredMarkerPackage[]; /** * Read the declared `opensipTools.kind` from a package's package.json. * Returns the kind if it parses, is a string, and matches the closed * MarkerKind union; otherwise undefined. Parse failures are logged at * debug — a malformed package.json under node_modules is not a discovery * concern, just an entry to skip. * * Exported as the canonical marker reader: every discovery path (tool, * fit-pack, sim-pack, graph-adapter) reads the marker through this one * function, so there is no second implementation to drift. */ export declare function readMarkerKind(packageDir: string): MarkerKind | undefined; //# sourceMappingURL=marker-discovery.d.ts.map