@camstack/addon-provider-bosch 0.1.55 → 0.1.56
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-DzGZkIwF.js → account-integration-offline-DOH2c7x2.js} +1 -1
- package/dist/{account-integration-offline-xi6muNeM.mjs → account-integration-offline-fB8V7XNu.mjs} +1 -1
- package/dist/{bosch-instances-DaWS-s0M.js → bosch-instances-BnuV5On6.js} +504 -275
- package/dist/{bosch-instances-g54r3Dus.mjs → bosch-instances-REcWLM14.mjs} +475 -276
- package/dist/home-connect/addon.js +2 -2
- package/dist/home-connect/addon.mjs +2 -2
- package/dist/homecom/addon.js +208 -53
- package/dist/homecom/addon.mjs +208 -53
- package/dist/shc/addon.js +1 -1
- package/dist/shc/addon.mjs +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_bosch_instances = require("../bosch-instances-
|
|
3
|
-
const require_account_integration_offline = require("../account-integration-offline-
|
|
2
|
+
const require_bosch_instances = require("../bosch-instances-BnuV5On6.js");
|
|
3
|
+
const require_account_integration_offline = require("../account-integration-offline-DOH2c7x2.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");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { a as loginFailureForAttempt, c as HOME_CONNECT_REDIRECT_URI, i as createSignInAttemptStore, n as cascadeRemoveDevicesForIntegration, o as parseOAuthCallback, r as buildSignInGuideFields, t as setIntegrationDevicesOnline } from "../account-integration-offline-
|
|
1
|
+
import { $ as literal, B as defineCustomActions, C as ingestReading, D as plainEventVocabulary, E as numericSensorCapability, G as isSecretMarkerLike, H as entryBody, I as RecordIntegrationInstances, J as _enum, K as rowsDepsOver, M as runningStateCapability, O as powerMeterCapability, R as createEvent, V as defineEntryKind, W as isSecretMarker, X as array, _ as enumSensorCapability, a as BaseDevice, at as unknown, c as RUNNING_STATE_COLD, ct as errMsg, d as binaryCapability, g as dishwasherCapability, h as deviceAdoptionCapability, i as testBoschInstance, it as union, j as runningFromDishwasherOperation, k as quantityFromUnit, lt as EventCategory, n as boschRowsPorts, nt as record, o as BaseDeviceProvider, ot as DeviceRole, p as consumablesCapability, r as keepBodyKeys, rt as string, s as DishwasherOperationStateSchema, st as DeviceType, t as boschRowsMigration, tt as object, v as eventEmitterCapability, w as integrationInstancesCapability, z as customAction } from "../bosch-instances-REcWLM14.mjs";
|
|
2
|
+
import { a as loginFailureForAttempt, c as HOME_CONNECT_REDIRECT_URI, i as createSignInAttemptStore, n as cascadeRemoveDevicesForIntegration, o as parseOAuthCallback, r as buildSignInGuideFields, t as setIntegrationDevicesOnline } from "../account-integration-offline-fB8V7XNu.mjs";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { connect } from "node:tls";
|
|
5
5
|
import { inflateRawSync } from "node:zlib";
|
package/dist/homecom/addon.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_bosch_instances = require("../bosch-instances-
|
|
3
|
-
const require_account_integration_offline = require("../account-integration-offline-
|
|
2
|
+
const require_bosch_instances = require("../bosch-instances-BnuV5On6.js");
|
|
3
|
+
const require_account_integration_offline = require("../account-integration-offline-DOH2c7x2.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
let node_child_process = require("node:child_process");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
@@ -458,6 +458,17 @@ async function exploreHomeComResources(input) {
|
|
|
458
458
|
}
|
|
459
459
|
//#endregion
|
|
460
460
|
//#region src/homecom/custom-actions.ts
|
|
461
|
+
/** A stored secret as the form sees it (`SecretFieldView`): set or not, never the value. */
|
|
462
|
+
var secretView = require_bosch_instances.custom(require_bosch_instances.isSecretFieldView, "a stored secret view");
|
|
463
|
+
/**
|
|
464
|
+
* A sign-in secret in the result: in clear only for a form that has no record yet (the wizard
|
|
465
|
+
* stores it on create); for an existing instance it is already stored and comes back as a view.
|
|
466
|
+
*/
|
|
467
|
+
var signInSecret = require_bosch_instances.union([
|
|
468
|
+
require_bosch_instances.string().min(1),
|
|
469
|
+
secretView,
|
|
470
|
+
require_bosch_instances._null()
|
|
471
|
+
]).meta({ secret: true });
|
|
461
472
|
var gatewayChoice = require_bosch_instances.object({
|
|
462
473
|
value: require_bosch_instances.string(),
|
|
463
474
|
label: require_bosch_instances.string(),
|
|
@@ -496,11 +507,17 @@ var homeComActions = require_bosch_instances.defineCustomActions({
|
|
|
496
507
|
}),
|
|
497
508
|
finishSignIn: require_bosch_instances.customAction(require_bosch_instances.object({
|
|
498
509
|
attemptId: require_bosch_instances.string().min(1),
|
|
499
|
-
callback: require_bosch_instances.string().min(1)
|
|
510
|
+
callback: require_bosch_instances.string().min(1),
|
|
511
|
+
/** An existing instance: the new sign-in is stored on it and applied at once. */
|
|
512
|
+
integrationId: require_bosch_instances.string().min(1).optional()
|
|
500
513
|
}), require_bosch_instances.object({
|
|
501
|
-
token:
|
|
502
|
-
refresh:
|
|
503
|
-
username: require_bosch_instances.
|
|
514
|
+
token: signInSecret,
|
|
515
|
+
refresh: signInSecret,
|
|
516
|
+
username: require_bosch_instances.union([
|
|
517
|
+
require_bosch_instances.string(),
|
|
518
|
+
secretView,
|
|
519
|
+
require_bosch_instances._null()
|
|
520
|
+
]).meta({ secret: true }),
|
|
504
521
|
accountLabel: require_bosch_instances.string(),
|
|
505
522
|
gatewayCount: require_bosch_instances.number(),
|
|
506
523
|
summary: require_bosch_instances.string(),
|
|
@@ -512,13 +529,18 @@ var homeComActions = require_bosch_instances.defineCustomActions({
|
|
|
512
529
|
kind: "mutation",
|
|
513
530
|
auth: "admin"
|
|
514
531
|
}),
|
|
515
|
-
signOut: require_bosch_instances.customAction(
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
532
|
+
signOut: require_bosch_instances.customAction(
|
|
533
|
+
/** An existing instance: its stored sign-in is cleared and its connection stopped. */
|
|
534
|
+
require_bosch_instances.object({ integrationId: require_bosch_instances.string().min(1).optional() }),
|
|
535
|
+
require_bosch_instances.object({
|
|
536
|
+
signedOut: require_bosch_instances.literal(true),
|
|
537
|
+
summary: require_bosch_instances.string()
|
|
538
|
+
}),
|
|
539
|
+
{
|
|
540
|
+
kind: "mutation",
|
|
541
|
+
auth: "admin"
|
|
542
|
+
}
|
|
543
|
+
),
|
|
522
544
|
/** Read-only walk of the gateway's resource tree, for diagnosing what it serves. */
|
|
523
545
|
exploreResources: require_bosch_instances.customAction(exploreResourcesInput, exploreResourcesOutput, {
|
|
524
546
|
kind: "query",
|
|
@@ -526,6 +548,104 @@ var homeComActions = require_bosch_instances.defineCustomActions({
|
|
|
526
548
|
})
|
|
527
549
|
});
|
|
528
550
|
//#endregion
|
|
551
|
+
//#region src/homecom/homecom-account.ts
|
|
552
|
+
/**
|
|
553
|
+
* Sign in / sign out of an EXISTING HomeCom instance, written through the instance record — the
|
|
554
|
+
* owner of the tokens (keychain-backed secret fields). The record's change hook reconciles the
|
|
555
|
+
* integration: new tokens are applied to the running manager, cleared ones stop it.
|
|
556
|
+
*/
|
|
557
|
+
/** Forget the account: the three secrets are cleared in the keychain, the account labels reset. */
|
|
558
|
+
async function signOutHomeComInstance(integrationId, instances) {
|
|
559
|
+
await instances.updateInstance({
|
|
560
|
+
id: integrationId,
|
|
561
|
+
values: {
|
|
562
|
+
token: require_bosch_instances.SECRET_CLEAR,
|
|
563
|
+
refresh: require_bosch_instances.SECRET_CLEAR,
|
|
564
|
+
username: require_bosch_instances.SECRET_CLEAR,
|
|
565
|
+
accountLabel: "",
|
|
566
|
+
gatewayCount: 0
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Store a finished sign-in on the instance. The gateway (and its brand / region) is written only
|
|
572
|
+
* when the sign-in settled on one: a choice still open keeps the stored gateway.
|
|
573
|
+
*/
|
|
574
|
+
async function storeHomeComSignIn(integrationId, finished, instances) {
|
|
575
|
+
await instances.updateInstance({
|
|
576
|
+
id: integrationId,
|
|
577
|
+
values: {
|
|
578
|
+
token: finished.token,
|
|
579
|
+
refresh: finished.refresh,
|
|
580
|
+
username: finished.username,
|
|
581
|
+
accountLabel: finished.accountLabel,
|
|
582
|
+
gatewayCount: finished.gatewayCount,
|
|
583
|
+
...finished.gatewayId !== void 0 ? { gatewayId: finished.gatewayId } : {},
|
|
584
|
+
...finished.brand !== void 0 ? { brand: finished.brand } : {},
|
|
585
|
+
...finished.region !== void 0 ? { region: finished.region } : {}
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* The answer to a sign-in on an existing instance: the tokens are on the record now, so the form
|
|
591
|
+
* gets the record's "set" views (as `hydrateSchema` hands them out) in their place — a Save that
|
|
592
|
+
* follows keeps them, and the values never travel to the browser.
|
|
593
|
+
*/
|
|
594
|
+
async function storedSignInResult(integrationId, finished, handle) {
|
|
595
|
+
const data = (await handle.get(integrationId))?.data ?? {};
|
|
596
|
+
const { token: _token, refresh: _refresh, username: _username, ...open } = finished;
|
|
597
|
+
return {
|
|
598
|
+
...open,
|
|
599
|
+
token: require_bosch_instances.toSecretFieldView(data["token"]),
|
|
600
|
+
refresh: require_bosch_instances.toSecretFieldView(data["refresh"]),
|
|
601
|
+
username: require_bosch_instances.toSecretFieldView(data["username"])
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
//#endregion
|
|
605
|
+
//#region src/homecom/homecom-reconcile.ts
|
|
606
|
+
/**
|
|
607
|
+
* Bring the running HomeCom managers in line with the enabled integrations:
|
|
608
|
+
*
|
|
609
|
+
* - signed in -> upsert (a changed connection is applied to the running manager);
|
|
610
|
+
* - signed out -> the manager stops and the devices go offline; the integration still
|
|
611
|
+
* exists, so its devices and its session alert are KEPT;
|
|
612
|
+
* - unreadable -> left as it is (a locked keychain is not a sign out, nor a deletion);
|
|
613
|
+
* - gone / disabled -> the manager stops and the caller drops what belonged to it.
|
|
614
|
+
*
|
|
615
|
+
* "Gone" is judged over EVERY id the addon still holds something for — a running manager, an
|
|
616
|
+
* instance record, a device — not only the running managers: an integration that was signed out
|
|
617
|
+
* or unreadable has no manager, and its devices and alert must still go when it is deleted.
|
|
618
|
+
*/
|
|
619
|
+
async function reconcileHomeComIntegrations(deps) {
|
|
620
|
+
const enabled = await deps.listEnabled();
|
|
621
|
+
const present = new Set(enabled.map((integration) => integration.id));
|
|
622
|
+
for (const integration of enabled) await reconcileOne(deps, integration);
|
|
623
|
+
const vanished = [...new Set([...deps.registry.list(), ...await deps.knownIds()])].filter((id) => !present.has(id));
|
|
624
|
+
await deps.registry.retain(present);
|
|
625
|
+
for (const integrationId of vanished) await deps.onVanished(integrationId);
|
|
626
|
+
}
|
|
627
|
+
async function reconcileOne(deps, integration) {
|
|
628
|
+
const tags = { integrationId: integration.id };
|
|
629
|
+
try {
|
|
630
|
+
const connection = await deps.connectionOf(integration.id);
|
|
631
|
+
deps.onNamed(integration.id, integration.name);
|
|
632
|
+
if (connection === null) {
|
|
633
|
+
if (deps.registry.has(integration.id)) {
|
|
634
|
+
await deps.registry.remove(integration.id);
|
|
635
|
+
deps.logger.info("HomeCom integration has no sign-in — stopped, devices offline", { tags });
|
|
636
|
+
}
|
|
637
|
+
deps.onSignedOut(integration.id);
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
await deps.registry.upsert(integration.id, integration.name, connection);
|
|
641
|
+
} catch (err) {
|
|
642
|
+
deps.logger.warn("HomeCom reconcile failed for integration", {
|
|
643
|
+
tags,
|
|
644
|
+
meta: { error: require_bosch_instances.errMsg(err) }
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
//#endregion
|
|
529
649
|
//#region src/homecom/homecom-session-alert.ts
|
|
530
650
|
/** The standard session-lost alert for HomeCom; "Sign in again" opens the integration page. */
|
|
531
651
|
function createHomeComSessionAlert(deps) {
|
|
@@ -534,7 +654,9 @@ function createHomeComSessionAlert(deps) {
|
|
|
534
654
|
providerName: "Bosch HomeCom",
|
|
535
655
|
logger: deps.logger,
|
|
536
656
|
getAlerts: deps.getAlerts,
|
|
537
|
-
debounceMs: deps.debounceMs ?? 0
|
|
657
|
+
debounceMs: deps.debounceMs ?? 0,
|
|
658
|
+
addonId: deps.addonId,
|
|
659
|
+
severity: "critical"
|
|
538
660
|
});
|
|
539
661
|
return {
|
|
540
662
|
authFailed: (integrationId) => tracker.lost(integrationId, {
|
|
@@ -542,7 +664,7 @@ function createHomeComSessionAlert(deps) {
|
|
|
542
664
|
reason: "token-expired",
|
|
543
665
|
action: {
|
|
544
666
|
label: "Sign in again",
|
|
545
|
-
href:
|
|
667
|
+
href: require_bosch_instances.integrationPageHref(deps.addonId, integrationId),
|
|
546
668
|
navigation: "app"
|
|
547
669
|
}
|
|
548
670
|
}),
|
|
@@ -3738,7 +3860,8 @@ var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDevice
|
|
|
3738
3860
|
const sessionAlert = createHomeComSessionAlert({
|
|
3739
3861
|
logger: this.ctx.logger,
|
|
3740
3862
|
getAlerts: () => this.ctx.api.alerts,
|
|
3741
|
-
nameOf: (id) => this.integrationNames.get(id) ?? id
|
|
3863
|
+
nameOf: (id) => this.integrationNames.get(id) ?? id,
|
|
3864
|
+
addonId: this.addonId
|
|
3742
3865
|
});
|
|
3743
3866
|
this.sessionAlert = sessionAlert;
|
|
3744
3867
|
this.clients = new HomeComClientRegistry(this.ctx.logger, {
|
|
@@ -3779,15 +3902,30 @@ var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDevice
|
|
|
3779
3902
|
...publishHomeComSignIn(homeComSignInAttempts, Date.now()),
|
|
3780
3903
|
summary: "Open the sign-in page, sign in, then paste the address the browser stops on."
|
|
3781
3904
|
}),
|
|
3782
|
-
finishSignIn: async (input) =>
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3905
|
+
finishSignIn: async (input) => {
|
|
3906
|
+
const finished = await finishHomeComSignIn({
|
|
3907
|
+
attemptId: input.attemptId,
|
|
3908
|
+
callback: input.callback,
|
|
3909
|
+
nowMs: Date.now()
|
|
3910
|
+
}, homeComSignInAttempts);
|
|
3911
|
+
const integrationId = input.integrationId;
|
|
3912
|
+
if (integrationId === void 0) return finished;
|
|
3913
|
+
await this.storeSignIn(integrationId, () => storeHomeComSignIn(integrationId, finished, built.instances));
|
|
3914
|
+
return storedSignInResult(integrationId, finished, built.handle);
|
|
3915
|
+
},
|
|
3916
|
+
signOut: async (input) => {
|
|
3917
|
+
const integrationId = input.integrationId;
|
|
3918
|
+
if (integrationId === void 0) return {
|
|
3919
|
+
signedOut: true,
|
|
3920
|
+
summary: "Signed out."
|
|
3921
|
+
};
|
|
3922
|
+
await this.storeSignIn(integrationId, () => signOutHomeComInstance(integrationId, built.instances));
|
|
3923
|
+
this.ctx.logger.info("HomeCom signed out — stored sign-in cleared", { tags: { integrationId } });
|
|
3924
|
+
return {
|
|
3925
|
+
signedOut: true,
|
|
3926
|
+
summary: "Signed out. The devices stay offline until you sign in again."
|
|
3927
|
+
};
|
|
3928
|
+
},
|
|
3791
3929
|
exploreResources: explore
|
|
3792
3930
|
}
|
|
3793
3931
|
};
|
|
@@ -3832,43 +3970,60 @@ var BoschHomeComProviderAddon = class extends require_bosch_instances.BaseDevice
|
|
|
3832
3970
|
if (typeof nativeId !== "string" || nativeId.length === 0) throw new Error("homecom generateStableId: nativeId required");
|
|
3833
3971
|
return homeComStableId(integrationId, nativeId);
|
|
3834
3972
|
}
|
|
3973
|
+
/** Write a sign-in change on an instance that exists; a missing one is refused by name. */
|
|
3974
|
+
async storeSignIn(integrationId, write) {
|
|
3975
|
+
if (await homeComStoredOf(this.requireInstances().instances, integrationId) === null) throw new Error(`HomeCom integration ${integrationId} does not exist`);
|
|
3976
|
+
await write();
|
|
3977
|
+
}
|
|
3835
3978
|
async reconcileIntegrations() {
|
|
3836
3979
|
const reg = this.requireClients();
|
|
3837
3980
|
try {
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
this.
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
this.
|
|
3848
|
-
integrationId: integration.id,
|
|
3849
|
-
error: require_bosch_instances.errMsg(err)
|
|
3850
|
-
} });
|
|
3851
|
-
}
|
|
3852
|
-
const vanished = reg.list().filter((id) => !surviving.has(id));
|
|
3853
|
-
await reg.retain(surviving);
|
|
3854
|
-
for (const integrationId of vanished) {
|
|
3855
|
-
this.integrationNames.delete(integrationId);
|
|
3856
|
-
this.sessionAlert?.removed(integrationId);
|
|
3857
|
-
}
|
|
3858
|
-
const deviceReg = this.ctx.kernel.deviceRegistry;
|
|
3859
|
-
const deviceApi = this.ctx.kernel.devices;
|
|
3860
|
-
if (deviceReg && deviceApi) for (const integrationId of vanished) await require_account_integration_offline.cascadeRemoveDevicesForIntegration({
|
|
3861
|
-
reg: deviceReg,
|
|
3862
|
-
devices: deviceApi,
|
|
3863
|
-
addonId: this.addonId,
|
|
3864
|
-
system: "homecom",
|
|
3865
|
-
integrationId,
|
|
3981
|
+
await reconcileHomeComIntegrations({
|
|
3982
|
+
listEnabled: async () => {
|
|
3983
|
+
return (await this.ctx.api.integrations.list.query()).filter((i) => i.addonId === this.ctx.id && i.enabled);
|
|
3984
|
+
},
|
|
3985
|
+
knownIds: () => this.knownIntegrationIds(),
|
|
3986
|
+
connectionOf: (id) => homeComConnectionOf(this.requireInstances().instances, id),
|
|
3987
|
+
registry: reg,
|
|
3988
|
+
onNamed: (id, name) => this.integrationNames.set(id, name),
|
|
3989
|
+
onSignedOut: (id) => this.setIntegrationDevicesOnline(id, false),
|
|
3990
|
+
onVanished: (id) => this.dropIntegration(id),
|
|
3866
3991
|
logger: this.ctx.logger
|
|
3867
3992
|
});
|
|
3868
3993
|
} catch (err) {
|
|
3869
3994
|
this.ctx.logger.warn("HomeCom integration reconcile failed", { meta: { error: require_bosch_instances.errMsg(err) } });
|
|
3870
3995
|
}
|
|
3871
3996
|
}
|
|
3997
|
+
/** Every integration this addon holds a record or a top-level device for. */
|
|
3998
|
+
async knownIntegrationIds() {
|
|
3999
|
+
const ids = new Set(this.integrationNames.keys());
|
|
4000
|
+
for (const row of await this.requireInstances().instances.listResolved()) ids.add(row.id);
|
|
4001
|
+
const reg = this.ctx.kernel.deviceRegistry;
|
|
4002
|
+
const devices = this.ctx.kernel.devices;
|
|
4003
|
+
if (reg && devices) for (const d of reg.getAllForAddon(this.addonId)) {
|
|
4004
|
+
if (d.parentDeviceId !== null) continue;
|
|
4005
|
+
const cfg = await devices.loadConfig(d.id).catch(() => ({}));
|
|
4006
|
+
const brokerId = cfg["brokerId"];
|
|
4007
|
+
if (cfg["system"] === "homecom" && typeof brokerId === "string") ids.add(brokerId);
|
|
4008
|
+
}
|
|
4009
|
+
return [...ids];
|
|
4010
|
+
}
|
|
4011
|
+
/** The integration is gone: its alert and its devices go with it. */
|
|
4012
|
+
async dropIntegration(integrationId) {
|
|
4013
|
+
this.integrationNames.delete(integrationId);
|
|
4014
|
+
this.sessionAlert?.removed(integrationId);
|
|
4015
|
+
const deviceReg = this.ctx.kernel.deviceRegistry;
|
|
4016
|
+
const deviceApi = this.ctx.kernel.devices;
|
|
4017
|
+
if (!deviceReg || !deviceApi) return;
|
|
4018
|
+
await require_account_integration_offline.cascadeRemoveDevicesForIntegration({
|
|
4019
|
+
reg: deviceReg,
|
|
4020
|
+
devices: deviceApi,
|
|
4021
|
+
addonId: this.addonId,
|
|
4022
|
+
system: "homecom",
|
|
4023
|
+
integrationId,
|
|
4024
|
+
logger: this.ctx.logger
|
|
4025
|
+
});
|
|
4026
|
+
}
|
|
3872
4027
|
subscribeIntegrationLifecycle() {
|
|
3873
4028
|
const handler = (event) => {
|
|
3874
4029
|
const addonId = event.data["addonId"];
|