/** * External system declarations * * A system OUTSIDE this repo that a service talks to — a database, a bucket, a cache. Until now * every one of them collapsed into the same grey dashed box, so `lib-firestore` (a datastore) was * indistinguishable from an HTTP service the repo happens not to implement. Declaring what a system * IS lets the runtime viz draw it as the thing it is. * * Split out of api-scanner.ts and runtime-graph.ts (both already at their file-size limit) so the * two halves of the feature — DECLARING a system and RESOLVING it to arrows — sit together. * * The two declaration sites exist because the two real cases differ in whether a contract exists: * * - **wrapped** — the repo has a vendor seam (`FirestoreAdminApi`), so the kind is declared with an * `@externalSystem [label]` JSDoc tag on the CONTRACT. A TS `interface` cannot carry a * decorator, and these seams are interfaces, so JSDoc is the only marker that fits in place. * - **unwrapped** — the service opens the connection itself (a `pg.Pool`, a TypeORM `DataSource`) * and there is no contract to mark, so the declaration is an `external::` nx tag * on that PROJECT. Wrapping such a datastore purely to gain a marker is not worth it: a TypeORM * facade never closes, unlike the ~8 hand-picked methods a firestore seam needs. * * Both resolve to the same `(kind, identity)` pair, and identity is the NODE identity — two projects * declaring `postgres` converge on one cylinder with an arrow each, rather than drawing a database * apiece. */ import type { ApiClassInfo, ExternalSystemDecls } from './api-relations'; import type { ProjectInfo } from '../project-info'; import type { RuntimeExternalSystem, RuntimeGraph, RuntimeService } from '../runtime-graph-model'; /** * The committed `externalSystems` table for architecture/dependencies.json, merging both declaration * sites into one identity-keyed map. * * A system may legitimately carry both: a repo can wrap a datastore behind a contract in one service * and open it directly in another. Takes the api index rather than the whole scan result so this * module never has to import api-scanner, which imports it. */ export declare function buildExternalSystems(apiIndex: Map, projectInfos: Map): ExternalSystemDecls; /** * Resolve declarations into drawable nodes: which services actually get an arrow to each system. * * Two resolutions, matching the two declaration sites. A CONTRACT-declared system is reached by * every service that `uses` one of its contracts, so the arrows follow real call sites. A * TAG-declared system is reached ONLY by the tagged project itself — a tag asserts "I open this * connection", and fanning it out to dependents would invent arrows nobody wrote (a service that * depends on the entity library only for a DTO type does not talk to the database). * * A system nothing reaches is dropped rather than drawn floating: a declaration whose users all * disappeared is stale, and an unconnected node on the graph reads as a live dependency. */ export declare function resolveExternalSystems(decls: ExternalSystemDecls, services: Record): Record; /** * Hang the resolved systems off the graph, and STAMP each declaring contract with its declaration. * * The stamp is what stops the same system being drawn twice: the visualizer skips an * `unresolvedUses` entry whose contract carries one, because that contract has already been drawn * with a real shape rather than as the generic grey box it would otherwise fall back to. * * A graph with nothing declared is left completely untouched — no empty key is written — so a repo * that adopts none of this keeps a byte-identical runtime-dependencies.json. */ export declare function attachExternalSystems(graph: RuntimeGraph, systems: Record): void;