@webda/debug 4.0.0-beta.3
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/LICENSE +166 -0
- package/README.md +95 -0
- package/lib/bodycapture.d.ts +66 -0
- package/lib/bodycapture.js +162 -0
- package/lib/bodycapture.js.map +1 -0
- package/lib/debugservice.service.d.ts +166 -0
- package/lib/debugservice.service.js +609 -0
- package/lib/debugservice.service.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +7 -0
- package/lib/index.js.map +1 -0
- package/lib/introspection.d.ts +115 -0
- package/lib/introspection.js +260 -0
- package/lib/introspection.js.map +1 -0
- package/lib/logbuffer.d.ts +75 -0
- package/lib/logbuffer.js +98 -0
- package/lib/logbuffer.js.map +1 -0
- package/lib/requestlog.d.ts +181 -0
- package/lib/requestlog.js +153 -0
- package/lib/requestlog.js.map +1 -0
- package/lib/tui/client.d.ts +165 -0
- package/lib/tui/client.js +220 -0
- package/lib/tui/client.js.map +1 -0
- package/lib/tui/panels/config.d.ts +79 -0
- package/lib/tui/panels/config.js +291 -0
- package/lib/tui/panels/config.js.map +1 -0
- package/lib/tui/panels/logs.d.ts +106 -0
- package/lib/tui/panels/logs.js +342 -0
- package/lib/tui/panels/logs.js.map +1 -0
- package/lib/tui/panels/models.d.ts +47 -0
- package/lib/tui/panels/models.js +193 -0
- package/lib/tui/panels/models.js.map +1 -0
- package/lib/tui/panels/operations.d.ts +55 -0
- package/lib/tui/panels/operations.js +241 -0
- package/lib/tui/panels/operations.js.map +1 -0
- package/lib/tui/panels/panel.d.ts +55 -0
- package/lib/tui/panels/panel.js +31 -0
- package/lib/tui/panels/panel.js.map +1 -0
- package/lib/tui/panels/requests.d.ts +156 -0
- package/lib/tui/panels/requests.js +512 -0
- package/lib/tui/panels/requests.js.map +1 -0
- package/lib/tui/panels/routes.d.ts +45 -0
- package/lib/tui/panels/routes.js +154 -0
- package/lib/tui/panels/routes.js.map +1 -0
- package/lib/tui/panels/services.d.ts +49 -0
- package/lib/tui/panels/services.js +266 -0
- package/lib/tui/panels/services.js.map +1 -0
- package/lib/tui/tui.d.ts +58 -0
- package/lib/tui/tui.js +236 -0
- package/lib/tui/tui.js.map +1 -0
- package/package.json +60 -0
- package/webui/app.js +177 -0
- package/webui/components/logs.js +128 -0
- package/webui/components/model-graph.js +292 -0
- package/webui/components/models.js +213 -0
- package/webui/components/operations.js +315 -0
- package/webui/components/requests.js +264 -0
- package/webui/components/schema-form.js +268 -0
- package/webui/components/services.js +248 -0
- package/webui/index.html +22 -0
- package/webui/logo.svg +1 -0
- package/webui/styles.css +685 -0
- package/webui/vendor/htm.js +1 -0
- package/webui/vendor/preact-hooks.js +2 -0
- package/webui/vendor/preact.js +2 -0
- package/webui/webda.png +0 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { Service, ServiceParameters, useDynamicService, useCoreEvents, useRouter } from "@webda/core";
|
|
36
|
+
import { Command } from "@webda/core";
|
|
37
|
+
import { createServer } from "node:http";
|
|
38
|
+
import { exec } from "node:child_process";
|
|
39
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
40
|
+
import { platform } from "node:os";
|
|
41
|
+
import { fileURLToPath } from "node:url";
|
|
42
|
+
import { dirname, join, extname } from "node:path";
|
|
43
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
44
|
+
import { RequestLog } from "./requestlog.js";
|
|
45
|
+
import { LogBuffer } from "./logbuffer.js";
|
|
46
|
+
import { captureBody, normalizeHeaders } from "./bodycapture.js";
|
|
47
|
+
import { getModels, getModel, getServices, getOperations, getRoutes, getConfig, getAppInfo } from "./introspection.js";
|
|
48
|
+
import { DebugTui } from "./tui/tui.js";
|
|
49
|
+
import { CancelablePromise } from "@webda/utils";
|
|
50
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
51
|
+
const WEBUI_DIR = join(__dirname, "..", "webui");
|
|
52
|
+
/** Origins that are always allowed to access the debug API. */
|
|
53
|
+
const ALLOWED_ORIGIN_EXACT = new Set([
|
|
54
|
+
"http://localhost:3000",
|
|
55
|
+
"http://127.0.0.1:3000",
|
|
56
|
+
"https://webda.io"
|
|
57
|
+
]);
|
|
58
|
+
/**
|
|
59
|
+
* Determine whether the given Origin header value is allowed to access the debug API.
|
|
60
|
+
*
|
|
61
|
+
* Allowed origins:
|
|
62
|
+
* - http://localhost:3000 (docs dev server)
|
|
63
|
+
* - http://127.0.0.1:3000 (docs dev server, alternate address)
|
|
64
|
+
* - https://webda.io (production docs)
|
|
65
|
+
* - https://*.webda.io (any HTTPS subdomain of webda.io)
|
|
66
|
+
*
|
|
67
|
+
* @param origin - The value of the HTTP `Origin` request header.
|
|
68
|
+
* @returns `true` if the origin is allowed, `false` otherwise.
|
|
69
|
+
*/
|
|
70
|
+
export function isAllowedOrigin(origin) {
|
|
71
|
+
if (!origin)
|
|
72
|
+
return false;
|
|
73
|
+
if (ALLOWED_ORIGIN_EXACT.has(origin))
|
|
74
|
+
return true;
|
|
75
|
+
// Allow any https:// subdomain of webda.io
|
|
76
|
+
try {
|
|
77
|
+
const u = new URL(origin);
|
|
78
|
+
return u.protocol === "https:" && u.hostname.endsWith(".webda.io");
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Map file extensions to MIME types for static file serving. */
|
|
85
|
+
const MIME_TYPES = {
|
|
86
|
+
".html": "text/html; charset=utf-8",
|
|
87
|
+
".css": "text/css; charset=utf-8",
|
|
88
|
+
".js": "text/javascript; charset=utf-8",
|
|
89
|
+
".json": "application/json; charset=utf-8",
|
|
90
|
+
".svg": "image/svg+xml",
|
|
91
|
+
".png": "image/png",
|
|
92
|
+
".ico": "image/x-icon"
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Configuration parameters for the {@link DebugService}.
|
|
96
|
+
*
|
|
97
|
+
* All capture knobs default to safe values — capture is enabled with a
|
|
98
|
+
* 64 KB inline body limit and a 4-byte hex preview for binary payloads.
|
|
99
|
+
*/
|
|
100
|
+
export class DebugServiceParameters extends ServiceParameters {
|
|
101
|
+
constructor() {
|
|
102
|
+
super(...arguments);
|
|
103
|
+
/**
|
|
104
|
+
* Whether to capture request/response headers and bodies for the debug UI.
|
|
105
|
+
* If `false`, only status code and duration are recorded.
|
|
106
|
+
*/
|
|
107
|
+
this.captureRequests = true;
|
|
108
|
+
/**
|
|
109
|
+
* Maximum number of bytes to keep inline for text bodies. Larger payloads
|
|
110
|
+
* are truncated to this size and reported as `text-truncated`.
|
|
111
|
+
*/
|
|
112
|
+
this.captureBodyLimit = 65536;
|
|
113
|
+
/**
|
|
114
|
+
* Number of leading bytes to include in the hex preview for binary bodies.
|
|
115
|
+
*/
|
|
116
|
+
this.captureBinaryPreview = 4;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Debug dashboard service that provides an HTTP API for introspection
|
|
121
|
+
* and a WebSocket feed of live request events.
|
|
122
|
+
*
|
|
123
|
+
* @WebdaModda
|
|
124
|
+
*/
|
|
125
|
+
let DebugService = (() => {
|
|
126
|
+
var _a;
|
|
127
|
+
let _classSuper = Service;
|
|
128
|
+
let _instanceExtraInitializers = [];
|
|
129
|
+
let _debug_decorators;
|
|
130
|
+
return _a = class DebugService extends _classSuper {
|
|
131
|
+
constructor() {
|
|
132
|
+
super(...arguments);
|
|
133
|
+
/** Ring buffer of recent HTTP requests */
|
|
134
|
+
this.requestLog = (__runInitializers(this, _instanceExtraInitializers), new RequestLog());
|
|
135
|
+
/** Ring buffer of application log entries */
|
|
136
|
+
this.logBuffer = new LogBuffer();
|
|
137
|
+
/** Connected WebSocket clients */
|
|
138
|
+
this.clients = new Set();
|
|
139
|
+
/** Unsubscribe functions for core event listeners */
|
|
140
|
+
this.unsubscribers = [];
|
|
141
|
+
/** Timing map: requestId -> start timestamp */
|
|
142
|
+
this.timings = new Map();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Resolve the typed parameters and the capture knobs (with safe defaults
|
|
146
|
+
* when the surrounding test environment does not load real parameters).
|
|
147
|
+
*
|
|
148
|
+
* @returns The effective `{ captureRequests, captureBodyLimit, captureBinaryPreview }` triple.
|
|
149
|
+
*/
|
|
150
|
+
getCaptureSettings() {
|
|
151
|
+
const params = (this.parameters || {});
|
|
152
|
+
return {
|
|
153
|
+
captureRequests: params.captureRequests !== false,
|
|
154
|
+
bodyLimit: typeof params.captureBodyLimit === "number" ? params.captureBodyLimit : 65536,
|
|
155
|
+
binaryPreview: typeof params.captureBinaryPreview === "number" ? params.captureBinaryPreview : 4
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Subscribe to core events to populate the request log.
|
|
160
|
+
* @returns this for chaining
|
|
161
|
+
*/
|
|
162
|
+
resolve() {
|
|
163
|
+
super.resolve();
|
|
164
|
+
this.subscribeToEvents();
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Wire up core event listeners for request tracking.
|
|
169
|
+
*/
|
|
170
|
+
subscribeToEvents() {
|
|
171
|
+
this.unsubscribers.push(useCoreEvents("Webda.Request", evt => {
|
|
172
|
+
const id = Math.random().toString(36).substring(2);
|
|
173
|
+
const ctx = evt.context;
|
|
174
|
+
ctx.setExtension("debugRequestId", id);
|
|
175
|
+
const http = ctx.getHttpContext?.();
|
|
176
|
+
const method = http?.getMethod?.() ?? "UNKNOWN";
|
|
177
|
+
const url = http?.getUrl?.() ?? "/";
|
|
178
|
+
this.timings.set(id, Date.now());
|
|
179
|
+
this.requestLog.startRequest(id, method, url);
|
|
180
|
+
}));
|
|
181
|
+
this.unsubscribers.push(useCoreEvents("Webda.Result", async (evt) => {
|
|
182
|
+
const ctx = evt.context;
|
|
183
|
+
const id = ctx.getExtension("debugRequestId");
|
|
184
|
+
if (!id)
|
|
185
|
+
return;
|
|
186
|
+
const start = this.timings.get(id);
|
|
187
|
+
const duration = start ? Date.now() - start : 0;
|
|
188
|
+
this.timings.delete(id);
|
|
189
|
+
const statusCode = ctx.statusCode ?? 200;
|
|
190
|
+
// Capture headers/bodies first so that `attachDetails` runs before
|
|
191
|
+
// `completeRequest` notifies subscribers — this keeps the UI's view
|
|
192
|
+
// of "the entry that just got a status code" consistent with the
|
|
193
|
+
// captured body.
|
|
194
|
+
const details = await this.collectDetails(ctx);
|
|
195
|
+
if (details) {
|
|
196
|
+
this.requestLog.attachDetails(id, details);
|
|
197
|
+
}
|
|
198
|
+
this.requestLog.completeRequest(id, statusCode, duration);
|
|
199
|
+
}));
|
|
200
|
+
this.unsubscribers.push(useCoreEvents("Webda.404", async (evt) => {
|
|
201
|
+
const ctx = evt.context;
|
|
202
|
+
const id = ctx.getExtension("debugRequestId");
|
|
203
|
+
if (!id)
|
|
204
|
+
return;
|
|
205
|
+
this.timings.delete(id);
|
|
206
|
+
// Even on 404 we can capture the request side (and any response
|
|
207
|
+
// headers Webda may have set) so the UI can show what was asked.
|
|
208
|
+
const details = await this.collectDetails(ctx);
|
|
209
|
+
if (details) {
|
|
210
|
+
this.requestLog.attachDetails(id, details);
|
|
211
|
+
}
|
|
212
|
+
this.requestLog.markNotFound(id);
|
|
213
|
+
}));
|
|
214
|
+
// Forward request log events to WebSocket clients
|
|
215
|
+
this.requestLog.onEvent(event => {
|
|
216
|
+
this.broadcast(event);
|
|
217
|
+
});
|
|
218
|
+
// Capture application logs and forward to WebSocket clients
|
|
219
|
+
this.logBuffer.subscribe();
|
|
220
|
+
this.logBuffer.onEvent(event => {
|
|
221
|
+
this.broadcast(event);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Collect headers, bodies, and any error from a finished context.
|
|
226
|
+
*
|
|
227
|
+
* Returns `undefined` if capture is disabled via configuration. Resolves
|
|
228
|
+
* once both request body (read via the HttpContext, which caches its
|
|
229
|
+
* Buffer after the first read) and response body (read from the
|
|
230
|
+
* WebContext's buffered output stream) have been captured. Failures
|
|
231
|
+
* during capture (e.g. a body that can't be read or that times out) are
|
|
232
|
+
* swallowed so the debug service never breaks the request itself.
|
|
233
|
+
*
|
|
234
|
+
* @param ctx - The finished web context.
|
|
235
|
+
* @returns A {@link RequestLogDetails} payload, or `undefined` when capture is off.
|
|
236
|
+
*/
|
|
237
|
+
async collectDetails(ctx) {
|
|
238
|
+
const settings = this.getCaptureSettings();
|
|
239
|
+
if (!settings.captureRequests)
|
|
240
|
+
return undefined;
|
|
241
|
+
const details = {};
|
|
242
|
+
// ----- Request headers + body -------------------------------------------
|
|
243
|
+
try {
|
|
244
|
+
const http = ctx.getHttpContext?.();
|
|
245
|
+
if (http) {
|
|
246
|
+
if (typeof http.getHeaders === "function") {
|
|
247
|
+
details.requestHeaders = normalizeHeaders(http.getHeaders());
|
|
248
|
+
}
|
|
249
|
+
// Webda's HttpContext caches the raw body Buffer the first time it
|
|
250
|
+
// is read, so awaiting getRawBody here is safe whether or not a
|
|
251
|
+
// route handler already consumed the stream. We cap at the body
|
|
252
|
+
// limit to avoid pulling huge uploads back into memory just for
|
|
253
|
+
// the debug log.
|
|
254
|
+
let buf;
|
|
255
|
+
try {
|
|
256
|
+
if (typeof http.getRawBody === "function") {
|
|
257
|
+
const result = await http.getRawBody(settings.bodyLimit);
|
|
258
|
+
buf = result ?? Buffer.alloc(0);
|
|
259
|
+
}
|
|
260
|
+
else if (typeof ctx.getRawInput === "function") {
|
|
261
|
+
const result = await ctx.getRawInput(settings.bodyLimit);
|
|
262
|
+
buf = result ?? Buffer.alloc(0);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
buf = undefined;
|
|
267
|
+
}
|
|
268
|
+
const reqContentType = typeof http.getUniqueHeader === "function" ? http.getUniqueHeader("content-type") : undefined;
|
|
269
|
+
if (buf !== undefined) {
|
|
270
|
+
details.requestBody = captureBody(buf, reqContentType, settings.bodyLimit, settings.binaryPreview);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
/* ignore — request capture is best-effort */
|
|
276
|
+
}
|
|
277
|
+
// ----- Response headers + body ------------------------------------------
|
|
278
|
+
try {
|
|
279
|
+
const responseHeaders = typeof ctx.getResponseHeaders === "function" ? ctx.getResponseHeaders() : {};
|
|
280
|
+
details.responseHeaders = normalizeHeaders(responseHeaders);
|
|
281
|
+
let respBuf;
|
|
282
|
+
try {
|
|
283
|
+
if (typeof ctx.getResponseBody === "function") {
|
|
284
|
+
const body = ctx.getResponseBody();
|
|
285
|
+
if (body === undefined || body === null) {
|
|
286
|
+
respBuf = Buffer.alloc(0);
|
|
287
|
+
}
|
|
288
|
+
else if (Buffer.isBuffer(body)) {
|
|
289
|
+
respBuf = body;
|
|
290
|
+
}
|
|
291
|
+
else if (typeof body === "string") {
|
|
292
|
+
respBuf = Buffer.from(body, "utf8");
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
respBuf = Buffer.from(String(body), "utf8");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else if (typeof ctx.getOutput === "function") {
|
|
299
|
+
const out = ctx.getOutput();
|
|
300
|
+
respBuf = out ? Buffer.from(String(out), "utf8") : Buffer.alloc(0);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
respBuf = undefined;
|
|
305
|
+
}
|
|
306
|
+
const respContentType = (responseHeaders && (responseHeaders["Content-Type"] ?? responseHeaders["content-type"])) ||
|
|
307
|
+
undefined;
|
|
308
|
+
if (respBuf !== undefined) {
|
|
309
|
+
details.responseBody = captureBody(respBuf, typeof respContentType === "string" ? respContentType : undefined, settings.bodyLimit, settings.binaryPreview);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
/* ignore — response capture is best-effort */
|
|
314
|
+
}
|
|
315
|
+
// ----- Error ------------------------------------------------------------
|
|
316
|
+
const err = ctx.error || ctx.getExtension?.("error");
|
|
317
|
+
if (err) {
|
|
318
|
+
const captured = { message: err.message ?? String(err) };
|
|
319
|
+
if (err.stack)
|
|
320
|
+
captured.stack = err.stack;
|
|
321
|
+
details.error = captured;
|
|
322
|
+
}
|
|
323
|
+
return details;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Start the application HTTP server and the debug HTTP+WS server.
|
|
327
|
+
*
|
|
328
|
+
* @param port - Port for the debug dashboard API
|
|
329
|
+
* @param servePort - Port for the application HTTP server
|
|
330
|
+
* @param web - Disable TUI and only serve the web dashboard
|
|
331
|
+
* @returns a promise settled once the service stops or the TUI quits
|
|
332
|
+
*/
|
|
333
|
+
debug(
|
|
334
|
+
/** @alias p @description Debug dashboard port */
|
|
335
|
+
port = 18181,
|
|
336
|
+
/** @alias s @description Application server port */
|
|
337
|
+
servePort = 18080,
|
|
338
|
+
/** @description Disable TUI and only serve the web dashboard */
|
|
339
|
+
web) {
|
|
340
|
+
// Stays pending until the service stops or the TUI quits
|
|
341
|
+
return new CancelablePromise((resolve, reject) => {
|
|
342
|
+
this.running = resolve;
|
|
343
|
+
this.startDebug(port, servePort, web).catch(reject);
|
|
344
|
+
}, async () => {
|
|
345
|
+
this.tui?.stop();
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Start the application server, the debug server and the TUI or browser
|
|
350
|
+
*
|
|
351
|
+
* @param port - Port for the debug dashboard API
|
|
352
|
+
* @param servePort - Port for the application HTTP server
|
|
353
|
+
* @param web - Disable TUI and only serve the web dashboard
|
|
354
|
+
*/
|
|
355
|
+
async startDebug(port, servePort, web) {
|
|
356
|
+
// Start the main application server
|
|
357
|
+
const httpServer = useDynamicService("HttpServer");
|
|
358
|
+
if (httpServer?.start) {
|
|
359
|
+
await httpServer.start(undefined, servePort);
|
|
360
|
+
this.log("INFO", `Application server started on port ${servePort}`);
|
|
361
|
+
}
|
|
362
|
+
// Start the debug HTTP + WebSocket server
|
|
363
|
+
await this.startDebugServer(port);
|
|
364
|
+
this.log("INFO", `Debug dashboard API listening on port ${port}`);
|
|
365
|
+
// Launch TUI by default, unless --web is passed
|
|
366
|
+
if (!web) {
|
|
367
|
+
this.tui = new DebugTui(port);
|
|
368
|
+
// Quitting the TUI ends the command
|
|
369
|
+
this.tui.onStop = () => this.settle();
|
|
370
|
+
await this.tui.start();
|
|
371
|
+
}
|
|
372
|
+
else if (!process.env.WEBDA_DEBUG_NO_BROWSER) {
|
|
373
|
+
// Headless callers (CI, Playwright's `webServer`, scripted smoke
|
|
374
|
+
// tests) set WEBDA_DEBUG_NO_BROWSER=1 to suppress the auto-open —
|
|
375
|
+
// they manage their own browser instance and don't want the local
|
|
376
|
+
// Chrome to pop a stray tab on every server start.
|
|
377
|
+
this.openBrowser(`http://localhost:${port}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Settle the running debug command
|
|
382
|
+
*/
|
|
383
|
+
settle() {
|
|
384
|
+
this.running?.();
|
|
385
|
+
this.running = undefined;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Open a URL in the default browser.
|
|
389
|
+
* @param url - URL to open
|
|
390
|
+
*/
|
|
391
|
+
openBrowser(url) {
|
|
392
|
+
const cmd = platform() === "darwin" ? "open" : platform() === "win32" ? "start" : "xdg-open";
|
|
393
|
+
exec(`${cmd} ${url}`);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Create and start the debug HTTP server with WebSocket support.
|
|
397
|
+
* @param port - Port to listen on
|
|
398
|
+
*/
|
|
399
|
+
async startDebugServer(port) {
|
|
400
|
+
this.server = createServer((req, res) => this.handleRequest(req, res));
|
|
401
|
+
this.wss = new WebSocketServer({ server: this.server });
|
|
402
|
+
this.wss.on("connection", (ws) => {
|
|
403
|
+
this.clients.add(ws);
|
|
404
|
+
ws.on("close", () => this.clients.delete(ws));
|
|
405
|
+
ws.on("error", () => this.clients.delete(ws));
|
|
406
|
+
});
|
|
407
|
+
await new Promise(resolve => {
|
|
408
|
+
this.server.listen(port, () => resolve());
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Route incoming HTTP requests to introspection handlers.
|
|
413
|
+
* @param req - Incoming HTTP request
|
|
414
|
+
* @param res - Server response
|
|
415
|
+
*/
|
|
416
|
+
handleRequest(req, res) {
|
|
417
|
+
// CORS: echo the origin back only if it is on the allowlist.
|
|
418
|
+
// If there is no matching origin the browser will block cross-origin access,
|
|
419
|
+
// which is the desired behaviour. We also set Vary: Origin so that CDN /
|
|
420
|
+
// proxy caches do not serve a response with an allowed origin header to a
|
|
421
|
+
// different (disallowed) origin.
|
|
422
|
+
const origin = req.headers.origin;
|
|
423
|
+
if (isAllowedOrigin(origin)) {
|
|
424
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
425
|
+
res.setHeader("Vary", "Origin");
|
|
426
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
427
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
428
|
+
}
|
|
429
|
+
if (req.method === "OPTIONS") {
|
|
430
|
+
res.writeHead(204);
|
|
431
|
+
res.end();
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const url = req.url || "/";
|
|
435
|
+
const pathname = url.split("?")[0];
|
|
436
|
+
try {
|
|
437
|
+
// Route to handlers
|
|
438
|
+
if (pathname === "/api/info") {
|
|
439
|
+
this.sendJson(res, getAppInfo());
|
|
440
|
+
}
|
|
441
|
+
else if (pathname === "/api/models") {
|
|
442
|
+
this.sendJson(res, getModels());
|
|
443
|
+
}
|
|
444
|
+
else if (pathname.startsWith("/api/models/")) {
|
|
445
|
+
const id = decodeURIComponent(pathname.slice("/api/models/".length));
|
|
446
|
+
const model = getModel(id);
|
|
447
|
+
if (model) {
|
|
448
|
+
this.sendJson(res, model);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
this.sendJson(res, { error: "Model not found" }, 404);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
else if (pathname === "/api/services") {
|
|
455
|
+
this.sendJson(res, getServices());
|
|
456
|
+
}
|
|
457
|
+
else if (pathname === "/api/operations") {
|
|
458
|
+
this.sendJson(res, getOperations());
|
|
459
|
+
}
|
|
460
|
+
else if (pathname === "/api/routes") {
|
|
461
|
+
this.sendJson(res, getRoutes());
|
|
462
|
+
}
|
|
463
|
+
else if (pathname === "/api/config") {
|
|
464
|
+
this.sendJson(res, getConfig());
|
|
465
|
+
}
|
|
466
|
+
else if (pathname === "/api/openapi") {
|
|
467
|
+
this.sendJson(res, this.getOpenAPISpec());
|
|
468
|
+
}
|
|
469
|
+
else if (pathname === "/api/requests") {
|
|
470
|
+
// List endpoint stays cheap — summaries only (no headers/bodies).
|
|
471
|
+
this.sendJson(res, this.requestLog.getSummaries());
|
|
472
|
+
}
|
|
473
|
+
else if (pathname.startsWith("/api/requests/")) {
|
|
474
|
+
const id = decodeURIComponent(pathname.slice("/api/requests/".length));
|
|
475
|
+
const entry = this.requestLog.getEntry(id);
|
|
476
|
+
if (entry) {
|
|
477
|
+
this.sendJson(res, entry);
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
this.sendJson(res, { error: "Request not found" }, 404);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
else if (pathname === "/api/logs") {
|
|
484
|
+
const searchParams = new URL(url, "http://localhost").searchParams;
|
|
485
|
+
const query = searchParams.get("q") || "";
|
|
486
|
+
this.sendJson(res, query ? this.logBuffer.search(query) : this.logBuffer.getEntries());
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
this.serveStaticFile(pathname, res);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch (err) {
|
|
493
|
+
this.log("ERROR", `Debug API error: ${err.message}`);
|
|
494
|
+
this.sendJson(res, { error: err.message || "Internal server error" }, 500);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Build an OpenAPI spec from the router.
|
|
499
|
+
* @returns OpenAPI document or a stub if the router is unavailable
|
|
500
|
+
*/
|
|
501
|
+
getOpenAPISpec() {
|
|
502
|
+
try {
|
|
503
|
+
const router = useRouter();
|
|
504
|
+
const doc = {
|
|
505
|
+
openapi: "3.0.3",
|
|
506
|
+
info: { title: "Webda Application", version: "1.0.0" },
|
|
507
|
+
paths: {},
|
|
508
|
+
tags: []
|
|
509
|
+
};
|
|
510
|
+
router.completeOpenAPI(doc);
|
|
511
|
+
return doc;
|
|
512
|
+
}
|
|
513
|
+
catch {
|
|
514
|
+
return { openapi: "3.0.3", info: { title: "Webda Application", version: "1.0.0" }, paths: {} };
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Serve a static file from the webui directory.
|
|
519
|
+
* Falls back to index.html for SPA-style routing.
|
|
520
|
+
* @param pathname - Request pathname
|
|
521
|
+
* @param res - Server response
|
|
522
|
+
*/
|
|
523
|
+
serveStaticFile(pathname, res) {
|
|
524
|
+
// Prevent directory traversal
|
|
525
|
+
const safePath = pathname.replace(/\.\./g, "").replace(/\/+/g, "/");
|
|
526
|
+
let filePath = join(WEBUI_DIR, safePath === "/" ? "index.html" : safePath);
|
|
527
|
+
// If the file doesn't exist, serve index.html (SPA fallback)
|
|
528
|
+
if (!existsSync(filePath)) {
|
|
529
|
+
filePath = join(WEBUI_DIR, "index.html");
|
|
530
|
+
}
|
|
531
|
+
if (!existsSync(filePath)) {
|
|
532
|
+
this.sendJson(res, { error: "Not found" }, 404);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
const content = readFileSync(filePath);
|
|
537
|
+
const ext = extname(filePath);
|
|
538
|
+
const mime = MIME_TYPES[ext] || "application/octet-stream";
|
|
539
|
+
res.writeHead(200, { "Content-Type": mime });
|
|
540
|
+
res.end(content);
|
|
541
|
+
}
|
|
542
|
+
catch {
|
|
543
|
+
this.sendJson(res, { error: "Internal server error" }, 500);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Write a JSON response.
|
|
548
|
+
* @param res - Server response
|
|
549
|
+
* @param data - Data to serialize
|
|
550
|
+
* @param statusCode - HTTP status code
|
|
551
|
+
*/
|
|
552
|
+
sendJson(res, data, statusCode = 200) {
|
|
553
|
+
res.writeHead(statusCode, { "Content-Type": "application/json" });
|
|
554
|
+
res.end(JSON.stringify(data));
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Broadcast a message to all connected WebSocket clients.
|
|
558
|
+
* @param data - Data to send (will be JSON-serialized)
|
|
559
|
+
*/
|
|
560
|
+
broadcast(data) {
|
|
561
|
+
const message = JSON.stringify(data);
|
|
562
|
+
for (const client of this.clients) {
|
|
563
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
564
|
+
client.send(message);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Clean up HTTP server and WebSocket connections.
|
|
570
|
+
*/
|
|
571
|
+
async stop() {
|
|
572
|
+
// Unsubscribe from core events and log buffer
|
|
573
|
+
for (const unsub of this.unsubscribers) {
|
|
574
|
+
unsub();
|
|
575
|
+
}
|
|
576
|
+
this.unsubscribers = [];
|
|
577
|
+
this.logBuffer.unsubscribe();
|
|
578
|
+
// Close WebSocket connections
|
|
579
|
+
for (const client of this.clients) {
|
|
580
|
+
client.close();
|
|
581
|
+
}
|
|
582
|
+
this.clients.clear();
|
|
583
|
+
// Close servers
|
|
584
|
+
if (this.wss) {
|
|
585
|
+
this.wss.close();
|
|
586
|
+
this.wss = undefined;
|
|
587
|
+
}
|
|
588
|
+
if (this.server) {
|
|
589
|
+
await new Promise(resolve => this.server.close(() => resolve()));
|
|
590
|
+
this.server = undefined;
|
|
591
|
+
}
|
|
592
|
+
this.timings.clear();
|
|
593
|
+
this.tui?.stop();
|
|
594
|
+
this.tui = undefined;
|
|
595
|
+
this.settle();
|
|
596
|
+
await super.stop();
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
(() => {
|
|
600
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
601
|
+
_debug_decorators = [Command("debug", { description: "Start dev server with debug dashboard", requires: ["router", "rest-domain", "http-server"] })];
|
|
602
|
+
__esDecorate(_a, null, _debug_decorators, { kind: "method", name: "debug", static: false, private: false, access: { has: obj => "debug" in obj, get: obj => obj.debug }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
603
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
604
|
+
})(),
|
|
605
|
+
_a.Parameters = DebugServiceParameters,
|
|
606
|
+
_a;
|
|
607
|
+
})();
|
|
608
|
+
export { DebugService };
|
|
609
|
+
//# sourceMappingURL=debugservice.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debugservice.service.js","sourceRoot":"","sources":["../src/debugservice.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtG,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,YAAY,EAA2C,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,EAAE,UAAU,EAAgD,MAAM,iBAAiB,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACvH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAEjD,+DAA+D;AAC/D,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,uBAAuB;IACvB,uBAAuB;IACvB,kBAAkB;CACnB,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,MAA0B;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,2CAA2C;IAC3C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1B,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,GAA2B;IACzC,OAAO,EAAE,0BAA0B;IACnC,MAAM,EAAE,yBAAyB;IACjC,KAAK,EAAE,gCAAgC;IACvC,OAAO,EAAE,iCAAiC;IAC1C,MAAM,EAAE,eAAe;IACvB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,cAAc;CACvB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,OAAO,sBAAuB,SAAQ,iBAAiB;IAA7D;;QACE;;;WAGG;QACH,oBAAe,GAAY,IAAI,CAAC;QAChC;;;WAGG;QACH,qBAAgB,GAAW,KAAK,CAAC;QACjC;;WAEG;QACH,yBAAoB,GAAW,CAAC,CAAC;IACnC,CAAC;CAAA;AAED;;;;;GAKG;IACU,YAAY;;sBAAS,OAAO;;;sBAA5B,YAAa,SAAQ,WAA+B;;;gBAE/D,0CAA0C;gBAC1C,eAAU,IAHC,mDAAY,EAGE,IAAI,UAAU,EAAE,EAAC;gBAC1C,6CAA6C;gBACrC,cAAS,GAAc,IAAI,SAAS,EAAE,CAAC;gBAK/C,kCAAkC;gBAC1B,YAAO,GAAmB,IAAI,GAAG,EAAE,CAAC;gBAC5C,qDAAqD;gBAC7C,kBAAa,GAAmB,EAAE,CAAC;gBAK3C,+CAA+C;gBACvC,YAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;YAwenD,CAAC;YAteC;;;;;eAKG;YACK,kBAAkB;gBACxB,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAoC,CAAC;gBAC1E,OAAO;oBACL,eAAe,EAAE,MAAM,CAAC,eAAe,KAAK,KAAK;oBACjD,SAAS,EAAE,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK;oBACxF,aAAa,EAAE,OAAO,MAAM,CAAC,oBAAoB,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;iBACjG,CAAC;YACJ,CAAC;YAED;;;eAGG;YACH,OAAO;gBACL,KAAK,CAAC,OAAO,EAAE,CAAC;gBAChB,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;YAED;;eAEG;YACK,iBAAiB;gBACvB,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,aAAa,CAAC,eAAe,EAAE,GAAG,CAAC,EAAE;oBACnC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBACnD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;oBACxB,GAAG,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;oBACvC,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC;oBACpC,MAAM,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,SAAS,CAAC;oBAChD,MAAM,GAAG,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,GAAG,CAAC;oBACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;oBACjC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;gBAChD,CAAC,CAAC,CACH,CAAC;gBAEF,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,aAAa,CAAC,cAAc,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;oBACxC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;oBACxB,MAAM,EAAE,GAAG,GAAG,CAAC,YAAY,CAAS,gBAAgB,CAAC,CAAC;oBACtD,IAAI,CAAC,EAAE;wBAAE,OAAO;oBAChB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;oBAChD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBACxB,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC;oBAEzC,mEAAmE;oBACnE,oEAAoE;oBACpE,iEAAiE;oBACjE,iBAAiB;oBACjB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;oBAC/C,IAAI,OAAO,EAAE,CAAC;wBACZ,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;oBAC7C,CAAC;oBAED,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;gBAC5D,CAAC,CAAC,CACH,CAAC;gBAEF,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,aAAa,CAAC,WAAW,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;oBACrC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;oBACxB,MAAM,EAAE,GAAG,GAAG,CAAC,YAAY,CAAS,gBAAgB,CAAC,CAAC;oBACtD,IAAI,CAAC,EAAE;wBAAE,OAAO;oBAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAExB,gEAAgE;oBAChE,iEAAiE;oBACjE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;oBAC/C,IAAI,OAAO,EAAE,CAAC;wBACZ,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;oBAC7C,CAAC;oBAED,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;gBACnC,CAAC,CAAC,CACH,CAAC;gBAEF,kDAAkD;gBAClD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;oBAC9B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACxB,CAAC,CAAC,CAAC;gBAEH,4DAA4D;gBAC5D,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;oBAC7B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACxB,CAAC,CAAC,CAAC;YACL,CAAC;YAED;;;;;;;;;;;;eAYG;YACK,KAAK,CAAC,cAAc,CAAC,GAAQ;gBACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC3C,IAAI,CAAC,QAAQ,CAAC,eAAe;oBAAE,OAAO,SAAS,CAAC;gBAEhD,MAAM,OAAO,GAAsB,EAAE,CAAC;gBAEtC,2EAA2E;gBAC3E,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC;oBACpC,IAAI,IAAI,EAAE,CAAC;wBACT,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;4BAC1C,OAAO,CAAC,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;wBAC/D,CAAC;wBACD,mEAAmE;wBACnE,gEAAgE;wBAChE,gEAAgE;wBAChE,gEAAgE;wBAChE,iBAAiB;wBACjB,IAAI,GAAuB,CAAC;wBAC5B,IAAI,CAAC;4BACH,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gCAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gCACzD,GAAG,GAAG,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;4BAClC,CAAC;iCAAM,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gCACjD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;gCACzD,GAAG,GAAG,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;4BAClC,CAAC;wBACH,CAAC;wBAAC,MAAM,CAAC;4BACP,GAAG,GAAG,SAAS,CAAC;wBAClB,CAAC;wBACD,MAAM,cAAc,GAClB,OAAO,IAAI,CAAC,eAAe,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;wBAChG,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;4BACtB,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;wBACrG,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,6CAA6C;gBAC/C,CAAC;gBAED,2EAA2E;gBAC3E,IAAI,CAAC;oBACH,MAAM,eAAe,GACnB,OAAO,GAAG,CAAC,kBAAkB,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/E,OAAO,CAAC,eAAe,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;oBAE5D,IAAI,OAA2B,CAAC;oBAChC,IAAI,CAAC;wBACH,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;4BAC9C,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;4BACnC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gCACxC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;4BAC5B,CAAC;iCAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gCACjC,OAAO,GAAG,IAAI,CAAC;4BACjB,CAAC;iCAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gCACpC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;4BACtC,CAAC;iCAAM,CAAC;gCACN,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;4BAC9C,CAAC;wBACH,CAAC;6BAAM,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;4BAC/C,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;4BAC5B,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;wBACrE,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,OAAO,GAAG,SAAS,CAAC;oBACtB,CAAC;oBAED,MAAM,eAAe,GACnB,CAAC,eAAe,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC;wBACzF,SAAS,CAAC;oBACZ,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;wBAC1B,OAAO,CAAC,YAAY,GAAG,WAAW,CAChC,OAAO,EACP,OAAO,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,EACjE,QAAQ,CAAC,SAAS,EAClB,QAAQ,CAAC,aAAa,CACvB,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,8CAA8C;gBAChD,CAAC;gBAED,2EAA2E;gBAC3E,MAAM,GAAG,GAAI,GAAW,CAAC,KAAK,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC;gBAC9D,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,QAAQ,GAAoB,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC1E,IAAI,GAAG,CAAC,KAAK;wBAAE,QAAQ,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;oBAC1C,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;gBAC3B,CAAC;gBAED,OAAO,OAAO,CAAC;YACjB,CAAC;YAGD;;;;;;;eAOG;YAEH,KAAK;YACH,iDAAiD;YACjD,IAAI,GAAW,KAAK;YACpB,oDAAoD;YACpD,SAAS,GAAW,KAAK;YACzB,gEAAgE;YAChE,GAAa;gBAEb,yDAAyD;gBACzD,OAAO,IAAI,iBAAiB,CAC1B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;oBAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;oBACvB,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACtD,CAAC,EACD,KAAK,IAAI,EAAE;oBACT,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;gBACnB,CAAC,CACF,CAAC;YACJ,CAAC;YAED;;;;;;eAMG;YACO,KAAK,CAAC,UAAU,CAAC,IAAY,EAAE,SAAiB,EAAE,GAAa;gBACvE,oCAAoC;gBACpC,MAAM,UAAU,GAAG,iBAAiB,CAAM,YAAY,CAAC,CAAC;gBACxD,IAAI,UAAU,EAAE,KAAK,EAAE,CAAC;oBACtB,MAAM,UAAU,CAAC,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;oBAC7C,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,sCAAsC,SAAS,EAAE,CAAC,CAAC;gBACtE,CAAC;gBAED,0CAA0C;gBAC1C,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;gBAClC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,yCAAyC,IAAI,EAAE,CAAC,CAAC;gBAElE,gDAAgD;gBAChD,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,IAAI,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAC9B,oCAAoC;oBACpC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACtC,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;gBACzB,CAAC;qBAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;oBAC/C,iEAAiE;oBACjE,kEAAkE;oBAClE,kEAAkE;oBAClE,mDAAmD;oBACnD,IAAI,CAAC,WAAW,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;YAED;;eAEG;YACK,MAAM;gBACZ,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;gBACjB,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;YAC3B,CAAC;YAED;;;eAGG;YACK,WAAW,CAAC,GAAW;gBAC7B,MAAM,GAAG,GAAG,QAAQ,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;gBAC7F,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;YACxB,CAAC;YAED;;;eAGG;YACH,KAAK,CAAC,gBAAgB,CAAC,IAAY;gBACjC,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;gBACvE,IAAI,CAAC,GAAG,GAAG,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAExD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,EAAa,EAAE,EAAE;oBAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACrB,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;oBAC9C,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChD,CAAC,CAAC,CAAC;gBAEH,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;oBAChC,IAAI,CAAC,MAAO,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC7C,CAAC,CAAC,CAAC;YACL,CAAC;YAED;;;;eAIG;YACK,aAAa,CAAC,GAAoB,EAAE,GAAmB;gBAC7D,6DAA6D;gBAC7D,6EAA6E;gBAC7E,yEAAyE;gBACzE,0EAA0E;gBAC1E,iCAAiC;gBACjC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;gBAClC,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5B,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAO,CAAC,CAAC;oBACtD,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;oBAChC,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;oBAC9D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;gBAChE,CAAC;gBAED,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;oBACV,OAAO;gBACT,CAAC;gBAED,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;gBAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAEnC,IAAI,CAAC;oBACH,oBAAoB;oBACpB,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;wBAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;oBACnC,CAAC;yBAAM,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;wBACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;oBAClC,CAAC;yBAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;wBAC/C,MAAM,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;wBACrE,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;wBAC3B,IAAI,KAAK,EAAE,CAAC;4BACV,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;wBAC5B,CAAC;6BAAM,CAAC;4BACN,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,GAAG,CAAC,CAAC;wBACxD,CAAC;oBACH,CAAC;yBAAM,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;wBACxC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;oBACpC,CAAC;yBAAM,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;wBAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC;oBACtC,CAAC;yBAAM,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;wBACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;oBAClC,CAAC;yBAAM,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;wBACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;oBAClC,CAAC;yBAAM,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;wBACvC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;oBAC5C,CAAC;yBAAM,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;wBACxC,kEAAkE;wBAClE,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;oBACrD,CAAC;yBAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;wBACjD,MAAM,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;wBACvE,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;wBAC3C,IAAI,KAAK,EAAE,CAAC;4BACV,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;wBAC5B,CAAC;6BAAM,CAAC;4BACN,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,GAAG,CAAC,CAAC;wBAC1D,CAAC;oBACH,CAAC;yBAAM,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;wBACpC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,YAAY,CAAC;wBACnE,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;wBAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC;oBACzF,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;oBACtC,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAClB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;oBACrD,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,uBAAuB,EAAE,EAAE,GAAG,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YAED;;;eAGG;YACK,cAAc;gBACpB,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;oBAC3B,MAAM,GAAG,GAAQ;wBACf,OAAO,EAAE,OAAO;wBAChB,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE;wBACtD,KAAK,EAAE,EAAE;wBACT,IAAI,EAAE,EAAE;qBACT,CAAC;oBACF,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;oBAC5B,OAAO,GAAG,CAAC;gBACb,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;gBACjG,CAAC;YACH,CAAC;YAED;;;;;eAKG;YACK,eAAe,CAAC,QAAgB,EAAE,GAAmB;gBAC3D,8BAA8B;gBAC9B,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBACpE,IAAI,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAE3E,6DAA6D;gBAC7D,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1B,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;gBAC3C,CAAC;gBAED,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,CAAC,CAAC;oBAChD,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;oBACvC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC;oBAC3D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC7C,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACnB,CAAC;gBAAC,MAAM,CAAC;oBACP,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,EAAE,GAAG,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YAED;;;;;eAKG;YACK,QAAQ,CAAC,GAAmB,EAAE,IAAa,EAAE,UAAU,GAAW,GAAG;gBAC3E,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAClE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAChC,CAAC;YAED;;;eAGG;YACH,SAAS,CAAC,IAAa;gBACrB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACrC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClC,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;wBACzC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;YAED;;eAEG;YACH,KAAK,CAAC,IAAI;gBACR,8CAA8C;gBAC9C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACvC,KAAK,EAAE,CAAC;gBACV,CAAC;gBACD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;gBACxB,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;gBAE7B,8BAA8B;gBAC9B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClC,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,CAAC;gBACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAErB,gBAAgB;gBAChB,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;oBACjB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;gBACvB,CAAC;gBACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChB,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;oBACxE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;gBAC1B,CAAC;gBAED,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACrB,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;gBACrB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACd,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACrB,CAAC;;;;iCAnRA,OAAO,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,uCAAuC,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,CAAC;YAC/H,gKAAA,KAAK,6DAkBJ;;;QAzPM,aAAU,GAAG,sBAAuB;;;SADhC,YAAY"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { RequestLog, type RequestLogEntry } from "./requestlog.js";
|
|
2
|
+
export { LogBuffer, type LogEntry } from "./logbuffer.js";
|
|
3
|
+
export { getModels, getModel, getServices, getOperations, getRoutes, getConfig, getAppInfo } from "./introspection.js";
|
|
4
|
+
export type { ModelInfo, ServiceInfo, OperationInfo, RouteInfoEntry } from "./introspection.js";
|
|
5
|
+
export { DebugService } from "./debugservice.service.js";
|
|
6
|
+
export { DebugClient } from "./tui/client.js";
|
|
7
|
+
export { DebugTui } from "./tui/tui.js";
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { RequestLog } from "./requestlog.js";
|
|
2
|
+
export { LogBuffer } from "./logbuffer.js";
|
|
3
|
+
export { getModels, getModel, getServices, getOperations, getRoutes, getConfig, getAppInfo } from "./introspection.js";
|
|
4
|
+
export { DebugService } from "./debugservice.service.js";
|
|
5
|
+
export { DebugClient } from "./tui/client.js";
|
|
6
|
+
export { DebugTui } from "./tui/tui.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAiB,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEvH,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
|