@camstack/addon-provider-bosch 0.1.35 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/{account-integration-offline-Bt3N9Zdk.mjs → account-integration-offline-9ooJuNrN.mjs} +1 -1
- package/dist/{account-integration-offline-De_H_EsP.js → account-integration-offline-Bnm17sAE.js} +2 -2
- package/dist/{dist-CyZFf49n.js → bosch-instances-BIvOtuzj.mjs} +33618 -31096
- package/dist/{dist-CkMPcvma.mjs → bosch-instances-CXmuRkef.js} +34363 -31255
- package/dist/home-connect/addon.js +348 -278
- package/dist/home-connect/addon.mjs +174 -104
- package/dist/homecom/addon.js +246 -117
- package/dist/homecom/addon.mjs +164 -35
- package/dist/shc/addon.js +216 -93
- package/dist/shc/addon.mjs +129 -6
- package/package.json +14 -2
package/dist/homecom/addon.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_account_integration_offline = require("../account-integration-offline-
|
|
2
|
+
const require_bosch_instances = require("../bosch-instances-CXmuRkef.js");
|
|
3
|
+
const require_account_integration_offline = require("../account-integration-offline-Bnm17sAE.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
//#region src/homecom/config.ts
|
|
6
6
|
var HOMECOM_BRANDS = ["bosch", "buderus"];
|
|
7
|
-
var HomeComBrandSchema =
|
|
7
|
+
var HomeComBrandSchema = require_bosch_instances._enum(HOMECOM_BRANDS);
|
|
8
8
|
var HOMECOM_REGIONS = ["eu", "us"];
|
|
9
|
-
var HomeComRegionSchema =
|
|
10
|
-
var homeComConfigSchema =
|
|
9
|
+
var HomeComRegionSchema = require_bosch_instances._enum(HOMECOM_REGIONS);
|
|
10
|
+
var homeComConfigSchema = require_bosch_instances.object({
|
|
11
11
|
/** Account email; filled by the sign-in, informational only. */
|
|
12
|
-
username:
|
|
13
|
-
token:
|
|
14
|
-
refresh:
|
|
12
|
+
username: require_bosch_instances.string().optional().describe("HomeCom / PointT account email").meta({ secret: true }),
|
|
13
|
+
token: require_bosch_instances.string().min(1).describe("OAuth access token").meta({ secret: true }),
|
|
14
|
+
refresh: require_bosch_instances.string().min(1).describe("OAuth refresh token").meta({ secret: true }),
|
|
15
15
|
brand: HomeComBrandSchema.default("bosch"),
|
|
16
16
|
region: HomeComRegionSchema.default("eu"),
|
|
17
17
|
/**
|
|
18
18
|
* The gateway this integration controls. Chosen from the account list after
|
|
19
19
|
* sign-in. A blank value is the same as absent: the id is not known yet.
|
|
20
20
|
*/
|
|
21
|
-
gatewayId:
|
|
21
|
+
gatewayId: require_bosch_instances.string().trim().optional().transform((value) => value === void 0 || value.length === 0 ? void 0 : value),
|
|
22
22
|
/** Shown on the sign-in field. Not a credential. */
|
|
23
|
-
accountLabel:
|
|
23
|
+
accountLabel: require_bosch_instances.string().optional(),
|
|
24
24
|
/** How many gateways the last sign-in listed. */
|
|
25
|
-
gatewayCount:
|
|
25
|
+
gatewayCount: require_bosch_instances.number().optional()
|
|
26
26
|
});
|
|
27
27
|
function connectionFromSettings(settings) {
|
|
28
28
|
const parsed = homeComConfigSchema.safeParse(settings);
|
|
@@ -42,11 +42,6 @@ var HOMECOM_GATEWAYS_PATH = "/pointt-api/api/v1/gateways/";
|
|
|
42
42
|
function homeComApiBase(_region) {
|
|
43
43
|
return HOMECOM_POINTT_API_ORIGIN;
|
|
44
44
|
}
|
|
45
|
-
var HOMECOM_SECRET_KEYS = [
|
|
46
|
-
"username",
|
|
47
|
-
"token",
|
|
48
|
-
"refresh"
|
|
49
|
-
];
|
|
50
45
|
var HIDDEN_UNTIL_ADVANCED = {
|
|
51
46
|
field: "__hidden__",
|
|
52
47
|
equals: "yes"
|
|
@@ -187,35 +182,35 @@ function buildHomeComFormSchema() {
|
|
|
187
182
|
}
|
|
188
183
|
//#endregion
|
|
189
184
|
//#region src/homecom/custom-actions.ts
|
|
190
|
-
var gatewayChoice =
|
|
191
|
-
value:
|
|
192
|
-
label:
|
|
185
|
+
var gatewayChoice = require_bosch_instances.object({
|
|
186
|
+
value: require_bosch_instances.string(),
|
|
187
|
+
label: require_bosch_instances.string(),
|
|
193
188
|
brand: HomeComBrandSchema,
|
|
194
189
|
region: HomeComRegionSchema
|
|
195
190
|
});
|
|
196
|
-
var homeComActions =
|
|
197
|
-
beginSignIn:
|
|
198
|
-
attemptId:
|
|
199
|
-
authorizeUrl:
|
|
200
|
-
summary:
|
|
191
|
+
var homeComActions = require_bosch_instances.defineCustomActions({
|
|
192
|
+
beginSignIn: require_bosch_instances.customAction(require_bosch_instances.object({}), require_bosch_instances.object({
|
|
193
|
+
attemptId: require_bosch_instances.string().min(1),
|
|
194
|
+
authorizeUrl: require_bosch_instances.string().min(1),
|
|
195
|
+
summary: require_bosch_instances.string()
|
|
201
196
|
}), {
|
|
202
197
|
kind: "mutation",
|
|
203
198
|
auth: "admin"
|
|
204
199
|
}),
|
|
205
|
-
finishSignIn:
|
|
206
|
-
attemptId:
|
|
207
|
-
callback:
|
|
208
|
-
}),
|
|
209
|
-
token:
|
|
210
|
-
refresh:
|
|
211
|
-
username:
|
|
212
|
-
accountLabel:
|
|
213
|
-
gatewayCount:
|
|
214
|
-
summary:
|
|
215
|
-
gatewayId:
|
|
200
|
+
finishSignIn: require_bosch_instances.customAction(require_bosch_instances.object({
|
|
201
|
+
attemptId: require_bosch_instances.string().min(1),
|
|
202
|
+
callback: require_bosch_instances.string().min(1)
|
|
203
|
+
}), require_bosch_instances.object({
|
|
204
|
+
token: require_bosch_instances.string().min(1).meta({ secret: true }),
|
|
205
|
+
refresh: require_bosch_instances.string().min(1).meta({ secret: true }),
|
|
206
|
+
username: require_bosch_instances.string().meta({ secret: true }),
|
|
207
|
+
accountLabel: require_bosch_instances.string(),
|
|
208
|
+
gatewayCount: require_bosch_instances.number(),
|
|
209
|
+
summary: require_bosch_instances.string(),
|
|
210
|
+
gatewayId: require_bosch_instances.string().optional(),
|
|
216
211
|
brand: HomeComBrandSchema.optional(),
|
|
217
212
|
region: HomeComRegionSchema.optional(),
|
|
218
|
-
choices:
|
|
213
|
+
choices: require_bosch_instances.array(gatewayChoice).optional()
|
|
219
214
|
}), {
|
|
220
215
|
kind: "mutation",
|
|
221
216
|
auth: "admin"
|
|
@@ -225,25 +220,25 @@ var homeComActions = require_dist.defineCustomActions({
|
|
|
225
220
|
* app-scheme redirect and finished the exchange, then the same fields `finishSignIn` returns.
|
|
226
221
|
* Claimed once. A failed exchange answers with its operator-facing message as an error.
|
|
227
222
|
*/
|
|
228
|
-
claimSignIn:
|
|
229
|
-
pending:
|
|
230
|
-
token:
|
|
231
|
-
refresh:
|
|
232
|
-
username:
|
|
233
|
-
accountLabel:
|
|
234
|
-
gatewayCount:
|
|
235
|
-
summary:
|
|
236
|
-
gatewayId:
|
|
223
|
+
claimSignIn: require_bosch_instances.customAction(require_bosch_instances.object({ attemptId: require_bosch_instances.string().min(1) }), require_bosch_instances.object({
|
|
224
|
+
pending: require_bosch_instances.boolean(),
|
|
225
|
+
token: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
226
|
+
refresh: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
227
|
+
username: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
228
|
+
accountLabel: require_bosch_instances.string().optional(),
|
|
229
|
+
gatewayCount: require_bosch_instances.number().optional(),
|
|
230
|
+
summary: require_bosch_instances.string().optional(),
|
|
231
|
+
gatewayId: require_bosch_instances.string().optional(),
|
|
237
232
|
brand: HomeComBrandSchema.optional(),
|
|
238
233
|
region: HomeComRegionSchema.optional(),
|
|
239
|
-
choices:
|
|
234
|
+
choices: require_bosch_instances.array(gatewayChoice).optional()
|
|
240
235
|
}), {
|
|
241
236
|
kind: "mutation",
|
|
242
237
|
auth: "admin"
|
|
243
238
|
}),
|
|
244
|
-
signOut:
|
|
245
|
-
signedOut:
|
|
246
|
-
summary:
|
|
239
|
+
signOut: require_bosch_instances.customAction(require_bosch_instances.object({}), require_bosch_instances.object({
|
|
240
|
+
signedOut: require_bosch_instances.literal(true),
|
|
241
|
+
summary: require_bosch_instances.string()
|
|
247
242
|
}), {
|
|
248
243
|
kind: "mutation",
|
|
249
244
|
auth: "admin"
|
|
@@ -1263,41 +1258,27 @@ function beginHomeComProxiedSignIn(deps) {
|
|
|
1263
1258
|
}
|
|
1264
1259
|
//#endregion
|
|
1265
1260
|
//#region src/homecom/homecom-token-persist.ts
|
|
1266
|
-
function unreadable(value) {
|
|
1267
|
-
return require_dist.isSecretMarker(value) || require_dist.isSecretMarkerLike(value);
|
|
1268
|
-
}
|
|
1269
1261
|
/**
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
* addon could not read, so the write would only fail.
|
|
1262
|
+
* Patch the integration's record, one write at a time per integration. Refuses (and says so,
|
|
1263
|
+
* without values) when the record's secrets cannot be read right now: the write would replace a
|
|
1264
|
+
* secret the addon cannot see.
|
|
1274
1265
|
*/
|
|
1275
1266
|
function buildSerialPatcher(deps) {
|
|
1276
1267
|
const tails = /* @__PURE__ */ new Map();
|
|
1277
1268
|
return (integrationId, patch) => {
|
|
1278
1269
|
const run = async () => {
|
|
1279
1270
|
try {
|
|
1280
|
-
const stored = await deps.
|
|
1281
|
-
|
|
1282
|
-
if (locked
|
|
1283
|
-
deps.logger.warn(`HomeCom not persisting ${deps.what} — stored secrets are locked`, {
|
|
1284
|
-
tags: { integrationId },
|
|
1285
|
-
meta: { locked }
|
|
1286
|
-
});
|
|
1271
|
+
const stored = await deps.read(integrationId);
|
|
1272
|
+
if (stored === null) return;
|
|
1273
|
+
if (stored.locked) {
|
|
1274
|
+
deps.logger.warn(`HomeCom not persisting ${deps.what} — stored secrets are locked`, { tags: { integrationId } });
|
|
1287
1275
|
return;
|
|
1288
1276
|
}
|
|
1289
|
-
await deps.
|
|
1290
|
-
id: integrationId,
|
|
1291
|
-
settings: {
|
|
1292
|
-
...stored,
|
|
1293
|
-
...patch
|
|
1294
|
-
},
|
|
1295
|
-
secretKeys: [...HOMECOM_SECRET_KEYS]
|
|
1296
|
-
});
|
|
1277
|
+
await deps.patch(integrationId, patch);
|
|
1297
1278
|
} catch (err) {
|
|
1298
1279
|
deps.logger.warn(`HomeCom failed to persist ${deps.what}`, {
|
|
1299
1280
|
tags: { integrationId },
|
|
1300
|
-
meta: { error:
|
|
1281
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
1301
1282
|
});
|
|
1302
1283
|
}
|
|
1303
1284
|
};
|
|
@@ -1330,7 +1311,7 @@ function buildHomeComGatewayPersister(deps) {
|
|
|
1330
1311
|
function buildHomeComCandidates(input) {
|
|
1331
1312
|
const out = [];
|
|
1332
1313
|
for (const dev of input.devices) {
|
|
1333
|
-
const type = dev.kind === "heating-circuit" ?
|
|
1314
|
+
const type = dev.kind === "heating-circuit" ? require_bosch_instances.DeviceType.Climate : require_bosch_instances.DeviceType.WaterHeater;
|
|
1334
1315
|
const caps = dev.kind === "heating-circuit" ? ["climate-control"] : ["water-heater"];
|
|
1335
1316
|
const adoptedId = input.adopted.get(dev.nativeId) ?? null;
|
|
1336
1317
|
out.push({
|
|
@@ -1401,7 +1382,7 @@ function buildHomeComAdoptionProvider(deps) {
|
|
|
1401
1382
|
lastDiscoveryAt: null,
|
|
1402
1383
|
candidateCount: 0,
|
|
1403
1384
|
adoptedCount: 0,
|
|
1404
|
-
lastError:
|
|
1385
|
+
lastError: require_bosch_instances.errMsg(err)
|
|
1405
1386
|
};
|
|
1406
1387
|
}
|
|
1407
1388
|
},
|
|
@@ -1451,7 +1432,7 @@ function buildHomeComAdoptionProvider(deps) {
|
|
|
1451
1432
|
logger.warn("homecom adopt failed", { meta: {
|
|
1452
1433
|
nativeId,
|
|
1453
1434
|
integrationId,
|
|
1454
|
-
error:
|
|
1435
|
+
error: require_bosch_instances.errMsg(err)
|
|
1455
1436
|
} });
|
|
1456
1437
|
failures++;
|
|
1457
1438
|
}
|
|
@@ -1574,7 +1555,7 @@ var HomeComIntegrationManager = class {
|
|
|
1574
1555
|
} catch (err) {
|
|
1575
1556
|
this.#logger.warn("HomeCom could not store the rotated tokens", {
|
|
1576
1557
|
tags: { integrationId: this.#id },
|
|
1577
|
-
meta: { error:
|
|
1558
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
1578
1559
|
});
|
|
1579
1560
|
}
|
|
1580
1561
|
};
|
|
@@ -1630,7 +1611,7 @@ var HomeComIntegrationManager = class {
|
|
|
1630
1611
|
}, this.#pollIntervalMs);
|
|
1631
1612
|
} catch (err) {
|
|
1632
1613
|
this.#status = "error";
|
|
1633
|
-
this.#error = err instanceof HomeComAuthError ? "authentication failed — sign in again" :
|
|
1614
|
+
this.#error = err instanceof HomeComAuthError ? "authentication failed — sign in again" : require_bosch_instances.errMsg(err);
|
|
1634
1615
|
this.#client = null;
|
|
1635
1616
|
this.#surfaceSink.set(this.#id, null);
|
|
1636
1617
|
this.#onDisconnected(this.#id);
|
|
@@ -1664,7 +1645,7 @@ var HomeComIntegrationManager = class {
|
|
|
1664
1645
|
} catch (err) {
|
|
1665
1646
|
this.#logger.warn("HomeCom poll failed", { meta: {
|
|
1666
1647
|
integrationId: this.#id,
|
|
1667
|
-
error:
|
|
1648
|
+
error: require_bosch_instances.errMsg(err)
|
|
1668
1649
|
} });
|
|
1669
1650
|
}
|
|
1670
1651
|
}
|
|
@@ -1739,7 +1720,7 @@ var HomeComClientRegistry = class {
|
|
|
1739
1720
|
} catch (err) {
|
|
1740
1721
|
this.#logger.warn("HomeComClientRegistry: applyConnection failed", { meta: {
|
|
1741
1722
|
integrationId,
|
|
1742
|
-
error:
|
|
1723
|
+
error: require_bosch_instances.errMsg(err)
|
|
1743
1724
|
} });
|
|
1744
1725
|
}
|
|
1745
1726
|
return;
|
|
@@ -1763,7 +1744,7 @@ var HomeComClientRegistry = class {
|
|
|
1763
1744
|
} catch (err) {
|
|
1764
1745
|
this.#logger.warn("HomeComClientRegistry: manager start failed", { meta: {
|
|
1765
1746
|
integrationId,
|
|
1766
|
-
error:
|
|
1747
|
+
error: require_bosch_instances.errMsg(err)
|
|
1767
1748
|
} });
|
|
1768
1749
|
}
|
|
1769
1750
|
}
|
|
@@ -1776,7 +1757,7 @@ var HomeComClientRegistry = class {
|
|
|
1776
1757
|
} catch (err) {
|
|
1777
1758
|
this.#logger.warn("HomeComClientRegistry: remove stop failed", { meta: {
|
|
1778
1759
|
integrationId,
|
|
1779
|
-
error:
|
|
1760
|
+
error: require_bosch_instances.errMsg(err)
|
|
1780
1761
|
} });
|
|
1781
1762
|
}
|
|
1782
1763
|
}
|
|
@@ -1789,7 +1770,7 @@ var HomeComClientRegistry = class {
|
|
|
1789
1770
|
} catch (err) {
|
|
1790
1771
|
this.#logger.warn("HomeComClientRegistry: shutdown stop failed", { meta: {
|
|
1791
1772
|
integrationId: id,
|
|
1792
|
-
error:
|
|
1773
|
+
error: require_bosch_instances.errMsg(err)
|
|
1793
1774
|
} });
|
|
1794
1775
|
}
|
|
1795
1776
|
this.#entries.clear();
|
|
@@ -1867,7 +1848,7 @@ function buildHomeComConnectionTestProvider(deps) {
|
|
|
1867
1848
|
outcome: "rejected",
|
|
1868
1849
|
error: "HomeCom refused the access token — sign in again to get a fresh one."
|
|
1869
1850
|
};
|
|
1870
|
-
logger.warn("HomeCom connection test inconclusive", { meta: { error:
|
|
1851
|
+
logger.warn("HomeCom connection test inconclusive", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
1871
1852
|
return {
|
|
1872
1853
|
outcome: "inconclusive",
|
|
1873
1854
|
error: "Could not reach the HomeCom cloud API."
|
|
@@ -1877,13 +1858,141 @@ function buildHomeComConnectionTestProvider(deps) {
|
|
|
1877
1858
|
};
|
|
1878
1859
|
}
|
|
1879
1860
|
//#endregion
|
|
1861
|
+
//#region src/homecom/homecom-instances.ts
|
|
1862
|
+
/**
|
|
1863
|
+
* HomeCom integrations as `integration-instances` (planning#416, D985, D1007): one `connections`
|
|
1864
|
+
* record per account under the `integrations` registry id. The body IS the account (the account
|
|
1865
|
+
* email and the OAuth tokens in the keychain; brand, region, the chosen gateway and the
|
|
1866
|
+
* signed-in label in the open), so the form the instances page edits is the stored shape.
|
|
1867
|
+
*/
|
|
1868
|
+
var homeComConnectionsEntryKind = require_bosch_instances.defineEntryKind("connections", {
|
|
1869
|
+
title: "HomeCom accounts",
|
|
1870
|
+
schema: require_bosch_instances.entryBody({
|
|
1871
|
+
username: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
1872
|
+
token: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
1873
|
+
refresh: require_bosch_instances.string().optional().meta({ secret: true }),
|
|
1874
|
+
brand: HomeComBrandSchema.optional(),
|
|
1875
|
+
region: HomeComRegionSchema.optional(),
|
|
1876
|
+
gatewayId: require_bosch_instances.string().optional(),
|
|
1877
|
+
accountLabel: require_bosch_instances.string().optional(),
|
|
1878
|
+
gatewayCount: require_bosch_instances.number().optional()
|
|
1879
|
+
}),
|
|
1880
|
+
writeTrigger: "an operator signs in, edits or removes a HomeCom account, or a connection stores a rotated token or its gateway"
|
|
1881
|
+
});
|
|
1882
|
+
/** Every kind this addon declares, keyed by its name. */
|
|
1883
|
+
var homeComRecordKinds = { connections: homeComConnectionsEntryKind };
|
|
1884
|
+
var LEGACY_KEYS = [
|
|
1885
|
+
"username",
|
|
1886
|
+
"token",
|
|
1887
|
+
"refresh",
|
|
1888
|
+
"brand",
|
|
1889
|
+
"region",
|
|
1890
|
+
"gatewayId",
|
|
1891
|
+
"accountLabel",
|
|
1892
|
+
"gatewayCount"
|
|
1893
|
+
];
|
|
1894
|
+
var SECRET_KEYS = [
|
|
1895
|
+
"username",
|
|
1896
|
+
"token",
|
|
1897
|
+
"refresh"
|
|
1898
|
+
];
|
|
1899
|
+
function text(value) {
|
|
1900
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
1901
|
+
}
|
|
1902
|
+
/** The record body of one account, from its legacy rows (secrets resolved). */
|
|
1903
|
+
function homeComBodyFromRows(values, log, integration) {
|
|
1904
|
+
const dropped = Object.keys(values).filter((key) => !LEGACY_KEYS.includes(key));
|
|
1905
|
+
if (dropped.length > 0) log.warn(`integration '${integration.id}': legacy settings nothing reads any more are dropped: ${dropped.join(", ")}`);
|
|
1906
|
+
const username = text(values["username"]);
|
|
1907
|
+
const token = text(values["token"]);
|
|
1908
|
+
const refresh = text(values["refresh"]);
|
|
1909
|
+
const brand = HomeComBrandSchema.safeParse(values["brand"]);
|
|
1910
|
+
const region = HomeComRegionSchema.safeParse(values["region"]);
|
|
1911
|
+
const gatewayId = text(values["gatewayId"])?.trim();
|
|
1912
|
+
const accountLabel = text(values["accountLabel"]);
|
|
1913
|
+
const count = values["gatewayCount"];
|
|
1914
|
+
return {
|
|
1915
|
+
name: integration.name,
|
|
1916
|
+
...username !== void 0 ? { username } : {},
|
|
1917
|
+
...token !== void 0 ? { token } : {},
|
|
1918
|
+
...refresh !== void 0 ? { refresh } : {},
|
|
1919
|
+
...brand.success ? { brand: brand.data } : {},
|
|
1920
|
+
...region.success ? { region: region.data } : {},
|
|
1921
|
+
...gatewayId !== void 0 && gatewayId.length > 0 ? { gatewayId } : {},
|
|
1922
|
+
...accountLabel !== void 0 ? { accountLabel } : {},
|
|
1923
|
+
...typeof count === "number" && Number.isFinite(count) ? { gatewayCount: count } : {}
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1926
|
+
/** The whole `bosch-homecom` catalogue (D987): offered to the engine at `onInitialize`. */
|
|
1927
|
+
var HOMECOM_MIGRATIONS = [require_bosch_instances.boschRowsMigration({
|
|
1928
|
+
addonId: "bosch-homecom",
|
|
1929
|
+
id: "bosch-homecom/2026-11-05-integration-rows-to-record",
|
|
1930
|
+
description: "Move every HomeCom account into a typed instance record keyed by its registry id, then clear the legacy integration settings rows and their keychain values",
|
|
1931
|
+
fixtureMark: "a legacy setting key the migration does not know",
|
|
1932
|
+
kind: homeComConnectionsEntryKind,
|
|
1933
|
+
bodyFrom: homeComBodyFromRows
|
|
1934
|
+
})];
|
|
1935
|
+
function homeComRowsPorts(deps) {
|
|
1936
|
+
return require_bosch_instances.boschRowsPorts({
|
|
1937
|
+
...deps,
|
|
1938
|
+
kind: homeComConnectionsEntryKind
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
async function homeComStoredOf(instances, id) {
|
|
1942
|
+
const read = await instances.readResolved(id);
|
|
1943
|
+
if (read === null) return null;
|
|
1944
|
+
return {
|
|
1945
|
+
settings: { ...read.body },
|
|
1946
|
+
locked: read.secrets === "unavailable"
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
/**
|
|
1950
|
+
* The live account of one integration, read from its record. null while it is not signed in; a
|
|
1951
|
+
* locked keychain throws so the caller keeps the client it has instead of reconfiguring it
|
|
1952
|
+
* without its tokens (D49).
|
|
1953
|
+
*/
|
|
1954
|
+
async function homeComConnectionOf(instances, id) {
|
|
1955
|
+
const stored = await homeComStoredOf(instances, id);
|
|
1956
|
+
if (stored === null) return null;
|
|
1957
|
+
if (stored.locked) throw new Error("the keychain is locked, the saved HomeCom tokens cannot be read");
|
|
1958
|
+
return connectionFromSettings(stored.settings);
|
|
1959
|
+
}
|
|
1960
|
+
function buildHomeComInstances(records, deps) {
|
|
1961
|
+
const handle = records.kind(homeComConnectionsEntryKind);
|
|
1962
|
+
const instances = new require_bosch_instances.RecordIntegrationInstances(records, homeComConnectionsEntryKind, {
|
|
1963
|
+
description: {
|
|
1964
|
+
role: "devices",
|
|
1965
|
+
instanceMode: "multiple",
|
|
1966
|
+
kind: "account",
|
|
1967
|
+
canTest: true
|
|
1968
|
+
},
|
|
1969
|
+
formSchema: () => buildHomeComFormSchema(),
|
|
1970
|
+
initialBody: (name) => ({ name }),
|
|
1971
|
+
configured: (body) => connectionFromSettings(body) !== null,
|
|
1972
|
+
onChanged: async (_id, change) => {
|
|
1973
|
+
if (change !== "deleted") await deps.onChanged();
|
|
1974
|
+
},
|
|
1975
|
+
test: (input) => require_bosch_instances.testBoschInstance({
|
|
1976
|
+
...input,
|
|
1977
|
+
tester: deps.tester,
|
|
1978
|
+
handle,
|
|
1979
|
+
secretKeys: SECRET_KEYS
|
|
1980
|
+
})
|
|
1981
|
+
});
|
|
1982
|
+
return {
|
|
1983
|
+
instances,
|
|
1984
|
+
handle,
|
|
1985
|
+
provider: require_bosch_instances.keepBodyKeys(instances.toProvider(), new Set(Object.keys(homeComConnectionsEntryKind.schema.shape)))
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
//#endregion
|
|
1880
1989
|
//#region src/homecom/devices/homecom-climate-device.ts
|
|
1881
|
-
var homeComClimateSchema =
|
|
1882
|
-
nativeId:
|
|
1883
|
-
brokerId:
|
|
1884
|
-
circuitId:
|
|
1885
|
-
system:
|
|
1886
|
-
integrationId:
|
|
1990
|
+
var homeComClimateSchema = require_bosch_instances.object({
|
|
1991
|
+
nativeId: require_bosch_instances.string().min(1),
|
|
1992
|
+
brokerId: require_bosch_instances.string().min(1),
|
|
1993
|
+
circuitId: require_bosch_instances.string().min(1),
|
|
1994
|
+
system: require_bosch_instances.literal("homecom").optional(),
|
|
1995
|
+
integrationId: require_bosch_instances.string().optional()
|
|
1887
1996
|
});
|
|
1888
1997
|
var CLIMATE_CAP = "climate-control";
|
|
1889
1998
|
var COLD_START$1 = {
|
|
@@ -1903,7 +2012,7 @@ var COLD_START$1 = {
|
|
|
1903
2012
|
swingHorizontal: null,
|
|
1904
2013
|
lastFetchedAt: 0
|
|
1905
2014
|
};
|
|
1906
|
-
var HomeComClimateDevice = class extends
|
|
2015
|
+
var HomeComClimateDevice = class extends require_bosch_instances.BaseDevice {
|
|
1907
2016
|
features = [];
|
|
1908
2017
|
#brokerId;
|
|
1909
2018
|
#circuitId;
|
|
@@ -1941,7 +2050,7 @@ var HomeComClimateDevice = class extends require_dist.BaseDevice {
|
|
|
1941
2050
|
return client;
|
|
1942
2051
|
}
|
|
1943
2052
|
registerClimateCap() {
|
|
1944
|
-
this.ctx.registerNativeCap(
|
|
2053
|
+
this.ctx.registerNativeCap(require_bosch_instances.climateControlCapability, {
|
|
1945
2054
|
getStatus: async () => {
|
|
1946
2055
|
this.refreshFromSnapshot();
|
|
1947
2056
|
return this.runtimeState.getCapState(CLIMATE_CAP) ?? COLD_START$1;
|
|
@@ -1989,11 +2098,11 @@ function hvacModeToHomeCom(mode) {
|
|
|
1989
2098
|
}
|
|
1990
2099
|
//#endregion
|
|
1991
2100
|
//#region src/homecom/devices/homecom-water-heater-device.ts
|
|
1992
|
-
var homeComWaterHeaterSchema =
|
|
1993
|
-
nativeId:
|
|
1994
|
-
brokerId:
|
|
1995
|
-
system:
|
|
1996
|
-
integrationId:
|
|
2101
|
+
var homeComWaterHeaterSchema = require_bosch_instances.object({
|
|
2102
|
+
nativeId: require_bosch_instances.string().min(1),
|
|
2103
|
+
brokerId: require_bosch_instances.string().min(1),
|
|
2104
|
+
system: require_bosch_instances.literal("homecom").optional(),
|
|
2105
|
+
integrationId: require_bosch_instances.string().optional()
|
|
1997
2106
|
});
|
|
1998
2107
|
var WH_CAP = "water-heater";
|
|
1999
2108
|
var COLD_START = {
|
|
@@ -2006,7 +2115,7 @@ var COLD_START = {
|
|
|
2006
2115
|
maxTemp: null,
|
|
2007
2116
|
lastChangedAt: 0
|
|
2008
2117
|
};
|
|
2009
|
-
var HomeComWaterHeaterDevice = class extends
|
|
2118
|
+
var HomeComWaterHeaterDevice = class extends require_bosch_instances.BaseDevice {
|
|
2010
2119
|
features = [];
|
|
2011
2120
|
#brokerId;
|
|
2012
2121
|
constructor(ctx) {
|
|
@@ -2042,7 +2151,7 @@ var HomeComWaterHeaterDevice = class extends require_dist.BaseDevice {
|
|
|
2042
2151
|
return client;
|
|
2043
2152
|
}
|
|
2044
2153
|
registerWaterHeaterCap() {
|
|
2045
|
-
this.ctx.registerNativeCap(
|
|
2154
|
+
this.ctx.registerNativeCap(require_bosch_instances.waterHeaterCapability, {
|
|
2046
2155
|
getStatus: async () => {
|
|
2047
2156
|
this.refreshFromSnapshot();
|
|
2048
2157
|
return this.runtimeState.getCapState(WH_CAP) ?? COLD_START;
|
|
@@ -2063,14 +2172,15 @@ var HomeComWaterHeaterDevice = class extends require_dist.BaseDevice {
|
|
|
2063
2172
|
};
|
|
2064
2173
|
//#endregion
|
|
2065
2174
|
//#region src/homecom/addon.ts
|
|
2066
|
-
var BoschHomeComProviderAddon = class extends
|
|
2175
|
+
var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDeviceProvider {
|
|
2067
2176
|
addonId = "bosch-homecom";
|
|
2068
2177
|
providerName = "Bosch HomeCom";
|
|
2069
2178
|
deviceClasses = {
|
|
2070
|
-
[
|
|
2071
|
-
[
|
|
2179
|
+
[require_bosch_instances.DeviceType.Climate]: HomeComClimateDevice,
|
|
2180
|
+
[require_bosch_instances.DeviceType.WaterHeater]: HomeComWaterHeaterDevice
|
|
2072
2181
|
};
|
|
2073
2182
|
clients = null;
|
|
2183
|
+
instances = null;
|
|
2074
2184
|
loginProxy = null;
|
|
2075
2185
|
loginPlane = null;
|
|
2076
2186
|
constructor() {
|
|
@@ -2078,10 +2188,23 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2078
2188
|
}
|
|
2079
2189
|
async onInitialize() {
|
|
2080
2190
|
const regs = this.providerRegistrationsFromSuper(await super.onInitialize());
|
|
2191
|
+
const records = this.ctx.records;
|
|
2192
|
+
if (records === void 0) throw new Error("bosch-homecom: ctx.records is required (hub-only addon)");
|
|
2193
|
+
await records.declare(homeComRecordKinds);
|
|
2194
|
+
await this.runMigrations(require_bosch_instances.defineAddonMigrations(HOMECOM_MIGRATIONS, homeComRowsPorts({
|
|
2195
|
+
api: require_bosch_instances.defaultIntegrationApiOver(this.ctx.api),
|
|
2196
|
+
records,
|
|
2197
|
+
warn: (message) => this.ctx.logger.warn(message)
|
|
2198
|
+
})));
|
|
2199
|
+
const built = buildHomeComInstances(records, {
|
|
2200
|
+
onChanged: () => this.reconcileIntegrations(),
|
|
2201
|
+
tester: this.buildConnectionTestProvider()
|
|
2202
|
+
});
|
|
2203
|
+
this.instances = built;
|
|
2081
2204
|
await this.serveLoginProxy();
|
|
2082
2205
|
const persistDeps = {
|
|
2083
|
-
|
|
2084
|
-
|
|
2206
|
+
read: (id) => homeComStoredOf(built.instances, id),
|
|
2207
|
+
patch: (id, patch) => built.handle.patch(id, patch),
|
|
2085
2208
|
logger: this.ctx.logger
|
|
2086
2209
|
};
|
|
2087
2210
|
const persistTokens = buildHomeComTokenPersister(persistDeps);
|
|
@@ -2102,12 +2225,16 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2102
2225
|
providers: [
|
|
2103
2226
|
...regs,
|
|
2104
2227
|
{
|
|
2105
|
-
capability:
|
|
2228
|
+
capability: require_bosch_instances.deviceAdoptionCapability,
|
|
2106
2229
|
provider: this.buildAdoptionProvider()
|
|
2107
2230
|
},
|
|
2108
2231
|
{
|
|
2109
|
-
capability:
|
|
2232
|
+
capability: require_bosch_instances.connectionTestCapability,
|
|
2110
2233
|
provider: this.buildConnectionTestProvider()
|
|
2234
|
+
},
|
|
2235
|
+
{
|
|
2236
|
+
capability: require_bosch_instances.integrationInstancesCapability,
|
|
2237
|
+
provider: built.provider
|
|
2111
2238
|
}
|
|
2112
2239
|
],
|
|
2113
2240
|
customActions: homeComActions,
|
|
@@ -2140,7 +2267,7 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2140
2267
|
}
|
|
2141
2268
|
/** The hub's HTTPS face for the vendor's login pages (D955): admin session only. */
|
|
2142
2269
|
async serveLoginProxy() {
|
|
2143
|
-
const proxy = new
|
|
2270
|
+
const proxy = new require_bosch_instances.VendorLoginProxy({
|
|
2144
2271
|
addonId: this.ctx.id,
|
|
2145
2272
|
logger: this.ctx.logger
|
|
2146
2273
|
});
|
|
@@ -2152,7 +2279,7 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2152
2279
|
}) ?? null;
|
|
2153
2280
|
if (this.loginPlane !== null) this.loginProxy = proxy;
|
|
2154
2281
|
} catch (err) {
|
|
2155
|
-
this.ctx.logger.warn("HomeCom login proxy failed to serve — sign-in falls back to paste", { meta: { error:
|
|
2282
|
+
this.ctx.logger.warn("HomeCom login proxy failed to serve — sign-in falls back to paste", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
2156
2283
|
}
|
|
2157
2284
|
}
|
|
2158
2285
|
async onShutdown() {
|
|
@@ -2162,9 +2289,10 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2162
2289
|
try {
|
|
2163
2290
|
await this.clients?.shutdown();
|
|
2164
2291
|
} catch (err) {
|
|
2165
|
-
this.ctx.logger.warn("HomeCom shutdown error", { meta: { error:
|
|
2292
|
+
this.ctx.logger.warn("HomeCom shutdown error", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
2166
2293
|
}
|
|
2167
2294
|
this.clients = null;
|
|
2295
|
+
this.instances = null;
|
|
2168
2296
|
await super.onShutdown();
|
|
2169
2297
|
}
|
|
2170
2298
|
requireClients() {
|
|
@@ -2184,14 +2312,14 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2184
2312
|
const mine = (await this.ctx.api.integrations.list.query()).filter((i) => i.addonId === this.ctx.id && i.enabled);
|
|
2185
2313
|
const surviving = /* @__PURE__ */ new Set();
|
|
2186
2314
|
for (const integration of mine) try {
|
|
2187
|
-
const connection =
|
|
2315
|
+
const connection = await homeComConnectionOf(this.requireInstances().instances, integration.id);
|
|
2188
2316
|
if (!connection) continue;
|
|
2189
2317
|
await reg.upsert(integration.id, integration.name, connection);
|
|
2190
2318
|
surviving.add(integration.id);
|
|
2191
2319
|
} catch (err) {
|
|
2192
2320
|
this.ctx.logger.warn("HomeCom reconcile failed for integration", { meta: {
|
|
2193
2321
|
integrationId: integration.id,
|
|
2194
|
-
error:
|
|
2322
|
+
error: require_bosch_instances.errMsg(err)
|
|
2195
2323
|
} });
|
|
2196
2324
|
}
|
|
2197
2325
|
const vanished = reg.list().filter((id) => !surviving.has(id));
|
|
@@ -2207,7 +2335,7 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2207
2335
|
logger: this.ctx.logger
|
|
2208
2336
|
});
|
|
2209
2337
|
} catch (err) {
|
|
2210
|
-
this.ctx.logger.warn("HomeCom integration reconcile failed", { meta: { error:
|
|
2338
|
+
this.ctx.logger.warn("HomeCom integration reconcile failed", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
2211
2339
|
}
|
|
2212
2340
|
}
|
|
2213
2341
|
subscribeIntegrationLifecycle() {
|
|
@@ -2216,9 +2344,9 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2216
2344
|
if (typeof addonId === "string" && addonId !== this.ctx.id) return;
|
|
2217
2345
|
this.reconcileIntegrations();
|
|
2218
2346
|
};
|
|
2219
|
-
this.ctx.eventBus.subscribe({ category:
|
|
2220
|
-
this.ctx.eventBus.subscribe({ category:
|
|
2221
|
-
this.ctx.eventBus.subscribe({ category:
|
|
2347
|
+
this.ctx.eventBus.subscribe({ category: require_bosch_instances.EventCategory.IntegrationEnabled }, handler);
|
|
2348
|
+
this.ctx.eventBus.subscribe({ category: require_bosch_instances.EventCategory.IntegrationDisabled }, handler);
|
|
2349
|
+
this.ctx.eventBus.subscribe({ category: require_bosch_instances.EventCategory.IntegrationDeleted }, handler);
|
|
2222
2350
|
}
|
|
2223
2351
|
buildConnectionTestProvider() {
|
|
2224
2352
|
return buildHomeComConnectionTestProvider({ logger: this.ctx.logger });
|
|
@@ -2273,9 +2401,6 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2273
2401
|
logger: this.ctx.logger
|
|
2274
2402
|
});
|
|
2275
2403
|
}
|
|
2276
|
-
globalSettingsSchema() {
|
|
2277
|
-
return buildHomeComFormSchema();
|
|
2278
|
-
}
|
|
2279
2404
|
async supportsManualCreation() {
|
|
2280
2405
|
return false;
|
|
2281
2406
|
}
|
|
@@ -2285,6 +2410,10 @@ var BoschHomeComProviderAddon = class extends require_dist.BaseDeviceProvider {
|
|
|
2285
2410
|
async onCreateDevice(_type, _config) {
|
|
2286
2411
|
throw new Error("HomeCom devices are adopted from the cloud");
|
|
2287
2412
|
}
|
|
2413
|
+
requireInstances() {
|
|
2414
|
+
if (!this.instances) throw new Error("HomeCom provider not initialised");
|
|
2415
|
+
return this.instances;
|
|
2416
|
+
}
|
|
2288
2417
|
setIntegrationDevicesOnline(integrationId, online) {
|
|
2289
2418
|
const reg = this.ctx.kernel.deviceRegistry;
|
|
2290
2419
|
if (!reg) return;
|