@glasshome/sync-layer 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/index.d.ts +1291 -54
  2. package/dist/index.js +203 -304
  3. package/dist/service-C8H42I-Q.d.ts +459 -0
  4. package/dist/solid/index.d.ts +119 -6
  5. package/dist/solid/index.js +20 -15
  6. package/dist/{statistics-CtRfIF6D.js → statistics-DyCCTwv2.js} +83 -95
  7. package/dist/worker/worker-main.d.ts +11 -8
  8. package/dist/worker/worker-main.js +2 -3
  9. package/dist/{worker-main-C-3QM4di.js → worker-main-D_wyGAIG.js} +47 -157
  10. package/package.json +3 -3
  11. package/dist/calendar/track.d.ts +0 -19
  12. package/dist/calendar/types.d.ts +0 -32
  13. package/dist/camera/fetch.d.ts +0 -16
  14. package/dist/camera/query.d.ts +0 -15
  15. package/dist/camera/types.d.ts +0 -85
  16. package/dist/camera/webrtc.d.ts +0 -31
  17. package/dist/commands/service.d.ts +0 -53
  18. package/dist/commands/types.d.ts +0 -113
  19. package/dist/connection/adapter.d.ts +0 -48
  20. package/dist/connection/auth.d.ts +0 -126
  21. package/dist/connection/bridged.d.ts +0 -16
  22. package/dist/connection/manager.d.ts +0 -51
  23. package/dist/connection/subscription-manager.d.ts +0 -48
  24. package/dist/connection/subscriptions.d.ts +0 -31
  25. package/dist/connection/types.d.ts +0 -151
  26. package/dist/core/privileged-conn.d.ts +0 -29
  27. package/dist/core/reducers.d.ts +0 -99
  28. package/dist/core/store.d.ts +0 -100
  29. package/dist/core/types.d.ts +0 -339
  30. package/dist/demo/demo-data.d.ts +0 -24
  31. package/dist/demo/demo-provider.d.ts +0 -40
  32. package/dist/demo/energy-sim.d.ts +0 -112
  33. package/dist/energy/prefs.d.ts +0 -56
  34. package/dist/entities/area-views.d.ts +0 -32
  35. package/dist/entities/index.d.ts +0 -54
  36. package/dist/entities/views.d.ts +0 -35
  37. package/dist/history/constants.d.ts +0 -16
  38. package/dist/history/fetch.d.ts +0 -19
  39. package/dist/history/query.d.ts +0 -27
  40. package/dist/history/statistics.d.ts +0 -55
  41. package/dist/history/types.d.ts +0 -146
  42. package/dist/host-api.d.ts +0 -50
  43. package/dist/media/url.d.ts +0 -14
  44. package/dist/query/area-builder.d.ts +0 -25
  45. package/dist/query/builder.d.ts +0 -18
  46. package/dist/query/helpers.d.ts +0 -21
  47. package/dist/query/memoization.d.ts +0 -18
  48. package/dist/query/projections.d.ts +0 -74
  49. package/dist/query/types.d.ts +0 -260
  50. package/dist/solid/hooks.d.ts +0 -119
  51. package/dist/solid/indices.d.ts +0 -15
  52. package/dist/weather/fetch.d.ts +0 -19
  53. package/dist/weather/query.d.ts +0 -23
  54. package/dist/weather/types.d.ts +0 -126
  55. package/dist/worker/bridge-client.d.ts +0 -47
  56. package/dist/worker/enforcement.d.ts +0 -53
  57. package/dist/worker/protocol.d.ts +0 -129
  58. package/dist/worker/token-store.d.ts +0 -3
@@ -1,113 +0,0 @@
1
- /**
2
- * Command types
3
- *
4
- * Type definitions for service calls and commands.
5
- *
6
- * @packageDocumentation
7
- */
8
- import type { Domain, ServiceCall, ServiceName, WsCommandType } from "@glasshome/ha-types";
9
- import type { EntityId } from "../core/types";
10
- /**
11
- * Service call options
12
- */
13
- export interface ServiceCallOptions {
14
- /** Entity ID or array of entity IDs to target */
15
- entity_id?: EntityId | EntityId[];
16
- /** Area ID or array of area IDs to target */
17
- area_id?: string | string[];
18
- /** Device ID or array of device IDs to target */
19
- device_id?: string | string[];
20
- }
21
- /**
22
- * Service call target
23
- *
24
- * Defines what entities the service call should affect
25
- */
26
- export interface ServiceTarget {
27
- /** Entity IDs */
28
- entity_id?: string | string[];
29
- /** Device IDs */
30
- device_id?: string | string[];
31
- /** Area IDs */
32
- area_id?: string | string[];
33
- }
34
- /**
35
- * Service call with full context
36
- */
37
- export interface ServiceCallContext {
38
- /** Domain (e.g., "light", "switch") */
39
- domain: Domain;
40
- /** Service name (e.g., "turn_on", "toggle") */
41
- service: ServiceName<Domain>;
42
- /** Service data */
43
- serviceData?: ServiceCall<Domain, ServiceName<Domain>>;
44
- /** Target entities/devices/areas */
45
- target?: ServiceTarget;
46
- }
47
- /**
48
- * Command success result
49
- */
50
- export interface CommandSuccess<T = unknown> {
51
- success: true;
52
- result: T;
53
- }
54
- /**
55
- * Command error result
56
- */
57
- export interface CommandError {
58
- success: false;
59
- error: {
60
- code: string;
61
- message: string;
62
- };
63
- }
64
- /**
65
- * Command result (success or error)
66
- */
67
- export type CommandResult<T = unknown> = CommandSuccess<T> | CommandError;
68
- /**
69
- * Entity registry update fields
70
- *
71
- * Fields that can be updated in the entity registry
72
- */
73
- export interface EntityUpdateFields {
74
- /** Friendly name */
75
- name?: string;
76
- /** Icon */
77
- icon?: string;
78
- /** Area ID */
79
- area_id?: string | null;
80
- /** Disabled by (null to enable) */
81
- disabled_by?: string | null;
82
- /** Hidden by (null to unhide) */
83
- hidden_by?: string | null;
84
- }
85
- /**
86
- * Entity registry update request
87
- */
88
- export interface EntityUpdateRequest {
89
- /** Entity ID to update */
90
- entity_id: EntityId;
91
- /** Fields to update */
92
- updates: EntityUpdateFields;
93
- }
94
- /**
95
- * Generic WebSocket command
96
- */
97
- export interface GenericCommand {
98
- /** Command type */
99
- type: WsCommandType | string;
100
- /** Command payload */
101
- [key: string]: unknown;
102
- }
103
- /**
104
- * Command execution options
105
- */
106
- export interface CommandOptions {
107
- /** Timeout in milliseconds */
108
- timeout?: number;
109
- /** Retry on failure */
110
- retry?: boolean;
111
- /** Number of retry attempts */
112
- retries?: number;
113
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * HA Connection Adapter
3
- *
4
- * Wraps home-assistant-js-websocket Connection to SyncLayerConnection interface.
5
- * This allows seamless swapping between mock and real connections.
6
- *
7
- * Debug listeners intercept messages at the adapter boundary:
8
- * - Outgoing: fired from sendMessagePromise, subscribeMessage, subscribeEvents
9
- * - Incoming: fired from subscribeMessage/subscribeEvents callbacks and sendMessagePromise responses
10
- *
11
- * @packageDocumentation
12
- */
13
- import type { Connection } from "home-assistant-js-websocket";
14
- import type { SyncLayerConnection } from "./types";
15
- /**
16
- * Register a listener for all outgoing WebSocket messages.
17
- * Returns an unsubscribe function.
18
- *
19
- * @param listener - Function called with each outgoing message object
20
- * @returns Unsubscribe function to remove the listener
21
- */
22
- export declare function addDebugOutgoingMessageListener(listener: (message: any) => void): () => void;
23
- /**
24
- * Register a listener for all incoming WebSocket messages.
25
- * Returns an unsubscribe function. Receives subscription updates,
26
- * event callbacks, and sendMessagePromise responses.
27
- *
28
- * @param listener - Function called with each incoming message object
29
- * @returns Unsubscribe function to remove the listener
30
- */
31
- export declare function addDebugIncomingMessageListener(listener: (message: any) => void): () => void;
32
- /**
33
- * Wrap HA Connection to SyncLayerConnection interface
34
- *
35
- * This adapter makes the real HA Connection compatible with our unified interface,
36
- * allowing it to be used interchangeably with MockConnection.
37
- *
38
- * @param conn - Home Assistant WebSocket connection
39
- * @returns Wrapped connection implementing SyncLayerConnection
40
- *
41
- * @example
42
- * ```typescript
43
- * const haConn = await createConnection({ auth });
44
- * const wrappedConn = wrapHAConnection(haConn);
45
- * await syncLayer.connect({ connection: wrappedConn });
46
- * ```
47
- */
48
- export declare function wrapHAConnection(conn: Connection): SyncLayerConnection;
@@ -1,126 +0,0 @@
1
- /**
2
- * Authentication Helpers
3
- *
4
- * Provides OAuth and token-based authentication for Home Assistant connections.
5
- *
6
- * @packageDocumentation
7
- */
8
- import { type Auth } from "home-assistant-js-websocket";
9
- /**
10
- * Options for OAuth authentication flow
11
- */
12
- export interface OAuthOptions {
13
- /**
14
- * Home Assistant instance URL
15
- * (e.g., "https://homeassistant.local:8123")
16
- */
17
- url: string;
18
- /**
19
- * Client ID for OAuth
20
- * Typically the same as the Home Assistant URL
21
- */
22
- clientId: string;
23
- /**
24
- * Redirect URI after OAuth authorization
25
- * (e.g., "https://myapp.com/auth/callback")
26
- */
27
- redirectUri?: string;
28
- /**
29
- * Optional authorization code if already obtained
30
- * If provided, will be used directly instead of starting OAuth flow
31
- */
32
- authCode?: string;
33
- /**
34
- * Optional function to get authorization code
35
- * If provided, will be called to get the code before token exchange
36
- */
37
- getAuthCode?: () => Promise<string>;
38
- /**
39
- * Optional function to save auth data
40
- * Useful for persisting auth tokens
41
- */
42
- saveAuth?: (auth: Auth) => void | Promise<void>;
43
- /**
44
- * Optional function to load saved auth data
45
- */
46
- loadAuth?: () => Promise<Auth | null>;
47
- /**
48
- * Optional flag to limit to specific Home Assistant instance
49
- */
50
- limitHassInstance?: boolean;
51
- }
52
- /**
53
- * Authenticate using OAuth flow
54
- *
55
- * This function uses `getAuth` from `home-assistant-js-websocket` which:
56
- * 1. Redirects the whole page to the Home Assistant authorization page
57
- * 2. Waits for user authorization
58
- * 3. On return, HA redirects back to the app URL with `?auth_callback=1&code=…`
59
- * 4. Exchanges the authorization code for tokens and returns an Auth object
60
- *
61
- * Note: For a complete OAuth flow, you typically need to:
62
- * - Set up a redirect URI endpoint in your app
63
- * - Handle the OAuth callback with the authorization code
64
- * - Use `getAuthCode` callback to provide the code
65
- *
66
- * In browser environments `getAuth` handles this automatically via a full-page
67
- * redirect (not a popup); native platforms supply `getAuthCode` instead.
68
- *
69
- * @param options - OAuth options
70
- * @returns Authenticated Auth object
71
- *
72
- * @example
73
- * ```typescript
74
- * // Basic OAuth flow (browser only)
75
- * const auth = await authenticateWithOAuth({
76
- * url: 'https://homeassistant.local:8123',
77
- * clientId: 'https://homeassistant.local:8123',
78
- * redirectUri: 'https://myapp.com/auth/callback',
79
- * });
80
- * ```
81
- *
82
- * @example
83
- * ```typescript
84
- * // OAuth with custom code handling
85
- * const auth = await authenticateWithOAuth({
86
- * url: 'https://homeassistant.local:8123',
87
- * clientId: 'https://homeassistant.local:8123',
88
- * redirectUri: 'https://myapp.com/auth/callback',
89
- * getAuthCode: async () => {
90
- * // Wait for user to authorize and get code from callback
91
- * return await waitForAuthCode();
92
- * },
93
- * });
94
- * ```
95
- */
96
- export declare function authenticateWithOAuth(options: OAuthOptions): Promise<Auth>;
97
- /**
98
- * Authenticate using a long-lived token
99
- *
100
- * @param url - Home Assistant instance URL
101
- * @param token - Long-lived access token
102
- * @returns Authenticated Auth object
103
- *
104
- * @example
105
- * ```typescript
106
- * const auth = authenticateWithToken(
107
- * 'https://homeassistant.local:8123',
108
- * 'your_long_lived_token'
109
- * );
110
- * ```
111
- */
112
- export declare function authenticateWithToken(url: string, token: string): Auth;
113
- /**
114
- * Check if auth object is valid
115
- *
116
- * @param auth - Auth object to check
117
- * @returns True if auth is valid
118
- */
119
- export declare function isAuthValid(auth: Auth): Promise<boolean>;
120
- /**
121
- * Refresh auth tokens
122
- *
123
- * @param auth - Auth object to refresh
124
- * @returns Refreshed Auth object
125
- */
126
- export declare function refreshAuth(auth: Auth): Promise<Auth>;
@@ -1,16 +0,0 @@
1
- import type { HaBridge } from "../worker/bridge-client";
2
- /**
3
- * Wire an HA bridge (worker-backed connection) into the store. The bridge's
4
- * facade rides the same load/subscribe pipeline as a direct socket; only the
5
- * lifecycle signals differ — they arrive as worker messages instead of
6
- * Connection events.
7
- *
8
- * Call after bridge.connect() resolved. Returns when initial data is loaded.
9
- */
10
- export declare function attachBridgeToStore(bridge: HaBridge, hassUrl: string, mediaProxyBase?: string): Promise<void>;
11
- /** Map worker connection-state messages onto the store. */
12
- export declare function applyBridgeConnState(state: "connected" | "disconnected" | "reconnecting"): void;
13
- /** Re-sync after the worker reports a completed reconnect. */
14
- export declare function reloadAfterBridgeReconnect(bridge: HaBridge): Promise<void>;
15
- /** Detach on shutdown; the caller terminates the worker itself. */
16
- export declare function detachBridgeFromStore(): void;
@@ -1,51 +0,0 @@
1
- /**
2
- * Connection Manager
3
- *
4
- * Handles WebSocket connection lifecycle, authentication,
5
- * and initial data loading.
6
- *
7
- * @packageDocumentation
8
- */
9
- import { type Auth, type Connection, type ConnectionOptions as HAConnectionOptions } from "home-assistant-js-websocket";
10
- import { type HaLink } from "../core/store";
11
- import { type OAuthOptions } from "./auth";
12
- /**
13
- * Options for initializing a connection
14
- */
15
- export interface ConnectionOptions {
16
- url: string;
17
- auth: Auth | string | OAuthOptions;
18
- createSocket?: HAConnectionOptions["createSocket"];
19
- onConnect?: () => void;
20
- onDisconnect?: () => void;
21
- onReconnect?: () => void;
22
- onError?: (error: Error) => void;
23
- }
24
- /**
25
- * Initialize connection to Home Assistant
26
- */
27
- export declare function initConnection(options: ConnectionOptions): Promise<Connection>;
28
- /**
29
- * Disconnect from Home Assistant
30
- */
31
- export declare function disconnect(): void;
32
- /**
33
- * Get current connection link
34
- */
35
- export declare function getConnection(): HaLink | null;
36
- /**
37
- * Check if currently connected
38
- */
39
- export declare function isConnected(): boolean;
40
- /**
41
- * Get the underlying socket's connected flag.
42
- *
43
- * Exposed so apps can render a connection indicator in the UI. Distinct from
44
- * `isConnected()` which reflects the manager's internal lifecycle state.
45
- */
46
- export declare function getConnectionState(): boolean;
47
- export declare function loadInitialData(conn: Pick<HaLink, "sendMessagePromise">): Promise<void>;
48
- /**
49
- * Refresh all data
50
- */
51
- export declare function refreshData(): Promise<void>;
@@ -1,48 +0,0 @@
1
- /**
2
- * Entity Subscription Manager
3
- *
4
- * Ref-counted registry that tracks which entity IDs need live updates
5
- * from Home Assistant. When the active set changes, resubscribes with
6
- * the new entity_ids filter so HA only sends diffs for displayed entities.
7
- *
8
- * @packageDocumentation
9
- */
10
- import type { EntityId } from "../core/types";
11
- import type { SyncLayerConnection } from "./types";
12
- type UnsubscribeFn = () => Promise<void> | void;
13
- declare global {
14
- var __GH_SYNC_LAYER_SUB_MGR__: boolean | undefined;
15
- }
16
- /**
17
- * Register an entity for live updates. Returns an unregister function.
18
- * Call from useEntity/useEntities hooks via onCleanup.
19
- */
20
- export declare function registerEntity(entityId: EntityId): () => void;
21
- /**
22
- * Get the current set of actively subscribed entity IDs.
23
- */
24
- export declare function getActiveEntityIds(): Set<EntityId>;
25
- /**
26
- * Set the connection reference used for resubscribing.
27
- */
28
- export declare function setManagerConnection(connection: SyncLayerConnection): void;
29
- /**
30
- * Set the resubscribe callback. Called by subscriptions.ts to wire
31
- * the manager into the actual WS subscription lifecycle.
32
- */
33
- export declare function setResubscribeHandler(handler: (conn: SyncLayerConnection, entityIds: EntityId[]) => Promise<UnsubscribeFn>): void;
34
- /**
35
- * Store the current entity subscription's unsub function.
36
- * Called after initial subscribe_entities.
37
- */
38
- export declare function setCurrentEntityUnsub(unsub: UnsubscribeFn): void;
39
- /**
40
- * Force a resubscribe with the current active set.
41
- * Used on reconnect.
42
- */
43
- export declare function forceResubscribe(): Promise<void>;
44
- /**
45
- * Reset manager state. Used on disconnect or for testing.
46
- */
47
- export declare function resetManager(): void;
48
- export {};
@@ -1,31 +0,0 @@
1
- /**
2
- * Event Subscriptions
3
- *
4
- * Sets up WebSocket event subscriptions to keep state in sync
5
- * with Home Assistant.
6
- *
7
- * @packageDocumentation
8
- */
9
- import type { EntityId } from "../core/types";
10
- import type { SyncLayerConnection } from "./types";
11
- /**
12
- * Subscribe to entity state updates with an entity_ids filter.
13
- * Called by the subscription manager on flush.
14
- */
15
- export declare function subscribeEntities(connection: SyncLayerConnection, entityIds: EntityId[]): Promise<() => Promise<void>>;
16
- /**
17
- * Subscribe to all relevant events from Home Assistant
18
- */
19
- export declare function subscribeToUpdates(conn: SyncLayerConnection): Promise<void>;
20
- /**
21
- * Clean up all active subscriptions
22
- */
23
- export declare function cleanupSubscriptions(): Promise<void>;
24
- /**
25
- * Check if subscriptions are active
26
- */
27
- export declare function hasActiveSubscriptions(): boolean;
28
- /**
29
- * Get number of active subscriptions
30
- */
31
- export declare function getSubscriptionCount(): number;
@@ -1,151 +0,0 @@
1
- /**
2
- * Connection Interface Types
3
- *
4
- * Defines the unified interface for both mock and real Home Assistant connections.
5
- * This allows seamless swapping between test and production connections.
6
- *
7
- * @packageDocumentation
8
- */
9
- import type { HAEvent } from "@glasshome/ha-types";
10
- /**
11
- * Unified connection interface for Home Assistant connections
12
- *
13
- * This interface is implemented by both:
14
- * - MockConnection (for testing)
15
- * - Wrapped HA Connection (for production)
16
- *
17
- * @example
18
- * ```typescript
19
- * // In tests
20
- * const mockConn: SyncLayerConnection = new MockConnection(fixtures);
21
- * await syncLayer.connect({ connection: mockConn });
22
- *
23
- * // In production
24
- * const haConn = await createConnection({ auth });
25
- * const wrappedConn: SyncLayerConnection = wrapHAConnection(haConn);
26
- * await syncLayer.connect({ connection: wrappedConn });
27
- * ```
28
- */
29
- export interface SyncLayerConnection {
30
- /**
31
- * Connect to Home Assistant (or mock)
32
- *
33
- * Establishes the WebSocket connection. For real HA connections,
34
- * this is called automatically by createConnection. For mock connections,
35
- * this simulates the connection process.
36
- *
37
- * @returns Promise that resolves when connection is established
38
- */
39
- connect(): Promise<void>;
40
- /**
41
- * Disconnect from Home Assistant
42
- *
43
- * Closes the WebSocket connection and cleans up resources.
44
- */
45
- disconnect(): void;
46
- /**
47
- * Check if connection is currently active
48
- *
49
- * @returns true if connected, false otherwise
50
- */
51
- get connected$(): boolean;
52
- /**
53
- * Authenticate with Home Assistant
54
- *
55
- * Sends authentication credentials. For real HA connections,
56
- * authentication is handled during connection creation. For mock connections,
57
- * this simulates the authentication process.
58
- *
59
- * @param accessToken - Access token for authentication
60
- * @returns Promise that resolves when authentication completes
61
- */
62
- authenticate(accessToken: string): Promise<void>;
63
- /**
64
- * Get current authentication state
65
- *
66
- * @returns Authentication state: "pending", "authenticated", or "failed"
67
- */
68
- get authState(): "pending" | "authenticated" | "failed";
69
- /**
70
- * Subscribe to Home Assistant events
71
- *
72
- * Registers a callback to receive events of a specific type (or all events).
73
- *
74
- * @param callback - Function called when events are received
75
- * @param eventType - Optional event type filter (e.g., "entity_registry_updated")
76
- * @returns Promise resolving to unsubscribe function
77
- *
78
- * @example
79
- * ```typescript
80
- * const unsubscribe = await connection.subscribeEvents((event) => {
81
- * console.log("Event received:", event);
82
- * }, "entity_registry_updated");
83
- *
84
- * // Later, unsubscribe
85
- * await unsubscribe();
86
- * ```
87
- */
88
- subscribeEvents(callback: (event: HAEvent<any>) => void, eventType?: string): Promise<() => void>;
89
- /**
90
- * Subscribe to message stream
91
- *
92
- * Used for streaming subscriptions like history/stream.
93
- * Sends a subscription message and receives streaming responses.
94
- *
95
- * @param callback - Function called when messages are received
96
- * @param message - Subscription message (e.g., { type: "history/stream", ... })
97
- * @returns Promise resolving to unsubscribe function
98
- *
99
- * @example
100
- * ```typescript
101
- * const unsubscribe = await connection.subscribeMessage((message) => {
102
- * console.log("Stream message:", message);
103
- * }, {
104
- * type: "history/stream",
105
- * entity_ids: ["sensor.temperature"],
106
- * start_time: startTime.toISOString(),
107
- * });
108
- *
109
- * // Later, unsubscribe
110
- * await unsubscribe();
111
- * ```
112
- */
113
- subscribeMessage<T>(callback: (message: T) => void, message: any): Promise<() => Promise<void>>;
114
- /**
115
- * Send a message and wait for response
116
- *
117
- * Sends a WebSocket message and returns a promise that resolves
118
- * with the response.
119
- *
120
- * @param message - Message to send
121
- * @returns Promise resolving to the response data
122
- *
123
- * @example
124
- * ```typescript
125
- * const states = await connection.sendMessagePromise({
126
- * type: "get_states",
127
- * });
128
- * ```
129
- */
130
- sendMessagePromise<T>(message: any): Promise<T>;
131
- /**
132
- * Add event listener for WebSocket messages
133
- *
134
- * Registers a handler for all WebSocket messages (not just events).
135
- * Useful for listening to auth messages, connection status, etc.
136
- *
137
- * @param handler - Function called when any message is received
138
- * @returns Unsubscribe function
139
- *
140
- * @example
141
- * ```typescript
142
- * const unsubscribe = connection.addEventListener((message) => {
143
- * console.log("Any message:", message);
144
- * });
145
- *
146
- * // Later, unsubscribe
147
- * unsubscribe();
148
- * ```
149
- */
150
- addEventListener(handler: (message: any) => void): () => void;
151
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * The privileged Home Assistant connection, held outside the shared store.
3
- *
4
- * This handle tunnels arbitrary HA traffic: the worker's `case "send"` forwards
5
- * whatever arrives on it after a shape check only, because capability
6
- * validation belongs on the per-widget MessagePorts, not here.
7
- *
8
- * It therefore must not be reachable from widget code. It used to live at
9
- * `state.conn`, and `state` is exported from this package's entry, which the
10
- * host serves to every widget bundle through its import map — so any widget
11
- * could read the handle and call any service on any entity, regardless of the
12
- * capabilities it declared and the user approved. Proven by execution, not
13
- * argued: a widget-side `useService()` emitted `call_service`/`lock.unlock`
14
- * onto the host's own channel (finding 46).
15
- *
16
- * Module-local and deliberately absent from `src/index.ts`. Not being exported
17
- * is the entire mechanism, so exporting it — directly, or by parking the value
18
- * on anything that is exported — reopens the hole. `check-widget-reachable-
19
- * surface.ts` fails the build if it ever becomes reachable again.
20
- *
21
- * Plain variable rather than store state: every reader takes it imperatively
22
- * inside an async fetcher or command, so none of them tracked it reactively.
23
- * `state.connectionState` remains the reactive signal for connection status.
24
- */
25
- import type { HaLink } from "./store";
26
- /** Read the live connection. Null before connect and after disconnect. */
27
- export declare function privilegedConn(): HaLink | null;
28
- /** Set by the connection layer on connect/disconnect. Host-side callers only. */
29
- export declare function setPrivilegedConn(conn: HaLink | null): void;