# @suaveplan/service-discovery - Universal service discovery primitives: ServiceRegistry with TTL/expiry, query, AbortSignal-aware watch, optional storage persistence and EventBusLike integration. Shared foundation for every network-discovery-* plugin. ## Summary Universal service-registry primitives. Provides the shared `ServiceDescriptor`, `ServiceQuery`, `RegistryEvent`, and `ServiceRegistry` contract consumed by every Wave-2 `network-discovery-*` plugin. ## Documentation tree - [service-registry](./src/core/service-registry/service-registry.md) — _(no submodules)_ - [service-registry](./src/core/service-registry/service-registry.md) — _(no submodules)_ - [errors](./src/errors/errors.md) — _(no submodules)_ - [errors](./src/errors/errors.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ - [service-registry](./src/core/service-registry/service-registry.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [service-registry](./src/core/service-registry/service-registry.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [service-registry](./src/core/service-registry/service-registry.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_- [service-registry](./src/core/service-registry/service-registry.md) — _(no submodules)_- [errors](./src/errors/errors.md) — _(no submodules)_ - [errors](./src/errors/errors.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_- [types](./src/types/types.md) — _(no submodules)_ - [types](./src/types/types.md) — _(no submodules)_ ## Install ```bash bun add @suaveplan/service-discovery ``` ## Basic usage ```ts import { ServiceRegistry } from "@suaveplan/service-discovery"; const registry = new ServiceRegistry({ ttlMs: 30_000 }); registry.register({ id: "api-1", name: "api", address: "10.0.0.1:8080", status: "healthy", region: "us-east-1", tags: ["v1"], }); const healthy = registry.query({ name: "api", status: "healthy" }); ``` ## Advanced usage: watch + bus + persistence ```ts import { ServiceRegistry } from "@suaveplan/service-discovery"; import type { EventBusLike } from "@suaveplan/types"; declare const bus: EventBusLike<{ "service:registered": import("@suaveplan/service-discovery").ServiceDescriptor; "service:deregistered": import("@suaveplan/service-discovery").ServiceDescriptor; "service:expired": import("@suaveplan/service-discovery").ServiceDescriptor; }>; declare const storage: import("@suaveplan/service-discovery").ServiceRegistryStorageLike; const registry = new ServiceRegistry({ ttlMs: 30_000, maxServices: 5_000, bus, storage, persistKey: "service-registry:v1", }); await registry.load(); const ac = new AbortController(); (async () => { for await (const ev of registry.watch({ name: "api" }, ac.signal)) { console.log(ev.type, ev.service.id); } })(); // later: await registry.flush(); ac.abort(); registry.dispose(); ``` ## What ships - `ServiceRegistry` — in-memory store with TTL expiry, query, AbortSignal- aware `watch()` async iterator, optional persistent backing, optional `EventBusLike` fan-out. - Typed error class `SvcDiscError` + frozen `SVC_DISC_CODES` registry (`DUPLICATE_REGISTRATION` / `QUERY_INVALID` / `REGISTRY_FULL` / `INVALID_OPTIONS`). - Zod schemas at every public boundary. - OTel: `svc_disc.registrations_total{outcome}`, `svc_disc.queries_total`, `svc_disc.query_duration_ms`, `svc_disc.active_services` gauge. See each feature module's sibling `.md` for the full surface.