/* Copyright(C) 2019-2026, HJD (https://github.com/hjdhjd). All rights reserved. * * index.ts: The public surface of the UniFi Protect library. */ // This file is the consumer contract, and the contract is Layer 3. The surface is curated by one rule, expressed in the type system so it cannot drift: // // - `export` a value only for what a consumer constructs, calls as a free function, tests `instanceof` against, or iterates as a vocabulary array: ProtectClient // (its static connect()), the error hierarchy, the selectors, the diagnostics channels, the default logger/clock, the timing constants, and the device-collection // key vocabulary. // - `export type` only for what a consumer receives but never builds: the device projections, the getter-return classes (StateStore / ConnectionMonitor / Transport / // ProtectResponse / LivestreamSubscription), and every event, state, option, and domain type reachable from a public signature. Exporting these as types makes a // second composition path unrepresentable - there is exactly one way to build a client, ProtectClient.connect() - so the single-source-of-truth rule is enforced by // the compiler rather than by documentation. The one blessed exception is `createStateStore`, a value export that constructs the real store standalone for test // harnesses; it widens only the store's own construction, never the client's, which stays the single `connect()` path. // - Export nothing that is pure composition internals: AuthSession, EventStream, EventBus, LivestreamSession, LivestreamPool, DeviceRegistry, the free codec/reducer // functions, and the internal interfaces and helpers. They are reachable in source for the reader, never on the published surface. // // The test the next contributor applies to any new symbol: does a consumer construct or call it (value), receive it (type), or neither (internal)? That keeps this file // a deliberate, reviewable contract rather than whatever each module happens to export. // Errors - the typed hierarchy. Consumers branch on these with `instanceof`, so they are value exports; the bootstrap-stage tag is a type. export { FatalError, ProtectAbortedError, ProtectAuthError, ProtectAuthorizationError, ProtectBootstrapError, ProtectCodecChangeError, ProtectError, ProtectLivestreamUnavailableError, ProtectNetworkError, ProtectProtocolError, ProtectRequestError, ProtectStallError, ProtectThrottledError, ProtectTimeoutError, ProtectUnsupportedError, RecoverableError } from "./errors.ts"; export type { ProtectBootstrapStage } from "./errors.ts"; // Logging - the consumer-injectable logger interface and the silent default a consumer may pass to suppress output. export { noopLog } from "./logging.ts"; export type { ProtectLogging } from "./logging.ts"; // Event bus - only the options type appears in a public signature (`stream(event, opts)`); the EventBus facade itself is internal machinery. export type { StreamOptions } from "./event-bus.ts"; // Transport - the documented `client.transport` escape hatch. Its instance type and the types in its method signatures are public; the class is never constructed by a // consumer (ProtectClient.connect() builds it), so it is a type-only export. export type { ProtectResponse, RequestOptions, SendOptions, Transport, TransportEvents } from "./transport/http.ts"; // The minimal WebSocket surface a consumer must return when injecting the optional `webSocket` factory via ConnectOptions; reachable from the public surface, so it // is named here even though the default undici-backed factory means most consumers never touch it. export type { ProtectWebSocket } from "./transport/ws.ts"; // Clock - the time abstraction (injected through ConnectOptions) and its production implementation a consumer may reuse. export { wallClock } from "./clock.ts"; export type { Clock } from "./clock.ts"; // Protocol - the realtime event taxonomy a consumer reads off the firehose. The pure codec/classifier/reducer functions stay internal; the static `ProtectClient` // .decodePacket() / .classifyPacket() methods are the consumer-facing codec entries (the offline counterpart of the rawPackets()/events() rails), so a second // free-function path would be the divergence the architecture forbids. `RawPacket` is the element type of the raw firehose (`client.rawPackets()`) and the // input/output of those codec statics: the decoded-but-unclassified frame, header plus payload, including ones the classifier drops. `ProtectEventHeader` is the // type of that frame's own `header` field, so it travels on the public surface alongside `RawPacket`. export type { ProtectEventHeader, RawPacket } from "./protocol/packet.ts"; export type { LivestreamSource, Segment } from "./transport/livestream-session.ts"; // The id-keyed device-collection vocabulary - the category key set the selector catalog and every per-category consumer iterate over. A value export (a consumer iterates // the runtime array to reach a category's selectors) plus its type; `DeviceModelKey` stays internal, since the collection vocabulary is the consumer-facing surface. export { DEVICE_COLLECTION_KEYS } from "./protocol/events.ts"; export type { AuthMethod, DeviceCollectionKey, SmartDetectType, StateModelKey, TypedEvent } from "./protocol/events.ts"; // Talkback - the send-direction two-way-audio session a consumer receives from `camera.talkback()` and its lifecycle-state type. Type-only: a consumer never constructs // one (the camera factory does), drives it through `send`/`close`/dispose, and reads `state`. export type { TalkbackSession, TalkbackState } from "./transport/talkback-session.ts"; export type { ProtectState } from "./protocol/reducer.ts"; // State - the observable store a consumer receives from `client.state`, and the memoized selectors a consumer passes to `observe` (or calls directly). `deviceSelectors` // is the category-keyed catalog: `deviceSelectors.` exposes that collection's quartet (`all`, `byId`, `online`, `adoptedIds`), and `adoptedIds` is the // content-memoized membership set - it changes reference only when a device is adopted or removed, so a consumer can `observe` one to drive accessory add/remove without // waking on routine config churn. `ProtectDeviceConfigMap` and the `CollectionSelectors` / `CollectionViews` shapes type a consumer's own generic iteration over it. // `livestreamAudioSampleRate` is the single source for a camera's fMP4 livestream audio sample rate - a doorbell's 48 kHz versus every other camera's 16 kHz. export { deviceSelectors, isDeviceAdopted, isDeviceOnline, livestreamAudioSampleRate, selectAuthUser, selectControllerName, selectIsAdmin, selectLiveview, selectLiveviews, selectNvr, selectRingtone, selectRingtones } from "./state/selectors.ts"; export type { CollectionSelectors, CollectionViews, ProtectDeviceConfigMap } from "./state/selectors.ts"; export { createStateStore } from "./state/store.ts"; export type { StateStore, StateStoreOptions } from "./state/store.ts"; // Devices - the projections a consumer receives from `client.cameras` / `client.camera(id)`. They are type-only: a consumer never constructs one (the registry does) and // narrows a handle by its `modelKey` tag rather than `instanceof`, which is the discriminated-union idiom the design is built on. export type { Camera, LivestreamOptions, SnapshotOptions } from "./devices/camera.ts"; export type { Chime, PlaySpeakerOptions } from "./devices/chime.ts"; export type { DeviceProjection, Projection, ProtectDeviceConfig } from "./devices/device.ts"; export type { Fob } from "./devices/fob.ts"; export type { Light } from "./devices/light.ts"; export type { Nvr } from "./devices/nvr.ts"; export type { Relay } from "./devices/relay.ts"; export type { Sensor } from "./devices/sensor.ts"; export type { Viewer } from "./devices/viewer.ts"; // Client - the one entry point. ProtectClient is a value export for its static `connect()` factory and `instanceof`; everything reachable through its getters // (ConnectionMonitor, LivestreamSubscription) and its method signatures is a type. export { ProtectClient } from "./client/client.ts"; export type { ConnectOptions, ProtectClientEvents } from "./client/client.ts"; export type { ConnectionEvents, ConnectionMonitor, ConnectionState, ConnectionTransition, ThrottleSource } from "./client/connection.ts"; // Livestream pool - the subscription handle a consumer receives (a type), the recovery-policy contract a consumer's injected `recoveryPolicy` is written against (types), // and the library's default policy a consumer may delegate to when composing its own (a value). export { defaultLivestreamRecoveryPolicy } from "./client/livestream-pool.ts"; export type { LivestreamSubscribeOptions, LivestreamSubscription, LivestreamSubscriptionState, LivestreamSubscriptionStats, RecoveryContext, RecoveryDecision, RecoveryPolicy } from "./client/livestream-pool.ts"; // Diagnostics - the named observability channels (subscribed by a consumer through `subscribeToChannel`), the typed channel shape they are declared with, and their // payload types. Part of the public contract. export { channels, subscribeToChannel } from "./diagnostics.ts"; export type { AdoptionContradictionPayload, AnyProtectDiagnosticsChannel, AuthReloginPayload, ConnectionRebootDetectedPayload, ConnectionTransitionPayload, EventsClosedPayload, EventsPacketPayload, EventsReconnectingPayload, HttpRequestEndPayload, HttpRequestStartPayload, HttpThrottleEnteredPayload, LivestreamCodecChangedPayload, LivestreamRecoveryExhaustedPayload, LivestreamRecoveryRecoveredPayload, LivestreamRecoveryStartedPayload, LivestreamSessionClosedPayload, LivestreamSessionOpenedPayload, LivestreamStallDetectedPayload, LivestreamSubscriptionCreatedPayload, LivestreamSubscriptionDisposedPayload, ProtectDiagnosticsChannel, SchemaUnknownModelKeyPayload, SchemaUnmodeledCollectionPayload, TalkbackSessionClosedPayload, TalkbackSessionOpenedPayload } from "./diagnostics.ts"; // Settings - the externally observable timing and retry constants behind the ConnectOptions defaults, exposed as documented reference values. export { PROTECT_API_ERROR_LIMIT, PROTECT_API_RETRY_INTERVAL, PROTECT_API_TIMEOUT, PROTECT_BOOTSTRAP_REFRESH_INTERVAL, PROTECT_EVENTS_WATCHDOG_TIMEOUT, PROTECT_LIVESTREAM_AWAIT_MARGIN_MS, PROTECT_LIVESTREAM_AWAIT_MAX_MS, PROTECT_LIVESTREAM_AWAIT_MIN_MS, PROTECT_LIVESTREAM_DEFAULT_TOLERANCE_MS, PROTECT_LIVESTREAM_ESTABLISH_BACKOFF_MS, PROTECT_LIVESTREAM_ESTABLISH_DEADLINE_MS, PROTECT_LIVESTREAM_HEARTBEAT_TIMEOUT, PROTECT_LIVESTREAM_RECOVERY_BACKOFF_MS, PROTECT_REBOOT_ANTICIPATION_WINDOW_MS, PROTECT_REBOOT_DETECTION_THRESHOLD, PROTECT_RECOVERY_BACKOFF_KNOWN_MS, PROTECT_RECOVERY_BACKOFF_UNKNOWN_MS, PROTECT_RECOVERY_STEADY_INTERVAL_MS } from "./settings.ts"; // Domain types - the Protect wire/configuration shapes. Every export here is intentionally public; consumers type their controller interactions against these. export type { DeepPartial, Nullable, ProtectAirQualityMetric, ProtectAirQualityMetricInterface, ProtectAirQualityThresholdSettings, ProtectAirQualityThresholdSettingsInterface, ProtectBridgeCandidate, ProtectCameraChannelConfig, ProtectCameraChannelConfigInterface, ProtectCameraConfig, ProtectCameraConfigInterface, ProtectCameraLcdMessageConfig, ProtectCameraLcdMessageConfigInterface, ProtectCameraRecordingPathSettings, ProtectCameraRecordingPathSettingsInterface, ProtectCameraTalkbackConfig, ProtectCameraTalkbackConfigInterface, ProtectChimeConfig, ProtectChimeConfigInterface, ProtectDeviceBase, ProtectDeviceBaseInterface, ProtectEventAdd, ProtectEventAddInterface, ProtectEventMetadata, ProtectEventMetadataDetectedThumbnail, ProtectEventMetadataDetectedThumbnailInterface, ProtectEventMetadataInterface, ProtectFobConfig, ProtectFobConfigInterface, ProtectKnownDevice, ProtectKnownJsonValue, ProtectLightConfig, ProtectLightConfigInterface, ProtectNvrAgreement, ProtectNvrAgreementInterface, ProtectNvrAiFeatureToggle, ProtectNvrAiFeatureToggleInterface, ProtectNvrBootstrap, ProtectNvrBootstrapInterface, ProtectNvrConfig, ProtectNvrConfigInterface, ProtectNvrLiveviewConfig, ProtectNvrLiveviewConfigInterface, ProtectNvrSystemEvent, ProtectNvrSystemEventController, ProtectNvrSystemEventControllerInterface, ProtectNvrSystemEventInterface, ProtectNvrSystemInfo, ProtectNvrSystemInfoInterface, ProtectNvrUserConfig, ProtectNvrUserConfigInterface, ProtectPtzAxisRange, ProtectPtzAxisRangeInterface, ProtectRelayConfig, ProtectRelayConfigInterface, ProtectRelayInputConfigInterface, ProtectRelayOutputConfigInterface, ProtectRingtoneConfig, ProtectRingtoneConfigInterface, ProtectSensorAirQuality, ProtectSensorAirQualityInterface, ProtectSensorAirQualitySettings, ProtectSensorAirQualitySettingsInterface, ProtectSensorConfig, ProtectSensorConfigInterface, ProtectSensorSensitivitySettings, ProtectSensorSensitivitySettingsInterface, ProtectSensorSmokeStatus, ProtectSensorSmokeStatusInterface, ProtectSmartZone, ProtectSmartZoneInterface, ProtectStateRecord, ProtectThresholdSettings, ProtectThresholdSettingsInterface, ProtectViewerConfig, ProtectViewerConfigInterface, ProtectWifiConnectionState, ProtectWifiConnectionStateInterface, ProtectWiredConnectionState, ProtectWiredConnectionStateInterface, ProtectWirelessConnectionSettings, ProtectWirelessConnectionSettingsInterface, ProtectWirelessConnectionState, ProtectWirelessConnectionStateInterface } from "./types/index.ts";