@iobroker/js-controller-adapter 7.2.3 → 8.0.0-alpha.2-20260923-99da17fcc

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 (108) hide show
  1. package/build/cjs/index.d.ts +0 -1
  2. package/build/cjs/index.js +5 -8
  3. package/build/cjs/index.js.map +2 -2
  4. package/build/cjs/lib/_Types.d.ts +394 -63
  5. package/build/cjs/lib/adapter/adapter.d.ts +1896 -177
  6. package/build/cjs/lib/adapter/adapter.js +788 -1035
  7. package/build/cjs/lib/adapter/adapter.js.map +2 -2
  8. package/build/cjs/lib/adapter/asyncAdapter.d.ts +167 -0
  9. package/build/cjs/lib/adapter/asyncAdapter.js +252 -0
  10. package/build/cjs/lib/adapter/asyncAdapter.js.map +7 -0
  11. package/build/cjs/lib/adapter/context.d.ts +34 -0
  12. package/build/cjs/lib/adapter/context.js +17 -0
  13. package/build/cjs/lib/adapter/context.js.map +7 -0
  14. package/build/cjs/lib/adapter/defaultObjs.d.ts +5 -0
  15. package/build/cjs/lib/adapter/defaultObjs.js +2 -0
  16. package/build/cjs/lib/adapter/defaultObjs.js.map +2 -2
  17. package/build/cjs/lib/adapter/log.d.ts +25 -0
  18. package/build/cjs/lib/adapter/log.js +29 -0
  19. package/build/cjs/lib/adapter/log.js.map +2 -2
  20. package/build/cjs/lib/adapter/managers/AdapterContextBase.d.ts +49 -0
  21. package/build/cjs/lib/adapter/managers/AdapterContextBase.js +98 -0
  22. package/build/cjs/lib/adapter/managers/AdapterContextBase.js.map +7 -0
  23. package/build/cjs/lib/adapter/managers/AliasManager.d.ts +103 -0
  24. package/build/cjs/lib/adapter/managers/AliasManager.js +293 -0
  25. package/build/cjs/lib/adapter/managers/AliasManager.js.map +7 -0
  26. package/build/cjs/lib/adapter/managers/CertificateManager.d.ts +50 -0
  27. package/build/cjs/lib/adapter/managers/CertificateManager.js +174 -0
  28. package/build/cjs/lib/adapter/managers/CertificateManager.js.map +7 -0
  29. package/build/cjs/lib/adapter/managers/MessagingManager.d.ts +58 -0
  30. package/build/cjs/lib/adapter/managers/MessagingManager.js +289 -0
  31. package/build/cjs/lib/adapter/managers/MessagingManager.js.map +7 -0
  32. package/build/cjs/lib/adapter/managers/ResourceManager.d.ts +69 -0
  33. package/build/cjs/lib/adapter/managers/ResourceManager.js +170 -0
  34. package/build/cjs/lib/adapter/managers/ResourceManager.js.map +7 -0
  35. package/build/cjs/lib/adapter/managers/SubscriptionManager.d.ts +107 -0
  36. package/build/cjs/lib/adapter/managers/SubscriptionManager.js +349 -0
  37. package/build/cjs/lib/adapter/managers/SubscriptionManager.js.map +7 -0
  38. package/build/cjs/lib/adapter/userInterfaceMessagingController.d.ts +10 -0
  39. package/build/cjs/lib/adapter/userInterfaceMessagingController.js +9 -2
  40. package/build/cjs/lib/adapter/userInterfaceMessagingController.js.map +2 -2
  41. package/build/cjs/lib/adapter/utils.js +15 -1
  42. package/build/cjs/lib/adapter/utils.js.map +2 -2
  43. package/build/cjs/lib/adapter/validator.d.ts +10 -5
  44. package/build/cjs/lib/adapter/validator.js +6 -5
  45. package/build/cjs/lib/adapter/validator.js.map +2 -2
  46. package/build/esm/index.d.ts +0 -1
  47. package/build/esm/index.d.ts.map +1 -1
  48. package/build/esm/index.js +0 -1
  49. package/build/esm/index.js.map +1 -1
  50. package/build/esm/lib/_Types.d.ts +394 -63
  51. package/build/esm/lib/_Types.d.ts.map +1 -1
  52. package/build/esm/lib/adapter/adapter.d.ts +1896 -177
  53. package/build/esm/lib/adapter/adapter.d.ts.map +1 -1
  54. package/build/esm/lib/adapter/adapter.js +900 -1215
  55. package/build/esm/lib/adapter/adapter.js.map +1 -1
  56. package/build/esm/lib/adapter/asyncAdapter.d.ts +167 -0
  57. package/build/esm/lib/adapter/asyncAdapter.d.ts.map +1 -0
  58. package/build/esm/lib/adapter/asyncAdapter.js +225 -0
  59. package/build/esm/lib/adapter/asyncAdapter.js.map +1 -0
  60. package/build/esm/lib/adapter/context.d.ts +34 -0
  61. package/build/esm/lib/adapter/context.d.ts.map +1 -0
  62. package/build/esm/lib/adapter/context.js +2 -0
  63. package/build/esm/lib/adapter/context.js.map +1 -0
  64. package/build/esm/lib/adapter/defaultObjs.d.ts +5 -0
  65. package/build/esm/lib/adapter/defaultObjs.d.ts.map +1 -1
  66. package/build/esm/lib/adapter/defaultObjs.js +5 -0
  67. package/build/esm/lib/adapter/defaultObjs.js.map +1 -1
  68. package/build/esm/lib/adapter/log.d.ts +25 -0
  69. package/build/esm/lib/adapter/log.d.ts.map +1 -1
  70. package/build/esm/lib/adapter/log.js +25 -0
  71. package/build/esm/lib/adapter/log.js.map +1 -1
  72. package/build/esm/lib/adapter/managers/AdapterContextBase.d.ts +49 -0
  73. package/build/esm/lib/adapter/managers/AdapterContextBase.d.ts.map +1 -0
  74. package/build/esm/lib/adapter/managers/AdapterContextBase.js +77 -0
  75. package/build/esm/lib/adapter/managers/AdapterContextBase.js.map +1 -0
  76. package/build/esm/lib/adapter/managers/AliasManager.d.ts +103 -0
  77. package/build/esm/lib/adapter/managers/AliasManager.d.ts.map +1 -0
  78. package/build/esm/lib/adapter/managers/AliasManager.js +269 -0
  79. package/build/esm/lib/adapter/managers/AliasManager.js.map +1 -0
  80. package/build/esm/lib/adapter/managers/CertificateManager.d.ts +50 -0
  81. package/build/esm/lib/adapter/managers/CertificateManager.d.ts.map +1 -0
  82. package/build/esm/lib/adapter/managers/CertificateManager.js +142 -0
  83. package/build/esm/lib/adapter/managers/CertificateManager.js.map +1 -0
  84. package/build/esm/lib/adapter/managers/MessagingManager.d.ts +58 -0
  85. package/build/esm/lib/adapter/managers/MessagingManager.d.ts.map +1 -0
  86. package/build/esm/lib/adapter/managers/MessagingManager.js +267 -0
  87. package/build/esm/lib/adapter/managers/MessagingManager.js.map +1 -0
  88. package/build/esm/lib/adapter/managers/ResourceManager.d.ts +69 -0
  89. package/build/esm/lib/adapter/managers/ResourceManager.d.ts.map +1 -0
  90. package/build/esm/lib/adapter/managers/ResourceManager.js +151 -0
  91. package/build/esm/lib/adapter/managers/ResourceManager.js.map +1 -0
  92. package/build/esm/lib/adapter/managers/SubscriptionManager.d.ts +107 -0
  93. package/build/esm/lib/adapter/managers/SubscriptionManager.d.ts.map +1 -0
  94. package/build/esm/lib/adapter/managers/SubscriptionManager.js +374 -0
  95. package/build/esm/lib/adapter/managers/SubscriptionManager.js.map +1 -0
  96. package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts +10 -0
  97. package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts.map +1 -1
  98. package/build/esm/lib/adapter/userInterfaceMessagingController.js +8 -2
  99. package/build/esm/lib/adapter/userInterfaceMessagingController.js.map +1 -1
  100. package/build/esm/lib/adapter/utils.d.ts.map +1 -1
  101. package/build/esm/lib/adapter/utils.js +1 -1
  102. package/build/esm/lib/adapter/utils.js.map +1 -1
  103. package/build/esm/lib/adapter/validator.d.ts +10 -5
  104. package/build/esm/lib/adapter/validator.d.ts.map +1 -1
  105. package/build/esm/lib/adapter/validator.js +8 -5
  106. package/build/esm/lib/adapter/validator.js.map +1 -1
  107. package/build/tsconfig.build.tsbuildinfo +1 -1
  108. package/package.json +25 -20
@@ -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
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/adapter/userInterfaceMessagingController.ts"],
4
- "sourcesContent": ["import type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { AdapterClass } from '@/lib/adapter/adapter.js';\nimport type {\n UserInterfaceClientRemoveMessage,\n UserInterfaceClientSubscribeHandler,\n UserInterfaceClientSubscribeReturnType,\n UserInterfaceClientUnsubscribeHandler,\n} from '@/lib/_Types.js';\n\nexport interface HeartbeatTimer {\n /** The actual timer */\n timer: NodeJS.Timeout;\n /** The heartbeat interval */\n heartbeat: number;\n}\n\nexport interface MessagingControllerOptions {\n /** The adapter using this messaging controller */\n adapter: AdapterClass;\n /** Callback to call if successfully subscribed */\n subscribeCallback?: UserInterfaceClientSubscribeHandler;\n /** Callback to call if successfully unsubscribed */\n unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;\n}\n\nexport interface SendToClientOptions {\n /** ID of the client to send the message to, will send to all if omitted */\n clientId: string;\n /** Data to send to the client */\n data: unknown;\n /** The states db */\n states: StatesInRedisClient;\n}\n\nexport type SendToAllClientOptions = Omit<SendToClientOptions, 'clientId'>;\n\nexport interface ClientHandler {\n /** The session id of the client connection */\n sid: string;\n /** Name of the subscriber */\n from: string;\n /** Individual type which can be specified */\n type: string;\n}\n\n/**\n * The message has short keys, to save bytes for high-throughput messaging\n */\ninterface UserInterfaceMessage {\n /** The individual type of the client handler */\n m: string;\n /** The session id of the client connection */\n s: string;\n /** The actual data */\n d: unknown;\n}\n\nexport class UserInterfaceMessagingController {\n /** The adapter using this messaging controller */\n private readonly adapter: AdapterClass;\n /** Callback to call if successfully subscribed */\n private readonly unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;\n /** Callback to call if successfully unsubscribed */\n private readonly subscribeCallback?: UserInterfaceClientSubscribeHandler;\n /** All currently registered client handlers */\n private readonly handlers = new Map<string, ClientHandler>();\n /** Collection of current heartbeat timers */\n private heartbeatTimers = new Map<string, HeartbeatTimer>();\n constructor(options: MessagingControllerOptions) {\n const { adapter, unsubscribeCallback, subscribeCallback } = options;\n\n this.adapter = adapter;\n this.unsubscribeCallback = unsubscribeCallback;\n this.subscribeCallback = subscribeCallback;\n }\n\n /**\n * Send a message to the given clientId\n *\n * @param options Data, states and client information\n */\n sendToClient(options: SendToClientOptions): Promise<void> {\n const { states, clientId, data } = options;\n\n if (!this.handlers.has(clientId)) {\n throw new Error(`Client \"${clientId}\" is not registered`);\n }\n\n const handler = this.handlers.get(clientId)!;\n\n return states.pushMessage(handler.from, {\n command: 'im',\n message: { m: handler.type, s: handler.sid, d: data } satisfies UserInterfaceMessage,\n from: `system.adapter.${this.adapter.namespace}`,\n });\n }\n\n /**\n * Send a message to all active clients\n *\n * @param options Data and states options\n */\n async sendToAllClients(options: SendToAllClientOptions): Promise<void> {\n const { states, data } = options;\n\n for (const clientId of Object.keys(this.handlers)) {\n await this.sendToClient({ clientId, data, states });\n }\n }\n\n /**\n * Register subscription from new client\n *\n * @param msg The subscribe message\n */\n async registerClientSubscribeByMessage(\n msg: ioBroker.Message,\n ): Promise<UserInterfaceClientSubscribeReturnType | undefined> {\n if (!this.subscribeCallback) {\n return;\n }\n\n const handler = this.extractHandlerFromMessage(msg);\n const clientId = this.handlerToId(handler);\n\n if (this.heartbeatTimers.has(clientId)) {\n this.heartbeatTimers.get(clientId)!.timer.refresh();\n return;\n }\n\n const resOrAwaitable = this.subscribeCallback({ clientId, message: msg });\n let res: UserInterfaceClientSubscribeReturnType;\n\n if (resOrAwaitable instanceof Promise) {\n res = await resOrAwaitable;\n } else {\n res = resOrAwaitable;\n }\n\n if (!res.accepted) {\n return res;\n }\n\n this.handlers.set(clientId, handler);\n if (res.heartbeat) {\n const timer = setTimeout(() => this.heartbeatExpired(clientId), res.heartbeat);\n this.heartbeatTimers.set(clientId, { heartbeat: res.heartbeat, timer });\n }\n\n return res;\n }\n\n /**\n * Remove a client subscription, issued by message\n * It contains an array of types which should be unsubscribed\n *\n * @param msg The unsubscribe message\n */\n removeClientSubscribeByMessage(msg: UserInterfaceClientRemoveMessage): void {\n const handler = this.extractHandlerFromMessage(msg);\n const reason = msg.command === 'clientSubscribeError' ? msg.command : msg.message.reason;\n\n const types = msg.message.type;\n\n for (const type of types) {\n const clientId = this.handlerToId({ ...handler, type });\n\n if (this.heartbeatTimers.has(clientId)) {\n const timer = this.heartbeatTimers.get(clientId)!;\n\n clearTimeout(timer.timer);\n this.heartbeatTimers.delete(clientId);\n }\n\n if (!this.handlers.has(clientId)) {\n return;\n }\n\n this.handlers.delete(clientId);\n if (this.unsubscribeCallback) {\n this.unsubscribeCallback({ clientId, message: msg, reason });\n }\n }\n }\n\n /**\n * Convert handler to id\n *\n * @param handler the client handler to creat the id for\n */\n private handlerToId(handler: ClientHandler): string {\n const { sid, type, from } = handler;\n\n return `${sid}-${from}-${type}`;\n }\n\n /**\n * Extract the client handler from a given message\n *\n * @param msg the subscribe or unsubscribe message\n */\n private extractHandlerFromMessage(msg: ioBroker.Message): ClientHandler {\n return { sid: msg.message.sid, from: msg.from, type: msg.message.type };\n }\n\n /**\n * Handle expired heartbeat\n *\n * @param clientId the id of the expired client\n */\n private heartbeatExpired(clientId: string): void {\n this.handlers.delete(clientId);\n this.heartbeatTimers.delete(clientId);\n\n if (this.unsubscribeCallback) {\n this.unsubscribeCallback({ clientId, reason: 'timeout' });\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Client as StatesInRedisClient } from '@iobroker/db-states-redis';\nimport type { AdapterClass } from '@/lib/adapter/adapter.js';\nimport type {\n UserInterfaceClientRemoveMessage,\n UserInterfaceClientSubscribeHandler,\n UserInterfaceClientSubscribeReturnType,\n UserInterfaceClientUnsubscribeHandler,\n} from '@/lib/_Types.js';\n\n/** A heartbeat timer for a subscribed UI client */\nexport interface HeartbeatTimer {\n /** The actual timer */\n timer: NodeJS.Timeout;\n /** The heartbeat interval */\n heartbeat: number;\n}\n\n/** Options for the UI messaging controller */\nexport interface MessagingControllerOptions {\n /** The adapter using this messaging controller */\n adapter: AdapterClass;\n /** Callback to call if successfully subscribed */\n subscribeCallback?: UserInterfaceClientSubscribeHandler;\n /** Callback to call if successfully unsubscribed */\n unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;\n}\n\n/** Options for sending a message to a single UI client */\nexport interface SendToClientOptions {\n /** ID of the client to send the message to, will send to all if omitted */\n clientId: string;\n /** Data to send to the client */\n data: unknown;\n /** The states db */\n states: StatesInRedisClient;\n}\n\nexport type SendToAllClientOptions = Omit<SendToClientOptions, 'clientId'>;\n\n/** Handler describing a subscribed UI client */\nexport interface ClientHandler {\n /** The session id of the client connection */\n sid: string;\n /** Name of the subscriber */\n from: string;\n /** Individual type which can be specified */\n type: string;\n}\n\n/**\n * The message has short keys, to save bytes for high-throughput messaging\n */\ninterface UserInterfaceMessage {\n /** The individual type of the client handler */\n m: string;\n /** The session id of the client connection */\n s: string;\n /** The actual data */\n d: unknown;\n}\n\n/**\n * Controller for messaging with UI clients (subscribe, heartbeat and sending data)\n */\nexport class UserInterfaceMessagingController {\n /** The adapter using this messaging controller */\n private readonly adapter: AdapterClass;\n /** Callback to call if successfully subscribed */\n private readonly unsubscribeCallback?: UserInterfaceClientUnsubscribeHandler;\n /** Callback to call if successfully unsubscribed */\n private readonly subscribeCallback?: UserInterfaceClientSubscribeHandler;\n /** All currently registered client handlers */\n private readonly handlers = new Map<string, ClientHandler>();\n /** Collection of current heartbeat timers */\n private heartbeatTimers = new Map<string, HeartbeatTimer>();\n /**\n * @param options The adapter and the subscribe/unsubscribe callbacks\n */\n constructor(options: MessagingControllerOptions) {\n const { adapter, unsubscribeCallback, subscribeCallback } = options;\n\n this.adapter = adapter;\n this.unsubscribeCallback = unsubscribeCallback;\n this.subscribeCallback = subscribeCallback;\n }\n\n /**\n * Send a message to the given clientId\n *\n * @param options Data, states and client information\n */\n sendToClient(options: SendToClientOptions): Promise<void> {\n const { states, clientId, data } = options;\n\n if (!this.handlers.has(clientId)) {\n throw new Error(`Client \"${clientId}\" is not registered`);\n }\n\n const handler = this.handlers.get(clientId)!;\n\n return states.pushMessage(handler.from, {\n command: 'im',\n message: { m: handler.type, s: handler.sid, d: data } satisfies UserInterfaceMessage,\n from: `system.adapter.${this.adapter.namespace}`,\n });\n }\n\n /**\n * Send a message to all active clients\n *\n * @param options Data and states options\n */\n async sendToAllClients(options: SendToAllClientOptions): Promise<void> {\n const { states, data } = options;\n\n for (const clientId of Object.keys(this.handlers)) {\n await this.sendToClient({ clientId, data, states });\n }\n }\n\n /**\n * Register subscription from new client\n *\n * @param msg The subscribe message\n */\n async registerClientSubscribeByMessage(\n msg: ioBroker.Message,\n ): Promise<UserInterfaceClientSubscribeReturnType | undefined> {\n if (!this.subscribeCallback) {\n return;\n }\n\n const handler = this.extractHandlerFromMessage(msg);\n const clientId = this.handlerToId(handler);\n\n if (this.heartbeatTimers.has(clientId)) {\n this.heartbeatTimers.get(clientId)!.timer.refresh();\n return;\n }\n\n const resOrAwaitable = this.subscribeCallback({ clientId, message: msg });\n let res: UserInterfaceClientSubscribeReturnType;\n\n if (resOrAwaitable instanceof Promise) {\n res = await resOrAwaitable;\n } else {\n res = resOrAwaitable;\n }\n\n if (!res.accepted) {\n return res;\n }\n\n this.handlers.set(clientId, handler);\n if (res.heartbeat) {\n const timer = setTimeout(() => this.heartbeatExpired(clientId), res.heartbeat);\n this.heartbeatTimers.set(clientId, { heartbeat: res.heartbeat, timer });\n }\n\n return res;\n }\n\n /**\n * Remove a client subscription, issued by message\n * It contains an array of types which should be unsubscribed\n *\n * @param msg The unsubscribe message\n */\n removeClientSubscribeByMessage(msg: UserInterfaceClientRemoveMessage): void {\n const handler = this.extractHandlerFromMessage(msg);\n const reason = msg.command === 'clientSubscribeError' ? msg.command : msg.message.reason;\n\n const types = msg.message.type;\n\n for (const type of types) {\n const clientId = this.handlerToId({ ...handler, type });\n\n if (this.heartbeatTimers.has(clientId)) {\n const timer = this.heartbeatTimers.get(clientId)!;\n\n clearTimeout(timer.timer);\n this.heartbeatTimers.delete(clientId);\n }\n\n if (!this.handlers.has(clientId)) {\n return;\n }\n\n this.handlers.delete(clientId);\n if (this.unsubscribeCallback) {\n Promise.resolve(this.unsubscribeCallback({ clientId, message: msg, reason })).catch(e =>\n this.adapter.log.error(`Error in unsubscribe callback: ${e.message}`),\n );\n }\n }\n }\n\n /**\n * Convert handler to id\n *\n * @param handler the client handler to creat the id for\n */\n private handlerToId(handler: ClientHandler): string {\n const { sid, type, from } = handler;\n\n return `${sid}-${from}-${type}`;\n }\n\n /**\n * Extract the client handler from a given message\n *\n * @param msg the subscribe or unsubscribe message\n */\n private extractHandlerFromMessage(msg: ioBroker.Message): ClientHandler {\n return { sid: msg.message.sid, from: msg.from, type: msg.message.type };\n }\n\n /**\n * Handle expired heartbeat\n *\n * @param clientId the id of the expired client\n */\n private heartbeatExpired(clientId: string): void {\n this.handlers.delete(clientId);\n this.heartbeatTimers.delete(clientId);\n\n if (this.unsubscribeCallback) {\n Promise.resolve(this.unsubscribeCallback({ clientId, reason: 'timeout' })).catch(e =>\n this.adapter.log.error(`Error in unsubscribe callback: ${e.message}`),\n );\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
9
  var __export = (target, all) => {
9
10
  for (var name in all)
10
11
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -50,9 +51,11 @@ function isMessageboxSupported(instanceCommon) {
50
51
  }
51
52
  return Object.values(instanceCommon.supportedMessages).find((val) => val !== false) !== void 0;
52
53
  }
54
+ __name(isMessageboxSupported, "isMessageboxSupported");
53
55
  function getSupportedFeatures() {
54
56
  return (0, import_js_controller_common.getSupportedFeatures)();
55
57
  }
58
+ __name(getSupportedFeatures, "getSupportedFeatures");
56
59
  function encryptArray(options) {
57
60
  const { secret, obj, keys } = options;
58
61
  for (const attr of keys) {
@@ -68,6 +71,7 @@ function encryptArray(options) {
68
71
  }
69
72
  }
70
73
  }
74
+ __name(encryptArray, "encryptArray");
71
75
  function decryptArray(options) {
72
76
  const { secret, obj, keys } = options;
73
77
  for (const attr of keys) {
@@ -83,6 +87,7 @@ function decryptArray(options) {
83
87
  }
84
88
  }
85
89
  }
90
+ __name(decryptArray, "decryptArray");
86
91
  function getAdapterScopedPackageIdentifier(options) {
87
92
  const { moduleName, namespace } = options;
88
93
  let internalModuleName = moduleName;
@@ -91,6 +96,7 @@ function getAdapterScopedPackageIdentifier(options) {
91
96
  }
92
97
  return `@${import_tools.appNameLowerCase}-${namespace}/${internalModuleName}`;
93
98
  }
99
+ __name(getAdapterScopedPackageIdentifier, "getAdapterScopedPackageIdentifier");
94
100
  async function listInstalledNodeModules(namespace) {
95
101
  const packJson = await import_fs_extra.default.readJson(import_node_path.default.join((0, import_tools.getRootDir)(), "package.json"));
96
102
  const dependencies = [];
@@ -108,13 +114,15 @@ async function listInstalledNodeModules(namespace) {
108
114
  }
109
115
  return dependencies;
110
116
  }
117
+ __name(listInstalledNodeModules, "listInstalledNodeModules");
111
118
  async function requestModuleNameByUrl(url) {
112
119
  const res = await (0, import_tools.execAsync)(`npm view ${url} name`);
113
120
  if (typeof res.stdout !== "string") {
114
- throw new Error(`Could not determine module name for url "${url}". Unexpected stdout: "${res.stdout ? res.stdout.toString() : ""}"`);
121
+ throw new Error(`Could not determine module name for url "${url}". Unexpected stdout: "${typeof res.stdout}"`);
115
122
  }
116
123
  return res.stdout.trim();
117
124
  }
125
+ __name(requestModuleNameByUrl, "requestModuleNameByUrl");
118
126
  function _getObjectAttribute(obj, attrParts, index) {
119
127
  if (index === attrParts.length - 1) {
120
128
  return obj[attrParts[index]];
@@ -131,12 +139,14 @@ function _getObjectAttribute(obj, attrParts, index) {
131
139
  }
132
140
  return _getObjectAttribute(obj[attrParts[index]], attrParts, index + 1);
133
141
  }
142
+ __name(_getObjectAttribute, "_getObjectAttribute");
134
143
  function getObjectAttribute(obj, attr) {
135
144
  if (!attr.includes(".")) {
136
145
  return obj[attr];
137
146
  }
138
147
  return _getObjectAttribute(obj, attr.split("."), 0);
139
148
  }
149
+ __name(getObjectAttribute, "getObjectAttribute");
140
150
  function _setObjectAttribute(obj, value, attrParts, index) {
141
151
  if (index === attrParts.length - 1) {
142
152
  obj[attrParts[index]] = value;
@@ -156,6 +166,7 @@ function _setObjectAttribute(obj, value, attrParts, index) {
156
166
  }
157
167
  _setObjectAttribute(obj[attrParts[index]], value, attrParts, index + 1);
158
168
  }
169
+ __name(_setObjectAttribute, "_setObjectAttribute");
159
170
  function setObjectAttribute(obj, attr, value) {
160
171
  if (!attr.includes(".")) {
161
172
  obj[attr] = value;
@@ -163,6 +174,7 @@ function setObjectAttribute(obj, attr, value) {
163
174
  }
164
175
  _setObjectAttribute(obj, value, attr.split("."), 0);
165
176
  }
177
+ __name(setObjectAttribute, "setObjectAttribute");
166
178
  function _deleteObjectAttribute(obj, attrParts, index) {
167
179
  if (index === attrParts.length - 1) {
168
180
  delete obj[attrParts[index]];
@@ -179,6 +191,7 @@ function _deleteObjectAttribute(obj, attrParts, index) {
179
191
  }
180
192
  _deleteObjectAttribute(obj[attrParts[index]], attrParts, index + 1);
181
193
  }
194
+ __name(_deleteObjectAttribute, "_deleteObjectAttribute");
182
195
  function deleteObjectAttribute(obj, attr) {
183
196
  if (!attr.includes(".")) {
184
197
  delete obj[attr];
@@ -186,6 +199,7 @@ function deleteObjectAttribute(obj, attr) {
186
199
  }
187
200
  _deleteObjectAttribute(obj, attr.split("."), 0);
188
201
  }
202
+ __name(deleteObjectAttribute, "deleteObjectAttribute");
189
203
  // Annotate the CommonJS export names for ESM import in node:
190
204
  0 && (module.exports = {
191
205
  decryptArray,