@iobroker/js-controller-adapter 7.2.3 → 8.0.0-alpha.1-20260921-e5941ca8a
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/build/cjs/index.d.ts +0 -1
- package/build/cjs/index.js +5 -8
- package/build/cjs/index.js.map +2 -2
- package/build/cjs/lib/_Types.d.ts +394 -63
- package/build/cjs/lib/adapter/adapter.d.ts +1818 -177
- package/build/cjs/lib/adapter/adapter.js +715 -1035
- package/build/cjs/lib/adapter/adapter.js.map +2 -2
- package/build/cjs/lib/adapter/asyncAdapter.d.ts +124 -0
- package/build/cjs/lib/adapter/asyncAdapter.js +184 -0
- package/build/cjs/lib/adapter/asyncAdapter.js.map +7 -0
- package/build/cjs/lib/adapter/context.d.ts +34 -0
- package/build/cjs/lib/adapter/context.js +17 -0
- package/build/cjs/lib/adapter/context.js.map +7 -0
- package/build/cjs/lib/adapter/defaultObjs.d.ts +5 -0
- package/build/cjs/lib/adapter/defaultObjs.js +2 -0
- package/build/cjs/lib/adapter/defaultObjs.js.map +2 -2
- package/build/cjs/lib/adapter/log.d.ts +25 -0
- package/build/cjs/lib/adapter/log.js +29 -0
- package/build/cjs/lib/adapter/log.js.map +2 -2
- package/build/cjs/lib/adapter/managers/AdapterContextBase.d.ts +49 -0
- package/build/cjs/lib/adapter/managers/AdapterContextBase.js +98 -0
- package/build/cjs/lib/adapter/managers/AdapterContextBase.js.map +7 -0
- package/build/cjs/lib/adapter/managers/AliasManager.d.ts +103 -0
- package/build/cjs/lib/adapter/managers/AliasManager.js +293 -0
- package/build/cjs/lib/adapter/managers/AliasManager.js.map +7 -0
- package/build/cjs/lib/adapter/managers/CertificateManager.d.ts +50 -0
- package/build/cjs/lib/adapter/managers/CertificateManager.js +174 -0
- package/build/cjs/lib/adapter/managers/CertificateManager.js.map +7 -0
- package/build/cjs/lib/adapter/managers/MessagingManager.d.ts +58 -0
- package/build/cjs/lib/adapter/managers/MessagingManager.js +289 -0
- package/build/cjs/lib/adapter/managers/MessagingManager.js.map +7 -0
- package/build/cjs/lib/adapter/managers/SubscriptionManager.d.ts +107 -0
- package/build/cjs/lib/adapter/managers/SubscriptionManager.js +349 -0
- package/build/cjs/lib/adapter/managers/SubscriptionManager.js.map +7 -0
- package/build/cjs/lib/adapter/userInterfaceMessagingController.d.ts +10 -0
- package/build/cjs/lib/adapter/userInterfaceMessagingController.js +9 -2
- package/build/cjs/lib/adapter/userInterfaceMessagingController.js.map +2 -2
- package/build/cjs/lib/adapter/utils.js +15 -1
- package/build/cjs/lib/adapter/utils.js.map +2 -2
- package/build/cjs/lib/adapter/validator.d.ts +10 -5
- package/build/cjs/lib/adapter/validator.js +6 -5
- package/build/cjs/lib/adapter/validator.js.map +2 -2
- package/build/esm/index.d.ts +0 -1
- package/build/esm/index.d.ts.map +1 -1
- package/build/esm/index.js +0 -1
- package/build/esm/index.js.map +1 -1
- package/build/esm/lib/_Types.d.ts +394 -63
- package/build/esm/lib/_Types.d.ts.map +1 -1
- package/build/esm/lib/adapter/adapter.d.ts +1818 -177
- package/build/esm/lib/adapter/adapter.d.ts.map +1 -1
- package/build/esm/lib/adapter/adapter.js +827 -1215
- package/build/esm/lib/adapter/adapter.js.map +1 -1
- package/build/esm/lib/adapter/asyncAdapter.d.ts +124 -0
- package/build/esm/lib/adapter/asyncAdapter.d.ts.map +1 -0
- package/build/esm/lib/adapter/asyncAdapter.js +157 -0
- package/build/esm/lib/adapter/asyncAdapter.js.map +1 -0
- package/build/esm/lib/adapter/context.d.ts +34 -0
- package/build/esm/lib/adapter/context.d.ts.map +1 -0
- package/build/esm/lib/adapter/context.js +2 -0
- package/build/esm/lib/adapter/context.js.map +1 -0
- package/build/esm/lib/adapter/defaultObjs.d.ts +5 -0
- package/build/esm/lib/adapter/defaultObjs.d.ts.map +1 -1
- package/build/esm/lib/adapter/defaultObjs.js +5 -0
- package/build/esm/lib/adapter/defaultObjs.js.map +1 -1
- package/build/esm/lib/adapter/log.d.ts +25 -0
- package/build/esm/lib/adapter/log.d.ts.map +1 -1
- package/build/esm/lib/adapter/log.js +25 -0
- package/build/esm/lib/adapter/log.js.map +1 -1
- package/build/esm/lib/adapter/managers/AdapterContextBase.d.ts +49 -0
- package/build/esm/lib/adapter/managers/AdapterContextBase.d.ts.map +1 -0
- package/build/esm/lib/adapter/managers/AdapterContextBase.js +77 -0
- package/build/esm/lib/adapter/managers/AdapterContextBase.js.map +1 -0
- package/build/esm/lib/adapter/managers/AliasManager.d.ts +103 -0
- package/build/esm/lib/adapter/managers/AliasManager.d.ts.map +1 -0
- package/build/esm/lib/adapter/managers/AliasManager.js +269 -0
- package/build/esm/lib/adapter/managers/AliasManager.js.map +1 -0
- package/build/esm/lib/adapter/managers/CertificateManager.d.ts +50 -0
- package/build/esm/lib/adapter/managers/CertificateManager.d.ts.map +1 -0
- package/build/esm/lib/adapter/managers/CertificateManager.js +142 -0
- package/build/esm/lib/adapter/managers/CertificateManager.js.map +1 -0
- package/build/esm/lib/adapter/managers/MessagingManager.d.ts +58 -0
- package/build/esm/lib/adapter/managers/MessagingManager.d.ts.map +1 -0
- package/build/esm/lib/adapter/managers/MessagingManager.js +267 -0
- package/build/esm/lib/adapter/managers/MessagingManager.js.map +1 -0
- package/build/esm/lib/adapter/managers/SubscriptionManager.d.ts +107 -0
- package/build/esm/lib/adapter/managers/SubscriptionManager.d.ts.map +1 -0
- package/build/esm/lib/adapter/managers/SubscriptionManager.js +374 -0
- package/build/esm/lib/adapter/managers/SubscriptionManager.js.map +1 -0
- package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts +10 -0
- package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts.map +1 -1
- package/build/esm/lib/adapter/userInterfaceMessagingController.js +8 -2
- package/build/esm/lib/adapter/userInterfaceMessagingController.js.map +1 -1
- package/build/esm/lib/adapter/utils.d.ts.map +1 -1
- package/build/esm/lib/adapter/utils.js +1 -1
- package/build/esm/lib/adapter/utils.js.map +1 -1
- package/build/esm/lib/adapter/validator.d.ts +10 -5
- package/build/esm/lib/adapter/validator.d.ts.map +1 -1
- package/build/esm/lib/adapter/validator.js +8 -5
- package/build/esm/lib/adapter/validator.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +25 -20
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Pattern } from '../../_Types.js';
|
|
2
|
+
import type { AdapterContext } from '../../../lib/adapter/context.js';
|
|
3
|
+
import { AdapterContextBase } from '../../../lib/adapter/managers/AdapterContextBase.js';
|
|
4
|
+
import type { AliasManager } from '../../../lib/adapter/managers/AliasManager.js';
|
|
5
|
+
/** Prefixes an id or pattern with this adapter's namespace unless already namespaced. Bound to the adapter's Validator. */
|
|
6
|
+
export type FixId = (id: string, isPattern?: boolean) => string;
|
|
7
|
+
type SubOptions = {
|
|
8
|
+
user?: ioBroker.ObjectIDs.User;
|
|
9
|
+
} | null | undefined;
|
|
10
|
+
/** Reads the objects matching a pattern, used to discover alias objects during state subscription. */
|
|
11
|
+
export interface ObjectAccess {
|
|
12
|
+
/**
|
|
13
|
+
* Objects matching `pattern`, keyed by id. Bound to the legacy `getForeignObjects(pattern, null, null, options)`
|
|
14
|
+
* call, whose `null` type/enums args clobber `options` — so no type filter and no user-ACL are applied;
|
|
15
|
+
* only `alias.*` ids in the result are consumed. Kept as-is for behavior parity.
|
|
16
|
+
*/
|
|
17
|
+
getForeignStateObjects(pattern: string, options?: {
|
|
18
|
+
user?: ioBroker.ObjectIDs.User;
|
|
19
|
+
} | null): Promise<Record<string, ioBroker.AnyObject>>;
|
|
20
|
+
}
|
|
21
|
+
/** Owns object-, file- and state-change subscriptions plus the auto-subscribe bookkeeping. */
|
|
22
|
+
export declare class SubscriptionManager extends AdapterContextBase {
|
|
23
|
+
#private;
|
|
24
|
+
/**
|
|
25
|
+
* @param ctx Shared adapter context providing live runtime state
|
|
26
|
+
* @param fixId Namespace-prefixer bound to the adapter's Validator
|
|
27
|
+
* @param aliasManager Alias subscription cache and bookkeeping
|
|
28
|
+
* @param objectAccess Reader for state-typed objects matching a pattern
|
|
29
|
+
*/
|
|
30
|
+
constructor(ctx: AdapterContext, fixId: FixId, aliasManager: AliasManager, objectAccess: ObjectAccess);
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe to object changes within this instance's namespace.
|
|
33
|
+
*
|
|
34
|
+
* @param pattern pattern without namespace, `*` for all own objects, or an array of patterns
|
|
35
|
+
* passed through as-is (not namespaced)
|
|
36
|
+
* @param options optional user context
|
|
37
|
+
*/
|
|
38
|
+
subscribeObjects(pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Unsubscribe from object changes within this instance's namespace.
|
|
41
|
+
*
|
|
42
|
+
* @param pattern pattern without namespace, `*` for all own objects, or an array of patterns
|
|
43
|
+
* passed through as-is (not namespaced)
|
|
44
|
+
* @param options optional user context
|
|
45
|
+
*/
|
|
46
|
+
unsubscribeObjects(pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Subscribe to object changes in any instance.
|
|
49
|
+
*
|
|
50
|
+
* @param pattern pattern or array of patterns
|
|
51
|
+
* @param options optional user context
|
|
52
|
+
*/
|
|
53
|
+
subscribeForeignObjects(pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Unsubscribe from object changes in any instance.
|
|
56
|
+
*
|
|
57
|
+
* @param pattern pattern or array of patterns (defaults to `*`)
|
|
58
|
+
* @param options optional user context
|
|
59
|
+
*/
|
|
60
|
+
unsubscribeForeignObjects(pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Subscribe to file changes in a specific instance.
|
|
63
|
+
*
|
|
64
|
+
* @param id adapter id, e.g. `vis-2.0`
|
|
65
|
+
* @param pattern pattern or array of patterns
|
|
66
|
+
* @param options optional user context
|
|
67
|
+
*/
|
|
68
|
+
subscribeForeignFiles(id: string, pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Unsubscribe from file changes in a specific instance.
|
|
71
|
+
*
|
|
72
|
+
* @param id adapter id, e.g. `vis-2.0`
|
|
73
|
+
* @param pattern pattern or array of patterns (defaults to `*`)
|
|
74
|
+
* @param options optional user context
|
|
75
|
+
*/
|
|
76
|
+
unsubscribeForeignFiles(id: string, pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Register an instance as auto-subscribable (its `subscribes` counter is maintained on subscribe/unsubscribe).
|
|
79
|
+
*
|
|
80
|
+
* @param id instance id, e.g. `pushover.0`
|
|
81
|
+
*/
|
|
82
|
+
addSubscribableInstance(id: string): void;
|
|
83
|
+
/**
|
|
84
|
+
* Stop treating an instance as auto-subscribable.
|
|
85
|
+
*
|
|
86
|
+
* @param id instance id, e.g. `pushover.0`
|
|
87
|
+
*/
|
|
88
|
+
removeSubscribableInstance(id: string): void;
|
|
89
|
+
/** Populate the auto-subscribe instance list from the objects DB. */
|
|
90
|
+
autoSubscribeOn(): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Subscribe to state changes in any instance, resolving aliases and maintaining auto-subscribe counters.
|
|
93
|
+
*
|
|
94
|
+
* @param pattern pattern, `*`, an `alias.*` id, or an array of ids/patterns
|
|
95
|
+
* @param options optional user context
|
|
96
|
+
*/
|
|
97
|
+
subscribeForeignStates(pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Unsubscribe from state changes in any instance, mirroring {@link subscribeForeignStates}.
|
|
100
|
+
*
|
|
101
|
+
* @param pattern pattern, `*`, an `alias.*` id, or an array of ids/patterns
|
|
102
|
+
* @param options optional user context
|
|
103
|
+
*/
|
|
104
|
+
unsubscribeForeignStates(pattern: Pattern, options?: SubOptions): Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
export {};
|
|
107
|
+
//# sourceMappingURL=SubscriptionManager.d.ts.map
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var SubscriptionManager_exports = {};
|
|
21
|
+
__export(SubscriptionManager_exports, {
|
|
22
|
+
SubscriptionManager: () => SubscriptionManager
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(SubscriptionManager_exports);
|
|
25
|
+
var import_js_controller_common = require("@iobroker/js-controller-common");
|
|
26
|
+
var import_AdapterContextBase = require("../../../lib/adapter/managers/AdapterContextBase.js");
|
|
27
|
+
var import_constants = require("../../../lib/adapter/constants.js");
|
|
28
|
+
class SubscriptionManager extends import_AdapterContextBase.AdapterContextBase {
|
|
29
|
+
static {
|
|
30
|
+
__name(this, "SubscriptionManager");
|
|
31
|
+
}
|
|
32
|
+
#fixId;
|
|
33
|
+
#alias;
|
|
34
|
+
#objectAccess;
|
|
35
|
+
#autoSubscribe = [];
|
|
36
|
+
/**
|
|
37
|
+
* @param ctx Shared adapter context providing live runtime state
|
|
38
|
+
* @param fixId Namespace-prefixer bound to the adapter's Validator
|
|
39
|
+
* @param aliasManager Alias subscription cache and bookkeeping
|
|
40
|
+
* @param objectAccess Reader for state-typed objects matching a pattern
|
|
41
|
+
*/
|
|
42
|
+
constructor(ctx, fixId, aliasManager, objectAccess) {
|
|
43
|
+
super(ctx);
|
|
44
|
+
this.#fixId = fixId;
|
|
45
|
+
this.#alias = aliasManager;
|
|
46
|
+
this.#objectAccess = objectAccess;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to object changes within this instance's namespace.
|
|
50
|
+
*
|
|
51
|
+
* @param pattern pattern without namespace, `*` for all own objects, or an array of patterns
|
|
52
|
+
* passed through as-is (not namespaced)
|
|
53
|
+
* @param options optional user context
|
|
54
|
+
*/
|
|
55
|
+
async subscribeObjects(pattern, options) {
|
|
56
|
+
const fixed = pattern === "*" ? `${this.namespace}.*` : Array.isArray(pattern) ? pattern : this.#fixId(pattern, true);
|
|
57
|
+
return this.objects.subscribeUserAsync(fixed, options ?? null);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Unsubscribe from object changes within this instance's namespace.
|
|
61
|
+
*
|
|
62
|
+
* @param pattern pattern without namespace, `*` for all own objects, or an array of patterns
|
|
63
|
+
* passed through as-is (not namespaced)
|
|
64
|
+
* @param options optional user context
|
|
65
|
+
*/
|
|
66
|
+
async unsubscribeObjects(pattern, options) {
|
|
67
|
+
const fixed = pattern === "*" ? `${this.namespace}.*` : Array.isArray(pattern) ? pattern : this.#fixId(pattern, true);
|
|
68
|
+
return this.objects.unsubscribeUserAsync(fixed, options ?? null);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Subscribe to object changes in any instance.
|
|
72
|
+
*
|
|
73
|
+
* @param pattern pattern or array of patterns
|
|
74
|
+
* @param options optional user context
|
|
75
|
+
*/
|
|
76
|
+
async subscribeForeignObjects(pattern, options) {
|
|
77
|
+
return this.objects.subscribeUserAsync(pattern, options ?? null);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Unsubscribe from object changes in any instance.
|
|
81
|
+
*
|
|
82
|
+
* @param pattern pattern or array of patterns (defaults to `*`)
|
|
83
|
+
* @param options optional user context
|
|
84
|
+
*/
|
|
85
|
+
async unsubscribeForeignObjects(pattern, options) {
|
|
86
|
+
return this.objects.unsubscribeUserAsync(pattern || "*", options ?? null);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Subscribe to file changes in a specific instance.
|
|
90
|
+
*
|
|
91
|
+
* @param id adapter id, e.g. `vis-2.0`
|
|
92
|
+
* @param pattern pattern or array of patterns
|
|
93
|
+
* @param options optional user context
|
|
94
|
+
*/
|
|
95
|
+
async subscribeForeignFiles(id, pattern, options) {
|
|
96
|
+
return this.objects.subscribeUserFile(id, pattern, options ?? void 0);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Unsubscribe from file changes in a specific instance.
|
|
100
|
+
*
|
|
101
|
+
* @param id adapter id, e.g. `vis-2.0`
|
|
102
|
+
* @param pattern pattern or array of patterns (defaults to `*`)
|
|
103
|
+
* @param options optional user context
|
|
104
|
+
*/
|
|
105
|
+
async unsubscribeForeignFiles(id, pattern, options) {
|
|
106
|
+
return this.objects.unsubscribeUserFile(id, pattern || "*", options ?? void 0);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Register an instance as auto-subscribable (its `subscribes` counter is maintained on subscribe/unsubscribe).
|
|
110
|
+
*
|
|
111
|
+
* @param id instance id, e.g. `pushover.0`
|
|
112
|
+
*/
|
|
113
|
+
addSubscribableInstance(id) {
|
|
114
|
+
if (!this.#autoSubscribe.includes(id)) {
|
|
115
|
+
this.#autoSubscribe.push(id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Stop treating an instance as auto-subscribable.
|
|
120
|
+
*
|
|
121
|
+
* @param id instance id, e.g. `pushover.0`
|
|
122
|
+
*/
|
|
123
|
+
removeSubscribableInstance(id) {
|
|
124
|
+
const pos = this.#autoSubscribe.indexOf(id);
|
|
125
|
+
if (pos !== -1) {
|
|
126
|
+
this.#autoSubscribe.splice(pos, 1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Populate the auto-subscribe instance list from the objects DB. */
|
|
130
|
+
async autoSubscribeOn() {
|
|
131
|
+
if (!this.#autoSubscribe && this.objects) {
|
|
132
|
+
try {
|
|
133
|
+
const res = await this.objects.getObjectViewAsync("system", "instance", {
|
|
134
|
+
startkey: "system.adapter.",
|
|
135
|
+
endkey: "system.adapter.\u9999"
|
|
136
|
+
});
|
|
137
|
+
this.#autoSubscribe = [];
|
|
138
|
+
for (const row of res.rows) {
|
|
139
|
+
if (row.value?.common.subscribable) {
|
|
140
|
+
const _id = row.id.substring(15);
|
|
141
|
+
if (!this.#autoSubscribe.includes(_id)) {
|
|
142
|
+
this.#autoSubscribe.push(_id);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
await this.objects.subscribeAsync("system.adapter.*");
|
|
147
|
+
} catch {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Subscribe to state changes in any instance, resolving aliases and maintaining auto-subscribe counters.
|
|
153
|
+
*
|
|
154
|
+
* @param pattern pattern, `*`, an `alias.*` id, or an array of ids/patterns
|
|
155
|
+
* @param options optional user context
|
|
156
|
+
*/
|
|
157
|
+
async subscribeForeignStates(pattern, options) {
|
|
158
|
+
await this.autoSubscribeOn();
|
|
159
|
+
void this.states;
|
|
160
|
+
void this.objects;
|
|
161
|
+
for (const autoSubEntry of this.#autoSubscribe) {
|
|
162
|
+
if (typeof pattern === "string" && (pattern === "*" || pattern.startsWith(`${autoSubEntry}.`))) {
|
|
163
|
+
let state;
|
|
164
|
+
try {
|
|
165
|
+
state = await this.states.getState(`system.adapter.${autoSubEntry}.subscribes`);
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
state = state || { val: "{}" };
|
|
169
|
+
state.val = state.val || "{}";
|
|
170
|
+
let subs;
|
|
171
|
+
try {
|
|
172
|
+
subs = JSON.parse(state.val);
|
|
173
|
+
} catch {
|
|
174
|
+
this.logger.error(`${this.namespaceLog} Cannot parse subscribes for "${autoSubEntry}.subscribes"`);
|
|
175
|
+
}
|
|
176
|
+
subs = import_js_controller_common.tools.isObject(subs) ? Object.assign(/* @__PURE__ */ Object.create(null), subs) : /* @__PURE__ */ Object.create(null);
|
|
177
|
+
if (!import_js_controller_common.tools.isObject(subs[pattern])) {
|
|
178
|
+
subs[pattern] = {};
|
|
179
|
+
}
|
|
180
|
+
if (typeof subs[pattern][this.namespace] !== "number") {
|
|
181
|
+
subs[pattern][this.namespace] = 0;
|
|
182
|
+
}
|
|
183
|
+
subs[pattern][this.namespace]++;
|
|
184
|
+
this.countOutput();
|
|
185
|
+
await this.states.setState(`system.adapter.${autoSubEntry}.subscribes`, JSON.stringify(subs));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (Array.isArray(pattern)) {
|
|
189
|
+
const aliasesIds = pattern.map((id) => id.startsWith(import_constants.ALIAS_STARTS_WITH) ? id : null).filter((id) => id);
|
|
190
|
+
const nonAliasesIds = pattern.map((id) => !id.startsWith(import_constants.ALIAS_STARTS_WITH) ? id : null).filter((id) => id);
|
|
191
|
+
for (const aliasPattern of pattern) {
|
|
192
|
+
if ((aliasPattern.startsWith(import_constants.ALIAS_STARTS_WITH) || aliasPattern.includes("*")) && !this.#alias.hasPattern(aliasPattern)) {
|
|
193
|
+
this.#alias.addPattern(aliasPattern);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const promises = new Array();
|
|
197
|
+
if (aliasesIds.length) {
|
|
198
|
+
this.#alias.ensureAliasObjectSubscription();
|
|
199
|
+
let aliasObjs;
|
|
200
|
+
try {
|
|
201
|
+
aliasObjs = await this.objects.getObjects(aliasesIds, options);
|
|
202
|
+
} catch (e) {
|
|
203
|
+
this.logger.error(`Could not get objects by array: ${e.message}`);
|
|
204
|
+
aliasObjs = [];
|
|
205
|
+
}
|
|
206
|
+
for (const aliasObj of aliasObjs) {
|
|
207
|
+
if (aliasObj) {
|
|
208
|
+
promises.push(this.#alias.addAliasSubscribe(aliasObj, aliasObj._id));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (nonAliasesIds.length) {
|
|
213
|
+
for (const id of nonAliasesIds) {
|
|
214
|
+
promises.push(new Promise((resolve) => this.states.subscribeUser(id, () => resolve())));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
try {
|
|
218
|
+
await Promise.all(promises);
|
|
219
|
+
} catch (e) {
|
|
220
|
+
this.logger.error(`${this.namespaceLog} Error on "subscribeForeignStates": ${e.message}`);
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
} else if (pattern.includes("*")) {
|
|
224
|
+
if (pattern === "*" || pattern.startsWith(import_constants.ALIAS_STARTS_WITH)) {
|
|
225
|
+
this.#alias.ensureAliasObjectSubscription();
|
|
226
|
+
try {
|
|
227
|
+
const objs = await this.#objectAccess.getForeignStateObjects(pattern, options);
|
|
228
|
+
const promises = new Array();
|
|
229
|
+
if (!this.#alias.hasPattern(pattern)) {
|
|
230
|
+
this.#alias.addPattern(pattern);
|
|
231
|
+
}
|
|
232
|
+
for (const id of Object.keys(objs)) {
|
|
233
|
+
if (id.startsWith(import_constants.ALIAS_STARTS_WITH)) {
|
|
234
|
+
const aliasObj = objs[id];
|
|
235
|
+
promises.push(this.#alias.addAliasSubscribe(aliasObj, pattern));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
await Promise.all(promises);
|
|
240
|
+
} catch (e) {
|
|
241
|
+
this.logger.error(`${this.namespaceLog} Error on "subscribeForeignStates": ${e.message}`);
|
|
242
|
+
}
|
|
243
|
+
const states = this.states;
|
|
244
|
+
if (promises.length && pattern !== "*") {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
return states.subscribeUser(pattern);
|
|
248
|
+
} catch (e) {
|
|
249
|
+
this.logger.warn(`${this.namespaceLog} Cannot subscribe to ${pattern}: ${e.message}`);
|
|
250
|
+
throw e;
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
return this.states.subscribeUser(pattern);
|
|
254
|
+
}
|
|
255
|
+
} else if (pattern.startsWith(import_constants.ALIAS_STARTS_WITH)) {
|
|
256
|
+
this.#alias.ensureAliasObjectSubscription();
|
|
257
|
+
try {
|
|
258
|
+
const aliasObj = await this.objects.getObject(pattern, options);
|
|
259
|
+
if (aliasObj) {
|
|
260
|
+
await this.#alias.addAliasSubscribe(aliasObj, pattern);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
return;
|
|
264
|
+
} catch (e) {
|
|
265
|
+
this.logger.warn(`${this.namespaceLog} cannot subscribe on alias "${pattern}": ${e.message}`);
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
return this.states.subscribeUser(pattern);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Unsubscribe from state changes in any instance, mirroring {@link subscribeForeignStates}.
|
|
273
|
+
*
|
|
274
|
+
* @param pattern pattern, `*`, an `alias.*` id, or an array of ids/patterns
|
|
275
|
+
* @param options optional user context
|
|
276
|
+
*/
|
|
277
|
+
async unsubscribeForeignStates(pattern, options) {
|
|
278
|
+
pattern = pattern || "*";
|
|
279
|
+
void this.states;
|
|
280
|
+
if (this.#autoSubscribe && typeof pattern === "string") {
|
|
281
|
+
for (const autoSub of this.#autoSubscribe) {
|
|
282
|
+
if (pattern === "*" || pattern.substring(0, autoSub.length + 1) === `${autoSub}.`) {
|
|
283
|
+
let state;
|
|
284
|
+
try {
|
|
285
|
+
state = await this.states.getState(`system.adapter.${autoSub}.subscribes`);
|
|
286
|
+
} catch {
|
|
287
|
+
}
|
|
288
|
+
if (!state || !state.val) {
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
let subs;
|
|
292
|
+
try {
|
|
293
|
+
subs = JSON.parse(state.val);
|
|
294
|
+
} catch {
|
|
295
|
+
this.logger.error(`${this.namespaceLog} Cannot parse subscribes for "${autoSub}.subscribes"`);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (!import_js_controller_common.tools.isObject(subs) || !import_js_controller_common.tools.isObject(subs[pattern]) || subs[pattern][this.namespace] === void 0) {
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
subs = Object.assign(/* @__PURE__ */ Object.create(null), subs);
|
|
302
|
+
if (typeof subs[pattern][this.namespace] === "number") {
|
|
303
|
+
subs[pattern][this.namespace]--;
|
|
304
|
+
if (subs[pattern][this.namespace] <= 0) {
|
|
305
|
+
delete subs[pattern][this.namespace];
|
|
306
|
+
}
|
|
307
|
+
} else {
|
|
308
|
+
delete subs[pattern][this.namespace];
|
|
309
|
+
}
|
|
310
|
+
if (!Object.keys(subs[pattern]).length) {
|
|
311
|
+
delete subs[pattern];
|
|
312
|
+
}
|
|
313
|
+
this.countOutput();
|
|
314
|
+
await this.states.setState(`system.adapter.${autoSub}.subscribes`, JSON.stringify(subs));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
let aliasPattern;
|
|
319
|
+
const promises = new Array();
|
|
320
|
+
if (Array.isArray(pattern)) {
|
|
321
|
+
for (const _pattern of pattern) {
|
|
322
|
+
promises.push(this.unsubscribeForeignStates(_pattern, options));
|
|
323
|
+
}
|
|
324
|
+
} else if (pattern.includes("*") || pattern.startsWith(import_constants.ALIAS_STARTS_WITH)) {
|
|
325
|
+
if (pattern === "*" || pattern.startsWith(import_constants.ALIAS_STARTS_WITH)) {
|
|
326
|
+
aliasPattern = pattern;
|
|
327
|
+
if (pattern === "*") {
|
|
328
|
+
promises.push(this.states.unsubscribeUser(pattern));
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
promises.push(this.states.unsubscribeUser(pattern));
|
|
332
|
+
}
|
|
333
|
+
} else {
|
|
334
|
+
promises.push(this.states.unsubscribeUser(pattern));
|
|
335
|
+
}
|
|
336
|
+
if (aliasPattern) {
|
|
337
|
+
this.#alias.deletePattern(aliasPattern);
|
|
338
|
+
promises.push(this.#alias.removeTargetsForPattern(aliasPattern));
|
|
339
|
+
}
|
|
340
|
+
await Promise.all(promises);
|
|
341
|
+
this.#alias.maybeDropAliasObjectSubscription();
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
346
|
+
0 && (module.exports = {
|
|
347
|
+
SubscriptionManager
|
|
348
|
+
});
|
|
349
|
+
//# sourceMappingURL=SubscriptionManager.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/lib/adapter/managers/SubscriptionManager.ts"],
|
|
4
|
+
"sourcesContent": ["import { tools } from '@iobroker/js-controller-common';\nimport type { Pattern } from '../../_Types.js';\nimport type { AdapterContext } from '@/lib/adapter/context.js';\nimport { AdapterContextBase } from '@/lib/adapter/managers/AdapterContextBase.js';\nimport type { AliasManager } from '@/lib/adapter/managers/AliasManager.js';\nimport { ALIAS_STARTS_WITH } from '@/lib/adapter/constants.js';\n\n/** Prefixes an id or pattern with this adapter's namespace unless already namespaced. Bound to the adapter's Validator. */\nexport type FixId = (id: string, isPattern?: boolean) => string;\n\ntype SubOptions = { user?: ioBroker.ObjectIDs.User } | null | undefined;\n\n/** Reads the objects matching a pattern, used to discover alias objects during state subscription. */\nexport interface ObjectAccess {\n /**\n * Objects matching `pattern`, keyed by id. Bound to the legacy `getForeignObjects(pattern, null, null, options)`\n * call, whose `null` type/enums args clobber `options` \u2014 so no type filter and no user-ACL are applied;\n * only `alias.*` ids in the result are consumed. Kept as-is for behavior parity.\n */\n getForeignStateObjects(\n pattern: string,\n options?: { user?: ioBroker.ObjectIDs.User } | null,\n ): Promise<Record<string, ioBroker.AnyObject>>;\n}\n\n/** Owns object-, file- and state-change subscriptions plus the auto-subscribe bookkeeping. */\nexport class SubscriptionManager extends AdapterContextBase {\n readonly #fixId: FixId;\n readonly #alias: AliasManager;\n readonly #objectAccess: ObjectAccess;\n #autoSubscribe: string[] = [];\n\n /**\n * @param ctx Shared adapter context providing live runtime state\n * @param fixId Namespace-prefixer bound to the adapter's Validator\n * @param aliasManager Alias subscription cache and bookkeeping\n * @param objectAccess Reader for state-typed objects matching a pattern\n */\n constructor(ctx: AdapterContext, fixId: FixId, aliasManager: AliasManager, objectAccess: ObjectAccess) {\n super(ctx);\n this.#fixId = fixId;\n this.#alias = aliasManager;\n this.#objectAccess = objectAccess;\n }\n\n /**\n * Subscribe to object changes within this instance's namespace.\n *\n * @param pattern pattern without namespace, `*` for all own objects, or an array of patterns\n * passed through as-is (not namespaced)\n * @param options optional user context\n */\n async subscribeObjects(pattern: Pattern, options?: SubOptions): Promise<void> {\n const fixed =\n pattern === '*' ? `${this.namespace}.*` : Array.isArray(pattern) ? pattern : this.#fixId(pattern, true);\n return this.objects.subscribeUserAsync(fixed, options ?? null);\n }\n\n /**\n * Unsubscribe from object changes within this instance's namespace.\n *\n * @param pattern pattern without namespace, `*` for all own objects, or an array of patterns\n * passed through as-is (not namespaced)\n * @param options optional user context\n */\n async unsubscribeObjects(pattern: Pattern, options?: SubOptions): Promise<void> {\n const fixed =\n pattern === '*' ? `${this.namespace}.*` : Array.isArray(pattern) ? pattern : this.#fixId(pattern, true);\n return this.objects.unsubscribeUserAsync(fixed, options ?? null);\n }\n\n /**\n * Subscribe to object changes in any instance.\n *\n * @param pattern pattern or array of patterns\n * @param options optional user context\n */\n async subscribeForeignObjects(pattern: Pattern, options?: SubOptions): Promise<void> {\n return this.objects.subscribeUserAsync(pattern, options ?? null);\n }\n\n /**\n * Unsubscribe from object changes in any instance.\n *\n * @param pattern pattern or array of patterns (defaults to `*`)\n * @param options optional user context\n */\n async unsubscribeForeignObjects(pattern: Pattern, options?: SubOptions): Promise<void> {\n return this.objects.unsubscribeUserAsync(pattern || '*', options ?? null);\n }\n\n /**\n * Subscribe to file changes in a specific instance.\n *\n * @param id adapter id, e.g. `vis-2.0`\n * @param pattern pattern or array of patterns\n * @param options optional user context\n */\n async subscribeForeignFiles(id: string, pattern: Pattern, options?: SubOptions): Promise<void> {\n return this.objects.subscribeUserFile(id, pattern, options ?? undefined);\n }\n\n /**\n * Unsubscribe from file changes in a specific instance.\n *\n * @param id adapter id, e.g. `vis-2.0`\n * @param pattern pattern or array of patterns (defaults to `*`)\n * @param options optional user context\n */\n async unsubscribeForeignFiles(id: string, pattern: Pattern, options?: SubOptions): Promise<void> {\n return this.objects.unsubscribeUserFile(id, pattern || '*', options ?? undefined);\n }\n\n /**\n * Register an instance as auto-subscribable (its `subscribes` counter is maintained on subscribe/unsubscribe).\n *\n * @param id instance id, e.g. `pushover.0`\n */\n addSubscribableInstance(id: string): void {\n if (!this.#autoSubscribe.includes(id)) {\n this.#autoSubscribe.push(id);\n }\n }\n\n /**\n * Stop treating an instance as auto-subscribable.\n *\n * @param id instance id, e.g. `pushover.0`\n */\n removeSubscribableInstance(id: string): void {\n const pos = this.#autoSubscribe.indexOf(id);\n if (pos !== -1) {\n this.#autoSubscribe.splice(pos, 1);\n }\n }\n\n /** Populate the auto-subscribe instance list from the objects DB. */\n async autoSubscribeOn(): Promise<void> {\n // Known-dead guard: #autoSubscribe is always truthy so the body never runs; the live fix is tracked separately \u2014 do not \"repair\" it here.\n if (!this.#autoSubscribe && this.objects) {\n try {\n // collect all\n const res = await this.objects.getObjectViewAsync('system', 'instance', {\n startkey: 'system.adapter.',\n endkey: 'system.adapter.\\u9999',\n });\n\n this.#autoSubscribe = [];\n for (const row of res.rows) {\n if (row.value?.common.subscribable) {\n const _id = row.id.substring(15); // cut system.adapter.\n if (!this.#autoSubscribe.includes(_id)) {\n this.#autoSubscribe.push(_id);\n }\n }\n }\n\n // because of autoSubscribe\n await this.objects.subscribeAsync('system.adapter.*');\n } catch {\n // ignore\n }\n }\n }\n\n /**\n * Subscribe to state changes in any instance, resolving aliases and maintaining auto-subscribe counters.\n *\n * @param pattern pattern, `*`, an `alias.*` id, or an array of ids/patterns\n * @param options optional user context\n */\n async subscribeForeignStates(pattern: Pattern, options?: SubOptions): Promise<void> {\n // Todo check rights for options\n await this.autoSubscribeOn();\n\n // Force the up-front connection check: a disconnected DB must reject (ERROR_DB_CLOSED) before any branch runs.\n void this.states;\n void this.objects;\n\n // compare if this pattern for one of auto-subscribe adapters\n for (const autoSubEntry of this.#autoSubscribe) {\n if (typeof pattern === 'string' && (pattern === '*' || pattern.startsWith(`${autoSubEntry}.`))) {\n // put this pattern into adapter list\n let state;\n try {\n state = await this.states.getState(`system.adapter.${autoSubEntry}.subscribes`);\n } catch {\n // ignore\n }\n state = state || { val: '{}' };\n state.val = state.val || '{}';\n let subs;\n try {\n subs = JSON.parse(state.val as any);\n } catch {\n this.logger.error(`${this.namespaceLog} Cannot parse subscribes for \"${autoSubEntry}.subscribes\"`);\n }\n\n // rebuild without a prototype so a \"__proto__\" key in the persisted value cannot\n // pollute Object.prototype via the subs[pattern] writes below\n subs = tools.isObject(subs) ? Object.assign(Object.create(null), subs) : Object.create(null);\n\n if (!tools.isObject(subs[pattern])) {\n subs[pattern] = {};\n }\n\n if (typeof subs[pattern][this.namespace] !== 'number') {\n subs[pattern][this.namespace] = 0;\n }\n\n subs[pattern][this.namespace]++;\n this.countOutput();\n await this.states.setState(`system.adapter.${autoSubEntry}.subscribes`, JSON.stringify(subs));\n }\n }\n\n if (Array.isArray(pattern)) {\n // get all aliases\n const aliasesIds = pattern\n .map(id => (id.startsWith(ALIAS_STARTS_WITH) ? id : null))\n .filter(id => id) as string[];\n\n // get all non aliases\n const nonAliasesIds = pattern\n .map(id => (!id.startsWith(ALIAS_STARTS_WITH) ? id : null))\n .filter(id => id) as string[];\n\n for (const aliasPattern of pattern) {\n if (\n (aliasPattern.startsWith(ALIAS_STARTS_WITH) || aliasPattern.includes('*')) &&\n !this.#alias.hasPattern(aliasPattern)\n ) {\n // it's a new alias conform pattern to store\n this.#alias.addPattern(aliasPattern);\n }\n }\n\n const promises = new Array<Promise<void>>();\n\n if (aliasesIds.length) {\n this.#alias.ensureAliasObjectSubscription();\n\n let aliasObjs: ioBroker.AnyObject[];\n try {\n aliasObjs = await this.objects.getObjects(aliasesIds, options);\n } catch (e: any) {\n this.logger.error(`Could not get objects by array: ${e.message}`);\n aliasObjs = [];\n }\n\n for (const aliasObj of aliasObjs) {\n if (aliasObj) {\n promises.push(this.#alias.addAliasSubscribe(aliasObj, aliasObj._id));\n }\n }\n }\n\n if (nonAliasesIds.length) {\n for (const id of nonAliasesIds) {\n promises.push(new Promise<void>(resolve => this.states.subscribeUser(id, () => resolve())));\n }\n }\n\n try {\n await Promise.all(promises);\n } catch (e: any) {\n this.logger.error(`${this.namespaceLog} Error on \"subscribeForeignStates\": ${e.message}`);\n }\n return;\n } else if (pattern.includes('*')) {\n if (pattern === '*' || pattern.startsWith(ALIAS_STARTS_WITH)) {\n this.#alias.ensureAliasObjectSubscription();\n\n // read all aliases\n try {\n const objs = await this.#objectAccess.getForeignStateObjects(pattern, options);\n const promises = new Array<Promise<void>>();\n if (!this.#alias.hasPattern(pattern)) {\n // it's a new pattern to store\n this.#alias.addPattern(pattern);\n }\n\n for (const id of Object.keys(objs)) {\n // If alias\n if (id.startsWith(ALIAS_STARTS_WITH)) {\n const aliasObj = objs[id];\n promises.push(this.#alias.addAliasSubscribe(aliasObj, pattern));\n }\n }\n\n try {\n await Promise.all(promises);\n } catch (e: any) {\n this.logger.error(`${this.namespaceLog} Error on \"subscribeForeignStates\": ${e.message}`);\n }\n\n // re-check: states may have disconnected during the awaits above\n const states = this.states;\n\n if (promises.length && pattern !== '*') {\n return;\n }\n // no alias objects found or pattern *\n return states.subscribeUser(pattern);\n } catch (e: any) {\n this.logger.warn(`${this.namespaceLog} Cannot subscribe to ${pattern}: ${e.message}`);\n throw e;\n }\n } else {\n return this.states.subscribeUser(pattern);\n }\n } else if (pattern.startsWith(ALIAS_STARTS_WITH)) {\n this.#alias.ensureAliasObjectSubscription();\n\n // just read one alias Object\n try {\n const aliasObj = await this.objects.getObject(pattern, options);\n if (aliasObj) {\n await this.#alias.addAliasSubscribe(aliasObj, pattern);\n return;\n }\n return;\n } catch (e: any) {\n this.logger.warn(`${this.namespaceLog} cannot subscribe on alias \"${pattern}\": ${e.message}`);\n }\n } else {\n return this.states.subscribeUser(pattern);\n }\n }\n\n /**\n * Unsubscribe from state changes in any instance, mirroring {@link subscribeForeignStates}.\n *\n * @param pattern pattern, `*`, an `alias.*` id, or an array of ids/patterns\n * @param options optional user context\n */\n async unsubscribeForeignStates(pattern: Pattern, options?: SubOptions): Promise<void> {\n // An empty pattern means \"all\" \u2014 matches the legacy public method, and applies per element\n // on the array-recursion path below.\n pattern = pattern || '*';\n\n // Force the up-front connection check (states getter throws ERROR_DB_CLOSED).\n void this.states;\n\n if (this.#autoSubscribe && typeof pattern === 'string') {\n for (const autoSub of this.#autoSubscribe) {\n if (pattern === '*' || pattern.substring(0, autoSub.length + 1) === `${autoSub}.`) {\n // remove this pattern from adapter list\n let state;\n try {\n state = await this.states.getState(`system.adapter.${autoSub}.subscribes`);\n } catch {\n // ignore\n }\n if (!state || !state.val) {\n continue;\n }\n let subs;\n try {\n subs = JSON.parse(state.val as any);\n } catch {\n this.logger.error(`${this.namespaceLog} Cannot parse subscribes for \"${autoSub}.subscribes\"`);\n continue;\n }\n\n if (\n !tools.isObject(subs) ||\n !tools.isObject(subs[pattern]) ||\n subs[pattern][this.namespace] === undefined\n ) {\n // check subs is a valid object, because it comes from state.val\n continue;\n }\n\n // rebuild without a prototype so a \"__proto__\" key cannot pollute Object.prototype\n subs = Object.assign(Object.create(null), subs);\n\n if (typeof subs[pattern][this.namespace] === 'number') {\n subs[pattern][this.namespace]--;\n if (subs[pattern][this.namespace] <= 0) {\n delete subs[pattern][this.namespace];\n }\n } else {\n // corrupted info, we can only delete\n delete subs[pattern][this.namespace];\n }\n\n // if no other subs are there\n if (!Object.keys(subs[pattern]).length) {\n delete subs[pattern];\n }\n this.countOutput();\n await this.states.setState(`system.adapter.${autoSub}.subscribes`, JSON.stringify(subs));\n }\n }\n }\n\n let aliasPattern;\n const promises = new Array<Promise<void>>();\n\n if (Array.isArray(pattern)) {\n // process every entry as single unsubscribe\n for (const _pattern of pattern) {\n promises.push(this.unsubscribeForeignStates(_pattern, options));\n }\n } else if (pattern.includes('*') || pattern.startsWith(ALIAS_STARTS_WITH)) {\n if (pattern === '*' || pattern.startsWith(ALIAS_STARTS_WITH)) {\n aliasPattern = pattern; // check all aliases\n if (pattern === '*') {\n promises.push(this.states.unsubscribeUser(pattern));\n }\n } else {\n promises.push(this.states.unsubscribeUser(pattern));\n }\n } else {\n promises.push(this.states.unsubscribeUser(pattern));\n }\n\n if (aliasPattern) {\n this.#alias.deletePattern(aliasPattern);\n promises.push(this.#alias.removeTargetsForPattern(aliasPattern));\n }\n\n await Promise.all(promises);\n this.#alias.maybeDropAliasObjectSubscription();\n return;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';
|
|
2
2
|
import type { AdapterClass } from '../../lib/adapter/adapter.js';
|
|
3
3
|
import type { UserInterfaceClientRemoveMessage, UserInterfaceClientSubscribeHandler, UserInterfaceClientSubscribeReturnType, UserInterfaceClientUnsubscribeHandler } from '../../lib/_Types.js';
|
|
4
|
+
/** A heartbeat timer for a subscribed UI client */
|
|
4
5
|
export interface HeartbeatTimer {
|
|
5
6
|
/** The actual timer */
|
|
6
7
|
timer: NodeJS.Timeout;
|
|
7
8
|
/** The heartbeat interval */
|
|
8
9
|
heartbeat: number;
|
|
9
10
|
}
|
|
11
|
+
/** Options for the UI messaging controller */
|
|
10
12
|
export interface MessagingControllerOptions {
|
|
11
13
|
/** The adapter using this messaging controller */
|
|
12
14
|
adapter: AdapterClass;
|
|
@@ -15,6 +17,7 @@ export interface MessagingControllerOptions {
|
|
|
15
17
|
/** Callback to call if successfully unsubscribed */
|
|
16
18
|
unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;
|
|
17
19
|
}
|
|
20
|
+
/** Options for sending a message to a single UI client */
|
|
18
21
|
export interface SendToClientOptions {
|
|
19
22
|
/** ID of the client to send the message to, will send to all if omitted */
|
|
20
23
|
clientId: string;
|
|
@@ -24,6 +27,7 @@ export interface SendToClientOptions {
|
|
|
24
27
|
states: StatesInRedisClient;
|
|
25
28
|
}
|
|
26
29
|
export type SendToAllClientOptions = Omit<SendToClientOptions, 'clientId'>;
|
|
30
|
+
/** Handler describing a subscribed UI client */
|
|
27
31
|
export interface ClientHandler {
|
|
28
32
|
/** The session id of the client connection */
|
|
29
33
|
sid: string;
|
|
@@ -32,6 +36,9 @@ export interface ClientHandler {
|
|
|
32
36
|
/** Individual type which can be specified */
|
|
33
37
|
type: string;
|
|
34
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Controller for messaging with UI clients (subscribe, heartbeat and sending data)
|
|
41
|
+
*/
|
|
35
42
|
export declare class UserInterfaceMessagingController {
|
|
36
43
|
/** The adapter using this messaging controller */
|
|
37
44
|
private readonly adapter;
|
|
@@ -43,6 +50,9 @@ export declare class UserInterfaceMessagingController {
|
|
|
43
50
|
private readonly handlers;
|
|
44
51
|
/** Collection of current heartbeat timers */
|
|
45
52
|
private heartbeatTimers;
|
|
53
|
+
/**
|
|
54
|
+
* @param options The adapter and the subscribe/unsubscribe callbacks
|
|
55
|
+
*/
|
|
46
56
|
constructor(options: MessagingControllerOptions);
|
|
47
57
|
/**
|
|
48
58
|
* Send a message to the given clientId
|
|
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
7
|
var __export = (target, all) => {
|
|
7
8
|
for (var name in all)
|
|
8
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -22,6 +23,9 @@ __export(userInterfaceMessagingController_exports, {
|
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(userInterfaceMessagingController_exports);
|
|
24
25
|
class UserInterfaceMessagingController {
|
|
26
|
+
static {
|
|
27
|
+
__name(this, "UserInterfaceMessagingController");
|
|
28
|
+
}
|
|
25
29
|
/** The adapter using this messaging controller */
|
|
26
30
|
adapter;
|
|
27
31
|
/** Callback to call if successfully subscribed */
|
|
@@ -32,6 +36,9 @@ class UserInterfaceMessagingController {
|
|
|
32
36
|
handlers = /* @__PURE__ */ new Map();
|
|
33
37
|
/** Collection of current heartbeat timers */
|
|
34
38
|
heartbeatTimers = /* @__PURE__ */ new Map();
|
|
39
|
+
/**
|
|
40
|
+
* @param options The adapter and the subscribe/unsubscribe callbacks
|
|
41
|
+
*/
|
|
35
42
|
constructor(options) {
|
|
36
43
|
const { adapter, unsubscribeCallback, subscribeCallback } = options;
|
|
37
44
|
this.adapter = adapter;
|
|
@@ -120,7 +127,7 @@ class UserInterfaceMessagingController {
|
|
|
120
127
|
}
|
|
121
128
|
this.handlers.delete(clientId);
|
|
122
129
|
if (this.unsubscribeCallback) {
|
|
123
|
-
this.unsubscribeCallback({ clientId, message: msg, reason });
|
|
130
|
+
Promise.resolve(this.unsubscribeCallback({ clientId, message: msg, reason })).catch((e) => this.adapter.log.error(`Error in unsubscribe callback: ${e.message}`));
|
|
124
131
|
}
|
|
125
132
|
}
|
|
126
133
|
}
|
|
@@ -150,7 +157,7 @@ class UserInterfaceMessagingController {
|
|
|
150
157
|
this.handlers.delete(clientId);
|
|
151
158
|
this.heartbeatTimers.delete(clientId);
|
|
152
159
|
if (this.unsubscribeCallback) {
|
|
153
|
-
this.unsubscribeCallback({ clientId, reason: "timeout" });
|
|
160
|
+
Promise.resolve(this.unsubscribeCallback({ clientId, reason: "timeout" })).catch((e) => this.adapter.log.error(`Error in unsubscribe callback: ${e.message}`));
|
|
154
161
|
}
|
|
155
162
|
}
|
|
156
163
|
}
|