@glasshome/sync-layer 0.1.5 → 0.1.7

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.
package/dist/index.d.ts CHANGED
@@ -36,4 +36,5 @@ export type { EntityHistoryData, EntityHistoryQueryOptions, EntityHistoryResult,
36
36
  export { fetchForecast, fetchForecastData, fetchForecasts } from "./weather/fetch";
37
37
  export { getForecast, getForecasts, refreshForecast, refreshForecasts } from "./weather/query";
38
38
  export type { EntityForecastQueryOptions, ForecastQueryOptions, ForecastResult, ForecastsResult, ForecastType, WeatherForecast, WeatherForecastData, WeatherForecasts, WeatherForecastsData, } from "./weather/types";
39
+ export { applyDemoServiceCall, createDemoFixtures, isDemoMode, loadDemoData, unloadDemoData, } from "./demo/demo-provider";
39
40
  export declare const VERSION = "0.1.0";
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
- import { resetStore, setState, state } from "./demo-data-gELwUOS_.js";
2
- import { applyDemoServiceCall, extractDomain } from "./demo-provider-I4BC9Woh.js";
1
+ import { createDemoFixtures, resetStore, setState, state } from "./demo-data-gELwUOS_.js";
3
2
  import { callService as callService$1, createConnection, createLongLivedTokenAuth, getAuth } from "home-assistant-js-websocket";
4
- import { produce } from "solid-js/store";
3
+ import { produce, reconcile } from "solid-js/store";
5
4
 
6
5
  //#region src/connection/adapter.ts
7
6
  /**
@@ -395,6 +394,114 @@ async function refreshAuth(auth) {
395
394
  return auth;
396
395
  }
397
396
 
397
+ //#endregion
398
+ //#region src/core/types.ts
399
+ /**
400
+ * Extract domain from entity ID
401
+ */
402
+ function extractDomain(entityId) {
403
+ return entityId.split(".")[0] ?? "";
404
+ }
405
+
406
+ //#endregion
407
+ //#region src/demo/demo-provider.ts
408
+ let _isDemoMode = false;
409
+ /**
410
+ * Whether demo mode is currently active.
411
+ */
412
+ function isDemoMode() {
413
+ return _isDemoMode;
414
+ }
415
+ /**
416
+ * Load demo fixtures into the SolidJS store.
417
+ *
418
+ * Populates entities, entity registry, areas, and devices.
419
+ * Sets connection state to "connected" (pretend connected).
420
+ */
421
+ async function loadDemoData() {
422
+ const fixtures = createDemoFixtures();
423
+ setState("entities", reconcile(fixtures.entities));
424
+ setState("entityRegistry", reconcile(fixtures.entityRegistry));
425
+ setState("areas", reconcile(fixtures.areas));
426
+ setState("devices", reconcile(fixtures.devices));
427
+ setState("hassUrl", "https://demo.home-assistant.local");
428
+ setState("connectionState", "connected");
429
+ _isDemoMode = true;
430
+ }
431
+ /**
432
+ * Unload demo data and reset to disconnected state.
433
+ */
434
+ function unloadDemoData() {
435
+ setState("entities", reconcile({}));
436
+ setState("entityRegistry", reconcile({}));
437
+ setState("areas", reconcile({}));
438
+ setState("devices", reconcile({}));
439
+ setState("hassUrl", null);
440
+ setState("connectionState", "disconnected");
441
+ _isDemoMode = false;
442
+ }
443
+ /**
444
+ * Apply an optimistic state update for demo mode.
445
+ *
446
+ * When a service call is made in demo mode, this updates the entity
447
+ * state locally (no WebSocket message sent). State resets on page refresh.
448
+ */
449
+ function applyDemoServiceCall(domain, service, _serviceData = {}, target = {}) {
450
+ if (!_isDemoMode) return;
451
+ const entityIds = Array.isArray(target.entity_id) ? target.entity_id : target.entity_id ? [target.entity_id] : [];
452
+ for (const entityId of entityIds) {
453
+ const entity$1 = state.entities[entityId];
454
+ if (!entity$1) continue;
455
+ const entityDomain = extractDomain(entityId);
456
+ setState(produce((s) => {
457
+ const e = s.entities[entityId];
458
+ if (!e) return;
459
+ const now = (/* @__PURE__ */ new Date()).toISOString();
460
+ e.last_changed = now;
461
+ e.last_updated = now;
462
+ if (service === "turn_on") applyTurnOn(e, entityDomain, _serviceData);
463
+ else if (service === "turn_off") applyTurnOff(e, entityDomain);
464
+ else if (service === "toggle") if (e.state === "on" || e.state === "playing" || e.state === "open") applyTurnOff(e, entityDomain);
465
+ else applyTurnOn(e, entityDomain, _serviceData);
466
+ else if (service === "lock") e.state = "locked";
467
+ else if (service === "unlock") e.state = "unlocked";
468
+ else if (service === "open_cover") {
469
+ e.state = "open";
470
+ e.attributes.current_position = 100;
471
+ } else if (service === "close_cover") {
472
+ e.state = "closed";
473
+ e.attributes.current_position = 0;
474
+ } else if (service === "set_cover_position" && _serviceData.position != null) {
475
+ e.attributes.current_position = _serviceData.position;
476
+ e.state = _serviceData.position > 0 ? "open" : "closed";
477
+ } else if (service === "set_temperature" && _serviceData.temperature != null) e.attributes.temperature = _serviceData.temperature;
478
+ else if (service === "set_hvac_mode" && _serviceData.hvac_mode != null) e.state = _serviceData.hvac_mode;
479
+ else if (service === "volume_set" && _serviceData.volume_level != null) e.attributes.volume_level = _serviceData.volume_level;
480
+ }));
481
+ }
482
+ }
483
+ function applyTurnOn(e, domain, serviceData = {}) {
484
+ if (domain === "light") {
485
+ e.state = "on";
486
+ e.attributes.brightness = serviceData.brightness ?? e.attributes.brightness ?? 255;
487
+ if (serviceData.color_temp_kelvin) e.attributes.color_temp_kelvin = serviceData.color_temp_kelvin;
488
+ } else if (domain === "media_player") e.state = "playing";
489
+ else if (domain === "cover") {
490
+ e.state = "open";
491
+ e.attributes.current_position = 100;
492
+ } else e.state = "on";
493
+ }
494
+ function applyTurnOff(e, domain) {
495
+ if (domain === "light") {
496
+ e.state = "off";
497
+ delete e.attributes.brightness;
498
+ } else if (domain === "media_player") e.state = "paused";
499
+ else if (domain === "cover") {
500
+ e.state = "closed";
501
+ e.attributes.current_position = 0;
502
+ } else e.state = "off";
503
+ }
504
+
398
505
  //#endregion
399
506
  //#region src/commands/service.ts
400
507
  /**
@@ -2067,4 +2174,4 @@ async function refreshForecasts(entityId, types) {
2067
2174
  const VERSION = "0.1.0";
2068
2175
 
2069
2176
  //#endregion
2070
- export { DOMAINS_USE_LAST_UPDATED, LINE_ATTRIBUTES_TO_KEEP, NEED_ATTRIBUTE_DOMAINS, VERSION, addDebugIncomingMessageListener, addDebugOutgoingMessageListener, appendHistoryPoint, area, areas, authenticateWithOAuth, authenticateWithToken, batchEntityUpdates, batchServiceCalls, buildAreaView, buildDeviceView, buildEntityView, callService, disconnect, entities, entitiesByAreaAndDomain, entitiesWhere, entity, entityIdHistoryNeedsAttributes, extractDomain, fetchEntityHistory, fetchForecast, fetchForecastData, fetchForecasts, fetchHistory, fetchStream, fetchStreamData, getAllEntityViews, getAreaView, getAreaViews, getConnection, getEntityView, getEntityViews, getForecast, getForecasts, getStream, getWebRtcClientConfig, historyStateToTimeline, initConnection, isAuthValid, isConnected, isHistoryTracked, refreshAuth, refreshForecast, refreshForecasts, refreshStream, resetStore, searchEntities, sendCommand, sendWebRtcCandidate, setState, startWebRtcSession, state, toggle, trackEntityHistory, turnOff, turnOn, untrackEntityHistory, updateEntity };
2177
+ export { DOMAINS_USE_LAST_UPDATED, LINE_ATTRIBUTES_TO_KEEP, NEED_ATTRIBUTE_DOMAINS, VERSION, addDebugIncomingMessageListener, addDebugOutgoingMessageListener, appendHistoryPoint, applyDemoServiceCall, area, areas, authenticateWithOAuth, authenticateWithToken, batchEntityUpdates, batchServiceCalls, buildAreaView, buildDeviceView, buildEntityView, callService, createDemoFixtures, disconnect, entities, entitiesByAreaAndDomain, entitiesWhere, entity, entityIdHistoryNeedsAttributes, extractDomain, fetchEntityHistory, fetchForecast, fetchForecastData, fetchForecasts, fetchHistory, fetchStream, fetchStreamData, getAllEntityViews, getAreaView, getAreaViews, getConnection, getEntityView, getEntityViews, getForecast, getForecasts, getStream, getWebRtcClientConfig, historyStateToTimeline, initConnection, isAuthValid, isConnected, isDemoMode, isHistoryTracked, loadDemoData, refreshAuth, refreshForecast, refreshForecasts, refreshStream, resetStore, searchEntities, sendCommand, sendWebRtcCandidate, setState, startWebRtcSession, state, toggle, trackEntityHistory, turnOff, turnOn, unloadDemoData, untrackEntityHistory, updateEntity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glasshome/sync-layer",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Type-safe, reactive state synchronization layer for Home Assistant",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,7 +9,7 @@
9
9
  "type": "module",
10
10
  "main": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts",
12
- "sideEffects": false,
12
+ "sideEffects": true,
13
13
  "exports": {
14
14
  ".": {
15
15
  "@glasshome/source": "./src/index.ts",
@@ -26,11 +26,6 @@
26
26
  "types": "./dist/testing/index.d.ts",
27
27
  "import": "./dist/testing/index.js"
28
28
  },
29
- "./demo": {
30
- "@glasshome/source": "./src/demo/demo-provider.ts",
31
- "types": "./dist/demo/demo-provider.d.ts",
32
- "import": "./dist/demo/demo-provider.js"
33
- },
34
29
  "./package.json": "./package.json"
35
30
  },
36
31
  "peerDependencies": {
@@ -1,4 +0,0 @@
1
- import { createDemoFixtures } from "../demo-data-gELwUOS_.js";
2
- import { applyDemoServiceCall, isDemoMode, loadDemoData, unloadDemoData } from "../demo-provider-I4BC9Woh.js";
3
-
4
- export { applyDemoServiceCall, createDemoFixtures, isDemoMode, loadDemoData, unloadDemoData };
@@ -1,112 +0,0 @@
1
- import { createDemoFixtures, setState, state } from "./demo-data-gELwUOS_.js";
2
- import { produce, reconcile } from "solid-js/store";
3
-
4
- //#region src/core/types.ts
5
- /**
6
- * Extract domain from entity ID
7
- */
8
- function extractDomain(entityId) {
9
- return entityId.split(".")[0] ?? "";
10
- }
11
-
12
- //#endregion
13
- //#region src/demo/demo-provider.ts
14
- let _isDemoMode = false;
15
- /**
16
- * Whether demo mode is currently active.
17
- */
18
- function isDemoMode() {
19
- return _isDemoMode;
20
- }
21
- /**
22
- * Load demo fixtures into the SolidJS store.
23
- *
24
- * Populates entities, entity registry, areas, and devices.
25
- * Sets connection state to "connected" (pretend connected).
26
- */
27
- async function loadDemoData() {
28
- const fixtures = createDemoFixtures();
29
- setState("entities", reconcile(fixtures.entities));
30
- setState("entityRegistry", reconcile(fixtures.entityRegistry));
31
- setState("areas", reconcile(fixtures.areas));
32
- setState("devices", reconcile(fixtures.devices));
33
- setState("hassUrl", "https://demo.home-assistant.local");
34
- setState("connectionState", "connected");
35
- _isDemoMode = true;
36
- }
37
- /**
38
- * Unload demo data and reset to disconnected state.
39
- */
40
- function unloadDemoData() {
41
- setState("entities", reconcile({}));
42
- setState("entityRegistry", reconcile({}));
43
- setState("areas", reconcile({}));
44
- setState("devices", reconcile({}));
45
- setState("hassUrl", null);
46
- setState("connectionState", "disconnected");
47
- _isDemoMode = false;
48
- }
49
- /**
50
- * Apply an optimistic state update for demo mode.
51
- *
52
- * When a service call is made in demo mode, this updates the entity
53
- * state locally (no WebSocket message sent). State resets on page refresh.
54
- */
55
- function applyDemoServiceCall(domain, service, _serviceData = {}, target = {}) {
56
- if (!_isDemoMode) return;
57
- const entityIds = Array.isArray(target.entity_id) ? target.entity_id : target.entity_id ? [target.entity_id] : [];
58
- for (const entityId of entityIds) {
59
- const entity = state.entities[entityId];
60
- if (!entity) continue;
61
- const entityDomain = extractDomain(entityId);
62
- setState(produce((s) => {
63
- const e = s.entities[entityId];
64
- if (!e) return;
65
- const now = (/* @__PURE__ */ new Date()).toISOString();
66
- e.last_changed = now;
67
- e.last_updated = now;
68
- if (service === "turn_on") applyTurnOn(e, entityDomain, _serviceData);
69
- else if (service === "turn_off") applyTurnOff(e, entityDomain);
70
- else if (service === "toggle") if (e.state === "on" || e.state === "playing" || e.state === "open") applyTurnOff(e, entityDomain);
71
- else applyTurnOn(e, entityDomain, _serviceData);
72
- else if (service === "lock") e.state = "locked";
73
- else if (service === "unlock") e.state = "unlocked";
74
- else if (service === "open_cover") {
75
- e.state = "open";
76
- e.attributes.current_position = 100;
77
- } else if (service === "close_cover") {
78
- e.state = "closed";
79
- e.attributes.current_position = 0;
80
- } else if (service === "set_cover_position" && _serviceData.position != null) {
81
- e.attributes.current_position = _serviceData.position;
82
- e.state = _serviceData.position > 0 ? "open" : "closed";
83
- } else if (service === "set_temperature" && _serviceData.temperature != null) e.attributes.temperature = _serviceData.temperature;
84
- else if (service === "set_hvac_mode" && _serviceData.hvac_mode != null) e.state = _serviceData.hvac_mode;
85
- else if (service === "volume_set" && _serviceData.volume_level != null) e.attributes.volume_level = _serviceData.volume_level;
86
- }));
87
- }
88
- }
89
- function applyTurnOn(e, domain, serviceData = {}) {
90
- if (domain === "light") {
91
- e.state = "on";
92
- e.attributes.brightness = serviceData.brightness ?? e.attributes.brightness ?? 255;
93
- if (serviceData.color_temp_kelvin) e.attributes.color_temp_kelvin = serviceData.color_temp_kelvin;
94
- } else if (domain === "media_player") e.state = "playing";
95
- else if (domain === "cover") {
96
- e.state = "open";
97
- e.attributes.current_position = 100;
98
- } else e.state = "on";
99
- }
100
- function applyTurnOff(e, domain) {
101
- if (domain === "light") {
102
- e.state = "off";
103
- delete e.attributes.brightness;
104
- } else if (domain === "media_player") e.state = "paused";
105
- else if (domain === "cover") {
106
- e.state = "closed";
107
- e.attributes.current_position = 0;
108
- } else e.state = "off";
109
- }
110
-
111
- //#endregion
112
- export { applyDemoServiceCall, extractDomain, isDemoMode, loadDemoData, unloadDemoData };