@attraccess/plugin-wago 0.1.0-nightly.1059.1 → 0.1.0-nightly.1064.1
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/index.js
CHANGED
|
@@ -5346,6 +5346,7 @@ var WagoService = class {
|
|
|
5346
5346
|
if (canonical && (admitted || !canTrackDiagnostics) && typeof rawHeartbeat.streamId === "string" && typeof rawHeartbeat.timestamp === "string") {
|
|
5347
5347
|
this.runtimeStatusHandler?.(controller.id, {
|
|
5348
5348
|
imageId: heartbeat.runtimeImageId ?? "",
|
|
5349
|
+
runtimeVersion: heartbeat.runtimeVersion,
|
|
5349
5350
|
streamId: rawHeartbeat.streamId,
|
|
5350
5351
|
timestamp: Date.parse(rawHeartbeat.timestamp),
|
|
5351
5352
|
receivedAt: Date.now(),
|
|
@@ -9345,15 +9346,40 @@ require_transaction
|
|
|
9345
9346
|
case "$(cat "$tx/phase")" in
|
|
9346
9347
|
accepted|accepted-cleaning)
|
|
9347
9348
|
owned_new_container || fail 'Foreign runtime container'
|
|
9349
|
+
test "$(docker inspect --format '{{.Image}}' attraccess-wago)" = "$(cat "$tx/image-id")" || fail 'Accepted runtime image changed'
|
|
9348
9350
|
phase accepted-cleaning
|
|
9349
9351
|
previous=$(docker container ls -a --no-trunc --filter 'name=^/attraccess-wago.previous$' --format '{{.ID}}')
|
|
9350
9352
|
if test -n "$previous"; then
|
|
9351
9353
|
test "$previous" = "$(cat "$tx/previous-id")" || fail 'Foreign previous runtime'
|
|
9352
9354
|
docker rm "$previous" >/dev/null
|
|
9353
|
-
fi
|
|
9354
|
-
|
|
9355
|
+
fi
|
|
9356
|
+
retired_image=$(cat "$tx/previous-image-id") ;;
|
|
9357
|
+
restored)
|
|
9358
|
+
test "$(docker inspect --format '{{.Image}}' attraccess-wago)" = "$(cat "$tx/previous-image-id")" || fail 'Restored runtime image changed'
|
|
9359
|
+
retired_image=$(cat "$tx/image-id") ;;
|
|
9355
9360
|
*) fail 'Update has not been accepted or restored' ;;
|
|
9356
9361
|
esac
|
|
9362
|
+
# Keep the receipt until image cleanup succeeds. A crash after image removal is
|
|
9363
|
+
# harmless: a successful inventory distinguishes an absent image from a failed
|
|
9364
|
+
# Docker query. Never force removal or prune images outside this transaction.
|
|
9365
|
+
retired_digest=\${retired_image#sha256:}
|
|
9366
|
+
test "$retired_image" != "$retired_digest" && test "\${#retired_digest}" = 64 || fail 'Invalid retired image identity'
|
|
9367
|
+
case "$retired_digest" in *[!a-f0-9]*) fail 'Invalid retired image identity' ;; esac
|
|
9368
|
+
images=$(docker image ls --no-trunc --quiet) || fail 'Cannot inventory runtime images'
|
|
9369
|
+
printf '%s\\n' "$images" | awk 'NF && ($0 !~ /^sha256:[a-f0-9]+$/ || length($0)!=71) {bad=1} END {exit bad}' || fail 'Invalid runtime image inventory'
|
|
9370
|
+
if printf '%s\\n' "$images" | grep -Fxq "$retired_image"; then
|
|
9371
|
+
containers=$(docker container ls -a --no-trunc --format '{{.ID}}') || fail 'Cannot inventory runtime containers'
|
|
9372
|
+
referenced=0
|
|
9373
|
+
for container in $containers; do
|
|
9374
|
+
container_image=$(docker inspect --format '{{.Image}}' "$container") || fail 'Cannot inspect runtime image references'
|
|
9375
|
+
if test "$container_image" = "$retired_image"; then referenced=1; fi
|
|
9376
|
+
done
|
|
9377
|
+
# Stopped containers also retain their images. Docker enforces this again if
|
|
9378
|
+
# an unrelated workload appears after the reference inventory.
|
|
9379
|
+
if test "$referenced" = 0; then
|
|
9380
|
+
docker image rm "$retired_image" >/dev/null || fail 'Retired runtime image cleanup failed'
|
|
9381
|
+
fi
|
|
9382
|
+
fi
|
|
9357
9383
|
mv "$tx" "$cleanup"
|
|
9358
9384
|
sync
|
|
9359
9385
|
rm -rf "$cleanup"
|
|
@@ -10182,6 +10208,9 @@ var import_node_stream2 = require("node:stream");
|
|
|
10182
10208
|
|
|
10183
10209
|
// backend/wago-runtime-update.ts
|
|
10184
10210
|
var import_node_crypto14 = require("node:crypto");
|
|
10211
|
+
function runtimeTargetImageId(desired, installed) {
|
|
10212
|
+
return installed.imageId && installed.runtimeVersion === desired.manifest.runtimeVersion ? installed.imageId : desired.imageId;
|
|
10213
|
+
}
|
|
10185
10214
|
var RuntimeUpdateError = class extends Error {
|
|
10186
10215
|
constructor(failure, storageDiagnostics) {
|
|
10187
10216
|
super(
|
|
@@ -10297,7 +10326,7 @@ var WagoRuntimeUpdateCoordinator = class {
|
|
|
10297
10326
|
}
|
|
10298
10327
|
const desired = await this.desired();
|
|
10299
10328
|
assertOwned();
|
|
10300
|
-
const contradictedCurrent = record2?.phase === "current" && observedImageId !== void 0 && observedImageId !==
|
|
10329
|
+
const contradictedCurrent = record2?.phase === "current" && observedImageId !== void 0 && observedImageId !== (record2.currentImageId ?? record2.desiredImageId);
|
|
10301
10330
|
if (record2 && !contradictedCurrent && record2.desiredImageId === desired.imageId && record2.retryAt > this.now())
|
|
10302
10331
|
return "deferred";
|
|
10303
10332
|
const attempt = (record2?.desiredImageId === desired.imageId ? record2.attempt : 0) + 1;
|
|
@@ -10368,11 +10397,12 @@ var WagoRuntimeUpdateCoordinator = class {
|
|
|
10368
10397
|
return "settled";
|
|
10369
10398
|
}
|
|
10370
10399
|
}
|
|
10371
|
-
|
|
10400
|
+
const targetImageId = runtimeTargetImageId(desired, inspection);
|
|
10401
|
+
if (inspection.imageId === targetImageId) {
|
|
10372
10402
|
const since = record2.startedAt;
|
|
10373
10403
|
try {
|
|
10374
|
-
const proof = await this.host.verify(controllerId, null,
|
|
10375
|
-
if (!proof.permanent || !proof.ready || proof.imageId !==
|
|
10404
|
+
const proof = await this.host.verify(controllerId, null, targetImageId, since, operation.signal);
|
|
10405
|
+
if (!proof.permanent || !proof.ready || proof.imageId !== targetImageId || !Number.isSafeInteger(proof.observedAt) || proof.observedAt <= since || proof.observedAt > this.now())
|
|
10376
10406
|
throw new RuntimeUpdateError("readiness");
|
|
10377
10407
|
await this.assertCurrent(desired.imageId);
|
|
10378
10408
|
} catch (error) {
|
|
@@ -10384,6 +10414,7 @@ var WagoRuntimeUpdateCoordinator = class {
|
|
|
10384
10414
|
return "settled";
|
|
10385
10415
|
}
|
|
10386
10416
|
record2.phase = "current";
|
|
10417
|
+
record2.currentImageId = targetImageId;
|
|
10387
10418
|
record2.attempt = 0;
|
|
10388
10419
|
record2.retryAt = this.now() + CURRENT_RECHECK_MS;
|
|
10389
10420
|
await persist(record2);
|
|
@@ -10417,6 +10448,7 @@ var WagoRuntimeUpdateCoordinator = class {
|
|
|
10417
10448
|
await persist(record2);
|
|
10418
10449
|
await this.host.accept(controllerId, record2.token, operation.signal);
|
|
10419
10450
|
record2.phase = "current";
|
|
10451
|
+
record2.currentImageId = desired.imageId;
|
|
10420
10452
|
record2.attempt = 0;
|
|
10421
10453
|
record2.retryAt = this.now() + CURRENT_RECHECK_MS;
|
|
10422
10454
|
await persist(record2);
|
|
@@ -10842,7 +10874,7 @@ var WagoManagedRuntimeService = class {
|
|
|
10842
10874
|
__publicField(this, "coordinator");
|
|
10843
10875
|
__publicField(this, "heartbeats", /* @__PURE__ */ new Map());
|
|
10844
10876
|
__publicField(this, "heartbeatStreams", /* @__PURE__ */ new Map());
|
|
10845
|
-
__publicField(this, "
|
|
10877
|
+
__publicField(this, "runtimeActivations", /* @__PURE__ */ new Map());
|
|
10846
10878
|
__publicField(this, "verifyingControllers", /* @__PURE__ */ new Set());
|
|
10847
10879
|
__publicField(this, "connectingControllers", /* @__PURE__ */ new Set());
|
|
10848
10880
|
__publicField(this, "reconciliationFailures", /* @__PURE__ */ new Map());
|
|
@@ -10888,7 +10920,7 @@ var WagoManagedRuntimeService = class {
|
|
|
10888
10920
|
this.heartbeatStreams.delete(oldest);
|
|
10889
10921
|
}
|
|
10890
10922
|
}
|
|
10891
|
-
if (!previous || previous.runtimePolicyToken !== heartbeat.runtimePolicyToken || previous.streamId !== heartbeat.streamId || previous.imageId !== heartbeat.imageId || heartbeat.receivedAt - previous.receivedAt > 9e4) {
|
|
10923
|
+
if (!previous || previous.runtimePolicyToken !== heartbeat.runtimePolicyToken || previous.streamId !== heartbeat.streamId || previous.imageId !== heartbeat.imageId || previous.runtimeVersion !== heartbeat.runtimeVersion || heartbeat.receivedAt - previous.receivedAt > 9e4) {
|
|
10892
10924
|
this.wago.blockRuntime?.(id);
|
|
10893
10925
|
if (!this.connectingControllers.has(id) && this.connectingControllers.size < 200) {
|
|
10894
10926
|
this.connectingControllers.add(id);
|
|
@@ -11039,7 +11071,10 @@ var WagoManagedRuntimeService = class {
|
|
|
11039
11071
|
runningVersion: controller.runtimeVersion,
|
|
11040
11072
|
runningImageId: this.heartbeats.get(controller.id)?.imageId || null,
|
|
11041
11073
|
desiredVersion: desired?.manifest.runtimeVersion ?? null,
|
|
11042
|
-
desiredImageId: desired && "imageId" in desired ? desired
|
|
11074
|
+
desiredImageId: desired && "imageId" in desired ? runtimeTargetImageId(desired, {
|
|
11075
|
+
imageId: this.heartbeats.get(controller.id)?.imageId ?? "",
|
|
11076
|
+
runtimeVersion: this.heartbeats.get(controller.id)?.runtimeVersion ?? controller.runtimeVersion
|
|
11077
|
+
}) : null
|
|
11043
11078
|
}
|
|
11044
11079
|
} : {},
|
|
11045
11080
|
...access?.controllerId && this.wago.isRuntimeUpdateRequired ? { runtimeUpdateRequired: this.wago.isRuntimeUpdateRequired(access.controllerId) } : {},
|
|
@@ -11330,9 +11365,13 @@ var WagoManagedRuntimeService = class {
|
|
|
11330
11365
|
if (!heartbeat || this.destroyed) return;
|
|
11331
11366
|
const access = await this.access.findOne({ where: { controllerId: id }, order: { sessionId: "DESC" } });
|
|
11332
11367
|
const enrolling = access?.state === "verified" || access?.state === "recovery_required";
|
|
11368
|
+
const controller = await this.controllers.findOneBy({ id, trustState: "claimed" });
|
|
11333
11369
|
await this.wago.setRuntimePolicy?.(
|
|
11334
11370
|
id,
|
|
11335
|
-
enrolling ? heartbeat.imageId : desired
|
|
11371
|
+
enrolling ? heartbeat.imageId : runtimeTargetImageId(desired, {
|
|
11372
|
+
imageId: heartbeat.imageId,
|
|
11373
|
+
runtimeVersion: heartbeat.runtimeVersion ?? controller?.runtimeVersion
|
|
11374
|
+
}),
|
|
11336
11375
|
heartbeat.imageId,
|
|
11337
11376
|
heartbeat.runtimePolicyToken
|
|
11338
11377
|
);
|
|
@@ -11631,7 +11670,7 @@ var WagoManagedRuntimeService = class {
|
|
|
11631
11670
|
if (!match) throw new RuntimeUpdateError("incompatible");
|
|
11632
11671
|
return {
|
|
11633
11672
|
imageId: match[2],
|
|
11634
|
-
runtimeVersion: controller?.runtimeVersion,
|
|
11673
|
+
runtimeVersion: this.heartbeats.get(id)?.runtimeVersion ?? controller?.runtimeVersion,
|
|
11635
11674
|
claimed: !!controller,
|
|
11636
11675
|
managed: true,
|
|
11637
11676
|
compatible: true,
|
|
@@ -11678,10 +11717,13 @@ var WagoManagedRuntimeService = class {
|
|
|
11678
11717
|
await bundle.cleanup();
|
|
11679
11718
|
}
|
|
11680
11719
|
},
|
|
11681
|
-
activate: async (id, token,
|
|
11720
|
+
activate: async (id, token, artifact, signal) => {
|
|
11682
11721
|
const heartbeat = this.heartbeats.get(id);
|
|
11683
|
-
|
|
11684
|
-
|
|
11722
|
+
this.runtimeActivations.set(token, {
|
|
11723
|
+
imageId: artifact.imageId,
|
|
11724
|
+
startedAt: Date.now(),
|
|
11725
|
+
previousStreamId: heartbeat?.streamId
|
|
11726
|
+
});
|
|
11685
11727
|
this.verifyingControllers.add(id);
|
|
11686
11728
|
await command(id, "activate", token, signal);
|
|
11687
11729
|
},
|
|
@@ -11689,11 +11731,13 @@ var WagoManagedRuntimeService = class {
|
|
|
11689
11731
|
const controller = await this.controllers.findOneByOrFail({ id, trustState: "claimed" });
|
|
11690
11732
|
if (!controller.mqttServerId) throw new RuntimeUpdateError("offline");
|
|
11691
11733
|
const prefix = (await this.wago.getSettings()).operationalPrefix;
|
|
11734
|
+
const activation = _token === null ? void 0 : this.runtimeActivations.get(_token);
|
|
11735
|
+
const freshSince = Math.max(since, activation?.startedAt ?? since);
|
|
11692
11736
|
for (let attempt = 0; attempt < 120; attempt++) {
|
|
11693
11737
|
signal.throwIfAborted();
|
|
11694
11738
|
const heartbeat = this.heartbeats.get(id);
|
|
11695
11739
|
const state = this.readiness.observe(controller.mqttServerId, controller.hardwareId, prefix);
|
|
11696
|
-
if (heartbeat?.imageId === imageId && (_token === null ||
|
|
11740
|
+
if (heartbeat?.imageId === imageId && (_token === null || activation?.imageId === imageId && heartbeat.streamId !== activation.previousStreamId) && heartbeat.timestamp > freshSince && heartbeat.receivedAt > freshSince && Date.now() - heartbeat.receivedAt < 9e4 && state?.timestamp > freshSince && Date.now() - state.timestamp < 9e4 && state.streamId === heartbeat.streamId && state.ready)
|
|
11697
11741
|
return { imageId, observedAt: heartbeat.receivedAt, permanent: true, ready: true };
|
|
11698
11742
|
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
11699
11743
|
}
|
|
@@ -11706,7 +11750,7 @@ var WagoManagedRuntimeService = class {
|
|
|
11706
11750
|
try {
|
|
11707
11751
|
await command(id, "acknowledge", token, signal);
|
|
11708
11752
|
} finally {
|
|
11709
|
-
this.
|
|
11753
|
+
this.runtimeActivations.delete(token);
|
|
11710
11754
|
this.verifyingControllers.delete(id);
|
|
11711
11755
|
}
|
|
11712
11756
|
},
|
|
@@ -11714,7 +11758,7 @@ var WagoManagedRuntimeService = class {
|
|
|
11714
11758
|
try {
|
|
11715
11759
|
await command(id, "recover", token, signal, previous);
|
|
11716
11760
|
} finally {
|
|
11717
|
-
this.
|
|
11761
|
+
this.runtimeActivations.delete(token);
|
|
11718
11762
|
this.verifyingControllers.delete(id);
|
|
11719
11763
|
}
|
|
11720
11764
|
}
|
|
@@ -11750,7 +11794,7 @@ var WagoManagedRuntimeService = class {
|
|
|
11750
11794
|
await stopped;
|
|
11751
11795
|
this.heartbeats.clear();
|
|
11752
11796
|
this.heartbeatStreams.clear();
|
|
11753
|
-
this.
|
|
11797
|
+
this.runtimeActivations.clear();
|
|
11754
11798
|
this.verifyingControllers.clear();
|
|
11755
11799
|
this.enrolmentProgress.clear();
|
|
11756
11800
|
}
|
|
@@ -15777,6 +15821,81 @@ WagoUpdatesController = __decorateClass([
|
|
|
15777
15821
|
__decorateParam(1, (0, import_common17.Inject)(WagoNetworkChangeService))
|
|
15778
15822
|
], WagoUpdatesController);
|
|
15779
15823
|
|
|
15824
|
+
// backend/wago-live-updates.service.ts
|
|
15825
|
+
var import_common18 = require("@nestjs/common");
|
|
15826
|
+
var import_plugins_backend_sdk21 = require("@attraccess/plugins-backend-sdk");
|
|
15827
|
+
var WagoLiveUpdatesService = class {
|
|
15828
|
+
constructor(context, wago, commissioning, diagnostics, managed, network) {
|
|
15829
|
+
__publicField(this, "context", context);
|
|
15830
|
+
__publicField(this, "wago", wago);
|
|
15831
|
+
__publicField(this, "commissioning", commissioning);
|
|
15832
|
+
__publicField(this, "diagnostics", diagnostics);
|
|
15833
|
+
__publicField(this, "managed", managed);
|
|
15834
|
+
__publicField(this, "network", network);
|
|
15835
|
+
__publicField(this, "sample", (0, import_plugins_backend_sdk21.createSharedLiveSampler)());
|
|
15836
|
+
}
|
|
15837
|
+
onModuleInit() {
|
|
15838
|
+
const live = this.context.liveUpdates;
|
|
15839
|
+
if (!live) throw new Error("WAGO live updates require a host with plugin live-update support");
|
|
15840
|
+
const register = (topic, interval, permission, kind, read) => {
|
|
15841
|
+
live.register({
|
|
15842
|
+
topic,
|
|
15843
|
+
identifier: kind === "none" ? "none" : "required",
|
|
15844
|
+
authorize: async ({ identifier: identifier3 }, user) => {
|
|
15845
|
+
if (!user.effectivePermissions?.has(permission)) throw new import_common18.ForbiddenException();
|
|
15846
|
+
if (kind === "none") return;
|
|
15847
|
+
const pattern = kind === "revisions" ? /^[1-9]\d*:(0|[1-9]\d*)$/ : /^[1-9]\d*$/;
|
|
15848
|
+
if (!pattern.test(identifier3 ?? "")) throw new import_common18.NotFoundException();
|
|
15849
|
+
const [id, offset = 0] = identifier3.split(":").map(Number);
|
|
15850
|
+
if (!Number.isSafeInteger(id) || !Number.isSafeInteger(offset)) throw new import_common18.NotFoundException();
|
|
15851
|
+
const exists = kind === "session" ? await this.context.getRepository(WagoCommissioningSession).existsBy({ id }) : await this.context.getRepository(WagoController).existsBy({ id });
|
|
15852
|
+
if (!exists) throw new import_common18.NotFoundException();
|
|
15853
|
+
},
|
|
15854
|
+
source: ({ identifier: identifier3 }) => this.sample(`${topic}:${identifier3 ?? ""}`, interval, () => {
|
|
15855
|
+
const [id = 0, offset = 0] = (identifier3 ?? "").split(":").map(Number);
|
|
15856
|
+
return read(id, offset);
|
|
15857
|
+
})
|
|
15858
|
+
});
|
|
15859
|
+
};
|
|
15860
|
+
register("controllers", 1e4, "resources.update", "none", () => this.wago.list());
|
|
15861
|
+
register("commissioning-sessions", 2e3, "system.settings.manage", "none", () => this.commissioning.list(100, 0));
|
|
15862
|
+
register("diagnostics", 2e3, "resources.update", "controller", (id) => this.diagnostics.get(id));
|
|
15863
|
+
register(
|
|
15864
|
+
"configuration-baseline",
|
|
15865
|
+
2e3,
|
|
15866
|
+
"resources.update",
|
|
15867
|
+
"controller",
|
|
15868
|
+
(id) => this.wago.getConfigurationBaseline(id)
|
|
15869
|
+
);
|
|
15870
|
+
register(
|
|
15871
|
+
"configuration-revisions",
|
|
15872
|
+
2e3,
|
|
15873
|
+
"resources.update",
|
|
15874
|
+
"revisions",
|
|
15875
|
+
(id, offset) => this.wago.revisionsFor(id, offset)
|
|
15876
|
+
);
|
|
15877
|
+
register(
|
|
15878
|
+
"commissioning-verification",
|
|
15879
|
+
5e3,
|
|
15880
|
+
"system.settings.manage",
|
|
15881
|
+
"session",
|
|
15882
|
+
(id) => this.commissioning.verification(id)
|
|
15883
|
+
);
|
|
15884
|
+
register("runtime-update", 5e3, "system.settings.manage", "controller", (id) => this.managed.status(id));
|
|
15885
|
+
register("managed-access", 5e3, "system.settings.manage", "session", (id) => this.managed.sessionStatus(id));
|
|
15886
|
+
register("network-change", 2e3, "system.settings.manage", "controller", (id) => this.network.status(id));
|
|
15887
|
+
}
|
|
15888
|
+
};
|
|
15889
|
+
WagoLiveUpdatesService = __decorateClass([
|
|
15890
|
+
(0, import_common18.Injectable)(),
|
|
15891
|
+
__decorateParam(0, (0, import_common18.Inject)(/* @__PURE__ */ Symbol.for("attraccess.plugin.context"))),
|
|
15892
|
+
__decorateParam(1, (0, import_common18.Inject)(WagoService)),
|
|
15893
|
+
__decorateParam(2, (0, import_common18.Inject)(WagoCommissioningService)),
|
|
15894
|
+
__decorateParam(3, (0, import_common18.Inject)(WagoDiagnosticsService)),
|
|
15895
|
+
__decorateParam(4, (0, import_common18.Inject)(WagoManagedRuntimeService)),
|
|
15896
|
+
__decorateParam(5, (0, import_common18.Inject)(WagoNetworkChangeService))
|
|
15897
|
+
], WagoLiveUpdatesService);
|
|
15898
|
+
|
|
15780
15899
|
// backend/plugin.ts
|
|
15781
15900
|
var PLUGIN_CONTEXT6 = /* @__PURE__ */ Symbol.for("attraccess.plugin.context");
|
|
15782
15901
|
var WagoPluginModule = class {
|
|
@@ -15835,7 +15954,8 @@ var plugin = {
|
|
|
15835
15954
|
WagoManagedRuntimeService,
|
|
15836
15955
|
WagoCommissioningService,
|
|
15837
15956
|
WagoCredentialRotationService,
|
|
15838
|
-
WagoNetworkChangeService
|
|
15957
|
+
WagoNetworkChangeService,
|
|
15958
|
+
WagoLiveUpdatesService
|
|
15839
15959
|
]
|
|
15840
15960
|
};
|
|
15841
15961
|
}
|
package/frontend/{__federation_expose_Plugin-BQawMHeJ.js → __federation_expose_Plugin-KY-OYpkJ.js}
RENAMED
|
@@ -61,9 +61,6 @@ function createPluginApiClient(basePath = "") {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
//#endregion
|
|
64
|
-
//#region ../../../libs/plugins-frontend-sdk/src/lib/frontend.slots.ts
|
|
65
|
-
var RESOURCE_OVERVIEW_SLOT = "resource.overview";
|
|
66
|
-
//#endregion
|
|
67
64
|
//#region ../../../node_modules/.pnpm/react@19.2.8/node_modules/react/cjs/react-jsx-runtime.production.js
|
|
68
65
|
/**
|
|
69
66
|
* @license React
|
|
@@ -99,10 +96,64 @@ var require_react_jsx_runtime_production = /* @__PURE__ */ __commonJSMin(((expor
|
|
|
99
96
|
exports.jsxs = jsxProd;
|
|
100
97
|
}));
|
|
101
98
|
//#endregion
|
|
102
|
-
//#region ../../../libs/plugins-frontend-sdk/src/lib/frontend.
|
|
99
|
+
//#region ../../../libs/plugins-frontend-sdk/src/lib/frontend.live-updates.tsx
|
|
103
100
|
var import_jsx_runtime = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
104
101
|
module.exports = require_react_jsx_runtime_production();
|
|
105
102
|
})))();
|
|
103
|
+
var { createContext, useCallback, useContext, useEffect: useEffect$12, useRef: useRef$5 } = await importShared("react");
|
|
104
|
+
var contextKey = Symbol.for("attraccess.plugin.live-updates.context");
|
|
105
|
+
var contexts = globalThis;
|
|
106
|
+
var LiveContext = contexts[contextKey] ??= createContext(null);
|
|
107
|
+
function usePluginLiveUpdates(props) {
|
|
108
|
+
const client = useContext(LiveContext);
|
|
109
|
+
const latest = useRef$5({
|
|
110
|
+
props,
|
|
111
|
+
client
|
|
112
|
+
});
|
|
113
|
+
latest.current = {
|
|
114
|
+
props,
|
|
115
|
+
client
|
|
116
|
+
};
|
|
117
|
+
const unsubscribe = useRef$5(null);
|
|
118
|
+
const { plugin, topic, identifier, enabled = true } = props;
|
|
119
|
+
useEffect$12(() => {
|
|
120
|
+
if (!client || !enabled) return;
|
|
121
|
+
let active = true;
|
|
122
|
+
const matches = () => active && latest.current.client === client && latest.current.props.enabled !== false && latest.current.props.plugin === plugin && latest.current.props.topic === topic && latest.current.props.identifier === identifier;
|
|
123
|
+
const remove = client.subscribe({
|
|
124
|
+
topic: `plugin:${encodeURIComponent(plugin)}:${topic}`,
|
|
125
|
+
...identifier !== void 0 ? { identifier } : {}
|
|
126
|
+
}, (payload) => {
|
|
127
|
+
if (matches()) return latest.current.props.onUpdate(payload);
|
|
128
|
+
}, () => {
|
|
129
|
+
if (matches()) return latest.current.props.onReconnect?.();
|
|
130
|
+
}, () => {
|
|
131
|
+
if (matches()) return latest.current.props.onUnavailable?.();
|
|
132
|
+
});
|
|
133
|
+
const cleanup = () => {
|
|
134
|
+
if (!active) return;
|
|
135
|
+
active = false;
|
|
136
|
+
remove();
|
|
137
|
+
};
|
|
138
|
+
unsubscribe.current = cleanup;
|
|
139
|
+
return () => {
|
|
140
|
+
cleanup();
|
|
141
|
+
if (unsubscribe.current === cleanup) unsubscribe.current = null;
|
|
142
|
+
};
|
|
143
|
+
}, [
|
|
144
|
+
client,
|
|
145
|
+
plugin,
|
|
146
|
+
topic,
|
|
147
|
+
identifier,
|
|
148
|
+
enabled
|
|
149
|
+
]);
|
|
150
|
+
return { abort: useCallback(() => unsubscribe.current?.(), []) };
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region ../../../libs/plugins-frontend-sdk/src/lib/frontend.slots.ts
|
|
154
|
+
var RESOURCE_OVERVIEW_SLOT = "resource.overview";
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region ../../../libs/plugins-frontend-sdk/src/lib/frontend.standard-drawer.tsx
|
|
106
157
|
var { DrawerBackdrop: DrawerBackdrop$1, DrawerContent: DrawerContent$1, DrawerDialog: DrawerDialog$1 } = await importShared("@heroui/react");
|
|
107
158
|
//#endregion
|
|
108
159
|
//#region ../../../libs/plugins-frontend-sdk/src/lib/frontend.standard-modal.tsx
|
|
@@ -112,6 +163,69 @@ var { Modal: Modal$3, ModalBackdrop: ModalBackdrop$2, ModalContainer: ModalConta
|
|
|
112
163
|
/** Invalidate this prefix after plugin configuration changes to refresh canvas summaries. */
|
|
113
164
|
var FLOW_NODE_PREVIEW_QUERY_KEY = ["flow-node-preview"];
|
|
114
165
|
//#endregion
|
|
166
|
+
//#region frontend/src/live-updates.ts
|
|
167
|
+
var { useQueryClient: useQueryClient$4 } = await importShared("@tanstack/react-query");
|
|
168
|
+
var liveStates = /* @__PURE__ */ new WeakMap();
|
|
169
|
+
/** Initial reads/mutations remain REST; the host stream owns snapshots and reconnect refresh. */
|
|
170
|
+
function useWagoLiveQuery(queryKey, topic, identifier, enabled = true) {
|
|
171
|
+
const client = useQueryClient$4();
|
|
172
|
+
const onUpdate = (event) => {
|
|
173
|
+
const existingQuery = client.getQueryCache().find({
|
|
174
|
+
queryKey,
|
|
175
|
+
exact: true
|
|
176
|
+
});
|
|
177
|
+
const previous = existingQuery && liveStates.get(existingQuery);
|
|
178
|
+
const cancellation = client.cancelQueries({
|
|
179
|
+
queryKey,
|
|
180
|
+
exact: true
|
|
181
|
+
});
|
|
182
|
+
if (event.eventType === "snapshot") client.setQueryData(queryKey, event.value);
|
|
183
|
+
else {
|
|
184
|
+
const query = client.getQueryCache().find({
|
|
185
|
+
queryKey,
|
|
186
|
+
exact: true
|
|
187
|
+
});
|
|
188
|
+
query?.setState({
|
|
189
|
+
...existingQuery === query && previous?.pendingRead === query.promise ? previous?.state : void 0,
|
|
190
|
+
status: "error",
|
|
191
|
+
error: /* @__PURE__ */ new Error("Live updates are temporarily unavailable."),
|
|
192
|
+
errorUpdatedAt: Date.now()
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
const query = client.getQueryCache().find({
|
|
196
|
+
queryKey,
|
|
197
|
+
exact: true
|
|
198
|
+
});
|
|
199
|
+
if (!query) return;
|
|
200
|
+
const state = query.state;
|
|
201
|
+
const pendingRead = query.promise;
|
|
202
|
+
liveStates.set(query, {
|
|
203
|
+
state,
|
|
204
|
+
pendingRead
|
|
205
|
+
});
|
|
206
|
+
return cancellation.then(() => {
|
|
207
|
+
if (liveStates.get(query)?.state === state && query.promise === pendingRead && client.getQueryCache().find({
|
|
208
|
+
queryKey,
|
|
209
|
+
exact: true
|
|
210
|
+
}) === query) {
|
|
211
|
+
liveStates.delete(query);
|
|
212
|
+
if (query.state !== state || query.state.fetchStatus !== "idle") query.setState({
|
|
213
|
+
...state,
|
|
214
|
+
fetchStatus: "idle"
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
return usePluginLiveUpdates({
|
|
220
|
+
plugin: "wago",
|
|
221
|
+
topic,
|
|
222
|
+
identifier,
|
|
223
|
+
enabled,
|
|
224
|
+
onUpdate,
|
|
225
|
+
onUnavailable: () => onUpdate({ eventType: "unavailable" })
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
//#endregion
|
|
115
229
|
//#region frontend/src/api.ts
|
|
116
230
|
var api$5 = createPluginApiClient("/api/wago");
|
|
117
231
|
var hostApi = createPluginApiClient("/api");
|
|
@@ -234,18 +348,17 @@ var queryKeys = {
|
|
|
234
348
|
commissioningSessions: ["wago", "commissioning-sessions"]
|
|
235
349
|
};
|
|
236
350
|
function useControllersQuery() {
|
|
351
|
+
useWagoLiveQuery(queryKeys.controllers, "controllers");
|
|
237
352
|
return useQuery$6({
|
|
238
353
|
queryKey: queryKeys.controllers,
|
|
239
|
-
queryFn: listControllers
|
|
240
|
-
refetchInterval: 1e4
|
|
354
|
+
queryFn: listControllers
|
|
241
355
|
});
|
|
242
356
|
}
|
|
243
357
|
function useCommissioningSessionsQuery() {
|
|
358
|
+
useWagoLiveQuery(queryKeys.commissioningSessions, "commissioning-sessions");
|
|
244
359
|
return useQuery$6({
|
|
245
360
|
queryKey: queryKeys.commissioningSessions,
|
|
246
|
-
queryFn: ({ signal }) => listCommissioningSessions(100, 0, signal)
|
|
247
|
-
refetchInterval: 2e3,
|
|
248
|
-
refetchIntervalInBackground: true
|
|
361
|
+
queryFn: ({ signal }) => listCommissioningSessions(100, 0, signal)
|
|
249
362
|
});
|
|
250
363
|
}
|
|
251
364
|
function useSettingsQuery() {
|
|
@@ -350,10 +463,10 @@ function useDraftQuery(controllerId) {
|
|
|
350
463
|
});
|
|
351
464
|
}
|
|
352
465
|
function useConfigurationRevisionsQuery(controllerId, offset) {
|
|
466
|
+
useWagoLiveQuery([...queryKeys.revisions(controllerId), offset], "configuration-revisions", `${controllerId}:${offset}`);
|
|
353
467
|
return useQuery$6({
|
|
354
468
|
queryKey: [...queryKeys.revisions(controllerId), offset],
|
|
355
|
-
queryFn: () => listConfigurationRevisions(controllerId, offset)
|
|
356
|
-
refetchInterval: 2e3
|
|
469
|
+
queryFn: () => listConfigurationRevisions(controllerId, offset)
|
|
357
470
|
});
|
|
358
471
|
}
|
|
359
472
|
function useConfigurationRevisionPreviewQuery(controllerId, revision, enabled) {
|
|
@@ -3382,16 +3495,23 @@ function ClaimControllerModal({ controllerId, onOpenChange }) {
|
|
|
3382
3495
|
//#region frontend/src/useRuntimeStatus.ts
|
|
3383
3496
|
var { useQuery: useQuery$5 } = await importShared("@tanstack/react-query");
|
|
3384
3497
|
function useRuntimeStatus(target) {
|
|
3498
|
+
const controllerId = target && "controller" in target ? target.controller.id : null;
|
|
3499
|
+
const sessionId = target && "session" in target ? target.session.id : null;
|
|
3500
|
+
useWagoLiveQuery([
|
|
3501
|
+
"wago",
|
|
3502
|
+
"runtime-update",
|
|
3503
|
+
controllerId,
|
|
3504
|
+
sessionId
|
|
3505
|
+
], controllerId !== null ? "runtime-update" : "managed-access", String(controllerId ?? sessionId), !!target);
|
|
3385
3506
|
return useQuery$5({
|
|
3386
3507
|
queryKey: [
|
|
3387
3508
|
"wago",
|
|
3388
3509
|
"runtime-update",
|
|
3389
|
-
|
|
3390
|
-
|
|
3510
|
+
controllerId,
|
|
3511
|
+
sessionId
|
|
3391
3512
|
],
|
|
3392
3513
|
queryFn: () => target && "controller" in target ? getRuntimeUpdateStatus(target.controller.id) : target && "session" in target ? getManagedAccessStatus(target.session.id) : Promise.reject(/* @__PURE__ */ new Error("No controller selected")),
|
|
3393
3514
|
enabled: !!target,
|
|
3394
|
-
refetchInterval: 5e3,
|
|
3395
3515
|
staleTime: 4e3,
|
|
3396
3516
|
retry: false
|
|
3397
3517
|
});
|
|
@@ -3692,6 +3812,11 @@ var { useEffect: useEffect$10, useState: useState$17 } = await importShared("rea
|
|
|
3692
3812
|
/** Enrollment evidence is independent of configuration and physical qualification. */
|
|
3693
3813
|
function useCommissioningVerification(session) {
|
|
3694
3814
|
const enabled = ["awaiting_verification", "completed"].includes(session.state);
|
|
3815
|
+
useWagoLiveQuery([
|
|
3816
|
+
"wago",
|
|
3817
|
+
"commissioning-verification",
|
|
3818
|
+
session.id
|
|
3819
|
+
], "commissioning-verification", String(session.id), enabled);
|
|
3695
3820
|
const query = useQuery$4({
|
|
3696
3821
|
queryKey: [
|
|
3697
3822
|
"wago",
|
|
@@ -3699,9 +3824,7 @@ function useCommissioningVerification(session) {
|
|
|
3699
3824
|
session.id
|
|
3700
3825
|
],
|
|
3701
3826
|
queryFn: () => getCommissioningVerification(session.id),
|
|
3702
|
-
enabled
|
|
3703
|
-
refetchInterval: 5e3,
|
|
3704
|
-
refetchIntervalInBackground: true
|
|
3827
|
+
enabled
|
|
3705
3828
|
});
|
|
3706
3829
|
const [now, setNow] = useState$17(Date.now);
|
|
3707
3830
|
useEffect$10(() => {
|
|
@@ -3740,10 +3863,10 @@ function NetworkChangeForm({ controllerId }) {
|
|
|
3740
3863
|
"network-change",
|
|
3741
3864
|
controllerId
|
|
3742
3865
|
];
|
|
3866
|
+
useWagoLiveQuery(queryKey, "network-change", String(controllerId));
|
|
3743
3867
|
const statusQuery = useQuery$3({
|
|
3744
3868
|
queryKey,
|
|
3745
3869
|
queryFn: () => getNetworkChangeStatus(controllerId),
|
|
3746
|
-
refetchInterval: 2e3,
|
|
3747
3870
|
retry: false
|
|
3748
3871
|
});
|
|
3749
3872
|
const servers = useQuery$3({
|
|
@@ -9258,7 +9381,12 @@ function DeviceSettings({ configuration, device: original, onChange, onClose, is
|
|
|
9258
9381
|
//#region frontend/src/diagnostics.ts
|
|
9259
9382
|
var { useQuery: useQuery$2 } = await importShared("@tanstack/react-query");
|
|
9260
9383
|
var api$1 = createPluginApiClient("/api/wago");
|
|
9261
|
-
function useWagoDiagnostics(controllerId
|
|
9384
|
+
function useWagoDiagnostics(controllerId) {
|
|
9385
|
+
useWagoLiveQuery([
|
|
9386
|
+
"wago",
|
|
9387
|
+
"diagnostics",
|
|
9388
|
+
controllerId
|
|
9389
|
+
], "diagnostics", String(controllerId), controllerId !== null);
|
|
9262
9390
|
return useQuery$2({
|
|
9263
9391
|
queryKey: [
|
|
9264
9392
|
"wago",
|
|
@@ -9267,7 +9395,6 @@ function useWagoDiagnostics(controllerId, refetchInterval = 5e3) {
|
|
|
9267
9395
|
],
|
|
9268
9396
|
queryFn: () => api$1.request(`/controllers/${controllerId}/diagnostics`),
|
|
9269
9397
|
enabled: controllerId !== null,
|
|
9270
|
-
refetchInterval,
|
|
9271
9398
|
retry: 1
|
|
9272
9399
|
});
|
|
9273
9400
|
}
|
|
@@ -9300,16 +9427,20 @@ function useFrontPanel(controllerId) {
|
|
|
9300
9427
|
];
|
|
9301
9428
|
const [restored] = useState$4(() => client.getQueryData(key));
|
|
9302
9429
|
const draft = useDraftQuery(controllerId);
|
|
9430
|
+
useWagoLiveQuery([
|
|
9431
|
+
"wago",
|
|
9432
|
+
"configuration-baseline",
|
|
9433
|
+
controllerId
|
|
9434
|
+
], "configuration-baseline", String(controllerId));
|
|
9303
9435
|
const baseline = useQuery$1({
|
|
9304
9436
|
queryKey: [
|
|
9305
9437
|
"wago",
|
|
9306
9438
|
"configuration-baseline",
|
|
9307
9439
|
controllerId
|
|
9308
9440
|
],
|
|
9309
|
-
queryFn: () => getConfigurationBaseline(controllerId)
|
|
9310
|
-
refetchInterval: 2e3
|
|
9441
|
+
queryFn: () => getConfigurationBaseline(controllerId)
|
|
9311
9442
|
});
|
|
9312
|
-
const diagnostics = useWagoDiagnostics(controllerId
|
|
9443
|
+
const diagnostics = useWagoDiagnostics(controllerId);
|
|
9313
9444
|
const [configuration, setConfiguration] = useState$4(restored?.configuration ?? null);
|
|
9314
9445
|
const loadedDraft = useRef(restored?.loadedDraft ?? null);
|
|
9315
9446
|
const [editing, setEditing] = useState$4(Boolean(restored));
|
package/frontend/remoteEntry.js
CHANGED
|
@@ -75,7 +75,7 @@ var exportSet = /* @__PURE__ */ new Set([
|
|
|
75
75
|
]);
|
|
76
76
|
var moduleMap = { "./plugin": () => {
|
|
77
77
|
dynamicLoadingCss(["style.css"], false, "./plugin");
|
|
78
|
-
return __federation_import("./__federation_expose_Plugin-
|
|
78
|
+
return __federation_import("./__federation_expose_Plugin-KY-OYpkJ.js").then((module) => Object.keys(module).every((item) => exportSet.has(item)) ? () => module.default : () => module);
|
|
79
79
|
} };
|
|
80
80
|
var seen = {};
|
|
81
81
|
var dynamicLoadingCss = (cssFilePaths, dontAppendStylesToHead, exposeItemName) => {
|