@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.
- package/back.js +242 -0
- package/front.js +259 -0
- 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
|
+
}
|