@digital-alchemy/hass 24.11.4 → 25.2.1
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/dynamic.d.mts +45 -44
- package/dist/dynamic.mjs +0 -1
- package/dist/dynamic.mjs.map +1 -1
- package/dist/helpers/utility.d.mts +1 -2
- package/dist/helpers/utility.mjs +1 -2
- package/dist/helpers/utility.mjs.map +1 -1
- package/dist/merge.d.mts +4 -0
- package/dist/merge.mjs +2 -0
- package/dist/merge.mjs.map +1 -0
- package/dist/mock_assistant/services/entity.service.mjs +2 -1
- package/dist/mock_assistant/services/entity.service.mjs.map +1 -1
- package/dist/mock_assistant/services/fixtures.service.mjs +2 -1
- package/dist/mock_assistant/services/fixtures.service.mjs.map +1 -1
- package/dist/services/backup.service.d.mts +1 -1
- package/dist/services/backup.service.mjs +2 -2
- package/dist/services/backup.service.mjs.map +1 -1
- package/dist/services/call-proxy.service.mjs +1 -1
- package/dist/services/call-proxy.service.mjs.map +1 -1
- package/dist/services/config.service.mjs +2 -1
- package/dist/services/config.service.mjs.map +1 -1
- package/dist/services/entity.service.mjs +2 -1
- package/dist/services/entity.service.mjs.map +1 -1
- package/dist/services/events.service.d.mts +1 -1
- package/dist/services/events.service.mjs +7 -8
- package/dist/services/events.service.mjs.map +1 -1
- package/dist/services/fetch-api.service.d.mts +1 -1
- package/dist/services/fetch-api.service.mjs +2 -2
- package/dist/services/fetch-api.service.mjs.map +1 -1
- package/dist/services/id-by.service.d.mts +1 -1
- package/dist/services/id-by.service.mjs +7 -8
- package/dist/services/id-by.service.mjs.map +1 -1
- package/dist/services/internal.service.d.mts +1 -1
- package/dist/services/internal.service.mjs +5 -3
- package/dist/services/internal.service.mjs.map +1 -1
- package/dist/services/reference.service.mjs +2 -1
- package/dist/services/reference.service.mjs.map +1 -1
- package/dist/services/websocket-api.service.mjs +15 -8
- package/dist/services/websocket-api.service.mjs.map +1 -1
- package/dist/testing/fetch-api.spec.mjs +1 -1
- package/dist/testing/fetch-api.spec.mjs.map +1 -1
- package/package.json +27 -27
- package/src/dynamic.mts +192 -149
- package/src/helpers/utility.mts +1 -2
- package/src/merge.mts +9 -0
- package/src/mock_assistant/services/entity.service.mts +2 -1
- package/src/mock_assistant/services/fixtures.service.mts +2 -1
- package/src/services/backup.service.mts +9 -2
- package/src/services/call-proxy.service.mts +2 -1
- package/src/services/config.service.mts +2 -9
- package/src/services/entity.service.mts +1 -1
- package/src/services/events.service.mts +8 -8
- package/src/services/fetch-api.service.mts +11 -2
- package/src/services/id-by.service.mts +14 -8
- package/src/services/internal.service.mts +6 -2
- package/src/services/reference.service.mts +2 -1
- package/src/services/websocket-api.service.mts +24 -9
- package/src/testing/fetch-api.spec.mts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TServiceParams } from "@digital-alchemy/core";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
AREA_REGISTRY_UPDATED,
|
|
@@ -11,31 +11,31 @@ import {
|
|
|
11
11
|
ZONE_REGISTRY_UPDATED,
|
|
12
12
|
} from "../helpers/index.mts";
|
|
13
13
|
|
|
14
|
-
export function EventsService({ event }: TServiceParams): HassEventsService {
|
|
14
|
+
export function EventsService({ event, internal }: TServiceParams): HassEventsService {
|
|
15
15
|
return {
|
|
16
16
|
onAreaRegistryUpdate: (callback: SimpleCallback) => {
|
|
17
17
|
event.on(AREA_REGISTRY_UPDATED, callback);
|
|
18
|
-
return
|
|
18
|
+
return internal.removeFn(() => event.removeListener(AREA_REGISTRY_UPDATED, callback));
|
|
19
19
|
},
|
|
20
20
|
onDeviceRegistryUpdate: (callback: SimpleCallback) => {
|
|
21
21
|
event.on(DEVICE_REGISTRY_UPDATED, callback);
|
|
22
|
-
return
|
|
22
|
+
return internal.removeFn(() => event.removeListener(DEVICE_REGISTRY_UPDATED, callback));
|
|
23
23
|
},
|
|
24
24
|
onEntityRegistryUpdate: (callback: SimpleCallback) => {
|
|
25
25
|
event.on(ENTITY_REGISTRY_UPDATED, callback);
|
|
26
|
-
return
|
|
26
|
+
return internal.removeFn(() => event.removeListener(ENTITY_REGISTRY_UPDATED, callback));
|
|
27
27
|
},
|
|
28
28
|
onFloorRegistryUpdate: (callback: SimpleCallback) => {
|
|
29
29
|
event.on(FLOOR_REGISTRY_UPDATED, callback);
|
|
30
|
-
return
|
|
30
|
+
return internal.removeFn(() => event.removeListener(FLOOR_REGISTRY_UPDATED, callback));
|
|
31
31
|
},
|
|
32
32
|
onLabelRegistryUpdate: (callback: SimpleCallback) => {
|
|
33
33
|
event.on(LABEL_REGISTRY_UPDATED, callback);
|
|
34
|
-
return
|
|
34
|
+
return internal.removeFn(() => event.removeListener(LABEL_REGISTRY_UPDATED, callback));
|
|
35
35
|
},
|
|
36
36
|
onZoneRegistryUpdate: (callback: SimpleCallback) => {
|
|
37
37
|
event.on(ZONE_REGISTRY_UPDATED, callback);
|
|
38
|
-
return
|
|
38
|
+
return internal.removeFn(() => event.removeListener(ZONE_REGISTRY_UPDATED, callback));
|
|
39
39
|
},
|
|
40
40
|
};
|
|
41
41
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DOWN,
|
|
1
|
+
import { DOWN, NO_CHANGE, SECOND, TServiceParams, UP } from "@digital-alchemy/core";
|
|
2
2
|
import dayjs, { Dayjs } from "dayjs";
|
|
3
3
|
import { lt } from "semver";
|
|
4
4
|
|
|
@@ -25,7 +25,16 @@ type SendBody<STATE extends string | number = string, ATTRIBUTES extends object
|
|
|
25
25
|
state?: STATE;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export function FetchAPI({
|
|
28
|
+
export function FetchAPI({
|
|
29
|
+
logger,
|
|
30
|
+
lifecycle,
|
|
31
|
+
context,
|
|
32
|
+
hass,
|
|
33
|
+
config,
|
|
34
|
+
internal: {
|
|
35
|
+
utils: { is },
|
|
36
|
+
},
|
|
37
|
+
}: TServiceParams) {
|
|
29
38
|
const fetcher = hass.internals({ context });
|
|
30
39
|
const { download: downloader } = fetcher;
|
|
31
40
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TServiceParams } from "@digital-alchemy/core";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
TAreaId,
|
|
@@ -22,14 +22,20 @@ import {
|
|
|
22
22
|
PICK_FROM_PLATFORM,
|
|
23
23
|
} from "../helpers/index.mts";
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
25
|
+
export function IDByExtension({
|
|
26
|
+
hass,
|
|
27
|
+
logger,
|
|
28
|
+
internal: {
|
|
29
|
+
utils: { is },
|
|
30
|
+
},
|
|
31
|
+
}: TServiceParams): IDByInterface {
|
|
32
|
+
const check = <RAW extends ANY_ENTITY>(raw: RAW[], domains: ALL_DOMAINS[]) => {
|
|
33
|
+
if (!is.empty(domains)) {
|
|
34
|
+
raw = raw.filter(entity => is.domain(entity, domains));
|
|
35
|
+
}
|
|
36
|
+
return raw;
|
|
37
|
+
};
|
|
31
38
|
|
|
32
|
-
export function IDByExtension({ hass, logger }: TServiceParams): IDByInterface {
|
|
33
39
|
// * byDomain
|
|
34
40
|
function byDomain<DOMAIN extends ALL_DOMAINS>(domain: DOMAIN) {
|
|
35
41
|
const MASTER_STATE = hass.entity._masterState();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FIRST, InternalError,
|
|
1
|
+
import { FIRST, InternalError, TServiceParams } from "@digital-alchemy/core";
|
|
2
2
|
import { createWriteStream } from "fs";
|
|
3
3
|
import { pipeline } from "stream";
|
|
4
4
|
import { promisify } from "util";
|
|
@@ -10,13 +10,17 @@ import {
|
|
|
10
10
|
FetcherOptions,
|
|
11
11
|
FetchProcessTypes,
|
|
12
12
|
FetchWith,
|
|
13
|
+
isDomain,
|
|
13
14
|
MaybeHttpError,
|
|
14
15
|
TFetchBody,
|
|
15
16
|
} from "../helpers/index.mts";
|
|
16
17
|
|
|
17
18
|
const streamPipeline = promisify(pipeline);
|
|
18
19
|
|
|
19
|
-
export function FetchInternals({ logger, context: parentContext }: TServiceParams) {
|
|
20
|
+
export function FetchInternals({ internal, logger, context: parentContext }: TServiceParams) {
|
|
21
|
+
const { is } = internal.utils;
|
|
22
|
+
is.domain = isDomain;
|
|
23
|
+
|
|
20
24
|
return ({ headers: base_headers, baseUrl: base_url, context: logContext }: FetcherOptions) => {
|
|
21
25
|
const capabilities: string[] = [];
|
|
22
26
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DOWN,
|
|
1
|
+
import { DOWN, NONE, sleep, TAnyFunction, TServiceParams, UP } from "@digital-alchemy/core";
|
|
2
2
|
import dayjs, { Dayjs } from "dayjs";
|
|
3
3
|
import { Get } from "type-fest";
|
|
4
4
|
|
|
@@ -86,6 +86,7 @@ export function ReferenceService({
|
|
|
86
86
|
internal,
|
|
87
87
|
event,
|
|
88
88
|
}: TServiceParams): HassReferenceService {
|
|
89
|
+
const { is } = internal.utils;
|
|
89
90
|
// #MARK:proxyGetLogic
|
|
90
91
|
function proxyGetLogic<ENTITY extends ANY_ENTITY = ANY_ENTITY, PROPERTY extends string = string>(
|
|
91
92
|
entity: ENTITY,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InternalError,
|
|
3
|
-
is,
|
|
4
3
|
SECOND,
|
|
5
4
|
sleep,
|
|
6
5
|
START,
|
|
@@ -27,6 +26,14 @@ const CONNECTION_FAILED = 2;
|
|
|
27
26
|
let messageCount = START;
|
|
28
27
|
export const SOCKET_CONNECTED = "SOCKET_CONNECTED";
|
|
29
28
|
|
|
29
|
+
type WaitingMap = Map<
|
|
30
|
+
number,
|
|
31
|
+
{
|
|
32
|
+
sent: unknown;
|
|
33
|
+
callback: (result: unknown) => TBlackHole;
|
|
34
|
+
}
|
|
35
|
+
>;
|
|
36
|
+
|
|
30
37
|
export function WebsocketAPI({
|
|
31
38
|
context,
|
|
32
39
|
event,
|
|
@@ -37,6 +44,8 @@ export function WebsocketAPI({
|
|
|
37
44
|
logger,
|
|
38
45
|
scheduler,
|
|
39
46
|
}: TServiceParams): HassWebsocketAPI {
|
|
47
|
+
const { is } = internal.utils;
|
|
48
|
+
|
|
40
49
|
/**
|
|
41
50
|
* Local attachment points for socket events
|
|
42
51
|
*/
|
|
@@ -45,7 +54,7 @@ export function WebsocketAPI({
|
|
|
45
54
|
|
|
46
55
|
let MESSAGE_TIMESTAMPS: number[] = [];
|
|
47
56
|
let onSocketReady: () => void;
|
|
48
|
-
const waitingCallback = new Map
|
|
57
|
+
const waitingCallback: WaitingMap = new Map();
|
|
49
58
|
const isOld = (date: Dayjs) =>
|
|
50
59
|
is.undefined(date) || date.diff(dayjs(), "s") >= config.hass.RETRY_INTERVAL;
|
|
51
60
|
|
|
@@ -248,7 +257,10 @@ export function WebsocketAPI({
|
|
|
248
257
|
return undefined;
|
|
249
258
|
}
|
|
250
259
|
return await new Promise<RESPONSE_VALUE>(async done => {
|
|
251
|
-
waitingCallback.set(id,
|
|
260
|
+
waitingCallback.set(id, {
|
|
261
|
+
callback: done as (result: unknown) => TBlackHole,
|
|
262
|
+
sent: data,
|
|
263
|
+
});
|
|
252
264
|
await hass.socket.waitForReply(id, data, sentAt);
|
|
253
265
|
});
|
|
254
266
|
}
|
|
@@ -258,6 +270,7 @@ export function WebsocketAPI({
|
|
|
258
270
|
if (!waitingCallback.has(id)) {
|
|
259
271
|
return;
|
|
260
272
|
}
|
|
273
|
+
const { sent } = waitingCallback.get(id);
|
|
261
274
|
// this could happen around dropped connections, or a number of other reasons
|
|
262
275
|
//
|
|
263
276
|
// discard the promise so whatever flow is depending on this can get garbage collected
|
|
@@ -266,6 +279,7 @@ export function WebsocketAPI({
|
|
|
266
279
|
{
|
|
267
280
|
message: data,
|
|
268
281
|
name: waitForReply,
|
|
282
|
+
sent,
|
|
269
283
|
sentAt: internal.utils.relativeDate(sentAt),
|
|
270
284
|
},
|
|
271
285
|
`sent message, did not receive reply`,
|
|
@@ -464,21 +478,22 @@ export function WebsocketAPI({
|
|
|
464
478
|
return;
|
|
465
479
|
}
|
|
466
480
|
if (waitingCallback.has(id)) {
|
|
467
|
-
const
|
|
481
|
+
const { callback } = waitingCallback.get(id);
|
|
468
482
|
waitingCallback.delete(id);
|
|
469
|
-
|
|
483
|
+
callback(message.event.result);
|
|
470
484
|
}
|
|
471
485
|
socketEvents.emit(message.event.event_type, message.event);
|
|
472
486
|
}
|
|
473
487
|
|
|
474
488
|
function onMessageResult(id: number, message: SocketMessageDTO) {
|
|
475
489
|
if (waitingCallback.has(id)) {
|
|
490
|
+
const { callback, sent } = waitingCallback.get(id);
|
|
491
|
+
waitingCallback.delete(id);
|
|
476
492
|
if (message.error) {
|
|
477
|
-
logger.error({ message, name: onMessageResult });
|
|
493
|
+
logger.error({ message, name: "onMessageResult", sent }, "message result error");
|
|
494
|
+
return;
|
|
478
495
|
}
|
|
479
|
-
|
|
480
|
-
waitingCallback.delete(id);
|
|
481
|
-
f(message.result);
|
|
496
|
+
callback(message.result);
|
|
482
497
|
}
|
|
483
498
|
}
|
|
484
499
|
|
|
@@ -9,7 +9,7 @@ describe("FetchAPI", () => {
|
|
|
9
9
|
const TOKEN =
|
|
10
10
|
// TODO: Replace hard coded token w/ faker when avail
|
|
11
11
|
// https://github.com/faker-js/faker/pull/2936
|
|
12
|
-
// eslint-disable-next-line @cspell/spellchecker
|
|
12
|
+
// eslint-disable-next-line @cspell/spellchecker, sonarjs/no-hardcoded-secrets
|
|
13
13
|
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2aWRlbyI6Imh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9ZFF3NHc5V2dYY1EifQ.gPIttZEaLZgov3VZziu3LovcgtDbj8H0-XfBg4f08Y0";
|
|
14
14
|
|
|
15
15
|
hassTestRunner.configure({
|