Files
skills/docs/devtools/tooling/overview/src/discover/discover.md
2026-05-29 08:20:56 +01:00

3.1 KiB

discover/discover.ts

(no submodules)

Purpose

Implements the filesystem walker that produces a validated SuavePlanManifest from a populated packages/<category>/<plugin>/<pkg>/package.json tree. Both the synchronous discoverPackages and the async discoverPackagesIter live here. The module is the only server-tier surface in @suaveplan/overview; it ships under the ./discover sub-path export so universal consumers can avoid the node:fs / node:path imports entirely.

Discovery is straightforward: walk three directory levels deep, read each package.json, infer its tier, collect workspace deps, validate against PackageRecordSchema, then aggregate the resulting rows into a manifest.

Features

  • Synchronous discoverPackages returning a fully-validated manifest
  • Async discoverPackagesIter honouring AbortSignal
  • onError: "throw" | "skip" for graceful handling of malformed package.json files
  • Optional tierHints extending SERVER_DEP_HINTS
  • Emits overview.packages_discovered_total, overview.records_rejected_total{reason}, and overview.discover_duration_ms
  • Built-in roll-up so the manifest carries plugins, categories, and tierCounts ready for consumption

Usage: Basic

import { discoverPackages } from "@suaveplan/overview/discover";

const manifest = discoverPackages({ root: process.cwd() });
console.log(`Found ${manifest.packages.length} packages.`);

Usage: Advanced

import { discoverPackagesIter } from "@suaveplan/overview/discover";

const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);

try {
  for await (const r of discoverPackagesIter({
    root: "/repo",
    signal: controller.signal,
    onError: "skip",
    tierHints: new Set(["custom-native-binding"]),
  })) {
    process.stdout.write(`${r.name}\n`);
  }
} catch (err) {
  // OverviewError with code OVERVIEW.DISCOVERY_ABORTED when the signal fired.
}

onError: "skip" is the right mode for tooling that should never abort on a single bad package.json (e.g. a long-running watcher); "throw" is right for one-shot CLIs that prefer a hard fail on corruption.

API Reference

  • discoverPackages(options: DiscoverOptions): SuavePlanManifest
  • discoverPackagesIter(options: AsyncDiscoverOptions): AsyncGenerator<PackageRecord>
  • interface DiscoverOptions { root, onError?, tierHints? }
  • interface AsyncDiscoverOptions extends DiscoverOptions { signal? }
  • type DiscoveryErrorMode = "throw" | "skip"

Implementation Notes

The walker enforces exactly three directory levels (category → plugin → package). Anything shallower or deeper is silently ignored — partial-migration trees are common and a permissive walker keeps the tooling robust. existsSync + statSync are used to filter non-directories and packages without a package.json; both are cheap on a populated tree because the OS will have cached the directory listings. The histogram observation uses performance.now() when available (it always is in Node 20+/Bun) and falls back to Date.now() otherwise.