@camstack/addon-provider-bosch 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-integration-offline-BhjIPfv5.js +119 -0
- package/dist/account-integration-offline-DW2D0vf8.mjs +102 -0
- package/dist/{dist-B-Un7bqT.js → dist-CIIror0W.js} +390 -294
- package/dist/{dist-BiZi19Lw.mjs → dist-DNznrlG_.mjs} +390 -294
- package/dist/home-connect/addon.js +50 -21
- package/dist/home-connect/addon.mjs +50 -21
- package/dist/homecom/addon.js +546 -123
- package/dist/homecom/addon.mjs +546 -123
- package/dist/shc/addon.js +1 -1
- package/dist/shc/addon.mjs +1 -1
- package/i18n/en.json +27 -1
- package/i18n/it.json +27 -1
- package/package.json +1 -1
- package/dist/account-integration-offline-BBqEtCgz.js +0 -50
- package/dist/account-integration-offline-BfoLYzxz.mjs +0 -39
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("../dist-
|
|
3
|
-
const require_account_integration_offline = require("../account-integration-offline-
|
|
2
|
+
const require_dist = require("../dist-CIIror0W.js");
|
|
3
|
+
const require_account_integration_offline = require("../account-integration-offline-BhjIPfv5.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
let node_tls = require("node:tls");
|
|
6
6
|
let node_zlib = require("node:zlib");
|
|
@@ -589,6 +589,14 @@ function tokensFromBody(body) {
|
|
|
589
589
|
refresh: typeof refresh === "string" ? refresh : ""
|
|
590
590
|
};
|
|
591
591
|
}
|
|
592
|
+
function isInvalidGrant(body) {
|
|
593
|
+
try {
|
|
594
|
+
const parsed = JSON.parse(body);
|
|
595
|
+
return isRecord$1(parsed) && parsed["error"] === "invalid_grant";
|
|
596
|
+
} catch {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
592
600
|
function accountSummary(appliances) {
|
|
593
601
|
if (appliances.length === 0) return "Signed in. No appliances on this account yet.";
|
|
594
602
|
const names = appliances.map((app) => app.name).join(", ");
|
|
@@ -752,27 +760,34 @@ function beginHomeConnectSignIn() {
|
|
|
752
760
|
state
|
|
753
761
|
};
|
|
754
762
|
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
763
|
+
var LOGIN_MESSAGES = {
|
|
764
|
+
empty: "Nothing was pasted. Paste the address the browser tried to open after you signed in.",
|
|
765
|
+
"no-code": "No sign-in code was found in what you pasted. Copy the whole address that starts with hcauth://, or just the code.",
|
|
766
|
+
"state-missing": "The pasted address has no state. Copy the complete address, or create the login link again.",
|
|
767
|
+
"state-mismatch": "State mismatch: this address belongs to a different sign-in attempt. Create the login link again and use the address that follows it.",
|
|
768
|
+
denied: "Home Connect refused the sign-in. Create the login link again and approve the access.",
|
|
769
|
+
"code-rejected": "The code was already used or has expired. Create the login link again; a code works once and only for a few minutes."
|
|
770
|
+
};
|
|
771
|
+
/** A failure the operator can act on; `reason` is stable, the message is for the form. */
|
|
772
|
+
var HomeConnectLoginError = class extends Error {
|
|
773
|
+
name = "HomeConnectLoginError";
|
|
774
|
+
reason;
|
|
775
|
+
constructor(reason) {
|
|
776
|
+
super(LOGIN_MESSAGES[reason]);
|
|
777
|
+
this.reason = reason;
|
|
761
778
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
779
|
+
};
|
|
780
|
+
function callbackParams(callback, expectedState) {
|
|
781
|
+
const parsed = require_account_integration_offline.parseOAuthCallback(callback, expectedState);
|
|
782
|
+
if (!parsed.ok) throw new HomeConnectLoginError(parsed.reason);
|
|
765
783
|
return {
|
|
766
|
-
code,
|
|
767
|
-
grantType:
|
|
768
|
-
state
|
|
784
|
+
code: parsed.code,
|
|
785
|
+
grantType: parsed.params.get("grant_type") ?? "authorization_code"
|
|
769
786
|
};
|
|
770
787
|
}
|
|
771
788
|
/** Exchange the pasted redirect for the account token and each appliance profile. */
|
|
772
789
|
async function completeHomeConnectSignIn(input, fetchImpl = homeConnectLoginFetch) {
|
|
773
|
-
const
|
|
774
|
-
if (parsed.state !== input.state) throw new Error("State mismatch. Create the login link again.");
|
|
775
|
-
const { code, grantType } = parsed;
|
|
790
|
+
const { code, grantType } = callbackParams(input.callback, input.state);
|
|
776
791
|
const token = await exchange(fetchImpl, new CookieJar(), `${OAUTH_BASE}token`, "POST", { "content-type": "application/x-www-form-urlencoded" }, new URLSearchParams({
|
|
777
792
|
grant_type: grantType,
|
|
778
793
|
client_id: APP_ID$1,
|
|
@@ -780,7 +795,10 @@ async function completeHomeConnectSignIn(input, fetchImpl = homeConnectLoginFetc
|
|
|
780
795
|
code_verifier: input.verifier,
|
|
781
796
|
redirect_uri: REDIRECT_URI
|
|
782
797
|
}).toString());
|
|
783
|
-
if (token.status >= 400)
|
|
798
|
+
if (token.status >= 400) {
|
|
799
|
+
if (isInvalidGrant(token.body)) throw new HomeConnectLoginError("code-rejected");
|
|
800
|
+
throw new Error("Home Connect sign-in was rejected");
|
|
801
|
+
}
|
|
784
802
|
return fetchHomeConnectAccount(tokensFromBody(token.body), fetchImpl);
|
|
785
803
|
}
|
|
786
804
|
//#endregion
|
|
@@ -1233,7 +1251,9 @@ function buildHomeConnectFormSchema() {
|
|
|
1233
1251
|
return { sections: [{
|
|
1234
1252
|
id: "gateway",
|
|
1235
1253
|
title: "Home Connect",
|
|
1236
|
-
|
|
1254
|
+
titleKey: "provider-bosch:home-connect.s_gateway.title",
|
|
1255
|
+
description: "Create the login link and open it in a browser, then sign in. The browser cannot open the app and stops on an address starting with hcauth://auth/prod?code=. Paste that whole address below (or only the code) and press Complete sign-in. The address is shown in Chrome and Edge under DevTools (F12) > Network, with Preserve log ticked before you sign in: select the last redirect and copy its Location header. In Firefox use Network > Headers > Location; in Safari use Develop > Show Web Inspector > Network. A code works once and expires within minutes. The appliances are then downloaded and spoken to on the local network.",
|
|
1256
|
+
descriptionKey: "provider-bosch:home-connect.s_gateway.description",
|
|
1237
1257
|
columns: 1,
|
|
1238
1258
|
fields: [
|
|
1239
1259
|
{
|
|
@@ -1241,6 +1261,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1241
1261
|
addonId: "bosch-home-connect",
|
|
1242
1262
|
key: "__home-connect-begin",
|
|
1243
1263
|
label: "Home Connect",
|
|
1264
|
+
labelKey: "provider-bosch:home-connect.s_gateway.__home-connect-begin.label",
|
|
1244
1265
|
buttonLabel: "Create login link",
|
|
1245
1266
|
action: "beginSignIn",
|
|
1246
1267
|
variant: "primary",
|
|
@@ -1255,13 +1276,15 @@ function buildHomeConnectFormSchema() {
|
|
|
1255
1276
|
type: "textarea",
|
|
1256
1277
|
key: "authorizeUrl",
|
|
1257
1278
|
label: "Login link",
|
|
1279
|
+
labelKey: "provider-bosch:home-connect.s_gateway.authorizeUrl.label",
|
|
1258
1280
|
required: false,
|
|
1259
1281
|
omitFromSettings: true
|
|
1260
1282
|
},
|
|
1261
1283
|
{
|
|
1262
|
-
type: "
|
|
1284
|
+
type: "textarea",
|
|
1263
1285
|
key: "callback",
|
|
1264
|
-
label: "Redirect address",
|
|
1286
|
+
label: "Redirect address or code",
|
|
1287
|
+
labelKey: "provider-bosch:home-connect.s_gateway.callback.label",
|
|
1265
1288
|
required: false,
|
|
1266
1289
|
placeholder: "hcauth://auth/prod?code=…&state=…",
|
|
1267
1290
|
omitFromSettings: true
|
|
@@ -1270,6 +1293,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1270
1293
|
type: "password",
|
|
1271
1294
|
key: "state",
|
|
1272
1295
|
label: "Login state",
|
|
1296
|
+
labelKey: "provider-bosch:home-connect.s_gateway.state.label",
|
|
1273
1297
|
required: false,
|
|
1274
1298
|
omitFromSettings: true,
|
|
1275
1299
|
showWhen: pairedOnly
|
|
@@ -1278,6 +1302,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1278
1302
|
type: "password",
|
|
1279
1303
|
key: "verifier",
|
|
1280
1304
|
label: "Login verifier",
|
|
1305
|
+
labelKey: "provider-bosch:home-connect.s_gateway.verifier.label",
|
|
1281
1306
|
required: false,
|
|
1282
1307
|
omitFromSettings: true,
|
|
1283
1308
|
showWhen: pairedOnly
|
|
@@ -1287,6 +1312,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1287
1312
|
addonId: "bosch-home-connect",
|
|
1288
1313
|
key: "__home-connect-finish",
|
|
1289
1314
|
label: "Finish",
|
|
1315
|
+
labelKey: "provider-bosch:home-connect.s_gateway.__home-connect-finish.label",
|
|
1290
1316
|
buttonLabel: "Complete sign-in",
|
|
1291
1317
|
action: "finishSignIn",
|
|
1292
1318
|
variant: "primary",
|
|
@@ -1307,6 +1333,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1307
1333
|
type: "password",
|
|
1308
1334
|
key: "token",
|
|
1309
1335
|
label: "Access token",
|
|
1336
|
+
labelKey: "provider-bosch:home-connect.s_gateway.token.label",
|
|
1310
1337
|
required: true,
|
|
1311
1338
|
showWhen: pairedOnly
|
|
1312
1339
|
},
|
|
@@ -1314,6 +1341,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1314
1341
|
type: "password",
|
|
1315
1342
|
key: "refresh",
|
|
1316
1343
|
label: "Refresh token",
|
|
1344
|
+
labelKey: "provider-bosch:home-connect.s_gateway.refresh.label",
|
|
1317
1345
|
required: false,
|
|
1318
1346
|
showWhen: pairedOnly
|
|
1319
1347
|
},
|
|
@@ -1321,6 +1349,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1321
1349
|
type: "textarea",
|
|
1322
1350
|
key: "appliances",
|
|
1323
1351
|
label: "Appliances",
|
|
1352
|
+
labelKey: "provider-bosch:home-connect.s_gateway.appliances.label",
|
|
1324
1353
|
required: true,
|
|
1325
1354
|
showWhen: pairedOnly
|
|
1326
1355
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as object, C as defineCustomActions, D as array, E as _enum, F as EventCategory, M as string, N as union, O as literal, P as unknown, S as customAction, T as isSecretMarkerLike, a as binaryCapability, b as errMsg, c as deviceAdoptionCapability, d as eventEmitterCapability, j as record, l as dishwasherCapability, m as powerMeterCapability, n as BaseDeviceProvider, p as numericSensorCapability, r as DishwasherOperationStateSchema, s as connectionTestCapability, t as BaseDevice, u as enumSensorCapability, v as DeviceRole, w as isSecretMarker, x as createEvent, y as DeviceType } from "../dist-
|
|
2
|
-
import { n as cascadeRemoveDevicesForIntegration, t as setIntegrationDevicesOnline } from "../account-integration-offline-
|
|
1
|
+
import { A as object, C as defineCustomActions, D as array, E as _enum, F as EventCategory, M as string, N as union, O as literal, P as unknown, S as customAction, T as isSecretMarkerLike, a as binaryCapability, b as errMsg, c as deviceAdoptionCapability, d as eventEmitterCapability, j as record, l as dishwasherCapability, m as powerMeterCapability, n as BaseDeviceProvider, p as numericSensorCapability, r as DishwasherOperationStateSchema, s as connectionTestCapability, t as BaseDevice, u as enumSensorCapability, v as DeviceRole, w as isSecretMarker, x as createEvent, y as DeviceType } from "../dist-DNznrlG_.mjs";
|
|
2
|
+
import { n as cascadeRemoveDevicesForIntegration, r as parseOAuthCallback, t as setIntegrationDevicesOnline } from "../account-integration-offline-DW2D0vf8.mjs";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { connect } from "node:tls";
|
|
5
5
|
import { inflateRawSync } from "node:zlib";
|
|
@@ -588,6 +588,14 @@ function tokensFromBody(body) {
|
|
|
588
588
|
refresh: typeof refresh === "string" ? refresh : ""
|
|
589
589
|
};
|
|
590
590
|
}
|
|
591
|
+
function isInvalidGrant(body) {
|
|
592
|
+
try {
|
|
593
|
+
const parsed = JSON.parse(body);
|
|
594
|
+
return isRecord$1(parsed) && parsed["error"] === "invalid_grant";
|
|
595
|
+
} catch {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
591
599
|
function accountSummary(appliances) {
|
|
592
600
|
if (appliances.length === 0) return "Signed in. No appliances on this account yet.";
|
|
593
601
|
const names = appliances.map((app) => app.name).join(", ");
|
|
@@ -751,27 +759,34 @@ function beginHomeConnectSignIn() {
|
|
|
751
759
|
state
|
|
752
760
|
};
|
|
753
761
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
762
|
+
var LOGIN_MESSAGES = {
|
|
763
|
+
empty: "Nothing was pasted. Paste the address the browser tried to open after you signed in.",
|
|
764
|
+
"no-code": "No sign-in code was found in what you pasted. Copy the whole address that starts with hcauth://, or just the code.",
|
|
765
|
+
"state-missing": "The pasted address has no state. Copy the complete address, or create the login link again.",
|
|
766
|
+
"state-mismatch": "State mismatch: this address belongs to a different sign-in attempt. Create the login link again and use the address that follows it.",
|
|
767
|
+
denied: "Home Connect refused the sign-in. Create the login link again and approve the access.",
|
|
768
|
+
"code-rejected": "The code was already used or has expired. Create the login link again; a code works once and only for a few minutes."
|
|
769
|
+
};
|
|
770
|
+
/** A failure the operator can act on; `reason` is stable, the message is for the form. */
|
|
771
|
+
var HomeConnectLoginError = class extends Error {
|
|
772
|
+
name = "HomeConnectLoginError";
|
|
773
|
+
reason;
|
|
774
|
+
constructor(reason) {
|
|
775
|
+
super(LOGIN_MESSAGES[reason]);
|
|
776
|
+
this.reason = reason;
|
|
760
777
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
778
|
+
};
|
|
779
|
+
function callbackParams(callback, expectedState) {
|
|
780
|
+
const parsed = parseOAuthCallback(callback, expectedState);
|
|
781
|
+
if (!parsed.ok) throw new HomeConnectLoginError(parsed.reason);
|
|
764
782
|
return {
|
|
765
|
-
code,
|
|
766
|
-
grantType:
|
|
767
|
-
state
|
|
783
|
+
code: parsed.code,
|
|
784
|
+
grantType: parsed.params.get("grant_type") ?? "authorization_code"
|
|
768
785
|
};
|
|
769
786
|
}
|
|
770
787
|
/** Exchange the pasted redirect for the account token and each appliance profile. */
|
|
771
788
|
async function completeHomeConnectSignIn(input, fetchImpl = homeConnectLoginFetch) {
|
|
772
|
-
const
|
|
773
|
-
if (parsed.state !== input.state) throw new Error("State mismatch. Create the login link again.");
|
|
774
|
-
const { code, grantType } = parsed;
|
|
789
|
+
const { code, grantType } = callbackParams(input.callback, input.state);
|
|
775
790
|
const token = await exchange(fetchImpl, new CookieJar(), `${OAUTH_BASE}token`, "POST", { "content-type": "application/x-www-form-urlencoded" }, new URLSearchParams({
|
|
776
791
|
grant_type: grantType,
|
|
777
792
|
client_id: APP_ID$1,
|
|
@@ -779,7 +794,10 @@ async function completeHomeConnectSignIn(input, fetchImpl = homeConnectLoginFetc
|
|
|
779
794
|
code_verifier: input.verifier,
|
|
780
795
|
redirect_uri: REDIRECT_URI
|
|
781
796
|
}).toString());
|
|
782
|
-
if (token.status >= 400)
|
|
797
|
+
if (token.status >= 400) {
|
|
798
|
+
if (isInvalidGrant(token.body)) throw new HomeConnectLoginError("code-rejected");
|
|
799
|
+
throw new Error("Home Connect sign-in was rejected");
|
|
800
|
+
}
|
|
783
801
|
return fetchHomeConnectAccount(tokensFromBody(token.body), fetchImpl);
|
|
784
802
|
}
|
|
785
803
|
//#endregion
|
|
@@ -1232,7 +1250,9 @@ function buildHomeConnectFormSchema() {
|
|
|
1232
1250
|
return { sections: [{
|
|
1233
1251
|
id: "gateway",
|
|
1234
1252
|
title: "Home Connect",
|
|
1235
|
-
|
|
1253
|
+
titleKey: "provider-bosch:home-connect.s_gateway.title",
|
|
1254
|
+
description: "Create the login link and open it in a browser, then sign in. The browser cannot open the app and stops on an address starting with hcauth://auth/prod?code=. Paste that whole address below (or only the code) and press Complete sign-in. The address is shown in Chrome and Edge under DevTools (F12) > Network, with Preserve log ticked before you sign in: select the last redirect and copy its Location header. In Firefox use Network > Headers > Location; in Safari use Develop > Show Web Inspector > Network. A code works once and expires within minutes. The appliances are then downloaded and spoken to on the local network.",
|
|
1255
|
+
descriptionKey: "provider-bosch:home-connect.s_gateway.description",
|
|
1236
1256
|
columns: 1,
|
|
1237
1257
|
fields: [
|
|
1238
1258
|
{
|
|
@@ -1240,6 +1260,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1240
1260
|
addonId: "bosch-home-connect",
|
|
1241
1261
|
key: "__home-connect-begin",
|
|
1242
1262
|
label: "Home Connect",
|
|
1263
|
+
labelKey: "provider-bosch:home-connect.s_gateway.__home-connect-begin.label",
|
|
1243
1264
|
buttonLabel: "Create login link",
|
|
1244
1265
|
action: "beginSignIn",
|
|
1245
1266
|
variant: "primary",
|
|
@@ -1254,13 +1275,15 @@ function buildHomeConnectFormSchema() {
|
|
|
1254
1275
|
type: "textarea",
|
|
1255
1276
|
key: "authorizeUrl",
|
|
1256
1277
|
label: "Login link",
|
|
1278
|
+
labelKey: "provider-bosch:home-connect.s_gateway.authorizeUrl.label",
|
|
1257
1279
|
required: false,
|
|
1258
1280
|
omitFromSettings: true
|
|
1259
1281
|
},
|
|
1260
1282
|
{
|
|
1261
|
-
type: "
|
|
1283
|
+
type: "textarea",
|
|
1262
1284
|
key: "callback",
|
|
1263
|
-
label: "Redirect address",
|
|
1285
|
+
label: "Redirect address or code",
|
|
1286
|
+
labelKey: "provider-bosch:home-connect.s_gateway.callback.label",
|
|
1264
1287
|
required: false,
|
|
1265
1288
|
placeholder: "hcauth://auth/prod?code=…&state=…",
|
|
1266
1289
|
omitFromSettings: true
|
|
@@ -1269,6 +1292,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1269
1292
|
type: "password",
|
|
1270
1293
|
key: "state",
|
|
1271
1294
|
label: "Login state",
|
|
1295
|
+
labelKey: "provider-bosch:home-connect.s_gateway.state.label",
|
|
1272
1296
|
required: false,
|
|
1273
1297
|
omitFromSettings: true,
|
|
1274
1298
|
showWhen: pairedOnly
|
|
@@ -1277,6 +1301,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1277
1301
|
type: "password",
|
|
1278
1302
|
key: "verifier",
|
|
1279
1303
|
label: "Login verifier",
|
|
1304
|
+
labelKey: "provider-bosch:home-connect.s_gateway.verifier.label",
|
|
1280
1305
|
required: false,
|
|
1281
1306
|
omitFromSettings: true,
|
|
1282
1307
|
showWhen: pairedOnly
|
|
@@ -1286,6 +1311,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1286
1311
|
addonId: "bosch-home-connect",
|
|
1287
1312
|
key: "__home-connect-finish",
|
|
1288
1313
|
label: "Finish",
|
|
1314
|
+
labelKey: "provider-bosch:home-connect.s_gateway.__home-connect-finish.label",
|
|
1289
1315
|
buttonLabel: "Complete sign-in",
|
|
1290
1316
|
action: "finishSignIn",
|
|
1291
1317
|
variant: "primary",
|
|
@@ -1306,6 +1332,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1306
1332
|
type: "password",
|
|
1307
1333
|
key: "token",
|
|
1308
1334
|
label: "Access token",
|
|
1335
|
+
labelKey: "provider-bosch:home-connect.s_gateway.token.label",
|
|
1309
1336
|
required: true,
|
|
1310
1337
|
showWhen: pairedOnly
|
|
1311
1338
|
},
|
|
@@ -1313,6 +1340,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1313
1340
|
type: "password",
|
|
1314
1341
|
key: "refresh",
|
|
1315
1342
|
label: "Refresh token",
|
|
1343
|
+
labelKey: "provider-bosch:home-connect.s_gateway.refresh.label",
|
|
1316
1344
|
required: false,
|
|
1317
1345
|
showWhen: pairedOnly
|
|
1318
1346
|
},
|
|
@@ -1320,6 +1348,7 @@ function buildHomeConnectFormSchema() {
|
|
|
1320
1348
|
type: "textarea",
|
|
1321
1349
|
key: "appliances",
|
|
1322
1350
|
label: "Appliances",
|
|
1351
|
+
labelKey: "provider-bosch:home-connect.s_gateway.appliances.label",
|
|
1323
1352
|
required: true,
|
|
1324
1353
|
showWhen: pairedOnly
|
|
1325
1354
|
},
|