@kwirthmagnify/kwirth-plugin-provider-debug 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 +272 -0
- package/front.js +428 -0
- package/package.json +12 -0
package/back.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
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
|
+
default: () => index_default
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(index_exports);
|
|
46
|
+
var import_kwirth_common_back = __toESM(require_kwirth_common_back(), 1);
|
|
47
|
+
var ProviderDebugChannel = class {
|
|
48
|
+
constructor(clusterInfo, backChannelObject) {
|
|
49
|
+
this.channelId = "provider-debug";
|
|
50
|
+
/**
|
|
51
|
+
* Deliberadamente vacío: el core solo instancia y arranca los providers que algún canal
|
|
52
|
+
* declara aquí, así que este canal se limita a depurar los que ya están en marcha por
|
|
53
|
+
* cuenta de otros plugins. Declarar providers concretos los arrancaría como efecto
|
|
54
|
+
* colateral de tener instalado un depurador, que es justo lo que no queremos.
|
|
55
|
+
*/
|
|
56
|
+
this.requirements = { storage: false, providers: [] };
|
|
57
|
+
this.webSockets = [];
|
|
58
|
+
this.getChannelData = () => ({
|
|
59
|
+
id: "provider-debug",
|
|
60
|
+
routable: false,
|
|
61
|
+
pauseable: true,
|
|
62
|
+
modifiable: false,
|
|
63
|
+
// F1: para cambiar de provider se para y se rearranca la instancia
|
|
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
|
+
// los providers son cluster-wide, no cuelgan de un pod
|
|
71
|
+
resourced: false
|
|
72
|
+
});
|
|
73
|
+
this.getChannelScopeLevel = (scope) => ["", "none", "cluster"].indexOf(scope);
|
|
74
|
+
this.startChannel = async () => {
|
|
75
|
+
};
|
|
76
|
+
// ---- registro: los canales cluster llegan aquí vía addObject('*all') ----
|
|
77
|
+
this.addObject = async (webSocket, instanceConfig, _ns, _pod, _container) => {
|
|
78
|
+
let socket = this.webSockets.find((s) => s.ws === webSocket);
|
|
79
|
+
if (!socket) {
|
|
80
|
+
const len = this.webSockets.push({ ws: webSocket, lastRefresh: Date.now(), instances: [] });
|
|
81
|
+
socket = this.webSockets[len - 1];
|
|
82
|
+
}
|
|
83
|
+
if (socket.instances.find((i) => i.instanceId === instanceConfig.instance)) return true;
|
|
84
|
+
const configData = instanceConfig.data ?? { providerId: "", subscriptionData: "" };
|
|
85
|
+
const instance = {
|
|
86
|
+
instanceId: instanceConfig.instance,
|
|
87
|
+
accessKey: (0, import_kwirth_common_back.accessKeyDeserialize)(instanceConfig.accessKey),
|
|
88
|
+
providerId: configData.providerId ?? "",
|
|
89
|
+
paused: false
|
|
90
|
+
};
|
|
91
|
+
socket.instances.push(instance);
|
|
92
|
+
this.sendProviders(socket, instance);
|
|
93
|
+
if (instance.providerId) this.subscribe(socket, instance, configData.subscriptionData);
|
|
94
|
+
return true;
|
|
95
|
+
};
|
|
96
|
+
this.deleteObject = async (webSocket, instanceConfig, _ns, _pod, _container) => {
|
|
97
|
+
this.removeInstance(webSocket, instanceConfig.instance);
|
|
98
|
+
return true;
|
|
99
|
+
};
|
|
100
|
+
this.pauseContinueInstance = (webSocket, instanceConfig, action) => {
|
|
101
|
+
const instance = this.getInstance(webSocket, instanceConfig.instance);
|
|
102
|
+
if (!instance) {
|
|
103
|
+
this.sendSignalMessage(webSocket, action, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.ERROR, instanceConfig.instance, "Provider debug instance not found");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (action === import_kwirth_common_back.EInstanceMessageAction.PAUSE) instance.paused = true;
|
|
107
|
+
if (action === import_kwirth_common_back.EInstanceMessageAction.CONTINUE) instance.paused = false;
|
|
108
|
+
};
|
|
109
|
+
this.modifyInstance = (_webSocket, _instanceConfig) => {
|
|
110
|
+
};
|
|
111
|
+
this.containsInstance = (instanceId) => this.webSockets.some((socket) => socket.instances.some((i) => i.instanceId === instanceId));
|
|
112
|
+
this.containsAsset = (_webSocket, _podNamespace, _podName, _containerName) => false;
|
|
113
|
+
this.stopInstance = (webSocket, instanceConfig) => {
|
|
114
|
+
const instance = this.getInstance(webSocket, instanceConfig.instance);
|
|
115
|
+
if (instance) {
|
|
116
|
+
this.removeInstance(webSocket, instanceConfig.instance);
|
|
117
|
+
this.sendSignalMessage(webSocket, import_kwirth_common_back.EInstanceMessageAction.STOP, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.INFO, instanceConfig.instance, "Provider debug instance stopped");
|
|
118
|
+
} else {
|
|
119
|
+
this.sendSignalMessage(webSocket, import_kwirth_common_back.EInstanceMessageAction.STOP, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.ERROR, instanceConfig.instance, "Provider debug instance not found");
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
this.removeInstance = (webSocket, instanceId) => {
|
|
123
|
+
const socket = this.webSockets.find((s) => s.ws === webSocket);
|
|
124
|
+
if (!socket) return;
|
|
125
|
+
const pos = socket.instances.findIndex((i) => i.instanceId === instanceId);
|
|
126
|
+
if (pos < 0) return;
|
|
127
|
+
this.unsubscribe(socket.instances[pos]);
|
|
128
|
+
socket.instances.splice(pos, 1);
|
|
129
|
+
};
|
|
130
|
+
this.processCommand = async (webSocket, instanceMessage) => {
|
|
131
|
+
if (instanceMessage.flow === import_kwirth_common_back.EInstanceMessageFlow.IMMEDIATE) return false;
|
|
132
|
+
const instance = this.getInstance(webSocket, instanceMessage.instance);
|
|
133
|
+
if (!instance) {
|
|
134
|
+
this.sendSignalMessage(webSocket, instanceMessage.action, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.ERROR, instanceMessage.instance, "Provider debug instance not found");
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
};
|
|
139
|
+
this.containsConnection = (webSocket) => Boolean(this.webSockets.find((s) => s.ws === webSocket));
|
|
140
|
+
this.removeConnection = (webSocket) => {
|
|
141
|
+
const pos = this.webSockets.findIndex((s) => s.ws === webSocket);
|
|
142
|
+
if (pos < 0) return;
|
|
143
|
+
for (const instance of this.webSockets[pos].instances) this.unsubscribe(instance);
|
|
144
|
+
this.webSockets.splice(pos, 1);
|
|
145
|
+
};
|
|
146
|
+
this.refreshConnection = (webSocket) => {
|
|
147
|
+
const socket = this.webSockets.find((s) => s.ws === webSocket);
|
|
148
|
+
if (socket) {
|
|
149
|
+
socket.lastRefresh = Date.now();
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
};
|
|
154
|
+
this.updateConnection = (newWebSocket, instanceId) => {
|
|
155
|
+
for (const entry of this.webSockets) {
|
|
156
|
+
if (entry.instances.find((i) => i.instanceId === instanceId)) {
|
|
157
|
+
entry.ws = newWebSocket;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
};
|
|
163
|
+
// ---- suscripción a un provider en marcha ---------------------------------
|
|
164
|
+
this.subscribe = (socket, instance, rawSubscriptionData) => {
|
|
165
|
+
const provider = this.clusterInfo.providers?.find((p) => p.id === instance.providerId);
|
|
166
|
+
if (!provider) {
|
|
167
|
+
this.sendSignalMessage(socket.ws, import_kwirth_common_back.EInstanceMessageAction.START, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.ERROR, instance.instanceId, `Provider '${instance.providerId}' is not running`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
let subscriptionData = {};
|
|
171
|
+
if (rawSubscriptionData && rawSubscriptionData.trim() !== "") {
|
|
172
|
+
try {
|
|
173
|
+
subscriptionData = JSON.parse(rawSubscriptionData);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
this.sendSignalMessage(socket.ws, import_kwirth_common_back.EInstanceMessageAction.START, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.ERROR, instance.instanceId, `Subscription payload is not valid JSON: ${String(err)}`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const subscriber = {
|
|
180
|
+
processProviderEvent: (providerId, obj) => this.deliver(socket, instance, providerId, obj)
|
|
181
|
+
};
|
|
182
|
+
instance.subscriber = subscriber;
|
|
183
|
+
instance.provider = provider;
|
|
184
|
+
provider.addSubscriber(subscriber, subscriptionData);
|
|
185
|
+
this.backChannelObject.logInfo?.(`Provider debug instance ${instance.instanceId} subscribed to provider '${instance.providerId}'`);
|
|
186
|
+
this.sendSignalMessage(socket.ws, import_kwirth_common_back.EInstanceMessageAction.START, import_kwirth_common_back.EInstanceMessageFlow.RESPONSE, import_kwirth_common_back.ESignalMessageLevel.INFO, instance.instanceId, `Subscribed to provider '${instance.providerId}'`);
|
|
187
|
+
};
|
|
188
|
+
this.unsubscribe = (instance) => {
|
|
189
|
+
if (instance.provider && instance.subscriber) {
|
|
190
|
+
instance.provider.removeSubscriber(instance.subscriber);
|
|
191
|
+
this.backChannelObject.logInfo?.(`Provider debug instance ${instance.instanceId} unsubscribed from provider '${instance.providerId}'`);
|
|
192
|
+
}
|
|
193
|
+
instance.provider = void 0;
|
|
194
|
+
instance.subscriber = void 0;
|
|
195
|
+
};
|
|
196
|
+
this.deliver = (socket, instance, providerId, obj) => {
|
|
197
|
+
if (instance.paused) return;
|
|
198
|
+
const msg = {
|
|
199
|
+
msgtype: "providerdebugmessageresponse",
|
|
200
|
+
channel: this.channelId,
|
|
201
|
+
action: import_kwirth_common_back.EInstanceMessageAction.NONE,
|
|
202
|
+
flow: import_kwirth_common_back.EInstanceMessageFlow.UNSOLICITED,
|
|
203
|
+
type: import_kwirth_common_back.EInstanceMessageType.DATA,
|
|
204
|
+
instance: instance.instanceId,
|
|
205
|
+
payloadType: "event" /* EVENT */,
|
|
206
|
+
event: { ts: Date.now(), providerId, event: obj }
|
|
207
|
+
};
|
|
208
|
+
socket.ws.send(JSON.stringify(msg));
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* getSubscriptionHelp() es opcional en IProvider y lo implementa quien quiere, así que se llama
|
|
212
|
+
* a la defensiva: ni existir es un error, ni lo es que reviente. Un provider mal escrito no
|
|
213
|
+
* puede tumbar el catálogo del resto.
|
|
214
|
+
*/
|
|
215
|
+
this.helpOf = (provider) => {
|
|
216
|
+
if (typeof provider.getSubscriptionHelp !== "function") return void 0;
|
|
217
|
+
try {
|
|
218
|
+
const help = provider.getSubscriptionHelp();
|
|
219
|
+
if (!help || typeof help.usage !== "string" || typeof help.example !== "object") return void 0;
|
|
220
|
+
return help;
|
|
221
|
+
} catch (err) {
|
|
222
|
+
this.backChannelObject.logWarning?.(`Provider '${provider.id}' failed to report its subscription help: ${String(err)}`);
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
this.sendProviders = (socket, instance) => {
|
|
227
|
+
const running = this.clusterInfo.providers ?? [];
|
|
228
|
+
const providers = running.map((p) => {
|
|
229
|
+
const help = this.helpOf(p);
|
|
230
|
+
return {
|
|
231
|
+
id: p.id,
|
|
232
|
+
providesRouter: p.providesRouter,
|
|
233
|
+
...p.routerAlias ? { routerAlias: p.routerAlias } : {},
|
|
234
|
+
...help ? { help } : {}
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
const msg = {
|
|
238
|
+
msgtype: "providerdebugmessageresponse",
|
|
239
|
+
channel: this.channelId,
|
|
240
|
+
action: import_kwirth_common_back.EInstanceMessageAction.NONE,
|
|
241
|
+
flow: import_kwirth_common_back.EInstanceMessageFlow.UNSOLICITED,
|
|
242
|
+
type: import_kwirth_common_back.EInstanceMessageType.DATA,
|
|
243
|
+
instance: instance.instanceId,
|
|
244
|
+
payloadType: "providers" /* PROVIDERS */,
|
|
245
|
+
providers
|
|
246
|
+
};
|
|
247
|
+
socket.ws.send(JSON.stringify(msg));
|
|
248
|
+
};
|
|
249
|
+
this.sendSignalMessage = (ws, action, flow, level, instanceId, text) => {
|
|
250
|
+
const resp = { action, flow, channel: this.channelId, instance: instanceId, type: import_kwirth_common_back.EInstanceMessageType.SIGNAL, text, level };
|
|
251
|
+
ws.send(JSON.stringify(resp));
|
|
252
|
+
};
|
|
253
|
+
this.clusterInfo = clusterInfo;
|
|
254
|
+
this.backChannelObject = backChannelObject;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Nunca se invoca: el canal no se registra a sí mismo como subscriber, cada instancia
|
|
258
|
+
* registra su propio proxy (ver IInstance.subscriber).
|
|
259
|
+
*/
|
|
260
|
+
processProviderEvent(_providerId, _obj) {
|
|
261
|
+
}
|
|
262
|
+
endpointRequest(_endpoint, _req, _res, _accessKey) {
|
|
263
|
+
}
|
|
264
|
+
websocketRequest(_newWebSocket, _instanceId, _instanceConfig) {
|
|
265
|
+
}
|
|
266
|
+
getInstance(webSocket, instanceId) {
|
|
267
|
+
const socket = this.webSockets.find((entry) => entry.ws === webSocket);
|
|
268
|
+
if (socket) return socket.instances.find((i) => i.instanceId === instanceId);
|
|
269
|
+
return void 0;
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
var index_default = ProviderDebugChannel;
|
package/front.js
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
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:@kwirthmagnify/kwirth-common
|
|
30
|
+
var require_kwirth_common = __commonJS({
|
|
31
|
+
"kwirth-globals:@kwirthmagnify/kwirth-common"(exports, module) {
|
|
32
|
+
var _m = window.__kwirth__.kwirthCommon;
|
|
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-front
|
|
40
|
+
var require_kwirth_common_front = __commonJS({
|
|
41
|
+
"kwirth-globals:@kwirthmagnify/kwirth-common-front"(exports, module) {
|
|
42
|
+
var _m = window.__kwirth__.kwirthCommonFront;
|
|
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:react
|
|
50
|
+
var require_react = __commonJS({
|
|
51
|
+
"kwirth-globals:react"(exports, module) {
|
|
52
|
+
var _m = window.__kwirth__.React;
|
|
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:@mui/icons-material
|
|
70
|
+
var require_icons_material = __commonJS({
|
|
71
|
+
"kwirth-globals:@mui/icons-material"(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/ProviderDebugChannel.ts
|
|
80
|
+
var import_kwirth_common = __toESM(require_kwirth_common(), 1);
|
|
81
|
+
var import_kwirth_common_front = __toESM(require_kwirth_common_front(), 1);
|
|
82
|
+
|
|
83
|
+
// src/front/ProviderDebugConfig.ts
|
|
84
|
+
var ProviderDebugConfig = class {
|
|
85
|
+
constructor() {
|
|
86
|
+
this.maxEvents = 200;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var ProviderDebugInstanceConfig = class {
|
|
90
|
+
constructor() {
|
|
91
|
+
this.providerId = "";
|
|
92
|
+
this.subscriptionData = "";
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/front/ProviderDebugData.ts
|
|
97
|
+
var ProviderDebugData = class {
|
|
98
|
+
constructor() {
|
|
99
|
+
this.events = [];
|
|
100
|
+
this.providers = [];
|
|
101
|
+
this.signals = [];
|
|
102
|
+
this.paused = false;
|
|
103
|
+
this.started = false;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/front/ProviderDebugSetup.tsx
|
|
108
|
+
var import_react = __toESM(require_react(), 1);
|
|
109
|
+
var import_material = __toESM(require_material(), 1);
|
|
110
|
+
var import_icons_material = __toESM(require_icons_material(), 1);
|
|
111
|
+
var ProviderDebugIcon = /* @__PURE__ */ import_react.default.createElement(import_icons_material.DataObjectOutlined, null);
|
|
112
|
+
var ProviderDebugSetup = (props) => {
|
|
113
|
+
const instanceConfig = props.setupConfig?.channelInstanceConfig || new ProviderDebugInstanceConfig();
|
|
114
|
+
const config = props.setupConfig?.channelConfig || new ProviderDebugConfig();
|
|
115
|
+
const data = props.channelObject.data;
|
|
116
|
+
const [providerId, setProviderId] = (0, import_react.useState)(instanceConfig.providerId);
|
|
117
|
+
const [subscriptionData, setSubscriptionData] = (0, import_react.useState)(instanceConfig.subscriptionData);
|
|
118
|
+
const [maxEvents, setMaxEvents] = (0, import_react.useState)(config.maxEvents);
|
|
119
|
+
const [catalogue, setCatalogue] = (0, import_react.useState)([]);
|
|
120
|
+
const [catalogueLoaded, setCatalogueLoaded] = (0, import_react.useState)(false);
|
|
121
|
+
const [mode, setMode] = (0, import_react.useState)("form" /* FORM */);
|
|
122
|
+
const defaultRef = (0, import_react.useRef)(null);
|
|
123
|
+
(0, import_react.useEffect)(() => {
|
|
124
|
+
const url = props.channelObject.clusterUrl;
|
|
125
|
+
if (!url) return;
|
|
126
|
+
const token = props.channelObject.accessString;
|
|
127
|
+
fetch(`${url}/core/providers`, token ? { headers: { Authorization: `Bearer ${token}` } } : void 0).then((r) => r.json()).then((list) => {
|
|
128
|
+
setCatalogue(Array.isArray(list) ? list.filter((p) => p && p.id) : []);
|
|
129
|
+
setCatalogueLoaded(true);
|
|
130
|
+
}).catch(() => {
|
|
131
|
+
});
|
|
132
|
+
}, []);
|
|
133
|
+
const options = () => {
|
|
134
|
+
const source = catalogueLoaded ? catalogue.map((e) => ({
|
|
135
|
+
id: e.id,
|
|
136
|
+
state: e.running ? "running" /* RUNNING */ : "notRunning" /* NOT_RUNNING */,
|
|
137
|
+
help: e.subscriptionHelp
|
|
138
|
+
})) : (data?.providers ?? []).map((p) => ({ id: p.id, state: "unknown" /* UNKNOWN */, help: p.help }));
|
|
139
|
+
if (providerId && !source.some((o) => o.id === providerId)) source.push({ id: providerId, state: "unknown" /* UNKNOWN */ });
|
|
140
|
+
return source.sort((a, b) => a.id.localeCompare(b.id));
|
|
141
|
+
};
|
|
142
|
+
const help = options().find((o) => o.id === providerId)?.help;
|
|
143
|
+
const fields = help?.fields ?? [];
|
|
144
|
+
const invalidJson = () => {
|
|
145
|
+
if (!subscriptionData || subscriptionData.trim() === "") return false;
|
|
146
|
+
try {
|
|
147
|
+
JSON.parse(subscriptionData);
|
|
148
|
+
return false;
|
|
149
|
+
} catch {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const payload = () => {
|
|
154
|
+
if (!subscriptionData || subscriptionData.trim() === "") return {};
|
|
155
|
+
try {
|
|
156
|
+
const parsed = JSON.parse(subscriptionData);
|
|
157
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
158
|
+
} catch {
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
const setField = (name, value) => {
|
|
163
|
+
const obj = payload();
|
|
164
|
+
if (value === void 0 || value === "" || Array.isArray(value) && value.length === 0) delete obj[name];
|
|
165
|
+
else obj[name] = value;
|
|
166
|
+
setSubscriptionData(Object.keys(obj).length === 0 ? "" : JSON.stringify(obj, null, 2));
|
|
167
|
+
};
|
|
168
|
+
const useExample = () => {
|
|
169
|
+
if (help) setSubscriptionData(JSON.stringify(help.example, null, 2));
|
|
170
|
+
};
|
|
171
|
+
const renderField = (field) => {
|
|
172
|
+
const current = payload()[field.name];
|
|
173
|
+
const label = field.required ? `${field.name} *` : field.name;
|
|
174
|
+
switch (field.type) {
|
|
175
|
+
case "boolean":
|
|
176
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
177
|
+
import_material.FormControlLabel,
|
|
178
|
+
{
|
|
179
|
+
key: field.name,
|
|
180
|
+
control: /* @__PURE__ */ import_react.default.createElement(import_material.Checkbox, { checked: current === true, onChange: (e) => setField(field.name, e.target.checked ? true : void 0) }),
|
|
181
|
+
label: /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "body2" }, label), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "caption", color: "text.secondary" }, field.description))
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
case "number":
|
|
185
|
+
return /* @__PURE__ */ import_react.default.createElement(import_material.TextField, { key: field.name, value: current ?? "", onChange: (e) => setField(field.name, e.target.value === "" ? void 0 : Number(e.target.value)), type: "number", variant: "standard", label, helperText: field.description, fullWidth: true });
|
|
186
|
+
case "string[]":
|
|
187
|
+
return /* @__PURE__ */ import_react.default.createElement(import_material.TextField, { key: field.name, value: Array.isArray(current) ? current.join(", ") : "", onChange: (e) => setField(field.name, e.target.value.split(",").map((s) => s.trim()).filter(Boolean)), variant: "standard", label, helperText: `${field.description} \u2014 comma separated`, fullWidth: true });
|
|
188
|
+
default:
|
|
189
|
+
return /* @__PURE__ */ import_react.default.createElement(import_material.TextField, { key: field.name, value: typeof current === "string" ? current : "", onChange: (e) => setField(field.name, e.target.value), variant: "standard", label, helperText: field.description, fullWidth: true });
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const renderHelp = () => {
|
|
193
|
+
if (!providerId) return /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "caption", color: "text.secondary" }, "Pick a provider to see how to subscribe to it.");
|
|
194
|
+
if (!help) {
|
|
195
|
+
return /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "caption", color: "text.secondary" }, `'${providerId}' does not publish subscription help (getSubscriptionHelp is optional). Check its README for the payload it expects.`);
|
|
196
|
+
}
|
|
197
|
+
return /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "caption", color: "text.secondary", sx: { whiteSpace: "pre-wrap" } }, help.usage);
|
|
198
|
+
};
|
|
199
|
+
const ok = () => {
|
|
200
|
+
config.maxEvents = maxEvents;
|
|
201
|
+
instanceConfig.providerId = providerId;
|
|
202
|
+
instanceConfig.subscriptionData = subscriptionData;
|
|
203
|
+
props.onChannelSetupClosed(props.channel, {
|
|
204
|
+
channelId: props.channel.channelId,
|
|
205
|
+
channelConfig: config,
|
|
206
|
+
channelInstanceConfig: instanceConfig
|
|
207
|
+
}, true, defaultRef.current?.checked || false);
|
|
208
|
+
};
|
|
209
|
+
const cancel = () => {
|
|
210
|
+
props.onChannelSetupClosed(props.channel, {
|
|
211
|
+
channelId: props.channel.channelId,
|
|
212
|
+
channelConfig: void 0,
|
|
213
|
+
channelInstanceConfig: void 0
|
|
214
|
+
}, false, false);
|
|
215
|
+
};
|
|
216
|
+
return /* @__PURE__ */ import_react.default.createElement(import_material.Dialog, { open: true, maxWidth: false, sx: { "& .MuiDialog-paper": { width: "46vw", maxWidth: "46vw", height: "76vh", maxHeight: "76vh" } } }, /* @__PURE__ */ import_react.default.createElement(import_material.DialogTitle, null, "Configure Provider Debug channel"), /* @__PURE__ */ import_react.default.createElement(import_material.DialogContent, null, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 2, sx: { m: 1 } }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 0.5 }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "caption", color: "text.secondary" }, "Provider"), /* @__PURE__ */ import_react.default.createElement(import_material.Select, { value: providerId, onChange: (e) => setProviderId(e.target.value), displayEmpty: true, size: "small", variant: "standard", inputProps: { "aria-label": "Provider" } }, /* @__PURE__ */ import_react.default.createElement(import_material.MenuItem, { value: "" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "body2", color: "text.secondary" }, "(none \u2014 just list the running providers)")), options().map((o) => /* @__PURE__ */ import_react.default.createElement(import_material.MenuItem, { key: o.id, value: o.id }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", spacing: 1, alignItems: "center" }, /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "body2" }, o.id), o.state === "notRunning" /* NOT_RUNNING */ && /* @__PURE__ */ import_react.default.createElement(import_material.Chip, { label: "not running", size: "small", variant: "outlined", color: "warning", sx: { fontSize: "0.65rem", height: 18 } }))))), /* @__PURE__ */ import_react.default.createElement(import_material.Typography, { variant: "caption", color: "text.secondary" }, catalogueLoaded ? "A provider only runs when some channel requires it. Only the ones marked as running can be subscribed to." : "Could not read the provider catalogue from the core \u2014 showing only what this channel already knows.")), /* @__PURE__ */ import_react.default.createElement(import_material.Box, { sx: { borderLeft: 3, borderColor: "divider", pl: 1.5 } }, renderHelp()), /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 1 }, /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between" }, /* @__PURE__ */ import_react.default.createElement(import_material.Tabs, { value: fields.length > 0 ? mode : "json" /* JSON */, onChange: (_e, v) => setMode(v), sx: { minHeight: 32, "& .MuiTab-root": { minHeight: 32, py: 0 } } }, /* @__PURE__ */ import_react.default.createElement(import_material.Tooltip, { title: fields.length > 0 ? "" : "This provider does not describe its payload field by field" }, /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement(import_material.Tab, { label: "Form", value: "form" /* FORM */, disabled: fields.length === 0 }))), /* @__PURE__ */ import_react.default.createElement(import_material.Tab, { label: "JSON", value: "json" /* JSON */ })), /* @__PURE__ */ import_react.default.createElement(import_material.Button, { size: "small", onClick: useExample, disabled: !help }, "USE EXAMPLE")), fields.length > 0 && mode === "form" /* FORM */ ? /* @__PURE__ */ import_react.default.createElement(import_material.Stack, { direction: "column", spacing: 1.5 }, fields.map((f) => renderField(f))) : /* @__PURE__ */ import_react.default.createElement(import_material.TextField, { value: subscriptionData, onChange: (e) => setSubscriptionData(e.target.value), variant: "standard", label: "Subscription payload (JSON)", placeholder: "{}", multiline: true, minRows: 4, maxRows: 4, error: invalidJson(), helperText: invalidJson() ? "Not valid JSON" : "Empty means {} \u2014 note most providers deliver nothing without a payload", fullWidth: true })), /* @__PURE__ */ import_react.default.createElement(import_material.TextField, { value: maxEvents, onChange: (e) => setMaxEvents(+e.target.value), type: "number", variant: "standard", label: "Max events", fullWidth: true }))), /* @__PURE__ */ import_react.default.createElement(import_material.DialogActions, null, /* @__PURE__ */ import_react.default.createElement(import_material.FormControlLabel, { control: /* @__PURE__ */ import_react.default.createElement(import_material.Checkbox, { slotProps: { input: { ref: defaultRef } } }), label: "Set as default", sx: { width: "100%", ml: "8px" } }), /* @__PURE__ */ import_react.default.createElement(import_material.Button, { variant: "outlined", onClick: ok, disabled: invalidJson() }, "OK"), /* @__PURE__ */ import_react.default.createElement(import_material.Button, { variant: "outlined", onClick: cancel }, "CANCEL")));
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// src/front/ProviderDebugTabContent.tsx
|
|
220
|
+
var import_react3 = __toESM(require_react(), 1);
|
|
221
|
+
var import_material3 = __toESM(require_material(), 1);
|
|
222
|
+
var import_icons_material2 = __toESM(require_icons_material(), 1);
|
|
223
|
+
|
|
224
|
+
// src/front/JsonBlock.tsx
|
|
225
|
+
var import_react2 = __toESM(require_react(), 1);
|
|
226
|
+
var import_material2 = __toESM(require_material(), 1);
|
|
227
|
+
var TOKEN = /("(?:\\u[a-fA-F0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(?:true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g;
|
|
228
|
+
var JsonBlock = (props) => {
|
|
229
|
+
const theme = (0, import_material2.useTheme)();
|
|
230
|
+
const colorOf = (token) => {
|
|
231
|
+
if (token.startsWith('"')) return token.trimEnd().endsWith(":") ? theme.palette.primary.main : theme.palette.success.main;
|
|
232
|
+
if (token === "true" || token === "false" || token === "null") return theme.palette.secondary.main;
|
|
233
|
+
return theme.palette.warning.main;
|
|
234
|
+
};
|
|
235
|
+
const render = () => {
|
|
236
|
+
let text;
|
|
237
|
+
try {
|
|
238
|
+
text = JSON.stringify(props.value, null, 2) ?? String(props.value);
|
|
239
|
+
} catch {
|
|
240
|
+
return [/* @__PURE__ */ import_react2.default.createElement("span", { key: "err" }, "<unserializable event>")];
|
|
241
|
+
}
|
|
242
|
+
const nodes = [];
|
|
243
|
+
let last = 0;
|
|
244
|
+
let match;
|
|
245
|
+
TOKEN.lastIndex = 0;
|
|
246
|
+
while ((match = TOKEN.exec(text)) !== null) {
|
|
247
|
+
if (match.index > last) nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `p${last}` }, text.slice(last, match.index)));
|
|
248
|
+
nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `t${match.index}`, style: { color: colorOf(match[0]) } }, match[0]));
|
|
249
|
+
last = match.index + match[0].length;
|
|
250
|
+
}
|
|
251
|
+
if (last < text.length) nodes.push(/* @__PURE__ */ import_react2.default.createElement("span", { key: `p${last}` }, text.slice(last)));
|
|
252
|
+
return nodes;
|
|
253
|
+
};
|
|
254
|
+
return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { component: "pre", sx: { m: 0, fontFamily: "monospace", fontSize: "0.75rem", whiteSpace: "pre-wrap", wordBreak: "break-all", overflowX: "auto" } }, render());
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// src/front/ProviderDebugTabContent.tsx
|
|
258
|
+
var ProviderDebugTabContent = (props) => {
|
|
259
|
+
const data = props.channelObject.data;
|
|
260
|
+
const config = props.channelObject.config;
|
|
261
|
+
const instanceConfig = props.channelObject.instanceConfig;
|
|
262
|
+
const boxRef = (0, import_react3.useRef)(null);
|
|
263
|
+
const [boxTop, setBoxTop] = (0, import_react3.useState)(0);
|
|
264
|
+
const [, forceRender] = (0, import_react3.useState)(0);
|
|
265
|
+
const [copied, setCopied] = (0, import_react3.useState)(null);
|
|
266
|
+
(0, import_react3.useEffect)(() => {
|
|
267
|
+
if (boxRef.current) setBoxTop(boxRef.current.getBoundingClientRect().top);
|
|
268
|
+
});
|
|
269
|
+
const clear = () => {
|
|
270
|
+
data.events = [];
|
|
271
|
+
data.signals = [];
|
|
272
|
+
forceRender((n) => n + 1);
|
|
273
|
+
};
|
|
274
|
+
const writeClipboard = async (text) => {
|
|
275
|
+
try {
|
|
276
|
+
await navigator.clipboard.writeText(text);
|
|
277
|
+
return true;
|
|
278
|
+
} catch {
|
|
279
|
+
try {
|
|
280
|
+
const area = document.createElement("textarea");
|
|
281
|
+
area.value = text;
|
|
282
|
+
area.style.position = "fixed";
|
|
283
|
+
area.style.opacity = "0";
|
|
284
|
+
document.body.appendChild(area);
|
|
285
|
+
area.select();
|
|
286
|
+
const ok = document.execCommand("copy");
|
|
287
|
+
document.body.removeChild(area);
|
|
288
|
+
return ok;
|
|
289
|
+
} catch {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
const copy = (event) => {
|
|
295
|
+
writeClipboard(JSON.stringify(event.event, null, 2)).then((ok) => {
|
|
296
|
+
if (!ok) return;
|
|
297
|
+
setCopied(event);
|
|
298
|
+
setTimeout(() => setCopied((current) => current === event ? null : current), 1500);
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
const summaryOf = (event) => {
|
|
302
|
+
if (event === null) return "null";
|
|
303
|
+
if (Array.isArray(event)) return `array \xB7 ${event.length} items`;
|
|
304
|
+
if (typeof event === "object") {
|
|
305
|
+
const keys = Object.keys(event);
|
|
306
|
+
return keys.length === 0 ? "{}" : keys.join(", ");
|
|
307
|
+
}
|
|
308
|
+
return String(event);
|
|
309
|
+
};
|
|
310
|
+
const formatProviders = () => {
|
|
311
|
+
if (data.providers.length === 0) return /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "body2", color: "text.secondary" }, "No providers running.");
|
|
312
|
+
return /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1, flexWrap: "wrap", useFlexGap: true }, data.providers.map((p) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Chip, { key: p.id, label: p.id, size: "small", variant: p.id === instanceConfig.providerId ? "filled" : "outlined" })));
|
|
313
|
+
};
|
|
314
|
+
const formatEvent = (event, index) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Accordion, { key: index, disableGutters: true, slotProps: { transition: { unmountOnExit: true } } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.AccordionSummary, { expandIcon: /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ExpandMore, null) }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", spacing: 1.5, alignItems: "center", sx: { minWidth: 0, width: "100%" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", sx: { fontFamily: "monospace" } }, new Date(event.ts).toISOString()), /* @__PURE__ */ import_react3.default.createElement(import_material3.Chip, { label: event.providerId, size: "small", variant: "outlined", sx: { fontSize: "0.65rem", height: 18 } }), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", noWrap: true }, summaryOf(event.event)), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: copied === event ? "Copied" : "Copy event JSON" }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Copy event JSON", sx: { ml: "auto" }, onClick: (e) => {
|
|
315
|
+
e.stopPropagation();
|
|
316
|
+
copy(event);
|
|
317
|
+
} }, copied === event ? /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Check, { fontSize: "small", color: "success" }) : /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ContentCopy, { fontSize: "small" }))))), /* @__PURE__ */ import_react3.default.createElement(import_material3.AccordionDetails, null, /* @__PURE__ */ import_react3.default.createElement(JsonBlock, { value: event.event })));
|
|
318
|
+
if (!data.started) {
|
|
319
|
+
return /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { sx: { p: 2 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { color: "text.secondary" }, "Provider Debug not started. Start the channel (tab settings \u2699 \u2192 Start) to subscribe to a provider and watch its raw events."));
|
|
320
|
+
}
|
|
321
|
+
return /* @__PURE__ */ import_react3.default.createElement(import_material3.Card, { sx: { flex: 1, width: "98%", alignSelf: "center", m: 1 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.CardHeader, { title: /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "row", alignItems: "center", sx: { width: "100%" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement("b", null, "Provider:"), " ", instanceConfig.providerId || "(none)"), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement("b", null, "Events:"), " ", data.events.length, " / ", config.maxEvents), /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { mr: 4 }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Info, { fontSize: "small", sx: { mb: 0.25 } }), /* @__PURE__ */ import_react3.default.createElement("b", null, "\xA0Status:"), " ", data.paused ? "paused" : data.started ? "started" : "stopped"), /* @__PURE__ */ import_react3.default.createElement(import_material3.Tooltip, { title: "Clear captured events" }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { marginLeft: "auto" } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.IconButton, { size: "small", "aria-label": "Clear captured events", onClick: clear, disabled: data.events.length === 0 && data.signals.length === 0 }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.DeleteSweep, { fontSize: "small" }))))) }), /* @__PURE__ */ import_react3.default.createElement(import_material3.CardContent, null, /* @__PURE__ */ import_react3.default.createElement(import_material3.Stack, { direction: "column", spacing: 1, sx: { mb: 1 } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary" }, "Running providers"), formatProviders(), data.signals.map((s, index) => /* @__PURE__ */ import_react3.default.createElement(import_material3.Typography, { key: index, variant: "caption", color: "text.secondary" }, "*** ", s, " ***"))), /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", overflowY: "auto", overflowX: "hidden", width: "100%", flexGrow: 1, height: `calc(100vh - ${boxTop}px - 35px)` } }, /* @__PURE__ */ import_react3.default.createElement(import_material3.Box, { sx: { flex: 1, overflowY: "auto", ml: 1, mr: 1 } }, data.events.map((e, index) => formatEvent(e, index))))));
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
// src/front/ProviderDebugChannel.ts
|
|
325
|
+
var ProviderDebugChannel = class {
|
|
326
|
+
constructor() {
|
|
327
|
+
this.setupVisible = false;
|
|
328
|
+
this.SetupDialog = ProviderDebugSetup;
|
|
329
|
+
this.TabContent = ProviderDebugTabContent;
|
|
330
|
+
this.channelId = "provider-debug";
|
|
331
|
+
this.requirements = {
|
|
332
|
+
accessString: true,
|
|
333
|
+
clusterUrl: true,
|
|
334
|
+
clusterInfo: false,
|
|
335
|
+
exit: false,
|
|
336
|
+
frontChannels: false,
|
|
337
|
+
metrics: false,
|
|
338
|
+
notifier: true,
|
|
339
|
+
notifications: true,
|
|
340
|
+
setup: true,
|
|
341
|
+
settings: false,
|
|
342
|
+
palette: false,
|
|
343
|
+
userSettings: false,
|
|
344
|
+
webSocket: false,
|
|
345
|
+
backChannels: false
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
getScope() {
|
|
349
|
+
return import_kwirth_common.EInstanceConfigScope.NONE;
|
|
350
|
+
}
|
|
351
|
+
getChannelIcon() {
|
|
352
|
+
return ProviderDebugIcon;
|
|
353
|
+
}
|
|
354
|
+
getSetupVisibility() {
|
|
355
|
+
return this.setupVisible;
|
|
356
|
+
}
|
|
357
|
+
setSetupVisibility(visibility) {
|
|
358
|
+
this.setupVisible = visibility;
|
|
359
|
+
}
|
|
360
|
+
processChannelMessage(channelObject, wsEvent) {
|
|
361
|
+
const msg = JSON.parse(wsEvent.data);
|
|
362
|
+
const data = channelObject.data;
|
|
363
|
+
const config = channelObject.config;
|
|
364
|
+
switch (msg.type) {
|
|
365
|
+
case import_kwirth_common.EInstanceMessageType.DATA:
|
|
366
|
+
if (msg.payloadType === "providers" /* PROVIDERS */) {
|
|
367
|
+
data.providers = msg.providers ?? [];
|
|
368
|
+
} else {
|
|
369
|
+
if (msg.event) {
|
|
370
|
+
data.events.push(msg.event);
|
|
371
|
+
while (data.events.length > config.maxEvents) data.events.shift();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
|
|
375
|
+
case import_kwirth_common.EInstanceMessageType.SIGNAL: {
|
|
376
|
+
const signalMessage = JSON.parse(wsEvent.data);
|
|
377
|
+
if (signalMessage.flow === import_kwirth_common.EInstanceMessageFlow.RESPONSE && signalMessage.action === import_kwirth_common.EInstanceMessageAction.START) {
|
|
378
|
+
channelObject.instanceId = signalMessage.instance;
|
|
379
|
+
}
|
|
380
|
+
if (signalMessage.text) data.signals.push(signalMessage.text);
|
|
381
|
+
return { action: import_kwirth_common_front.EChannelRefreshAction.REFRESH };
|
|
382
|
+
}
|
|
383
|
+
default:
|
|
384
|
+
return { action: import_kwirth_common_front.EChannelRefreshAction.NONE };
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
async initChannel(channelObject) {
|
|
388
|
+
channelObject.instanceConfig = new ProviderDebugInstanceConfig();
|
|
389
|
+
channelObject.config = new ProviderDebugConfig();
|
|
390
|
+
channelObject.data = new ProviderDebugData();
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
startChannel(channelObject) {
|
|
394
|
+
const data = channelObject.data;
|
|
395
|
+
data.events = [];
|
|
396
|
+
data.signals = [];
|
|
397
|
+
data.paused = false;
|
|
398
|
+
data.started = true;
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
pauseChannel(channelObject) {
|
|
402
|
+
const data = channelObject.data;
|
|
403
|
+
data.paused = true;
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
continueChannel(channelObject) {
|
|
407
|
+
const data = channelObject.data;
|
|
408
|
+
data.paused = false;
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
stopChannel(channelObject) {
|
|
412
|
+
const data = channelObject.data;
|
|
413
|
+
data.paused = false;
|
|
414
|
+
data.started = false;
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
socketDisconnected(_channelObject) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
socketReconnect(_channelObject) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/front/index.ts
|
|
426
|
+
window.__kwirth_plugins__ = window.__kwirth_plugins__ || {};
|
|
427
|
+
window.__kwirth_plugins__["provider-debug"] = ProviderDebugChannel;
|
|
428
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "commonjs",
|
|
3
|
+
"extensionType": "plugin",
|
|
4
|
+
"id": "provider-debug",
|
|
5
|
+
"name": "@kwirthmagnify/kwirth-plugin-provider-debug",
|
|
6
|
+
"displayName": "Provider Debug",
|
|
7
|
+
"version": "0.1.0",
|
|
8
|
+
"description": "Provider debugging channel for Kwirth - subscribes to a running provider and streams its raw events",
|
|
9
|
+
"icon": "DataObjectOutlined",
|
|
10
|
+
"requiresRestart": false,
|
|
11
|
+
"requiresExtension": []
|
|
12
|
+
}
|