@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.
Files changed (101) 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 +1818 -177
  6. package/build/cjs/lib/adapter/adapter.js +715 -1035
  7. package/build/cjs/lib/adapter/adapter.js.map +2 -2
  8. package/build/cjs/lib/adapter/asyncAdapter.d.ts +124 -0
  9. package/build/cjs/lib/adapter/asyncAdapter.js +184 -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/SubscriptionManager.d.ts +107 -0
  33. package/build/cjs/lib/adapter/managers/SubscriptionManager.js +349 -0
  34. package/build/cjs/lib/adapter/managers/SubscriptionManager.js.map +7 -0
  35. package/build/cjs/lib/adapter/userInterfaceMessagingController.d.ts +10 -0
  36. package/build/cjs/lib/adapter/userInterfaceMessagingController.js +9 -2
  37. package/build/cjs/lib/adapter/userInterfaceMessagingController.js.map +2 -2
  38. package/build/cjs/lib/adapter/utils.js +15 -1
  39. package/build/cjs/lib/adapter/utils.js.map +2 -2
  40. package/build/cjs/lib/adapter/validator.d.ts +10 -5
  41. package/build/cjs/lib/adapter/validator.js +6 -5
  42. package/build/cjs/lib/adapter/validator.js.map +2 -2
  43. package/build/esm/index.d.ts +0 -1
  44. package/build/esm/index.d.ts.map +1 -1
  45. package/build/esm/index.js +0 -1
  46. package/build/esm/index.js.map +1 -1
  47. package/build/esm/lib/_Types.d.ts +394 -63
  48. package/build/esm/lib/_Types.d.ts.map +1 -1
  49. package/build/esm/lib/adapter/adapter.d.ts +1818 -177
  50. package/build/esm/lib/adapter/adapter.d.ts.map +1 -1
  51. package/build/esm/lib/adapter/adapter.js +827 -1215
  52. package/build/esm/lib/adapter/adapter.js.map +1 -1
  53. package/build/esm/lib/adapter/asyncAdapter.d.ts +124 -0
  54. package/build/esm/lib/adapter/asyncAdapter.d.ts.map +1 -0
  55. package/build/esm/lib/adapter/asyncAdapter.js +157 -0
  56. package/build/esm/lib/adapter/asyncAdapter.js.map +1 -0
  57. package/build/esm/lib/adapter/context.d.ts +34 -0
  58. package/build/esm/lib/adapter/context.d.ts.map +1 -0
  59. package/build/esm/lib/adapter/context.js +2 -0
  60. package/build/esm/lib/adapter/context.js.map +1 -0
  61. package/build/esm/lib/adapter/defaultObjs.d.ts +5 -0
  62. package/build/esm/lib/adapter/defaultObjs.d.ts.map +1 -1
  63. package/build/esm/lib/adapter/defaultObjs.js +5 -0
  64. package/build/esm/lib/adapter/defaultObjs.js.map +1 -1
  65. package/build/esm/lib/adapter/log.d.ts +25 -0
  66. package/build/esm/lib/adapter/log.d.ts.map +1 -1
  67. package/build/esm/lib/adapter/log.js +25 -0
  68. package/build/esm/lib/adapter/log.js.map +1 -1
  69. package/build/esm/lib/adapter/managers/AdapterContextBase.d.ts +49 -0
  70. package/build/esm/lib/adapter/managers/AdapterContextBase.d.ts.map +1 -0
  71. package/build/esm/lib/adapter/managers/AdapterContextBase.js +77 -0
  72. package/build/esm/lib/adapter/managers/AdapterContextBase.js.map +1 -0
  73. package/build/esm/lib/adapter/managers/AliasManager.d.ts +103 -0
  74. package/build/esm/lib/adapter/managers/AliasManager.d.ts.map +1 -0
  75. package/build/esm/lib/adapter/managers/AliasManager.js +269 -0
  76. package/build/esm/lib/adapter/managers/AliasManager.js.map +1 -0
  77. package/build/esm/lib/adapter/managers/CertificateManager.d.ts +50 -0
  78. package/build/esm/lib/adapter/managers/CertificateManager.d.ts.map +1 -0
  79. package/build/esm/lib/adapter/managers/CertificateManager.js +142 -0
  80. package/build/esm/lib/adapter/managers/CertificateManager.js.map +1 -0
  81. package/build/esm/lib/adapter/managers/MessagingManager.d.ts +58 -0
  82. package/build/esm/lib/adapter/managers/MessagingManager.d.ts.map +1 -0
  83. package/build/esm/lib/adapter/managers/MessagingManager.js +267 -0
  84. package/build/esm/lib/adapter/managers/MessagingManager.js.map +1 -0
  85. package/build/esm/lib/adapter/managers/SubscriptionManager.d.ts +107 -0
  86. package/build/esm/lib/adapter/managers/SubscriptionManager.d.ts.map +1 -0
  87. package/build/esm/lib/adapter/managers/SubscriptionManager.js +374 -0
  88. package/build/esm/lib/adapter/managers/SubscriptionManager.js.map +1 -0
  89. package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts +10 -0
  90. package/build/esm/lib/adapter/userInterfaceMessagingController.d.ts.map +1 -1
  91. package/build/esm/lib/adapter/userInterfaceMessagingController.js +8 -2
  92. package/build/esm/lib/adapter/userInterfaceMessagingController.js.map +1 -1
  93. package/build/esm/lib/adapter/utils.d.ts.map +1 -1
  94. package/build/esm/lib/adapter/utils.js +1 -1
  95. package/build/esm/lib/adapter/utils.js.map +1 -1
  96. package/build/esm/lib/adapter/validator.d.ts +10 -5
  97. package/build/esm/lib/adapter/validator.d.ts.map +1 -1
  98. package/build/esm/lib/adapter/validator.js +8 -5
  99. package/build/esm/lib/adapter/validator.js.map +1 -1
  100. package/build/tsconfig.build.tsbuildinfo +1 -1
  101. package/package.json +25 -20
@@ -0,0 +1,103 @@
1
+ import type { AliasTargetEntry } from '../../_Types.js';
2
+ import type { ValidateIdOptions } from '../../../lib/adapter/validator.js';
3
+ import type { AdapterContext } from '../../../lib/adapter/context.js';
4
+ import { AdapterContextBase } from '../../../lib/adapter/managers/AdapterContextBase.js';
5
+ /** Validates a (possibly foreign) id; throws on invalid. Bound to the adapter's Validator. */
6
+ export type ValidateId = (id: string, isForeignId: boolean, options?: ValidateIdOptions | null) => void;
7
+ /**
8
+ * Owns the alias subscription cache and its bookkeeping: which real (source) states feed which
9
+ * `alias.*` targets, the alias subscription patterns, and the single `alias.*` object subscription.
10
+ * The source-state change fan-out ({@link resolveSourceChange}) is synchronous by contract so the
11
+ * state-change handler cannot interleave a cache mutation mid-fan-out.
12
+ */
13
+ export declare class AliasManager extends AdapterContextBase {
14
+ #private;
15
+ /**
16
+ * @param ctx Shared adapter context providing live runtime state
17
+ * @param validateId Bound id validator from the adapter's Validator instance
18
+ */
19
+ constructor(ctx: AdapterContext, validateId: ValidateId);
20
+ /**
21
+ * Whether the given source (real) state id currently feeds any alias.
22
+ *
23
+ * @param id the real source state id
24
+ */
25
+ hasSource(id: string): boolean;
26
+ /** Number of tracked source states. */
27
+ get size(): number;
28
+ /**
29
+ * Whether the given subscription pattern is tracked.
30
+ *
31
+ * @param pattern the subscription pattern
32
+ */
33
+ hasPattern(pattern: string): boolean;
34
+ /**
35
+ * Track a subscription pattern.
36
+ *
37
+ * @param pattern the subscription pattern
38
+ */
39
+ addPattern(pattern: string): void;
40
+ /**
41
+ * Stop tracking a subscription pattern.
42
+ *
43
+ * @param pattern the subscription pattern
44
+ */
45
+ deletePattern(pattern: string): void;
46
+ /**
47
+ * Whether `id` falls into any tracked alias pattern (wildcards via pattern2RegEx).
48
+ *
49
+ * @param id the id to test against the tracked patterns
50
+ */
51
+ matchesAnyPattern(id: string): boolean;
52
+ /**
53
+ * Reacts to a change of an `alias.*` object: re-points, updates, or removes the target across the
54
+ * tracked sources, and picks up a newly-appeared alias that falls into a tracked pattern.
55
+ * Live-iterates the cache while awaiting add/remove — the loop lives here, with the map, to
56
+ * preserve the original mutation-during-iteration semantics exactly.
57
+ *
58
+ * @param id the changed alias object id
59
+ * @param obj the new object (null/undefined if deleted)
60
+ */
61
+ handleAliasObjectChange(id: string, obj: ioBroker.Object | null | undefined): Promise<void>;
62
+ /**
63
+ * Removes every target subscribed under the given pattern, live-iterating the cache so a removal
64
+ * mutating the map mid-loop keeps the original semantics. Awaits each removal.
65
+ *
66
+ * @param pattern the subscription pattern being unsubscribed
67
+ */
68
+ removeTargetsForPattern(pattern: string): Promise<void>;
69
+ /**
70
+ * Synchronously computes the fan-out of a source (real) state change to its alias targets.
71
+ * Returns one `{ targetId, state }` per unique target. MUST NOT await — the caller relies on the
72
+ * cache not mutating between read and emit.
73
+ *
74
+ * @param sourceId the changed real state id
75
+ * @param state the new state value (or null on deletion)
76
+ */
77
+ resolveSourceChange(sourceId: string, state: ioBroker.State | null | undefined): Array<{
78
+ targetId: string;
79
+ state: ioBroker.State | null;
80
+ }>;
81
+ /** Subscribe the `alias.*` object range once (idempotent). */
82
+ ensureAliasObjectSubscription(): void;
83
+ /** Drop the `alias.*` object subscription when no aliases remain. */
84
+ maybeDropAliasObjectSubscription(): void;
85
+ /**
86
+ * Register an alias target for its source state, subscribing the source state (and reading its
87
+ * metadata once). Preserves the create-before-await ordering and the post-await existence
88
+ * re-check that guard a concurrent removal.
89
+ *
90
+ * @param aliasObj the `alias.*` object being subscribed
91
+ * @param pattern the subscription pattern that pulled it in
92
+ */
93
+ addAliasSubscribe(aliasObj: ioBroker.AnyObject, pattern: string): Promise<void>;
94
+ /**
95
+ * Remove one alias target from its source; when the source has no targets left, delete the entry
96
+ * and unsubscribe the source state.
97
+ *
98
+ * @param sourceId the real source state id
99
+ * @param aliasObjOrIdx the target entry or its index in the targets array
100
+ */
101
+ removeAliasSubscribe(sourceId: string, aliasObjOrIdx: number | AliasTargetEntry): Promise<void>;
102
+ }
103
+ //# sourceMappingURL=AliasManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AliasManager.d.ts","sourceRoot":"","sources":["../../../../../src/lib/adapter/managers/AliasManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAGlF,8FAA8F;AAC9F,MAAM,MAAM,UAAU,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC;AAExG;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,kBAAkB;;IAMhD;;;OAGG;gBACS,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU;IAKvD;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI9B,uCAAuC;IACvC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIpC;;;;OAIG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;OAIG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIpC;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IActC;;;;;;;;OAQG;IACG,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCjG;;;;;OAKG;IACG,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY7D;;;;;;;OAOG;IACH,mBAAmB,CACf,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,IAAI,GAAG,SAAS,GACzC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAA;KAAE,CAAC;IA+B5D,8DAA8D;IAC9D,6BAA6B,IAAI,IAAI;IAOrC,qEAAqE;IACrE,gCAAgC,IAAI,IAAI;IAOxC;;;;;;;OAOG;IACG,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+CrF;;;;;;OAMG;IACG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;CAcxG"}
@@ -0,0 +1,269 @@
1
+ import { tools } from '@iobroker/js-controller-common';
2
+ import deepClone from 'deep-clone';
3
+ import { AdapterContextBase } from '../../../lib/adapter/managers/AdapterContextBase.js';
4
+ import { ALIAS_STARTS_WITH, SYSTEM_ADMIN_USER } from '../../../lib/adapter/constants.js';
5
+ /**
6
+ * Owns the alias subscription cache and its bookkeeping: which real (source) states feed which
7
+ * `alias.*` targets, the alias subscription patterns, and the single `alias.*` object subscription.
8
+ * The source-state change fan-out ({@link resolveSourceChange}) is synchronous by contract so the
9
+ * state-change handler cannot interleave a cache mutation mid-fan-out.
10
+ */
11
+ export class AliasManager extends AdapterContextBase {
12
+ #aliases = new Map();
13
+ #aliasPatterns = new Set();
14
+ #aliasObjectsSubscribed = false;
15
+ #validateId;
16
+ /**
17
+ * @param ctx Shared adapter context providing live runtime state
18
+ * @param validateId Bound id validator from the adapter's Validator instance
19
+ */
20
+ constructor(ctx, validateId) {
21
+ super(ctx);
22
+ this.#validateId = validateId;
23
+ }
24
+ /**
25
+ * Whether the given source (real) state id currently feeds any alias.
26
+ *
27
+ * @param id the real source state id
28
+ */
29
+ hasSource(id) {
30
+ return this.#aliases.has(id);
31
+ }
32
+ /** Number of tracked source states. */
33
+ get size() {
34
+ return this.#aliases.size;
35
+ }
36
+ /**
37
+ * Whether the given subscription pattern is tracked.
38
+ *
39
+ * @param pattern the subscription pattern
40
+ */
41
+ hasPattern(pattern) {
42
+ return this.#aliasPatterns.has(pattern);
43
+ }
44
+ /**
45
+ * Track a subscription pattern.
46
+ *
47
+ * @param pattern the subscription pattern
48
+ */
49
+ addPattern(pattern) {
50
+ this.#aliasPatterns.add(pattern);
51
+ }
52
+ /**
53
+ * Stop tracking a subscription pattern.
54
+ *
55
+ * @param pattern the subscription pattern
56
+ */
57
+ deletePattern(pattern) {
58
+ this.#aliasPatterns.delete(pattern);
59
+ }
60
+ /**
61
+ * Whether `id` falls into any tracked alias pattern (wildcards via pattern2RegEx).
62
+ *
63
+ * @param id the id to test against the tracked patterns
64
+ */
65
+ matchesAnyPattern(id) {
66
+ for (const aliasPattern of this.#aliasPatterns) {
67
+ const testPattern = aliasPattern.slice(-1) === '*' ? new RegExp(tools.pattern2RegEx(aliasPattern)) : aliasPattern;
68
+ if ((typeof testPattern === 'string' && aliasPattern === id) ||
69
+ (testPattern instanceof RegExp && testPattern.test(id))) {
70
+ return true;
71
+ }
72
+ }
73
+ return false;
74
+ }
75
+ /**
76
+ * Reacts to a change of an `alias.*` object: re-points, updates, or removes the target across the
77
+ * tracked sources, and picks up a newly-appeared alias that falls into a tracked pattern.
78
+ * Live-iterates the cache while awaiting add/remove — the loop lives here, with the map, to
79
+ * preserve the original mutation-during-iteration semantics exactly.
80
+ *
81
+ * @param id the changed alias object id
82
+ * @param obj the new object (null/undefined if deleted)
83
+ */
84
+ async handleAliasObjectChange(id, obj) {
85
+ let isNewAlias = true;
86
+ for (const [sourceId, alias] of this.#aliases) {
87
+ const targetAlias = alias.targets.find(entry => entry.id === id);
88
+ if (targetAlias) {
89
+ isNewAlias = false;
90
+ if (obj?.common?.alias?.id) {
91
+ const newSourceId = typeof obj.common.alias.id.read === 'string' ? obj.common.alias.id.read : obj.common.alias.id;
92
+ if (newSourceId !== sourceId) {
93
+ await this.removeAliasSubscribe(sourceId, targetAlias);
94
+ try {
95
+ await this.addAliasSubscribe(obj, targetAlias.pattern);
96
+ }
97
+ catch (e) {
98
+ this.logger.error(`${this.namespaceLog} Could not add alias subscription: ${e.message}`);
99
+ }
100
+ }
101
+ else {
102
+ targetAlias.min = obj.common.min;
103
+ targetAlias.max = obj.common.max;
104
+ targetAlias.type = obj.common.type;
105
+ targetAlias.alias = deepClone(obj.common.alias);
106
+ }
107
+ }
108
+ else {
109
+ await this.removeAliasSubscribe(sourceId, targetAlias);
110
+ }
111
+ }
112
+ }
113
+ if (isNewAlias && obj && this.matchesAnyPattern(id)) {
114
+ try {
115
+ await this.addAliasSubscribe(obj, id);
116
+ }
117
+ catch (e) {
118
+ this.logger.warn(`${this.namespaceLog} Could not add alias subscription: ${e.message}`);
119
+ }
120
+ }
121
+ }
122
+ /**
123
+ * Removes every target subscribed under the given pattern, live-iterating the cache so a removal
124
+ * mutating the map mid-loop keeps the original semantics. Awaits each removal.
125
+ *
126
+ * @param pattern the subscription pattern being unsubscribed
127
+ */
128
+ async removeTargetsForPattern(pattern) {
129
+ const promises = new Array();
130
+ for (const [sourceId, alias] of this.#aliases) {
131
+ for (let i = alias.targets.length - 1; i >= 0; i--) {
132
+ if (alias.targets[i].pattern === pattern) {
133
+ promises.push(this.removeAliasSubscribe(sourceId, i));
134
+ }
135
+ }
136
+ }
137
+ await Promise.all(promises);
138
+ }
139
+ /**
140
+ * Synchronously computes the fan-out of a source (real) state change to its alias targets.
141
+ * Returns one `{ targetId, state }` per unique target. MUST NOT await — the caller relies on the
142
+ * cache not mutating between read and emit.
143
+ *
144
+ * @param sourceId the changed real state id
145
+ * @param state the new state value (or null on deletion)
146
+ */
147
+ resolveSourceChange(sourceId, state) {
148
+ const out = new Array();
149
+ const alias = this.#aliases.get(sourceId);
150
+ if (!alias) {
151
+ return out;
152
+ }
153
+ const uniqueTargets = new Set();
154
+ for (const target of alias.targets) {
155
+ const targetId = target.id;
156
+ if (uniqueTargets.has(targetId)) {
157
+ continue;
158
+ }
159
+ uniqueTargets.add(targetId);
160
+ const aState = state
161
+ ? tools.formatAliasValue({
162
+ sourceCommon: alias.source,
163
+ targetCommon: target,
164
+ state: deepClone(state),
165
+ logger: this.logger,
166
+ logNamespace: this.namespaceLog,
167
+ sourceId,
168
+ targetId,
169
+ })
170
+ : null;
171
+ if (aState || !state) {
172
+ out.push({ targetId, state: aState });
173
+ }
174
+ }
175
+ return out;
176
+ }
177
+ /** Subscribe the `alias.*` object range once (idempotent). */
178
+ ensureAliasObjectSubscription() {
179
+ if (!this.#aliasObjectsSubscribed) {
180
+ this.#aliasObjectsSubscribed = true;
181
+ this.objects.subscribe(`${ALIAS_STARTS_WITH}*`);
182
+ }
183
+ }
184
+ /** Drop the `alias.*` object subscription when no aliases remain. */
185
+ maybeDropAliasObjectSubscription() {
186
+ if (!this.#aliases.size && this.#aliasObjectsSubscribed) {
187
+ this.#aliasObjectsSubscribed = false;
188
+ this.objects.unsubscribe(`${ALIAS_STARTS_WITH}*`);
189
+ }
190
+ }
191
+ /**
192
+ * Register an alias target for its source state, subscribing the source state (and reading its
193
+ * metadata once). Preserves the create-before-await ordering and the post-await existence
194
+ * re-check that guard a concurrent removal.
195
+ *
196
+ * @param aliasObj the `alias.*` object being subscribed
197
+ * @param pattern the subscription pattern that pulled it in
198
+ */
199
+ async addAliasSubscribe(aliasObj, pattern) {
200
+ if (aliasObj.type !== 'state') {
201
+ return;
202
+ }
203
+ if (!aliasObj.common?.alias?.id) {
204
+ this.logger.warn(`${this.namespaceLog} Alias ${aliasObj._id} has no target 5`);
205
+ throw new Error(`Alias ${aliasObj._id} has no target`);
206
+ }
207
+ const sourceId = tools.isObject(aliasObj.common.alias.id)
208
+ ? aliasObj.common.alias.id.read
209
+ : aliasObj.common.alias.id;
210
+ try {
211
+ this.#validateId(sourceId, true, null);
212
+ }
213
+ catch (e) {
214
+ throw new Error(`Error validating alias id of ${aliasObj._id}: ${e.message}`);
215
+ }
216
+ const targetEntry = {
217
+ alias: deepClone(aliasObj.common.alias),
218
+ id: aliasObj._id,
219
+ pattern,
220
+ type: aliasObj.common.type,
221
+ max: aliasObj.common.max,
222
+ min: aliasObj.common.min,
223
+ unit: aliasObj.common.unit,
224
+ };
225
+ let aliasDetails;
226
+ if (!this.#aliases.has(sourceId)) {
227
+ aliasDetails = { targets: [] };
228
+ this.#aliases.set(sourceId, aliasDetails);
229
+ }
230
+ else {
231
+ aliasDetails = this.#aliases.get(sourceId);
232
+ }
233
+ if (!aliasDetails.source) {
234
+ await this.states.subscribe(sourceId);
235
+ const sourceObj = await this.objects.getObject(sourceId, { user: SYSTEM_ADMIN_USER });
236
+ if (sourceObj?.common && this.#aliases.has(sourceObj._id)) {
237
+ aliasDetails.source = {
238
+ min: sourceObj.common.min,
239
+ max: sourceObj.common.max,
240
+ type: sourceObj.common.type,
241
+ unit: sourceObj.common.unit,
242
+ };
243
+ }
244
+ }
245
+ aliasDetails.targets.push(targetEntry);
246
+ }
247
+ /**
248
+ * Remove one alias target from its source; when the source has no targets left, delete the entry
249
+ * and unsubscribe the source state.
250
+ *
251
+ * @param sourceId the real source state id
252
+ * @param aliasObjOrIdx the target entry or its index in the targets array
253
+ */
254
+ async removeAliasSubscribe(sourceId, aliasObjOrIdx) {
255
+ if (!this.#aliases.has(sourceId)) {
256
+ return;
257
+ }
258
+ const alias = this.#aliases.get(sourceId);
259
+ const pos = typeof aliasObjOrIdx === 'number' ? aliasObjOrIdx : alias.targets.indexOf(aliasObjOrIdx);
260
+ if (pos !== -1) {
261
+ alias.targets.splice(pos, 1);
262
+ if (!alias.targets.length) {
263
+ this.#aliases.delete(sourceId);
264
+ await this.states.unsubscribe(sourceId);
265
+ }
266
+ }
267
+ }
268
+ }
269
+ //# sourceMappingURL=AliasManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AliasManager.js","sourceRoot":"","sources":["../../../../../src/lib/adapter/managers/AliasManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,SAAS,MAAM,YAAY,CAAC;AAInC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAKlF;;;;;GAKG;AACH,MAAM,OAAO,YAAa,SAAQ,kBAAkB;IACvC,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC3C,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IAC5C,uBAAuB,GAAG,KAAK,CAAC;IACvB,WAAW,CAAa;IAEjC;;;OAGG;IACH,YAAY,GAAmB,EAAE,UAAsB;QACnD,KAAK,CAAC,GAAG,CAAC,CAAC;QACX,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,uCAAuC;IACvC,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,OAAe;QACtB,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,OAAe;QACtB,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,OAAe;QACzB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,EAAU;QACxB,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC7C,MAAM,WAAW,GACb,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YAClG,IACI,CAAC,OAAO,WAAW,KAAK,QAAQ,IAAI,YAAY,KAAK,EAAE,CAAC;gBACxD,CAAC,WAAW,YAAY,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EACzD,CAAC;gBACC,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,uBAAuB,CAAC,EAAU,EAAE,GAAuC;QAC7E,IAAI,UAAU,GAAG,IAAI,CAAC;QACtB,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACjE,IAAI,WAAW,EAAE,CAAC;gBACd,UAAU,GAAG,KAAK,CAAC;gBACnB,IAAI,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;oBACzB,MAAM,WAAW,GACb,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClG,IAAI,WAAW,KAAK,QAAQ,EAAE,CAAC;wBAC3B,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;wBACvD,IAAI,CAAC;4BACD,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;wBAC3D,CAAC;wBAAC,OAAO,CAAM,EAAE,CAAC;4BACd,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,YAAY,sCAAsC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;wBAC7F,CAAC;oBACL,CAAC;yBAAM,CAAC;wBACJ,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;wBACjC,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;wBACjC,WAAW,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;wBACnC,WAAW,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACpD,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACJ,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;gBAC3D,CAAC;YACL,CAAC;QACL,CAAC;QACD,IAAI,UAAU,IAAI,GAAG,IAAI,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC;gBACD,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,sCAAsC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5F,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,uBAAuB,CAAC,OAAe;QACzC,MAAM,QAAQ,GAAG,IAAI,KAAK,EAAiB,CAAC;QAC5C,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5C,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACjD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;oBACvC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC1D,CAAC;YACL,CAAC;QACL,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED;;;;;;;OAOG;IACH,mBAAmB,CACf,QAAgB,EAChB,KAAwC;QAExC,MAAM,GAAG,GAAG,IAAI,KAAK,EAAsD,CAAC;QAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACT,OAAO,GAAG,CAAC;QACf,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;YAC3B,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,SAAS;YACb,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK;gBAChB,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;oBACnB,YAAY,EAAE,KAAK,CAAC,MAAM;oBAC1B,YAAY,EAAE,MAAM;oBACpB,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC;oBACvB,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,YAAY,EAAE,IAAI,CAAC,YAAY;oBAC/B,QAAQ;oBACR,QAAQ;iBACX,CAAC;gBACJ,CAAC,CAAC,IAAI,CAAC;YACX,IAAI,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;gBACnB,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1C,CAAC;QACL,CAAC;QACD,OAAO,GAAG,CAAC;IACf,CAAC;IAED,8DAA8D;IAC9D,6BAA6B;QACzB,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAChC,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,iBAAiB,GAAG,CAAC,CAAC;QACpD,CAAC;IACL,CAAC;IAED,qEAAqE;IACrE,gCAAgC;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACtD,IAAI,CAAC,uBAAuB,GAAG,KAAK,CAAC;YACrC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,iBAAiB,GAAG,CAAC,CAAC;QACtD,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,iBAAiB,CAAC,QAA4B,EAAE,OAAe;QACjE,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC5B,OAAO;QACX,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,UAAU,QAAQ,CAAC,GAAG,kBAAkB,CAAC,CAAC;YAC/E,MAAM,IAAI,KAAK,CAAC,SAAS,QAAQ,CAAC,GAAG,gBAAgB,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI;YAC/B,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC;YACD,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,gCAAgC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,WAAW,GAAqB;YAClC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;YACvC,EAAE,EAAE,QAAQ,CAAC,GAAG;YAChB,OAAO;YACP,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI;YAC1B,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG;YACxB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG;YACxB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI;SAC7B,CAAC;QACF,IAAI,YAA0B,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,YAAY,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACJ,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACtC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC;YACtF,IAAI,SAAS,EAAE,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxD,YAAY,CAAC,MAAM,GAAG;oBAClB,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG;oBACzB,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG;oBACzB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI;oBAC3B,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI;iBAC9B,CAAC;YACN,CAAC;QACL,CAAC;QACD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,oBAAoB,CAAC,QAAgB,EAAE,aAAwC;QACjF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,OAAO;QACX,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACrG,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACb,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC/B,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC5C,CAAC;QACL,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,50 @@
1
+ import type { InternalGetCertificatesResult } from '../../_Types.js';
2
+ import type { AdapterContext } from '../../../lib/adapter/context.js';
3
+ import { AdapterContextBase } from '../../../lib/adapter/managers/AdapterContextBase.js';
4
+ /** ID of the object holding all configured certificates */
5
+ export declare const CERTIFICATES_OBJECT_ID = "system.certificates";
6
+ /** Fetches SSL certificates from `system.certificates`, resolving file-backed values to their contents. */
7
+ export declare class CertificateManager extends AdapterContextBase {
8
+ #private;
9
+ /**
10
+ * @param ctx Shared adapter context providing live runtime state
11
+ */
12
+ constructor(ctx: AdapterContext);
13
+ /**
14
+ * Tells whether a new version of the `system.certificates` object actually changes one of the
15
+ * certificates handed out by the last {@link getCertificates} call. Unrelated certificates being
16
+ * added, changed or removed are ignored, so that editing some other adapter's certificate does
17
+ * not restart this one.
18
+ *
19
+ * Compares the raw (unresolved) values: for a file-backed certificate that is the path, so
20
+ * repointing it to a different file counts as a change, while a change of the file content is
21
+ * left to the file watcher.
22
+ *
23
+ * @param obj the new `system.certificates` object, or null/undefined if it was deleted
24
+ */
25
+ hasRelevantChange(obj: ioBroker.OtherObject | null | undefined): boolean;
26
+ /**
27
+ * Forgets the certificates handed out by the last {@link getCertificates} call, so a subsequent
28
+ * change of `system.certificates` is no longer treated as relevant by {@link hasRelevantChange}.
29
+ * Used when the adapter stops watching its certificates.
30
+ */
31
+ stopWatching(): void;
32
+ /**
33
+ * Loads the named certificates from `system.certificates`. File-backed values (short strings that
34
+ * are existing paths) are read from disk and their paths collected in `certFilePaths` so the caller
35
+ * can watch them.
36
+ *
37
+ * @param names public/private/chained certificate names
38
+ * @param names.publicName Name of the public certificate
39
+ * @param names.privateName Name of the private key
40
+ * @param names.chainedName Name of the chained certificate
41
+ * @throws {Error} `ERROR_DB_CLOSED` when the objects database is not connected
42
+ * @throws {Error} `ERROR_NOT_FOUND` when the requested certificates are not configured
43
+ */
44
+ getCertificates(names: {
45
+ publicName?: string;
46
+ privateName?: string;
47
+ chainedName?: string;
48
+ }): Promise<InternalGetCertificatesResult>;
49
+ }
50
+ //# sourceMappingURL=CertificateManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CertificateManager.d.ts","sourceRoot":"","sources":["../../../../../src/lib/adapter/managers/CertificateManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAElF,2DAA2D;AAC3D,eAAO,MAAM,sBAAsB,wBAAwB,CAAC;AAE5D,2GAA2G;AAC3G,qBAAa,kBAAmB,SAAQ,kBAAkB;;IAQtD;;OAEG;gBACS,GAAG,EAAE,cAAc;IAI/B;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO;IAkBxE;;;;OAIG;IACH,YAAY,IAAI,IAAI;IAIpB;;;;;;;;;;;OAWG;IACG,eAAe,CAAC,KAAK,EAAE;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,6BAA6B,CAAC;CAyF7C"}
@@ -0,0 +1,142 @@
1
+ import fs from 'fs-extra';
2
+ import { tools } from '@iobroker/js-controller-common';
3
+ import { AdapterContextBase } from '../../../lib/adapter/managers/AdapterContextBase.js';
4
+ /** ID of the object holding all configured certificates */
5
+ export const CERTIFICATES_OBJECT_ID = 'system.certificates';
6
+ /** Fetches SSL certificates from `system.certificates`, resolving file-backed values to their contents. */
7
+ export class CertificateManager extends AdapterContextBase {
8
+ /**
9
+ * Raw (unresolved) values of the certificates handed out by the last {@link getCertificates} call,
10
+ * keyed by certificate name. Used to tell a relevant change of `system.certificates` from an
11
+ * unrelated one. `undefined` until certificates have been requested at least once.
12
+ */
13
+ #usedCertificates;
14
+ /**
15
+ * @param ctx Shared adapter context providing live runtime state
16
+ */
17
+ constructor(ctx) {
18
+ super(ctx);
19
+ }
20
+ /**
21
+ * Tells whether a new version of the `system.certificates` object actually changes one of the
22
+ * certificates handed out by the last {@link getCertificates} call. Unrelated certificates being
23
+ * added, changed or removed are ignored, so that editing some other adapter's certificate does
24
+ * not restart this one.
25
+ *
26
+ * Compares the raw (unresolved) values: for a file-backed certificate that is the path, so
27
+ * repointing it to a different file counts as a change, while a change of the file content is
28
+ * left to the file watcher.
29
+ *
30
+ * @param obj the new `system.certificates` object, or null/undefined if it was deleted
31
+ */
32
+ hasRelevantChange(obj) {
33
+ const usedCertificates = this.#usedCertificates;
34
+ if (!usedCertificates) {
35
+ // certificates were never requested, so nothing can have changed for us
36
+ return false;
37
+ }
38
+ const certificates = obj?.native?.certificates;
39
+ for (const [name, value] of usedCertificates) {
40
+ if (certificates?.[name] !== value) {
41
+ return true;
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ /**
47
+ * Forgets the certificates handed out by the last {@link getCertificates} call, so a subsequent
48
+ * change of `system.certificates` is no longer treated as relevant by {@link hasRelevantChange}.
49
+ * Used when the adapter stops watching its certificates.
50
+ */
51
+ stopWatching() {
52
+ this.#usedCertificates = undefined;
53
+ }
54
+ /**
55
+ * Loads the named certificates from `system.certificates`. File-backed values (short strings that
56
+ * are existing paths) are read from disk and their paths collected in `certFilePaths` so the caller
57
+ * can watch them.
58
+ *
59
+ * @param names public/private/chained certificate names
60
+ * @param names.publicName Name of the public certificate
61
+ * @param names.privateName Name of the private key
62
+ * @param names.chainedName Name of the chained certificate
63
+ * @throws {Error} `ERROR_DB_CLOSED` when the objects database is not connected
64
+ * @throws {Error} `ERROR_NOT_FOUND` when the requested certificates are not configured
65
+ */
66
+ async getCertificates(names) {
67
+ const { publicName, privateName, chainedName } = names;
68
+ const objects = this.objects;
69
+ let obj;
70
+ try {
71
+ obj = await objects.getObject(CERTIFICATES_OBJECT_ID);
72
+ }
73
+ catch {
74
+ // ignore
75
+ }
76
+ if (!obj?.native.certificates ||
77
+ !publicName ||
78
+ !privateName ||
79
+ !obj.native.certificates[publicName] ||
80
+ !obj.native.certificates[privateName] ||
81
+ (chainedName && !obj.native.certificates[chainedName])) {
82
+ this.logger.error(`${this.namespaceLog} Cannot configure secure web server, because no certificates found: ${publicName}, ${privateName}, ${chainedName}`);
83
+ if (publicName === 'defaultPublic' || privateName === 'defaultPrivate') {
84
+ this.logger.info(`${this.namespaceLog} Default certificates seem to be configured but missing. You can execute "iobroker cert create" in your shell to create these.`);
85
+ }
86
+ throw new Error(tools.ERRORS.ERROR_NOT_FOUND);
87
+ }
88
+ const certFilePaths = new Array();
89
+ let ca;
90
+ if (chainedName) {
91
+ const chained = this.#resolveCert(obj.native.certificates[chainedName], certFilePaths).split('-----END CERTIFICATE-----\r\n');
92
+ if (chained.join('').length >= 512) {
93
+ const caArr = new Array();
94
+ for (const cert of chained) {
95
+ if (cert.replace(/(\r\n|\r|\n)/g, '').trim()) {
96
+ caArr.push(`${cert}-----END CERTIFICATE-----\r\n`);
97
+ }
98
+ }
99
+ ca = caArr.join('');
100
+ }
101
+ }
102
+ const certs = {
103
+ key: this.#resolveCert(obj.native.certificates[privateName], certFilePaths),
104
+ cert: this.#resolveCert(obj.native.certificates[publicName], certFilePaths),
105
+ ca,
106
+ };
107
+ // remember the raw values, so a change of `system.certificates` can be told from an unrelated one
108
+ this.#usedCertificates = new Map();
109
+ for (const name of [publicName, privateName, chainedName]) {
110
+ if (name) {
111
+ this.#usedCertificates.set(name, obj.native.certificates[name]);
112
+ }
113
+ }
114
+ return { certs, useLetsEncrypt: obj.native.letsEncrypt, certFilePaths };
115
+ }
116
+ /**
117
+ * Returns the certificate content. When `value` is a short string that is an existing file path,
118
+ * reads the file, records the path in `certFilePaths` (deduped), and returns the file content.
119
+ * Otherwise returns `value` unchanged.
120
+ *
121
+ * @param value inline certificate or a path to one
122
+ * @param certFilePaths accumulator for file-backed paths (mutated)
123
+ */
124
+ #resolveCert(value, certFilePaths) {
125
+ if (typeof value === 'string') {
126
+ try {
127
+ if (value.length < 1024 && fs.existsSync(value)) {
128
+ const content = fs.readFileSync(value, 'utf8');
129
+ if (!certFilePaths.includes(value)) {
130
+ certFilePaths.push(value);
131
+ }
132
+ return content;
133
+ }
134
+ }
135
+ catch (e) {
136
+ this.logger.error(`${this.namespaceLog} Could not read certificate from file ${value}: ${e.message}`);
137
+ }
138
+ }
139
+ return value;
140
+ }
141
+ }
142
+ //# sourceMappingURL=CertificateManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CertificateManager.js","sourceRoot":"","sources":["../../../../../src/lib/adapter/managers/CertificateManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { InternalSendToHostOptions, InternalSendToOptions, NotificationOptions, SendToUserInterfaceClientOptions } from '../../_Types.js';
2
+ import type { AdapterContext } from '../../../lib/adapter/context.js';
3
+ import { AdapterContextBase } from '../../../lib/adapter/managers/AdapterContextBase.js';
4
+ /** Owns the adapter's outbound messaging and the pending-reply registry. */
5
+ export declare class MessagingManager extends AdapterContextBase {
6
+ #private;
7
+ /**
8
+ * @param ctx Shared adapter context providing live runtime state
9
+ */
10
+ constructor(ctx: AdapterContext);
11
+ /**
12
+ * Sends a message to another adapter instance.
13
+ *
14
+ * When `opts.expectReply` is true and the target is a specific instance (not broadcast),
15
+ * the returned promise resolves with the reply message when it arrives, or rejects with
16
+ * `Error('Timeout exceeded')` if `opts.options.timeout` elapses.
17
+ *
18
+ * @param opts Normalized send options
19
+ */
20
+ sendTo(opts: InternalSendToOptions): Promise<any>;
21
+ /**
22
+ * Sends a message to a host, or broadcasts to all hosts when `hostName` is `null`.
23
+ *
24
+ * When `opts.expectReply` is true and a specific host is targeted, the returned promise
25
+ * resolves with the reply message when it arrives, or rejects with `Error('Timeout exceeded')`
26
+ * if `opts.options.timeout` elapses. Broadcasts (hostName === null) resolve void.
27
+ *
28
+ * @param opts Normalized send options
29
+ */
30
+ sendToHost(opts: InternalSendToHostOptions): Promise<any>;
31
+ /**
32
+ * Resolves a pending reply promise for an acked messagebox message.
33
+ * Returns true if a pending entry was found and consumed.
34
+ *
35
+ * @param obj incoming message object from the messagebox
36
+ */
37
+ resolveCallback(obj: ioBroker.Message): boolean;
38
+ /**
39
+ * Rejects all pending reply promises and clears their timers (used on stop).
40
+ */
41
+ clearPendingCallbacks(): void;
42
+ /**
43
+ * Sends a message to a single UI client, or broadcasts to all connected UI clients when `clientId` is omitted.
44
+ *
45
+ * @param options clientId and data options
46
+ */
47
+ sendToUI(options: SendToUserInterfaceClientOptions): Promise<void>;
48
+ /**
49
+ * Sends an addNotification command to the host of this adapter instance.
50
+ *
51
+ * @param scope notification scope
52
+ * @param category notification category, or `null` to match by scope regex
53
+ * @param message notification message
54
+ * @param options additional notification options
55
+ */
56
+ registerNotification(scope: string, category: string | null, message: string, options?: NotificationOptions): Promise<void>;
57
+ }
58
+ //# sourceMappingURL=MessagingManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessagingManager.d.ts","sourceRoot":"","sources":["../../../../../src/lib/adapter/managers/MessagingManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EAEnB,gCAAgC,EACnC,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AAWlF,4EAA4E;AAC5E,qBAAa,gBAAiB,SAAQ,kBAAkB;;IAKpD;;OAEG;gBACS,GAAG,EAAE,cAAc;IAI/B;;;;;;;;OAQG;IACG,MAAM,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC;IA8IvD;;;;;;;;OAQG;IACG,UAAU,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,GAAG,CAAC;IA2C/D;;;;;OAKG;IACH,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO;IA0B/C;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAa7B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,gCAAgC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlE;;;;;;;OAOG;IACG,oBAAoB,CACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,mBAAmB,GAC9B,OAAO,CAAC,IAAI,CAAC;CAiBnB"}