@kwirthmagnify/kwirth-plugin-status 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/back.js +242 -0
  2. package/front.js +259 -0
  3. package/package.json +12 -0
package/back.js ADDED
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // kwirth-back-globals:@kwirthmagnify/kwirth-common-back
34
+ var require_kwirth_common_back = __commonJS({
35
+ "kwirth-back-globals:@kwirthmagnify/kwirth-common-back"(exports2, module2) {
36
+ module2.exports = global.__kwirth_back__.kwirthCommonBack;
37
+ }
38
+ });
39
+
40
+ // src/back/index.ts
41
+ var index_exports = {};
42
+ __export(index_exports, {
43
+ StatusChannel: () => StatusChannel,
44
+ default: () => index_default
45
+ });
46
+ module.exports = __toCommonJS(index_exports);
47
+ var import_kwirth_common_back = __toESM(require_kwirth_common_back(), 1);
48
+ var StatusChannel = class {
49
+ constructor(clusterInfo, backChannelObject) {
50
+ this.channelId = "status";
51
+ /*
52
+ Sin providers y sin almacenamiento. Declarar un provider aquí lo ARRANCARÍA como efecto colateral
53
+ de tener instalado un visor de estado —el core instancia lo que algún canal declara—, y entonces
54
+ esta pantalla estaría modificando justo lo que dice observar.
55
+ */
56
+ this.requirements = { storage: false, providers: [] };
57
+ this.webSockets = [];
58
+ this.getChannelData = () => ({
59
+ id: "status",
60
+ routable: false,
61
+ pauseable: false,
62
+ // no hay flujo que pausar: es una foto bajo demanda
63
+ modifiable: false,
64
+ reconnectable: true,
65
+ metrics: false,
66
+ sources: [import_kwirth_common_back.EClusterType.KUBERNETES, import_kwirth_common_back.EClusterType.DOCKER],
67
+ endpoints: [],
68
+ websocket: false,
69
+ cluster: true,
70
+ // lo que se mira es el Kwirth entero, no un pod
71
+ resourced: false
72
+ });
73
+ /*
74
+ Ver el inventario completo es una vista privilegiada: enseña todas las extensiones montadas y su
75
+ estado. Por eso el nivel mínimo es 'cluster' y no hay escalón por namespace — no tendría sentido
76
+ un inventario "de un namespace", y dejarlo en 'none' lo abriría a cualquiera.
77
+ */
78
+ this.getChannelScopeLevel = (scope) => ["", "none", "cluster"].indexOf(scope);
79
+ this.startChannel = async () => {
80
+ };
81
+ this.addObject = async (webSocket, instanceConfig, _ns, _pod, _container) => {
82
+ let socket = this.webSockets.find((s) => s.ws === webSocket);
83
+ if (!socket) {
84
+ socket = { ws: webSocket, lastRefresh: Date.now(), instanceIds: [] };
85
+ this.webSockets.push(socket);
86
+ }
87
+ if (!socket.instanceIds.includes(instanceConfig.instance)) socket.instanceIds.push(instanceConfig.instance);
88
+ this.sendInventory(socket, instanceConfig.instance);
89
+ return true;
90
+ };
91
+ this.deleteObject = async (_webSocket, _instanceConfig, _ns, _pod, _container) => true;
92
+ this.pauseContinueInstance = (_webSocket, _instanceConfig, _action) => {
93
+ };
94
+ this.modifyInstance = (_webSocket, _instanceConfig) => {
95
+ };
96
+ this.containsInstance = (instanceId) => this.webSockets.some((socket) => socket.instanceIds.includes(instanceId));
97
+ this.containsAsset = (_webSocket, _podNamespace, _podName, _containerName) => false;
98
+ this.stopInstance = (webSocket, instanceConfig) => {
99
+ this.removeInstance(webSocket, instanceConfig.instance);
100
+ };
101
+ this.removeInstance = (webSocket, instanceId) => {
102
+ const socket = this.webSockets.find((s) => s.ws === webSocket);
103
+ if (!socket) return;
104
+ const pos = socket.instanceIds.indexOf(instanceId);
105
+ if (pos >= 0) socket.instanceIds.splice(pos, 1);
106
+ };
107
+ /*
108
+ Volver a pedir la foto. Es la ÚNICA forma de que este canal haga trabajo: alguien con la pantalla
109
+ abierta pulsa refrescar. No hay refresco automático a propósito — sería recolección disfrazada.
110
+ */
111
+ this.processCommand = async (webSocket, instanceMessage) => {
112
+ if (instanceMessage.flow === import_kwirth_common_back.EInstanceMessageFlow.IMMEDIATE) return false;
113
+ const socket = this.webSockets.find((s) => s.ws === webSocket);
114
+ if (!socket || !socket.instanceIds.includes(instanceMessage.instance)) {
115
+ this.sendSignalMessage(webSocket, instanceMessage.action, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.ERROR, instanceMessage.instance, "Status instance not found");
116
+ return false;
117
+ }
118
+ this.sendInventory(socket, instanceMessage.instance);
119
+ return true;
120
+ };
121
+ this.containsConnection = (webSocket) => Boolean(this.webSockets.find((s) => s.ws === webSocket));
122
+ this.removeConnection = (webSocket) => {
123
+ const pos = this.webSockets.findIndex((s) => s.ws === webSocket);
124
+ if (pos >= 0) this.webSockets.splice(pos, 1);
125
+ };
126
+ this.refreshConnection = (webSocket) => {
127
+ const socket = this.webSockets.find((s) => s.ws === webSocket);
128
+ if (!socket) return false;
129
+ socket.lastRefresh = Date.now();
130
+ return true;
131
+ };
132
+ this.updateConnection = (newWebSocket, instanceId) => {
133
+ for (const entry of this.webSockets) {
134
+ if (entry.instanceIds.includes(instanceId)) {
135
+ entry.ws = newWebSocket;
136
+ return true;
137
+ }
138
+ }
139
+ return false;
140
+ };
141
+ // ---- el inventario -------------------------------------------------------
142
+ /*
143
+ Estado de un provider con lo que el core sabe HOY.
144
+
145
+ Deliberadamente NO se distingue "activo" de "ocioso": para eso hay que preguntarle al provider
146
+ cuántos suscriptores tiene, y ese contrato todavía no existe (llega en S2). Inventar el dato sería
147
+ peor que no darlo — un administrador que lea "ocioso" va a ir a desinstalar algo.
148
+ */
149
+ this.healthOfProvider = (p) => {
150
+ if (p.started !== true) {
151
+ return {
152
+ health: "not-instantiated" /* NOT_INSTANTIATED */,
153
+ // El core solo instancia los providers que algún canal declara en sus requirements.
154
+ reason: "No installed channel declares this provider, so the core never started it"
155
+ };
156
+ }
157
+ if (p.configRouter && p.configRouterStarted !== true) {
158
+ return {
159
+ health: "pending-restart" /* PENDING_RESTART */,
160
+ reason: "Its configuration endpoint is not mounted \u2014 the server has not been restarted since it was installed"
161
+ };
162
+ }
163
+ return { health: "instantiated" /* INSTANTIATED */ };
164
+ };
165
+ this.buildInventory = () => {
166
+ const components = [];
167
+ for (const p of this.clusterInfo.providers ?? []) {
168
+ const { health, reason } = this.healthOfProvider(p);
169
+ components.push({ kind: "provider" /* PROVIDER */, id: p.id, displayName: p.id, health, ...reason ? { reason } : {} });
170
+ }
171
+ for (const pluviderId of (this.clusterInfo.pluviders ?? /* @__PURE__ */ new Map()).keys()) {
172
+ components.push({
173
+ kind: "pluvider" /* PLUVIDER */,
174
+ id: pluviderId,
175
+ displayName: pluviderId,
176
+ health: "instantiated" /* INSTANTIATED */
177
+ });
178
+ }
179
+ for (const s of this.clusterInfo.senders?.listSenders() ?? []) {
180
+ components.push({
181
+ kind: "sender" /* SENDER */,
182
+ id: s.id,
183
+ displayName: s.id,
184
+ health: "instantiated" /* INSTANTIATED */,
185
+ reason: s.configNames.length === 0 ? "Installed, but it has no configuration yet, so it cannot deliver anything" : void 0
186
+ });
187
+ }
188
+ for (const w of this.clusterInfo.webhooks?.listWebhooks() ?? []) {
189
+ components.push({
190
+ kind: "webhook" /* WEBHOOK */,
191
+ id: w.id,
192
+ displayName: w.id,
193
+ health: "instantiated" /* INSTANTIATED */,
194
+ reason: w.configNames.length === 0 ? "Installed, but it has no configuration yet, so nothing can reach it" : void 0
195
+ });
196
+ }
197
+ return {
198
+ cluster: this.clusterInfo.name ?? "",
199
+ takenAt: Date.now(),
200
+ components
201
+ };
202
+ };
203
+ this.sendInventory = (socket, instanceId) => {
204
+ const msg = {
205
+ msgtype: "statusmessageresponse",
206
+ channel: this.channelId,
207
+ action: import_kwirth_common_back.EInstanceMessageAction.NONE,
208
+ flow: import_kwirth_common_back.EInstanceMessageFlow.UNSOLICITED,
209
+ type: import_kwirth_common_back.EInstanceMessageType.DATA,
210
+ instance: instanceId,
211
+ payloadType: "inventory" /* INVENTORY */,
212
+ inventory: this.buildInventory()
213
+ };
214
+ socket.ws.send(JSON.stringify(msg));
215
+ };
216
+ this.sendSignalMessage = (ws, action, flow, level, instanceId, text) => {
217
+ const msg = {
218
+ action,
219
+ flow,
220
+ level,
221
+ channel: this.channelId,
222
+ instance: instanceId,
223
+ type: import_kwirth_common_back.EInstanceMessageType.SIGNAL,
224
+ text
225
+ };
226
+ ws.send(JSON.stringify(msg));
227
+ };
228
+ this.clusterInfo = clusterInfo;
229
+ this.backChannelObject = backChannelObject;
230
+ }
231
+ processProviderEvent(_providerId, _obj) {
232
+ }
233
+ endpointRequest(_endpoint, _req, _res, _accessKey) {
234
+ }
235
+ websocketRequest(_newWebSocket, _instanceId, _instanceConfig) {
236
+ }
237
+ };
238
+ var index_default = StatusChannel;
239
+ // Annotate the CommonJS export names for ESM import in node:
240
+ 0 && (module.exports = {
241
+ StatusChannel
242
+ });
package/front.js ADDED
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ (() => {
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+
29
+ // kwirth-globals:react
30
+ var require_react = __commonJS({
31
+ "kwirth-globals:react"(exports, module) {
32
+ var _m = window.__kwirth__.React;
33
+ var _d = _m != null && "default" in Object(_m) ? _m.default : _m;
34
+ if (typeof _d !== "function" && _d != null && typeof _d.default !== "undefined") _d = _d.default;
35
+ module.exports = Object.assign({}, typeof _m === "object" && _m !== null ? _m : {}, { default: _d, __esModule: true });
36
+ }
37
+ });
38
+
39
+ // kwirth-globals:@kwirthmagnify/kwirth-common
40
+ var require_kwirth_common = __commonJS({
41
+ "kwirth-globals:@kwirthmagnify/kwirth-common"(exports, module) {
42
+ var _m = window.__kwirth__.kwirthCommon;
43
+ var _d = _m != null && "default" in Object(_m) ? _m.default : _m;
44
+ if (typeof _d !== "function" && _d != null && typeof _d.default !== "undefined") _d = _d.default;
45
+ module.exports = Object.assign({}, typeof _m === "object" && _m !== null ? _m : {}, { default: _d, __esModule: true });
46
+ }
47
+ });
48
+
49
+ // kwirth-globals:@kwirthmagnify/kwirth-common-front
50
+ var require_kwirth_common_front = __commonJS({
51
+ "kwirth-globals:@kwirthmagnify/kwirth-common-front"(exports, module) {
52
+ var _m = window.__kwirth__.kwirthCommonFront;
53
+ var _d = _m != null && "default" in Object(_m) ? _m.default : _m;
54
+ if (typeof _d !== "function" && _d != null && typeof _d.default !== "undefined") _d = _d.default;
55
+ module.exports = Object.assign({}, typeof _m === "object" && _m !== null ? _m : {}, { default: _d, __esModule: true });
56
+ }
57
+ });
58
+
59
+ // kwirth-globals:@mui/material
60
+ var require_material = __commonJS({
61
+ "kwirth-globals:@mui/material"(exports, module) {
62
+ var _m = window.__kwirth__.MUI.material;
63
+ var _d = _m != null && "default" in Object(_m) ? _m.default : _m;
64
+ if (typeof _d !== "function" && _d != null && typeof _d.default !== "undefined") _d = _d.default;
65
+ module.exports = Object.assign({}, typeof _m === "object" && _m !== null ? _m : {}, { default: _d, __esModule: true });
66
+ }
67
+ });
68
+
69
+ // kwirth-globals:@kwirthmagnify/kwirth-common-front/icons
70
+ var require_icons = __commonJS({
71
+ "kwirth-globals:@kwirthmagnify/kwirth-common-front/icons"(exports, module) {
72
+ var _m = window.__kwirth__.MUI.icons;
73
+ var _d = _m != null && "default" in Object(_m) ? _m.default : _m;
74
+ if (typeof _d !== "function" && _d != null && typeof _d.default !== "undefined") _d = _d.default;
75
+ module.exports = Object.assign({}, typeof _m === "object" && _m !== null ? _m : {}, { default: _d, __esModule: true });
76
+ }
77
+ });
78
+
79
+ // src/front/StatusChannel.ts
80
+ var import_react3 = __toESM(require_react(), 1);
81
+ var import_kwirth_common2 = __toESM(require_kwirth_common(), 1);
82
+ var import_kwirth_common_front = __toESM(require_kwirth_common_front(), 1);
83
+
84
+ // src/front/icons.tsx
85
+ var import_react = __toESM(require_react(), 1);
86
+ var import_material = __toESM(require_material(), 1);
87
+ var StatusIcon = (props) => /* @__PURE__ */ import_react.default.createElement(import_material.SvgIcon, { ...props, viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react.default.createElement("g", { fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("rect", { x: "2.6", y: "4.6", width: "18.8", height: "14.8", rx: "2.2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M6 12h2.6l1.5-3.4 2.6 6.8 1.5-3.4H18" })));
88
+
89
+ // src/front/StatusData.ts
90
+ var StatusData = class {
91
+ constructor() {
92
+ this.signals = [];
93
+ this.configAccepted = false;
94
+ this.started = false;
95
+ }
96
+ };
97
+
98
+ // src/front/StatusTabContent.tsx
99
+ var import_react2 = __toESM(require_react(), 1);
100
+ var import_material2 = __toESM(require_material(), 1);
101
+ var import_icons = __toESM(require_icons(), 1);
102
+ var import_kwirth_common = __toESM(require_kwirth_common(), 1);
103
+ var HEALTH_LABEL = {
104
+ ["instantiated" /* INSTANTIATED */]: { label: "Running", color: "success" },
105
+ ["not-instantiated" /* NOT_INSTANTIATED */]: { label: "Not started", color: "warning" },
106
+ ["pending-restart" /* PENDING_RESTART */]: { label: "Needs restart", color: "warning" },
107
+ ["failed" /* FAILED */]: { label: "Failed", color: "error" },
108
+ ["unknown" /* UNKNOWN */]: { label: "Not reported", color: "default" }
109
+ };
110
+ var KIND_LABEL = {
111
+ ["provider" /* PROVIDER */]: "Provider",
112
+ ["pluvider" /* PLUVIDER */]: "Pluvider",
113
+ ["sender" /* SENDER */]: "Sender",
114
+ ["webhook" /* WEBHOOK */]: "Webhook",
115
+ ["channel" /* CHANNEL */]: "Channel"
116
+ };
117
+ var StatusTabContent = (props) => {
118
+ const data = props.channelObject.data;
119
+ const [filter, setFilter] = import_react2.default.useState("");
120
+ const boxRef = import_react2.default.useRef(null);
121
+ const [boxTop, setBoxTop] = import_react2.default.useState(0);
122
+ import_react2.default.useEffect(() => {
123
+ if (boxRef.current) setBoxTop(boxRef.current.getBoundingClientRect().top);
124
+ });
125
+ const refresh = () => {
126
+ props.channelObject.webSocket?.send(JSON.stringify({
127
+ msgtype: "statusmessage",
128
+ channel: "status",
129
+ action: import_kwirth_common.EInstanceMessageAction.COMMAND,
130
+ flow: import_kwirth_common.EInstanceMessageFlow.REQUEST,
131
+ type: import_kwirth_common.EInstanceMessageType.DATA,
132
+ accessKey: props.channelObject.accessString,
133
+ instance: props.channelObject.instanceId,
134
+ command: "refresh" /* REFRESH */
135
+ }));
136
+ };
137
+ const inventory = data.inventory;
138
+ const componentes = (inventory?.components ?? []).filter((c) => {
139
+ if (!filter) return true;
140
+ const f = filter.toLowerCase();
141
+ return c.id.toLowerCase().includes(f) || KIND_LABEL[c.kind].toLowerCase().includes(f);
142
+ });
143
+ const ORDEN = [
144
+ "failed" /* FAILED */,
145
+ "pending-restart" /* PENDING_RESTART */,
146
+ "not-instantiated" /* NOT_INSTANTIATED */,
147
+ "unknown" /* UNKNOWN */,
148
+ "instantiated" /* INSTANTIATED */
149
+ ];
150
+ componentes.sort((a, b) => {
151
+ const d = ORDEN.indexOf(a.health) - ORDEN.indexOf(b.health);
152
+ if (d !== 0) return d;
153
+ return a.kind === b.kind ? a.id.localeCompare(b.id) : a.kind.localeCompare(b.kind);
154
+ });
155
+ const fila = (c) => {
156
+ const estado = HEALTH_LABEL[c.health];
157
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, { key: `${c.kind}-${c.id}` }, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { sx: { whiteSpace: "nowrap" } }, KIND_LABEL[c.kind]), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", sx: { fontWeight: 500 } }, c.displayName)), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Chip, { size: "small", label: estado.label, color: estado.color, variant: c.health === "instantiated" /* INSTANTIATED */ ? "outlined" : "filled" })), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", color: "text.secondary" }, c.reason ?? "")));
158
+ };
159
+ if (!inventory) {
160
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { p: 2 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", color: "text.secondary" }, "Waiting for the inventory\u2026"));
161
+ }
162
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { p: 2, display: "flex", flexDirection: "column", minHeight: 0 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", alignItems: "center", spacing: 1, sx: { mb: 1 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "subtitle2" }, "What this Kwirth has inside"), /* @__PURE__ */ import_react2.default.createElement(import_material2.Chip, { size: "small", variant: "outlined", label: `${inventory.components.length} components` }), /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { flexGrow: 1 } }), /* @__PURE__ */ import_react2.default.createElement(import_material2.TextField, { size: "small", placeholder: "Filter\u2026", value: filter, onChange: (e) => setFilter(e.target.value), sx: { width: 220 } }), /* @__PURE__ */ import_react2.default.createElement(import_material2.Tooltip, { title: "Take a new snapshot" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { size: "small", onClick: refresh }, /* @__PURE__ */ import_react2.default.createElement(import_icons.Refresh, { fontSize: "small" })))), /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1 } }, "Snapshot taken at ", new Date(inventory.takenAt).toLocaleTimeString(), " \u2014 it does not refresh on its own"), /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", overflowY: "auto", overflowX: "hidden", width: "100%", flexGrow: 1, height: `calc(100vh - ${boxTop}px - 35px)` } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Table, { size: "small", stickyHeader: true }, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableHead, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Kind"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Name"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "State"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Why"))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableBody, null, componentes.map(fila)))), data.signals.length > 0 && /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { mt: 1 } }, data.signals.map((s, i) => /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { key: i, variant: "caption", color: "error", display: "block" }, s))));
163
+ };
164
+
165
+ // src/front/StatusChannel.ts
166
+ var StatusSetup = () => import_react3.default.createElement("div", null, "Kwirth Status has nothing to configure: open it and it shows what this Kwirth has inside.");
167
+ var StatusChannel = class {
168
+ constructor() {
169
+ this.setupVisible = false;
170
+ this.SetupDialog = StatusSetup;
171
+ this.TabContent = StatusTabContent;
172
+ this.channelId = "status";
173
+ this.requirements = {
174
+ accessString: true,
175
+ // los comandos viajan con su accessKey o el core los descarta
176
+ clusterUrl: true,
177
+ clusterInfo: false,
178
+ exit: false,
179
+ frontChannels: false,
180
+ metrics: false,
181
+ notifier: true,
182
+ notifications: true,
183
+ setup: false,
184
+ // no hay nada que preguntar antes de arrancar
185
+ settings: false,
186
+ palette: false,
187
+ userSettings: false,
188
+ webSocket: true,
189
+ // el refresco se pide por el socket de la instancia
190
+ backChannels: false
191
+ };
192
+ }
193
+ getScope() {
194
+ return import_kwirth_common2.EInstanceConfigScope.NONE;
195
+ }
196
+ getChannelIcon() {
197
+ return import_react3.default.createElement(StatusIcon);
198
+ }
199
+ getSetupVisibility() {
200
+ return this.setupVisible;
201
+ }
202
+ setSetupVisibility(visibility) {
203
+ this.setupVisible = visibility;
204
+ }
205
+ processChannelMessage(channelObject, wsEvent) {
206
+ const msg = JSON.parse(wsEvent.data);
207
+ const data = channelObject.data;
208
+ switch (msg.type) {
209
+ case import_kwirth_common2.EInstanceMessageType.DATA:
210
+ if (msg.payloadType === "inventory" /* INVENTORY */ && msg.inventory) {
211
+ data.inventory = msg.inventory;
212
+ }
213
+ return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
214
+ case import_kwirth_common2.EInstanceMessageType.SIGNAL: {
215
+ const signalMessage = JSON.parse(wsEvent.data);
216
+ if (signalMessage.flow === import_kwirth_common2.EInstanceMessageFlow.RESPONSE && signalMessage.action === import_kwirth_common2.EInstanceMessageAction.START) {
217
+ channelObject.instanceId = signalMessage.instance;
218
+ data.configAccepted = true;
219
+ data.started = true;
220
+ }
221
+ if (signalMessage.level === import_kwirth_common2.ESignalMessageLevel.ERROR) data.signals.push(signalMessage.text ?? "Unknown error");
222
+ return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
223
+ }
224
+ default:
225
+ return { action: import_kwirth_common_front.EChannelRefreshAction.NONE };
226
+ }
227
+ }
228
+ async initChannel(channelObject) {
229
+ channelObject.data = new StatusData();
230
+ return true;
231
+ }
232
+ startChannel(_channelObject) {
233
+ return true;
234
+ }
235
+ stopChannel(_channelObject) {
236
+ return true;
237
+ }
238
+ pauseChannel(_channelObject) {
239
+ return true;
240
+ }
241
+ continueChannel(_channelObject) {
242
+ return true;
243
+ }
244
+ socketDisconnected(_channelObject) {
245
+ return true;
246
+ }
247
+ /*
248
+ false = el core rehace la instancia al reconectar, en vez de dar por buena la anterior. Es lo que
249
+ queremos: tras una reconexion la foto que hubiera en pantalla puede ser vieja, y se pide otra.
250
+ */
251
+ socketReconnect(_channelObject) {
252
+ return false;
253
+ }
254
+ };
255
+
256
+ // src/front/index.ts
257
+ window.__kwirth_plugins__ = window.__kwirth_plugins__ || {};
258
+ window.__kwirth_plugins__["status"] = StatusChannel;
259
+ })();
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "type": "commonjs",
3
+ "extensionType": "plugin",
4
+ "id": "status",
5
+ "name": "@kwirthmagnify/kwirth-plugin-status",
6
+ "displayName": "Kwirth Status",
7
+ "version": "0.1.0",
8
+ "description": "A look inside Kwirth: what is installed, how it is doing and who consumes what",
9
+ "icon": "<svg viewBox='0 0 24 24'><g fill='none' stroke='currentColor' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><rect x='2.6' y='4.6' width='18.8' height='14.8' rx='2.2'/><path d='M6 12h2.6l1.5-3.4 2.6 6.8 1.5-3.4H18'/></g></svg>",
10
+ "requiresRestart": false,
11
+ "requiresExtension": []
12
+ }