@digital-alchemy/hass 25.11.16 → 25.11.23

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 (54) hide show
  1. package/dist/helpers/entity-state.d.mts +20 -3
  2. package/dist/helpers/fetch/service-list.d.mts +86 -5
  3. package/dist/helpers/id-by.d.mts +1 -1
  4. package/dist/helpers/utility.d.mts +1 -1
  5. package/dist/mock_assistant/mock-assistant.module.mjs.map +1 -1
  6. package/dist/mock_assistant/services/websocket-api.service.d.mts +3 -1
  7. package/dist/mock_assistant/services/websocket-api.service.mjs +43 -4
  8. package/dist/mock_assistant/services/websocket-api.service.mjs.map +1 -1
  9. package/dist/services/feature.service.d.mts +2 -2
  10. package/dist/services/feature.service.mjs.map +1 -1
  11. package/dist/services/id-by.service.mjs +4 -1
  12. package/dist/services/id-by.service.mjs.map +1 -1
  13. package/dist/services/reference.service.d.mts +1 -1
  14. package/dist/services/reference.service.mjs +62 -7
  15. package/dist/services/reference.service.mjs.map +1 -1
  16. package/dist/testing/area.spec.mjs +142 -1
  17. package/dist/testing/area.spec.mjs.map +1 -1
  18. package/dist/testing/call-proxy.spec.d.mts +1 -0
  19. package/dist/testing/call-proxy.spec.mjs +204 -0
  20. package/dist/testing/call-proxy.spec.mjs.map +1 -0
  21. package/dist/testing/conversation.spec.mjs +1 -1
  22. package/dist/testing/conversation.spec.mjs.map +1 -1
  23. package/dist/testing/entity.spec.mjs +14 -0
  24. package/dist/testing/entity.spec.mjs.map +1 -1
  25. package/dist/testing/id-by.spec.mjs +38 -0
  26. package/dist/testing/id-by.spec.mjs.map +1 -1
  27. package/dist/testing/ref-by.spec.mjs +805 -4
  28. package/dist/testing/ref-by.spec.mjs.map +1 -1
  29. package/dist/testing/scheduler.spec.d.mts +1 -0
  30. package/dist/testing/scheduler.spec.mjs +412 -0
  31. package/dist/testing/scheduler.spec.mjs.map +1 -0
  32. package/dist/testing/websocket.spec.mjs +25 -0
  33. package/dist/testing/websocket.spec.mjs.map +1 -1
  34. package/dist/testing/workflow.spec.mjs +1 -1
  35. package/dist/testing/workflow.spec.mjs.map +1 -1
  36. package/package.json +17 -16
  37. package/src/helpers/entity-state.mts +20 -3
  38. package/src/helpers/fetch/service-list.mts +89 -5
  39. package/src/helpers/id-by.mts +1 -0
  40. package/src/helpers/utility.mts +1 -1
  41. package/src/mock_assistant/mock-assistant.module.mts +0 -1
  42. package/src/mock_assistant/services/websocket-api.service.mts +46 -4
  43. package/src/services/feature.service.mts +9 -6
  44. package/src/services/id-by.service.mts +4 -1
  45. package/src/services/reference.service.mts +78 -9
  46. package/src/testing/area.spec.mts +166 -2
  47. package/src/testing/call-proxy.spec.mts +241 -0
  48. package/src/testing/conversation.spec.mts +1 -1
  49. package/src/testing/entity.spec.mts +15 -0
  50. package/src/testing/id-by.spec.mts +50 -0
  51. package/src/testing/ref-by.spec.mts +965 -4
  52. package/src/testing/scheduler.spec.mts +444 -0
  53. package/src/testing/websocket.spec.mts +33 -0
  54. package/src/testing/workflow.spec.mts +1 -1
@@ -1,4 +1,4 @@
1
- import type { FIRST, RemoveCallback, TBlackHole } from "@digital-alchemy/core";
1
+ import type { FIRST, RemoveCallback, TBlackHole, TContext, TOffset } from "@digital-alchemy/core";
2
2
  import type { Dayjs } from "dayjs";
3
3
  import type { Except } from "type-fest";
4
4
  import type { ALL_DOMAINS, ANY_ENTITY, GetDomain, iCallService, PICK_ENTITY, TAreaId, TDeviceId, TLabelId, TPlatformId, TRawDomains } from "../user.mts";
@@ -26,6 +26,17 @@ export type EntityHistoryItem = {
26
26
  };
27
27
  export type TEntityUpdateCallback<ENTITY_ID extends ANY_ENTITY> = (new_state: NonNullable<ENTITY_STATE<ENTITY_ID>>, old_state: NonNullable<ENTITY_STATE<ENTITY_ID>>, remove: () => TBlackHole) => TBlackHole;
28
28
  export type RemovableCallback<ENTITY_ID extends ANY_ENTITY> = (callback: TEntityUpdateCallback<ENTITY_ID>) => RemoveCallback;
29
+ export type OnStateForOptions<ENTITY_ID extends ANY_ENTITY> = ((Pick<ENTITY_STATE<ENTITY_ID>, "state"> & {
30
+ matches?: never;
31
+ }) | ({
32
+ matches: (new_state: ENTITY_STATE<ENTITY_ID>, old_state: ENTITY_STATE<ENTITY_ID>) => boolean;
33
+ } & {
34
+ state?: never;
35
+ })) & {
36
+ for: TOffset;
37
+ context?: TContext;
38
+ exec: (state: ByIdProxy<ENTITY_ID>) => TBlackHole;
39
+ };
29
40
  export type ByIdProxy<ENTITY_ID extends ANY_ENTITY> = ENTITY_STATE<ENTITY_ID> & {
30
41
  entity_id: ENTITY_ID;
31
42
  /**
@@ -43,11 +54,17 @@ export type ByIdProxy<ENTITY_ID extends ANY_ENTITY> = ENTITY_STATE<ENTITY_ID> &
43
54
  /**
44
55
  * Will resolve with the next state of the next value. No time limit
45
56
  */
46
- nextState: (timeoutMs?: number) => Promise<ENTITY_STATE<ENTITY_ID>>;
57
+ nextState: (timeout?: TOffset) => Promise<ENTITY_STATE<ENTITY_ID>>;
58
+ /**
59
+ * Runs on state change -
60
+ * If state matches the indicated target, then a timer will be initiated
61
+ * As long as the condition holds true, the callback will be executed at end of the timer
62
+ */
63
+ onStateFor: (options: OnStateForOptions<ENTITY_ID>) => RemoveCallback;
47
64
  /**
48
65
  * Will resolve when state
49
66
  */
50
- waitForState: (state: string | number, timeoutMs?: number) => Promise<ENTITY_STATE<ENTITY_ID>>;
67
+ waitForState: (state: string | number, timeout?: TOffset) => Promise<ENTITY_STATE<ENTITY_ID>>;
51
68
  /**
52
69
  * Access the immediate previous entity state
53
70
  */
@@ -1,6 +1,8 @@
1
1
  import type { LiteralUnion } from "type-fest";
2
2
  import type { ALL_DOMAINS, PICK_ENTITY, TPlatformId } from "../../user.mts";
3
+ import type { SupportedCountries } from "../countries.mts";
3
4
  import type { ColorMode } from "../features.mts";
5
+ import type { SupportedLanguages } from "../languages.mts";
4
6
  export type EntityFilterSelector = {
5
7
  integration?: TPlatformId;
6
8
  domain?: ALL_DOMAINS | ALL_DOMAINS[];
@@ -27,16 +29,23 @@ export type LegacyDeviceSelector = {
27
29
  export interface ServiceListSelector {
28
30
  action: null;
29
31
  addon: {
32
+ /** The name of the addon */
30
33
  name?: string;
34
+ /** The slug identifier of the addon */
31
35
  slug?: string;
32
36
  };
33
37
  area: {
38
+ /** Device filter selector(s) to filter areas by device */
34
39
  device?: DeviceFilterSelector | DeviceFilterSelector[];
40
+ /** Entity filter selector(s) to filter areas by entity */
35
41
  entity?: EntityFilterSelector | EntityFilterSelector[];
42
+ /** Whether multiple areas can be selected */
36
43
  multiple?: boolean;
37
44
  };
38
45
  attribute: {
46
+ /** The entity ID to get attributes from */
39
47
  entity_id?: PICK_ENTITY;
48
+ /** List of attribute names to hide from the selector */
40
49
  hide_attributes?: string[];
41
50
  };
42
51
  assist_pipeline: null;
@@ -44,130 +53,202 @@ export interface ServiceListSelector {
44
53
  boolean: null;
45
54
  color_rgb: null;
46
55
  color_temp: {
56
+ /** The unit of measurement for color temperature */
47
57
  unit?: "kelvin" | "mired";
58
+ /** Minimum color temperature value */
48
59
  min?: number;
60
+ /** Maximum color temperature value */
49
61
  max?: number;
62
+ /** Maximum color temperature in mireds */
50
63
  max_mireds?: number;
64
+ /** Minimum color temperature in mireds */
51
65
  min_mireds?: number;
52
66
  };
53
67
  condition: null;
54
68
  config_entry: {
69
+ /** The integration platform ID */
55
70
  integration: TPlatformId;
56
71
  };
57
72
  constant: {
73
+ /** Display label for the constant value */
58
74
  label?: string;
75
+ /** The constant value */
59
76
  value: string | number | boolean;
77
+ /** Translation key for the label */
60
78
  translation_key?: string;
61
79
  };
62
80
  conversation_agent: {
81
+ /** Language code for the conversation agent */
63
82
  language?: string;
64
83
  };
65
84
  country: {
66
- countries?: string | string[];
85
+ /** Country code(s) to include in the selector */
86
+ countries?: SupportedCountries | SupportedCountries[];
87
+ /** Whether to disable sorting of countries */
67
88
  no_sort?: boolean;
68
89
  };
69
90
  date: null;
70
91
  datetime: null;
71
92
  device: LegacyDeviceSelector & {
93
+ /** Whether multiple devices can be selected */
72
94
  multiple?: boolean;
95
+ /** Device filter selector(s) to filter devices */
73
96
  filter?: DeviceFilterSelector | DeviceFilterSelector[];
97
+ /** Entity filter selector(s) to filter devices by their entities */
74
98
  entity?: EntityFilterSelector | EntityFilterSelector[];
75
99
  };
76
100
  duration: {
101
+ /** Whether to enable day selection in duration input */
77
102
  enable_day?: boolean;
103
+ /** Whether to enable millisecond precision in duration input */
78
104
  enable_millisecond?: boolean;
105
+ /** Whether to allow negative duration values */
79
106
  allow_negative?: boolean;
80
107
  };
81
108
  entity: LegacyEntitySelector & {
82
- exclude_entities?: PICK_ENTITY | PICK_ENTITY[];
83
- include_entities?: PICK_ENTITY | PICK_ENTITY[];
109
+ /** Whether multiple entities can be selected */
84
110
  multiple?: boolean;
111
+ /** Whether entities can be reordered */
85
112
  reorder?: boolean;
113
+ /** Entity filter selector(s) to filter entities */
86
114
  filter?: EntityFilterSelector | EntityFilterSelector[];
87
- };
115
+ } & ({
116
+ /** Entity ID(s) to exclude from the selector */
117
+ exclude_entities?: PICK_ENTITY | PICK_ENTITY[];
118
+ include_entities: never;
119
+ } | {
120
+ /** Entity ID(s) to include in the selector */
121
+ include_entities?: PICK_ENTITY | PICK_ENTITY[];
122
+ exclude_entities: never;
123
+ });
88
124
  file: {
125
+ /** MIME type(s) or file extension(s) to accept */
89
126
  accept: string;
90
127
  };
91
128
  floor: {
129
+ /** Entity filter selector(s) to filter floors by entity */
92
130
  entity?: EntityFilterSelector | EntityFilterSelector[];
131
+ /** Device filter selector(s) to filter floors by device */
93
132
  device?: DeviceFilterSelector | DeviceFilterSelector[];
133
+ /** Whether multiple floors can be selected */
94
134
  multiple?: boolean;
95
135
  };
96
136
  icon: {
137
+ /** Placeholder text for the icon selector */
97
138
  placeholder?: string;
98
139
  };
99
140
  label: {
141
+ /** Whether multiple labels can be selected */
100
142
  multiple?: boolean;
101
143
  };
102
144
  language: {
103
- languages?: string | string[];
145
+ /** Language code(s) to include in the selector */
146
+ languages?: SupportedLanguages | SupportedLanguages[];
147
+ /** Whether to display native language names */
104
148
  native_name?: boolean;
149
+ /** Whether to disable sorting of languages */
105
150
  no_sort?: boolean;
106
151
  };
107
152
  location: {
153
+ /** Whether to include radius selection */
108
154
  radius?: boolean;
155
+ /** Icon to display for the location selector */
109
156
  icon?: string;
110
157
  };
111
158
  media: {
159
+ /** MIME type(s) or file extension(s) to accept */
112
160
  accept?: string | string[];
113
161
  };
114
162
  number: {
163
+ /** Minimum value allowed */
115
164
  min?: number;
165
+ /** Maximum value allowed */
116
166
  max?: number;
167
+ /** Input mode: "box" for text input or "slider" for slider control */
117
168
  mode?: "box" | "slider";
169
+ /** Translation key for the number field */
118
170
  translation_key?: string;
171
+ /** Step value for increment/decrement, or "any" for no step */
119
172
  step?: number | "any";
173
+ /** Unit of measurement to display */
120
174
  unit_of_measurement?: string;
121
175
  };
122
176
  object: {
177
+ /** Field definitions for the object structure */
123
178
  fields?: Record<string, {
124
179
  selector: ServiceListSelector;
125
180
  required?: boolean;
126
181
  label?: string;
127
182
  }>;
183
+ /** Whether multiple objects can be selected */
128
184
  multiple?: boolean;
185
+ /** Field name to use as the label for each object */
129
186
  label_field?: string;
187
+ /** Field name to use as the description for each object */
130
188
  description_field?: string;
189
+ /** Translation key for the object selector */
131
190
  translation_key?: string;
132
191
  };
133
192
  qr_code: {
193
+ /** Data to encode in the QR code */
134
194
  data: string;
195
+ /** Scale factor for the QR code size */
135
196
  scale?: number;
197
+ /** Error correction level: L (low), M (medium), Q (quartile), H (high) */
136
198
  error_correction_level?: "L" | "M" | "Q" | "H";
137
199
  };
138
200
  select: {
201
+ /** Available options for selection */
139
202
  options: (string | {
140
203
  label: string;
141
204
  value: string;
142
205
  })[];
206
+ /** Whether multiple options can be selected */
143
207
  multiple?: boolean;
208
+ /** Whether custom values can be entered */
144
209
  custom_value?: boolean;
210
+ /** Display mode: "dropdown" or "list" */
145
211
  mode?: "dropdown" | "list";
212
+ /** Translation key for the select field */
146
213
  translation_key?: string;
214
+ /** Whether to sort the options */
147
215
  sort?: boolean;
148
216
  };
149
217
  state: {
218
+ /** Entity ID to get states from */
150
219
  entity_id?: PICK_ENTITY;
220
+ /** Whether multiple states can be selected */
151
221
  multiple?: boolean;
222
+ /** List of state values to hide from the selector */
152
223
  hide_states?: string[];
153
224
  };
154
225
  statistic: {
226
+ /** Whether multiple statistics can be selected */
155
227
  multiple?: boolean;
156
228
  };
157
229
  target: {
230
+ /** Entity filter selector(s) to filter targets by entity */
158
231
  entity?: EntityFilterSelector | EntityFilterSelector[];
232
+ /** Device filter selector(s) to filter targets by device */
159
233
  device?: DeviceFilterSelector | DeviceFilterSelector[];
160
234
  };
161
235
  template: null;
162
236
  text: {
237
+ /** HTML input type for the text field */
163
238
  type?: "color" | "date" | "datetime-local" | "email" | "month" | "number" | "password" | "search" | "tel" | "text" | "time" | "url" | "week";
239
+ /** Autocomplete attribute value */
164
240
  autocomplete?: string;
241
+ /** Whether the text input should be multiline */
165
242
  multiline?: boolean;
243
+ /** Prefix text to display before the input */
166
244
  prefix?: string;
245
+ /** Suffix text to display after the input */
167
246
  suffix?: string;
247
+ /** Whether multiple text values can be entered */
168
248
  multiple?: boolean;
169
249
  };
170
250
  theme: {
251
+ /** Whether to include default themes in the selector */
171
252
  include_defaults?: boolean;
172
253
  };
173
254
  time: null;
@@ -6,5 +6,5 @@ export type IDByInterface = {
6
6
  floor: <FLOOR extends TFloorId, DOMAIN extends ALL_DOMAINS>(floor: FLOOR, ...domains: DOMAIN[]) => PICK_FROM_FLOOR<FLOOR, DOMAIN>[];
7
7
  label: <LABEL extends TLabelId, DOMAIN extends ALL_DOMAINS>(label: LABEL, ...domains: DOMAIN[]) => PICK_FROM_LABEL<LABEL, DOMAIN>[];
8
8
  platform: <PLATFORM extends TPlatformId, DOMAIN extends ALL_DOMAINS>(platform: PLATFORM, ...domains: DOMAIN[]) => PICK_FROM_PLATFORM<PLATFORM, DOMAIN>[];
9
- unique_id: <UNIQUE_ID extends TUniqueId, ENTITY_ID extends Extract<HassUniqueIdMapping[UNIQUE_ID], ANY_ENTITY> = Extract<HassUniqueIdMapping[UNIQUE_ID], TRawEntityIds>>(unique_id: UNIQUE_ID) => ENTITY_ID;
9
+ unique_id: <UNIQUE_ID extends TUniqueId, ENTITY_ID extends Extract<HassUniqueIdMapping[UNIQUE_ID], ANY_ENTITY> = Extract<HassUniqueIdMapping[UNIQUE_ID], TRawEntityIds>>(unique_id: UNIQUE_ID, platform?: TPlatformId) => ENTITY_ID;
10
10
  };
@@ -1,5 +1,5 @@
1
1
  import type { TBlackHole } from "@digital-alchemy/core";
2
- import type { Dayjs } from "dayjs";
2
+ import { type Dayjs } from "dayjs";
3
3
  import type { Get } from "type-fest";
4
4
  import type { ALL_DOMAINS, ANY_ENTITY, HassEntitySetupMapping, iCallService, PICK_ENTITY, TRawEntityIds } from "../user.mts";
5
5
  import type { HassEntityContext } from "./entity-state.mts";
@@ -1 +1 @@
1
- {"version":3,"file":"mock-assistant.module.mjs","sourceRoot":"","sources":["../../src/mock_assistant/mock-assistant.module.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,2BAA2B,EAC3B,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;IAC9C,aAAa,EAAE;QACb,UAAU,EAAE;YACV,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,wDAAwD;YACrE,IAAI,EAAE,QAAQ;SACf;QACD,aAAa,EAAE;YACb,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC;YACrC,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,QAAQ;SACf;QACD,SAAS,EAAE;YACT,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,+BAA+B;YAC5C,IAAI,EAAE,SAAS;SAChB;KACF;IACD,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,IAAI,EAAE,gBAAgB;IACtB,YAAY,EAAE;QACZ,QAAQ;QACR,OAAO;QACP,QAAQ;QACR,MAAM;QACN,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,iBAAiB;QACjB,UAAU;QACV,UAAU;KACX;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,mBAAmB;QAC3B,MAAM,EAAE,mBAAmB;QAC3B,eAAe,EAAE,2BAA2B;QAC5C,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,YAAY;QACtB,KAAK,EAAE,kBAAkB;QACzB,KAAK,EAAE,kBAAkB;QACzB,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,gBAAgB;QACxB,IAAI,EAAE,iBAAiB;KACxB;CACF,CAAC,CAAC;AAQH;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,YAAY;KACT,WAAW,CAAC,QAAQ,CAAC;KACrB,MAAM,EAAE;KACR,MAAM,EAAE;KACR,SAAS,CAAC;IACT,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;CAC/B,CAAC;KACD,UAAU,CAAC;IACV,aAAa,EAAE;QACb,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,KAAK;QACV,IAAI,EAAE,KAAK;KACZ;CACF,CAAC;KACD,aAAa,CAAC,kBAAkB,CAAC,CAAC;AAEvC,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"mock-assistant.module.mjs","sourceRoot":"","sources":["../../src/mock_assistant/mock-assistant.module.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,2BAA2B,EAC3B,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;IAC9C,aAAa,EAAE;QACb,UAAU,EAAE;YACV,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,wDAAwD;YACrE,IAAI,EAAE,QAAQ;SACf;QACD,aAAa,EAAE;YACb,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC;YACrC,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,QAAQ;SACf;QACD,SAAS,EAAE;YACT,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,+BAA+B;YAC5C,IAAI,EAAE,SAAS;SAChB;KACF;IACD,OAAO,EAAE,CAAC,QAAQ,CAAC;IACnB,IAAI,EAAE,gBAAgB;IACtB,YAAY,EAAE;QACZ,QAAQ;QACR,OAAO;QACP,QAAQ;QACR,MAAM;QACN,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,iBAAiB;QACjB,UAAU;QACV,UAAU;KACX;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,mBAAmB;QAC3B,MAAM,EAAE,mBAAmB;QAC3B,eAAe,EAAE,2BAA2B;QAC5C,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,YAAY;QACtB,KAAK,EAAE,kBAAkB;QACzB,KAAK,EAAE,kBAAkB;QACzB,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,gBAAgB;QACxB,IAAI,EAAE,iBAAiB;KACxB;CACF,CAAC,CAAC;AAQH;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,YAAY;KACT,WAAW,CAAC,QAAQ,CAAC;KACrB,MAAM,EAAE;KACR,MAAM,EAAE;KACR,SAAS,CAAC;IACT,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;CAC/B,CAAC;KACD,UAAU,CAAC;IACV,aAAa,EAAE;QACb,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,KAAK;QACV,IAAI,EAAE,KAAK;KACZ;CACF,CAAC;KACD,aAAa,CAAC,kBAAkB,CAAC,CAAC;AAEvC,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,EAAE,CAAC"}
@@ -3,8 +3,10 @@ import type { PartialDeep } from "type-fest";
3
3
  import type WS from "ws";
4
4
  import type { SocketMessageDTO } from "../../helpers/index.mts";
5
5
  export declare const INTERNAL_MESSAGE = "INTERNAL_MESSAGE";
6
- export declare function MockWebsocketAPI({ hass, config, lifecycle }: TServiceParams): {
6
+ export declare function MockWebsocketAPI({ hass, config, lifecycle, event }: TServiceParams): {
7
+ attachScheduledFunctions: () => void;
7
8
  connection: WS;
9
+ init: () => Promise<void>;
8
10
  onMessage<DATA extends object>(type: string, callback: (data: DATA & MessageData) => TBlackHole): void;
9
11
  sendMessage: (data: PartialDeep<SocketMessageDTO>) => void;
10
12
  };
@@ -1,11 +1,12 @@
1
1
  import { START } from "@digital-alchemy/core";
2
2
  import EventEmitter from "events";
3
+ import { SOCKET_CONNECTED } from "../../services/websocket-api.service.mjs";
3
4
  const CONNECTION_CLOSED = 0;
4
5
  // const CONNECTION_OPEN = 1;
5
6
  // const CONNECTION_FAILED = 2;
6
7
  const UNLIMITED = 0;
7
8
  export const INTERNAL_MESSAGE = "INTERNAL_MESSAGE";
8
- export function MockWebsocketAPI({ hass, config, lifecycle }) {
9
+ export function MockWebsocketAPI({ hass, config, lifecycle, event }) {
9
10
  const connection = new EventEmitter();
10
11
  connection.setMaxListeners(UNLIMITED);
11
12
  lifecycle.onShutdownStart(() => {
@@ -18,7 +19,8 @@ export function MockWebsocketAPI({ hass, config, lifecycle }) {
18
19
  };
19
20
  // connection.send = (...data) =>
20
21
  hass.socket.createConnection = () => {
21
- setImmediate(() => {
22
+ // Use Promise.resolve().then() instead of setImmediate for better compatibility with fake timers
23
+ Promise.resolve().then(() => {
22
24
  if (!config.mock_assistant.PASS_AUTH) {
23
25
  return;
24
26
  }
@@ -26,6 +28,37 @@ export function MockWebsocketAPI({ hass, config, lifecycle }) {
26
28
  });
27
29
  return connection;
28
30
  };
31
+ // Mock init - resolves immediately for tests
32
+ // The real service's init() waits for onSocketReady, but in tests we don't need that
33
+ async function init() {
34
+ if (hass.socket.connection) {
35
+ return;
36
+ }
37
+ hass.socket.connection = hass.socket.createConnection("");
38
+ hass.socket.setConnectionState("connecting");
39
+ // Set up message handler - the real service's handlers registered in onPreInit
40
+ // will process messages via registerMessageHandler
41
+ connection.on("message", async (message) => {
42
+ try {
43
+ JSON.parse(message.toString());
44
+ // Real service's handlers will process this via onMessage/registerMessageHandler
45
+ }
46
+ catch {
47
+ // Ignore parse errors
48
+ }
49
+ });
50
+ // In tests, we can resolve immediately without waiting for real socket handshake
51
+ // The real service's onBootstrap calls this, and it needs to complete for lifecycle to progress
52
+ hass.socket.setConnectionState("connected");
53
+ // Emit auth_ok to trigger the real service's handlers (registered in onPreInit)
54
+ // This allows the real service's auth_ok handler to run and do its setup
55
+ if (config.mock_assistant.PASS_AUTH) {
56
+ // Use microtask to ensure handlers are registered first
57
+ await Promise.resolve();
58
+ sendMessage({ type: "auth_ok" });
59
+ event.emit(SOCKET_CONNECTED);
60
+ }
61
+ }
29
62
  connection.send = (data) => {
30
63
  const payload = JSON.parse(data);
31
64
  connection.emit(INTERNAL_MESSAGE, payload);
@@ -38,7 +71,7 @@ export function MockWebsocketAPI({ hass, config, lifecycle }) {
38
71
  return;
39
72
  }
40
73
  default: {
41
- setImmediate(() => {
74
+ Promise.resolve().then(() => {
42
75
  sendMessage({
43
76
  id: payload.id,
44
77
  result: null,
@@ -49,12 +82,18 @@ export function MockWebsocketAPI({ hass, config, lifecycle }) {
49
82
  }
50
83
  };
51
84
  function sendMessage(data) {
52
- setImmediate(() => {
85
+ // Use Promise.resolve() instead of setImmediate for better fake timer compatibility
86
+ Promise.resolve().then(() => {
53
87
  connection.emit("message", JSON.stringify(data));
54
88
  });
55
89
  }
56
90
  return {
91
+ attachScheduledFunctions: () => {
92
+ // Mock implementation - no-op for tests
93
+ // The real websocket service sets up intervals here, but we don't need them in tests
94
+ },
57
95
  connection: connection,
96
+ init,
58
97
  onMessage(type, callback) {
59
98
  connection.on(INTERNAL_MESSAGE, (data) => {
60
99
  if (data.type === type) {
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-api.service.mjs","sourceRoot":"","sources":["../../../src/mock_assistant/services/websocket-api.service.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,YAAY,MAAM,QAAQ,CAAC;AAMlC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,6BAA6B;AAC7B,+BAA+B;AAC/B,MAAM,SAAS,GAAG,CAAC,CAAC;AAEpB,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAEnD,MAAM,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAkB;IAC1E,MAAM,UAAU,GAAG,IAAI,YAAY,EAAsB,CAAC;IAC1D,UAAU,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IACtC,SAAS,CAAC,eAAe,CAAC,GAAG,EAAE;QAC7B,UAAU,CAAC,kBAAkB,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,UAAU,GAAG,iBAAiB,CAAC;IAC1C,IAAI,EAAE,GAAG,KAAK,CAAC;IACf,UAAU,CAAC,KAAK,GAAG,GAAG,EAAE;QACtB,UAAU,CAAC,UAAU,GAAG,iBAAiB,CAAC;IAC5C,CAAC,CAAC;IACF,iCAAiC;IAEjC,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,GAAG,EAAE;QAClC,YAAY,CAAC,GAAG,EAAE;YAChB,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;gBACrC,OAAO;YACT,CAAC;YACD,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IAEF,UAAU,CAAC,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiC,CAAC;QACjE,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QAC3C,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACxC,OAAO;YACT,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,OAAO,CAAC,CAAC,CAAC;gBACR,YAAY,CAAC,GAAG,EAAE;oBAChB,WAAW,CAAC;wBACV,EAAE,EAAE,OAAO,CAAC,EAAE;wBACd,MAAM,EAAE,IAAI;wBACZ,IAAI,EAAE,QAAQ;qBACf,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,SAAS,WAAW,CAAC,IAAmC;QACtD,YAAY,CAAC,GAAG,EAAE;YAChB,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,UAAU,EAAE,UAAgB;QAC5B,SAAS,CACP,IAAY,EACZ,QAAkD;YAElD,UAAU,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,IAAwB,EAAE,EAAE;gBAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;oBACvB,QAAQ,CAAC,IAA0B,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,WAAW;KACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"websocket-api.service.mjs","sourceRoot":"","sources":["../../../src/mock_assistant/services/websocket-api.service.mts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ import type { SupportedEntityFeatures, UsedSupportedFeatureDomains } from "../in
4
4
  import type { PICK_ENTITY } from "../user.mts";
5
5
  export declare function HassFeatureService({ hass, logger, internal: { utils: { is }, }, }: TServiceParams): {
6
6
  createSupportedFeatures: <T extends UsedSupportedFeatureDomains>(features: (number | SupportedEntityFeatures<T>)[]) => number;
7
- getSupportedFeatures: (input: number | PICK_ENTITY | ByIdProxy<PICK_ENTITY>) => number[];
7
+ getSupportedFeatures: <T extends UsedSupportedFeatureDomains>(input: number | PICK_ENTITY | ByIdProxy<PICK_ENTITY<T>>) => number[];
8
8
  hasFeature: <T extends UsedSupportedFeatureDomains>(input: number | PICK_ENTITY<T> | ByIdProxy<PICK_ENTITY<T>>, feature: number | SupportedEntityFeatures<T>) => boolean;
9
- listEntityFeatures: <DOMAIN extends UsedSupportedFeatureDomains = UsedSupportedFeatureDomains>(input: PICK_ENTITY<DOMAIN> | ByIdProxy<PICK_ENTITY<DOMAIN>>) => SupportedEntityFeatures<DOMAIN>[];
9
+ listEntityFeatures: <DOMAIN extends UsedSupportedFeatureDomains, ENTITY extends PICK_ENTITY<DOMAIN> = PICK_ENTITY<DOMAIN>>(input: ENTITY | ByIdProxy<ENTITY>) => SupportedEntityFeatures<DOMAIN>[];
10
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"feature.service.mjs","sourceRoot":"","sources":["../../src/services/feature.service.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature.service.mjs","sourceRoot":"","sources":["../../src/services/feature.service.mts"],"names":[],"mappings":"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"}
@@ -27,9 +27,12 @@ export function IDByExtension({ hass, logger, config, internal: { utils: { is },
27
27
  * The logic here will look up ALL entities with the "unique"_id, then check to see if there are multiple results
28
28
  * It is assumed by both this code and type-writer that the unique_id lookup will refer to the not update entity
29
29
  */
30
- function unique_id(unique_id) {
30
+ function unique_id(unique_id, platform) {
31
31
  hass.entity.warnEarly("byUniqueId");
32
32
  let list = hass.entity.registry.current.filter(i => i.unique_id === unique_id);
33
+ if (!is.empty(platform)) {
34
+ list = list.filter(i => i.platform === platform);
35
+ }
33
36
  if (is.empty(list)) {
34
37
  logger.error({ name: unique_id, unique_id }, `could not find an entity`);
35
38
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"id-by.service.mjs","sourceRoot":"","sources":["../../src/services/id-by.service.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"id-by.service.mjs","sourceRoot":"","sources":["../../src/services/id-by.service.mts"],"names":[],"mappings":"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"}
@@ -50,4 +50,4 @@ import type { HassReferenceService } from "../helpers/index.mts";
50
50
  * The reference may call the remove all active event listeners and timers at any time.
51
51
  * It will interrupt any timers (nextState/waitForState), as well as detach any event listeners
52
52
  */
53
- export declare function ReferenceService({ hass, logger, internal, event, }: TServiceParams): HassReferenceService;
53
+ export declare function ReferenceService({ hass, logger, internal, scheduler, event, }: TServiceParams): HassReferenceService;
@@ -53,10 +53,13 @@ import { SOCKET_CONNECTED } from "./websocket-api.service.mjs";
53
53
  * The reference may call the remove all active event listeners and timers at any time.
54
54
  * It will interrupt any timers (nextState/waitForState), as well as detach any event listeners
55
55
  */
56
- export function ReferenceService({ hass, logger, internal, event, }) {
56
+ export function ReferenceService({ hass, logger, internal, scheduler, event, }) {
57
57
  const { is } = internal.utils;
58
58
  // #MARK:proxyGetLogic
59
59
  function proxyGetLogic(entity, property) {
60
+ if (!is.string(property)) {
61
+ return undefined;
62
+ }
60
63
  const valid = ["state", "attributes", "last"].some(i => property.startsWith(i));
61
64
  if (!valid) {
62
65
  logger.error({ entity, name: proxyGetLogic, property }, `invalid property lookup`);
@@ -91,9 +94,12 @@ export function ReferenceService({ hass, logger, internal, event, }) {
91
94
  "attributes",
92
95
  "entity_id",
93
96
  "history",
94
- "last",
97
+ "last_changed",
98
+ "last_reported",
99
+ "last_updated",
95
100
  "nextState",
96
101
  "once",
102
+ "onStateFor",
97
103
  "onUpdate",
98
104
  "previous",
99
105
  "removeAllListeners",
@@ -127,8 +133,50 @@ export function ReferenceService({ hass, logger, internal, event, }) {
127
133
  // things that shouldn't be needed: this extract
128
134
  // eslint-disable-next-line sonarjs/function-return-type
129
135
  get: (_, property) => {
136
+ // Handle Symbol properties (e.g., when vitest formats test output)
137
+ if (!is.string(property)) {
138
+ return undefined;
139
+ }
130
140
  hass.diagnostics.reference?.get_property.publish({ entity_id, property });
131
141
  switch (property) {
142
+ // #MARK: runAfter
143
+ case "onStateFor": {
144
+ return function ({ context, ...options }) {
145
+ let timerRemove;
146
+ const remove = proxy.onUpdate((new_state, old_state) => {
147
+ const matches = options.matches
148
+ ? options.matches(new_state, old_state)
149
+ : options.state === new_state.state;
150
+ if (!matches) {
151
+ if (timerRemove) {
152
+ timerRemove();
153
+ timerRemove = undefined;
154
+ logger.trace({ context, entity_id }, "cleared timer - state no longer matches");
155
+ }
156
+ return;
157
+ }
158
+ if (timerRemove) {
159
+ logger.trace({ context, entity_id }, "timer already running, skipping");
160
+ return;
161
+ }
162
+ timerRemove = scheduler.setTimeout(async () => {
163
+ logger.trace({ context, entity_id, for: options.for }, "timer fired - executing callback");
164
+ internal.safeExec({
165
+ context,
166
+ exec: async () => await options.exec(proxy),
167
+ });
168
+ }, options.for);
169
+ logger.trace({ context, entity_id, for: options.for }, "started timer for state condition");
170
+ });
171
+ return internal.removeFn(() => {
172
+ if (timerRemove) {
173
+ timerRemove();
174
+ }
175
+ remove();
176
+ logger.trace({ context, entity_id }, "removed [onStateFor] listener");
177
+ });
178
+ };
179
+ }
132
180
  // #MARK: onUpdate
133
181
  case "onUpdate": {
134
182
  return (callback) => {
@@ -215,9 +263,13 @@ export function ReferenceService({ hass, logger, internal, event, }) {
215
263
  event.once(entity_id, complete);
216
264
  // - race!
217
265
  let wait;
218
- if (is.number(timeout) && timeout > NONE) {
266
+ if (is.undefined(timeout)) {
267
+ return;
268
+ }
269
+ const duration = internal.utils.getIntervalMs(timeout);
270
+ if (duration > NONE) {
219
271
  // keep track of sleep so it can be cleaned up also
220
- wait = sleep(timeout);
272
+ wait = sleep(duration);
221
273
  await wait;
222
274
  wait = undefined;
223
275
  if (done) {
@@ -232,7 +284,6 @@ export function ReferenceService({ hass, logger, internal, event, }) {
232
284
  case "waitForState": {
233
285
  return async (state, timeout) => await new Promise(async (done) => {
234
286
  const remove = () => {
235
- done = undefined;
236
287
  listeners.delete(remove);
237
288
  done = undefined;
238
289
  logger.trace({ entity_id }, "remove [waitForState] listener");
@@ -259,8 +310,12 @@ export function ReferenceService({ hass, logger, internal, event, }) {
259
310
  };
260
311
  event.on(entity_id, complete);
261
312
  let wait;
262
- if (is.number(timeout) && timeout > NONE) {
263
- wait = sleep(timeout);
313
+ if (is.undefined(timeout)) {
314
+ return;
315
+ }
316
+ const duration = internal.utils.getIntervalMs(timeout);
317
+ if (duration > NONE) {
318
+ wait = sleep(duration);
264
319
  await wait;
265
320
  wait = undefined;
266
321
  if (done) {