@glasshome/sync-layer 0.10.0 → 0.10.2

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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as setPrivilegedConn, A as unloadDemoData, B as getAreaView, C as demoTimeMap, D as resetDemo, E as loadDemoHouse, F as MAX_HISTORY_POINTS, G as getEntityView, H as buildEntityView, I as appendHistoryPoint, J as forceResubscribe, K as getEntityViews, L as bulkAppendHistoryPoints, M as demoEnergyPreferences, N as isEnergyEntity, O as startDemoEnergyTicker, P as synthesizeEnergyHistory, Q as privilegedConn, R as buildAreaView, S as demoReplayModel, T as loadDemoData, U as entityViewEquals, V as getAreaViews, W as getAllEntityViews, X as setManagerConnection, Y as registerEntity, Z as setResubscribeHandler, _ as applyDemoServiceCall, a as fetchForecastData, b as demoCallLog, c as normalizeStatisticTime, d as callService, et as setState, f as sendCommand, g as updateEntity, h as turnOn, i as fetchForecast, j as demoAssetUrl, k as stopDemoEnergyTicker, l as batchEntityUpdates, m as turnOff, o as fetchForecasts, p as toggle, q as extractDomain, s as fetchStatisticsDuringPeriod, t as forceResubscribeCalendars, tt as state, u as batchServiceCalls, v as applyVisitorHolds, w as isDemoMode, x as demoModel, y as createDemoFixtures, z as buildDeviceView } from "./track-BAfgOjMk.js";
1
+ import { $ as setPrivilegedConn, A as unloadDemoData, B as getAreaView, C as demoTimeMap, D as resetDemo, E as loadDemoHouse, F as MAX_HISTORY_POINTS, G as getEntityView, H as buildEntityView, I as appendHistoryPoint, J as forceResubscribe, K as getEntityViews, L as bulkAppendHistoryPoints, M as demoEnergyPreferences, N as isEnergyEntity, O as startDemoEnergyTicker, P as synthesizeEnergyHistory, Q as privilegedConn, R as buildAreaView, S as demoReplayModel, T as loadDemoData, U as entityViewEquals, V as getAreaViews, W as getAllEntityViews, X as setManagerConnection, Y as registerEntity, Z as setResubscribeHandler, _ as applyDemoServiceCall, a as fetchForecastData, b as demoCallLog, c as normalizeStatisticTime, d as callService, et as setState, f as sendCommand, g as updateEntity, h as turnOn, i as fetchForecast, j as demoAssetUrl, k as stopDemoEnergyTicker, l as batchEntityUpdates, m as turnOff, o as fetchForecasts, p as toggle, q as extractDomain, s as fetchStatisticsDuringPeriod, t as forceResubscribeCalendars, tt as state, u as batchServiceCalls, v as applyVisitorHolds, w as isDemoMode, x as demoModel, y as createDemoFixtures, z as buildDeviceView } from "./track-BmoU1-vZ.js";
2
2
  import { t as runHaBridgeWorker } from "./worker-main-B6eeHPDQ.js";
3
3
  import { produce } from "solid-js/store";
4
4
  //#region src/core/reducers.ts
@@ -1034,7 +1034,8 @@ function demoHistory(entityIds, startMs, endMs, toWallMs = (ms) => ms) {
1034
1034
  const startC = Math.max(startMs, endC - DAY_MS);
1035
1035
  if (startC >= endC) return result;
1036
1036
  const log = demoCallLog();
1037
- const modelStartMs = log.length > 0 ? Math.min(startC, log[0].simMs) : startC;
1037
+ const first = log[0];
1038
+ const modelStartMs = first ? Math.min(startC, first.simMs) : startC;
1038
1039
  const replayModel = demoReplayModel(modelStartMs);
1039
1040
  if (!replayModel) return result;
1040
1041
  const replay = replayModel;
@@ -1053,15 +1054,15 @@ function demoHistory(entityIds, startMs, endMs, toWallMs = (ms) => ms) {
1053
1054
  record(replay.nowMs);
1054
1055
  let logIdx = 0;
1055
1056
  while (replay.nowMs < endC) {
1056
- const nextLogMs = logIdx < log.length ? log[logIdx].simMs : Number.POSITIVE_INFINITY;
1057
+ const next = log[logIdx];
1058
+ const nextLogMs = next ? next.simMs : Number.POSITIVE_INFINITY;
1057
1059
  const windowBoundary = replay.nowMs < startC ? startC : Number.POSITIVE_INFINITY;
1058
1060
  const targetMs = Math.min(replay.nowMs + STEP_MS, endC, nextLogMs, windowBoundary);
1059
1061
  replay.advanceTo(targetMs, STEP_MS);
1060
1062
  record(replay.nowMs);
1061
- if (logIdx < log.length && log[logIdx].simMs === replay.nowMs) {
1062
- const entry = log[logIdx];
1063
- replay.dispatch(entry.call);
1064
- applyVisitorHolds(replay, entry.call.entityIds);
1063
+ if (next && next.simMs === replay.nowMs) {
1064
+ replay.dispatch(next.call);
1065
+ applyVisitorHolds(replay, next.call.entityIds);
1065
1066
  logIdx++;
1066
1067
  record(replay.nowMs);
1067
1068
  }
@@ -1097,7 +1098,7 @@ async function fetchHistory(options) {
1097
1098
  const endMs = timeMap.toSim((endTime ?? /* @__PURE__ */ new Date()).getTime());
1098
1099
  const energyStepMs = timeMap.toSim(6e4) - timeMap.toSim(0);
1099
1100
  const toWallSeconds = (simSeconds) => Math.round(timeMap.toWall(simSeconds * 1e3) / 1e3);
1100
- const replayed = demoHistory(entityIds.filter((id) => !isEnergyEntity(id)), startMs, endMs, timeMap.toWall);
1101
+ const replayed = demoHistory(entityIds.filter((id) => !isEnergyEntity(id)), startMs, endMs, (ms) => timeMap.toWall(ms));
1101
1102
  const result = {};
1102
1103
  for (const id of entityIds) result[id] = isEnergyEntity(id) ? synthesizeEnergyHistory(id, startMs, endMs, energyStepMs).map((p) => ({
1103
1104
  s: p.s,
@@ -1,4 +1,4 @@
1
- import { G as getEntityView, Q as privilegedConn, R as buildAreaView, U as entityViewEquals, V as getAreaViews, Y as registerEntity, d as callService, et as setState, h as turnOn, m as turnOff, n as trackCalendarEvents, p as toggle, q as extractDomain, r as buildDemoForecast, s as fetchStatisticsDuringPeriod, tt as state, w as isDemoMode } from "../track-BAfgOjMk.js";
1
+ import { G as getEntityView, Q as privilegedConn, R as buildAreaView, U as entityViewEquals, V as getAreaViews, Y as registerEntity, d as callService, et as setState, h as turnOn, m as turnOff, n as trackCalendarEvents, p as toggle, q as extractDomain, r as buildDemoForecast, s as fetchStatisticsDuringPeriod, tt as state, w as isDemoMode } from "../track-BmoU1-vZ.js";
2
2
  import { produce } from "solid-js/store";
3
3
  import { createEffect, createMemo, createResource, onCleanup } from "solid-js";
4
4
  //#region src/weather/track.ts
@@ -504,7 +504,19 @@ const WEEKDAYS = {
504
504
  Fri: 5,
505
505
  Sat: 6
506
506
  };
507
+ const RECENT_LIMIT = 256;
508
+ const recent = /* @__PURE__ */ new Map();
507
509
  function parts(ms, timeZone) {
510
+ const key = `${timeZone}|${ms}`;
511
+ let p = recent.get(key);
512
+ if (!p) {
513
+ if (recent.size >= RECENT_LIMIT) recent.clear();
514
+ p = readParts(ms, timeZone);
515
+ recent.set(key, p);
516
+ }
517
+ return p;
518
+ }
519
+ function readParts(ms, timeZone) {
508
520
  const out = {};
509
521
  for (const p of formatter(timeZone).formatToParts(ms)) out[p.type] = p.value;
510
522
  return {
@@ -1244,18 +1256,18 @@ const fan = {
1244
1256
  on: percentage > 0
1245
1257
  };
1246
1258
  }
1247
- case "set_preset_mode": return data.preset_mode != null ? {
1259
+ case "set_preset_mode": return typeof data.preset_mode === "string" ? {
1248
1260
  ...s,
1249
- presetMode: String(data.preset_mode),
1261
+ presetMode: data.preset_mode,
1250
1262
  on: true
1251
1263
  } : s;
1252
1264
  case "oscillate": return data.oscillating != null ? {
1253
1265
  ...s,
1254
1266
  oscillating: Boolean(data.oscillating)
1255
1267
  } : s;
1256
- case "set_direction": return data.direction != null ? {
1268
+ case "set_direction": return typeof data.direction === "string" ? {
1257
1269
  ...s,
1258
- direction: String(data.direction)
1270
+ direction: data.direction
1259
1271
  } : s;
1260
1272
  default: return s;
1261
1273
  }
@@ -1508,17 +1520,17 @@ const climate = {
1508
1520
  if (data.target_temp_high != null) next.targetTempHigh = Number(data.target_temp_high);
1509
1521
  return next;
1510
1522
  }
1511
- case "set_hvac_mode": return data.hvac_mode != null ? {
1523
+ case "set_hvac_mode": return typeof data.hvac_mode === "string" ? {
1512
1524
  ...s,
1513
- hvacMode: String(data.hvac_mode)
1525
+ hvacMode: data.hvac_mode
1514
1526
  } : s;
1515
- case "set_fan_mode": return data.fan_mode != null ? {
1527
+ case "set_fan_mode": return typeof data.fan_mode === "string" ? {
1516
1528
  ...s,
1517
- fanMode: String(data.fan_mode)
1529
+ fanMode: data.fan_mode
1518
1530
  } : s;
1519
- case "set_preset_mode": return data.preset_mode != null ? {
1531
+ case "set_preset_mode": return typeof data.preset_mode === "string" ? {
1520
1532
  ...s,
1521
- presetMode: String(data.preset_mode)
1533
+ presetMode: data.preset_mode
1522
1534
  } : s;
1523
1535
  default: return s;
1524
1536
  }
@@ -1593,9 +1605,9 @@ const waterHeater = {
1593
1605
  ...s,
1594
1606
  targetTemp: Number(data.temperature)
1595
1607
  } : s;
1596
- case "set_operation_mode": return data.operation_mode != null ? {
1608
+ case "set_operation_mode": return typeof data.operation_mode === "string" ? {
1597
1609
  ...s,
1598
- mode: String(data.operation_mode)
1610
+ mode: data.operation_mode
1599
1611
  } : s;
1600
1612
  case "set_away_mode": return data.away_mode != null ? {
1601
1613
  ...s,
@@ -1698,9 +1710,9 @@ const ACTUATORS = {
1698
1710
  ...s,
1699
1711
  volume: Number(data.volume_level)
1700
1712
  } : s;
1701
- case "select_source": return data.source != null ? {
1713
+ case "select_source": return typeof data.source === "string" ? {
1702
1714
  ...s,
1703
- source: String(data.source)
1715
+ source: data.source
1704
1716
  } : s;
1705
1717
  default: return s;
1706
1718
  }
@@ -2018,7 +2030,7 @@ const weather = {
2018
2030
  const sunUp = solarElevation(ctx.nowMs, ctx.world.latitude, ctx.world.longitude) > -.833;
2019
2031
  const dateKey = localTime$1(ctx.nowMs, ctx.world.timeZone).dateKey;
2020
2032
  const noiseVal = ctx.noise(`weather:condition:${dateKey}`);
2021
- const forecast = Array.from({ length: 7 }, (_, i) => weatherForecastDay(ctx.nowMs, ctx.world, i, ctx.noise));
2033
+ const forecast = Array.from({ length: 7 }, (_, i) => weatherForecastDay(ctx.nowMs, ctx.world, i, (key) => ctx.noise(key)));
2022
2034
  return { [id]: {
2023
2035
  state: weatherCondition(cloud, sunUp, noiseVal),
2024
2036
  attributes: {
@@ -2890,7 +2902,8 @@ function toCategory(c) {
2890
2902
  return c ?? null;
2891
2903
  }
2892
2904
  function entityEntry(p, seed, name, createdIso) {
2893
- const platform = String(p.spec.params.integration ?? "demo");
2905
+ const integration = p.spec.params.integration;
2906
+ const platform = typeof integration === "string" ? integration : "demo";
2894
2907
  return {
2895
2908
  aliases: [],
2896
2909
  area_id: null,
@@ -2925,7 +2938,8 @@ function entityEntry(p, seed, name, createdIso) {
2925
2938
  };
2926
2939
  }
2927
2940
  function deviceEntry(owner, id, createdIso) {
2928
- const platform = String(owner.params.integration ?? "demo");
2941
+ const integration = owner.params.integration;
2942
+ const platform = typeof integration === "string" ? integration : "demo";
2929
2943
  const entry = `${platform}_entry`;
2930
2944
  return {
2931
2945
  id,
package/package.json CHANGED
@@ -1,15 +1,32 @@
1
1
  {
2
2
  "name": "@glasshome/sync-layer",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "Type-safe, reactive state synchronization layer for Home Assistant",
5
+ "keywords": [
6
+ "home-assistant",
7
+ "reactive",
8
+ "smart-home",
9
+ "solidjs",
10
+ "typescript",
11
+ "websocket"
12
+ ],
13
+ "homepage": "https://github.com/glasshome/sync-layer#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/glasshome/sync-layer/issues"
16
+ },
17
+ "license": "MIT",
18
+ "author": "GlassHome Labs",
5
19
  "repository": {
6
20
  "type": "git",
7
21
  "url": "https://github.com/glasshome/sync-layer.git"
8
22
  },
23
+ "files": [
24
+ "dist"
25
+ ],
9
26
  "type": "module",
27
+ "sideEffects": true,
10
28
  "main": "./dist/index.js",
11
29
  "types": "./dist/index.d.ts",
12
- "sideEffects": true,
13
30
  "exports": {
14
31
  ".": {
15
32
  "@glasshome/source": "./src/index.ts",
@@ -33,59 +50,45 @@
33
50
  },
34
51
  "./package.json": "./package.json"
35
52
  },
36
- "peerDependencies": {
37
- "@glasshome/ha-types": "0.2.0",
38
- "solid-js": "^1.9.0"
39
- },
40
- "peerDependenciesMeta": {
41
- "@glasshome/ha-types": {
42
- "optional": false
43
- },
44
- "solid-js": {
45
- "optional": true
46
- }
53
+ "publishConfig": {
54
+ "access": "public"
47
55
  },
48
- "files": [
49
- "dist"
50
- ],
51
56
  "scripts": {
52
57
  "build": "tsdown && tsc --noEmit && bun scripts/check-widget-reachable-surface.ts",
53
58
  "dev": "tsdown --watch",
54
59
  "test": "bun test",
55
- "lint": "tsc --noEmit",
60
+ "lint": "oxlint --type-aware . && oxfmt --check . && tsc --noEmit",
56
61
  "gen:demo-ids": "bun scripts/gen-demo-ids.ts",
57
62
  "check:dead": "fallow dead-code --fail-on-issues"
58
63
  },
59
64
  "dependencies": {
60
- "home-assistant-js-websocket": "^9.6.0",
61
- "@glasshome/widget-contract": "0.3.0"
65
+ "@glasshome/widget-contract": "0.3.0",
66
+ "home-assistant-js-websocket": "^9.6.0"
62
67
  },
63
68
  "devDependencies": {
64
69
  "@glasshome/ha-types": "0.2.0",
65
70
  "@types/bun": "^1.4.0",
66
71
  "fallow": "3.17.0",
72
+ "oxfmt": "0.65.0",
73
+ "oxlint": "1.81.0",
74
+ "oxlint-tsgolint": "7.0.2001",
67
75
  "solid-js": "^1.9.0",
68
76
  "tsdown": "^0.22.14",
69
77
  "typescript": "^7.0.2"
70
78
  },
71
- "homepage": "https://github.com/glasshome/sync-layer#readme",
72
- "bugs": {
73
- "url": "https://github.com/glasshome/sync-layer/issues"
79
+ "peerDependencies": {
80
+ "@glasshome/ha-types": "0.2.0",
81
+ "solid-js": "^1.9.0"
74
82
  },
75
- "publishConfig": {
76
- "access": "public"
83
+ "peerDependenciesMeta": {
84
+ "@glasshome/ha-types": {
85
+ "optional": false
86
+ },
87
+ "solid-js": {
88
+ "optional": true
89
+ }
77
90
  },
78
91
  "engines": {
79
92
  "node": ">=18"
80
- },
81
- "keywords": [
82
- "home-assistant",
83
- "websocket",
84
- "typescript",
85
- "reactive",
86
- "solidjs",
87
- "smart-home"
88
- ],
89
- "author": "GlassHome Labs",
90
- "license": "MIT"
93
+ }
91
94
  }