@module-federation/devtools 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +3 -0
  2. package/dist/es/App.js +17 -2
  3. package/dist/es/App_module.css +3 -3
  4. package/dist/es/component/LoadingTrace/index.js +944 -0
  5. package/dist/es/component/LoadingTrace/index.module.js +5 -0
  6. package/dist/es/component/LoadingTrace/index_module.css +876 -0
  7. package/dist/es/i18n/index.js +178 -0
  8. package/dist/es/utils/chrome/index.js +3 -4
  9. package/dist/es/utils/chrome/messages.js +7 -1
  10. package/dist/es/utils/chrome/observability-plugin.js +93 -0
  11. package/dist/es/utils/chrome/observability-shared.js +99 -0
  12. package/dist/es/utils/chrome/observability.js +208 -0
  13. package/dist/es/utils/chrome/override-remote.js +2 -42
  14. package/dist/es/utils/chrome/post-message-listener.js +14 -0
  15. package/dist/es/utils/chrome/snapshot-plugin.js +2 -36
  16. package/dist/es/utils/data/index.js +5 -25
  17. package/dist/es/vendor/basic-proxy-core.js +155 -0
  18. package/dist/es/worker/index.js +27 -8
  19. package/dist/lib/App.js +17 -2
  20. package/dist/lib/App_module.css +3 -3
  21. package/dist/lib/component/LoadingTrace/index.js +954 -0
  22. package/dist/lib/component/LoadingTrace/index.module.js +25 -0
  23. package/dist/lib/component/LoadingTrace/index_module.css +876 -0
  24. package/dist/lib/i18n/index.js +178 -0
  25. package/dist/lib/utils/chrome/index.js +3 -4
  26. package/dist/lib/utils/chrome/messages.js +11 -2
  27. package/dist/lib/utils/chrome/observability-plugin.js +86 -0
  28. package/dist/lib/utils/chrome/observability-shared.js +126 -0
  29. package/dist/lib/utils/chrome/observability.js +234 -0
  30. package/dist/lib/utils/chrome/override-remote.js +5 -52
  31. package/dist/lib/utils/chrome/post-message-listener.js +11 -0
  32. package/dist/lib/utils/chrome/snapshot-plugin.js +5 -46
  33. package/dist/lib/utils/data/index.js +6 -28
  34. package/dist/lib/vendor/basic-proxy-core.js +147 -0
  35. package/dist/lib/worker/index.js +27 -8
  36. package/dist/types/src/component/LoadingTrace/index.d.ts +6 -0
  37. package/dist/types/src/utils/chrome/messages.d.ts +3 -0
  38. package/dist/types/src/utils/chrome/observability-plugin.d.ts +1 -0
  39. package/dist/types/src/utils/chrome/observability-shared.d.ts +41 -0
  40. package/dist/types/src/utils/chrome/observability.d.ts +110 -0
  41. package/dist/types/src/utils/chrome/snapshot-plugin.d.ts +0 -3
  42. package/dist/types/src/utils/data/index.d.ts +0 -1
  43. package/package.json +4 -3
  44. package/dist/es/utils/data/snapshot.js +0 -82
  45. package/dist/lib/utils/data/snapshot.js +0 -107
  46. package/dist/types/src/utils/data/snapshot.d.ts +0 -3
@@ -0,0 +1,944 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
40
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
41
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
42
+ import { Button, Empty, Input, Modal, Switch } from "@arco-design/web-react";
43
+ import {
44
+ IconDownload,
45
+ IconPlayArrow,
46
+ IconQuestionCircle,
47
+ IconRefresh,
48
+ IconSearch,
49
+ IconSettings
50
+ } from "@arco-design/web-react/icon";
51
+ import { useTranslation } from "react-i18next";
52
+ import {
53
+ applyObservabilityConfig,
54
+ disableObservabilityConfig,
55
+ getObservabilityReportScopeLabel,
56
+ mergeObservabilityReports,
57
+ readObservabilityConfig,
58
+ readObservabilitySnapshot,
59
+ reloadInspectedPage
60
+ } from "../../utils/chrome/observability";
61
+ import {
62
+ DEFAULT_OBSERVABILITY_DEVTOOLS_CONFIG,
63
+ normalizeObservabilityDevtoolsConfig
64
+ } from "../../utils/chrome/observability-shared";
65
+ import { MESSAGE_OBSERVABILITY_DEVTOOLS_EVENT } from "../../utils/chrome/messages";
66
+ import styles from "./index.module";
67
+ const FieldLabel = ({ label, tip }) => /* @__PURE__ */ jsxs("span", { className: styles.labelWithHelp, children: [
68
+ /* @__PURE__ */ jsx("span", { className: styles.labelText, children: label }),
69
+ /* @__PURE__ */ jsx(
70
+ "span",
71
+ {
72
+ className: styles.helpIcon,
73
+ "data-tip": tip,
74
+ tabIndex: 0,
75
+ "aria-label": tip,
76
+ children: /* @__PURE__ */ jsx(IconQuestionCircle, {})
77
+ }
78
+ ),
79
+ /* @__PURE__ */ jsx("span", { className: styles.labelColon, children: ":" })
80
+ ] });
81
+ const SegmentedControl = ({
82
+ value,
83
+ options,
84
+ onChange
85
+ }) => /* @__PURE__ */ jsx("div", { className: styles.segmentedControl, role: "group", children: options.map((option) => {
86
+ const isActive = option.value === value;
87
+ return /* @__PURE__ */ jsx(
88
+ "button",
89
+ {
90
+ type: "button",
91
+ className: `${styles.segmentButton} ${isActive ? styles.segmentButtonActive : ""}`,
92
+ "aria-pressed": isActive,
93
+ onClick: () => onChange(option.value),
94
+ children: option.label
95
+ },
96
+ option.value
97
+ );
98
+ }) });
99
+ const formatTime = (timestamp) => {
100
+ if (!timestamp) {
101
+ return "-";
102
+ }
103
+ try {
104
+ return new Date(timestamp).toLocaleTimeString();
105
+ } catch (e) {
106
+ return "-";
107
+ }
108
+ };
109
+ const getReportTitle = (report) => {
110
+ var _a, _b;
111
+ return report.requestId || ((_a = report.remote) == null ? void 0 : _a.name) || ((_b = report.shared) == null ? void 0 : _b.name) || report.traceId || "unknown";
112
+ };
113
+ const getReportOutcome = (report) => {
114
+ var _a;
115
+ return ((_a = report.summary) == null ? void 0 : _a.outcome) || report.status || "pending";
116
+ };
117
+ const parseStableVersion = (version) => {
118
+ const matched = version == null ? void 0 : version.match(/^(\d+)\.(\d+)\.(\d+)(?:\+[\w.-]+)?$/);
119
+ if (!matched) {
120
+ return null;
121
+ }
122
+ return {
123
+ major: Number(matched[1]),
124
+ minor: Number(matched[2]),
125
+ patch: Number(matched[3])
126
+ };
127
+ };
128
+ const isVersionLessThan = (version, target) => {
129
+ if (!version) {
130
+ return false;
131
+ }
132
+ if (version.major !== target.major) {
133
+ return version.major < target.major;
134
+ }
135
+ if (version.minor !== target.minor) {
136
+ return version.minor < target.minor;
137
+ }
138
+ return version.patch < target.patch;
139
+ };
140
+ const getLimitedObservabilityLabel = (report) => {
141
+ const runtimeVersion = parseStableVersion(report.runtimeVersion);
142
+ if (runtimeVersion && isVersionLessThan(runtimeVersion, { major: 2, minor: 5, patch: 0 })) {
143
+ return "lowVersion";
144
+ }
145
+ if (!report.runtimeVersion) {
146
+ return "unknownVersion";
147
+ }
148
+ return void 0;
149
+ };
150
+ const getReportState = (report) => {
151
+ var _a;
152
+ const outcome = getReportOutcome(report);
153
+ const limitedObservability = getLimitedObservabilityLabel(report);
154
+ if (outcome === "recovered" || ((_a = report.summary) == null ? void 0 : _a.recovered)) {
155
+ return "recovered";
156
+ }
157
+ if (report.status === "error" || outcome === "failed" || report.failedPhase || report.errorMessage) {
158
+ return "failed";
159
+ }
160
+ if (outcome === "pending" && report.status === "success" && limitedObservability) {
161
+ return "success";
162
+ }
163
+ if (outcome === "pending") {
164
+ return "pending";
165
+ }
166
+ if (report.status === "success") {
167
+ return "success";
168
+ }
169
+ return "pending";
170
+ };
171
+ const getEventStatusState = (status) => {
172
+ switch (status) {
173
+ case "success":
174
+ case "complete":
175
+ return "success";
176
+ case "error":
177
+ case "failed":
178
+ return "failed";
179
+ case "start":
180
+ case "pending":
181
+ return "pending";
182
+ default:
183
+ return "neutral";
184
+ }
185
+ };
186
+ const getReportSearchText = (report) => {
187
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
188
+ return [
189
+ getReportTitle(report),
190
+ report.traceId,
191
+ report.status,
192
+ getReportOutcome(report),
193
+ report.hostName,
194
+ report.runtimeVersion,
195
+ (_a = report.remote) == null ? void 0 : _a.name,
196
+ (_b = report.remote) == null ? void 0 : _b.alias,
197
+ (_c = report.remote) == null ? void 0 : _c.entry,
198
+ (_d = report.shared) == null ? void 0 : _d.name,
199
+ (_e = report.shared) == null ? void 0 : _e.provider,
200
+ (_f = report.shared) == null ? void 0 : _f.requiredVersion,
201
+ (_g = report.shared) == null ? void 0 : _g.selectedVersion,
202
+ (_i = (_h = report.shared) == null ? void 0 : _h.availableVersions) == null ? void 0 : _i.join(" "),
203
+ report.expose,
204
+ report.failedPhase,
205
+ report.errorCode,
206
+ report.errorName,
207
+ report.errorMessage,
208
+ report.ownerHint,
209
+ ((_j = report.summary) == null ? void 0 : _j.recovered) ? "recovered" : void 0,
210
+ (_k = report.summary) == null ? void 0 : _k.lastPhase,
211
+ (_l = report.diagnosis) == null ? void 0 : _l.title,
212
+ (_n = (_m = report.loadedBefore) == null ? void 0 : _m.consumers) == null ? void 0 : _n.map(
213
+ (consumer) => [consumer.name, ...consumer.exposes || []].join(" ")
214
+ ).join(" "),
215
+ report.__scope
216
+ ].filter(Boolean).join(" ").toLowerCase();
217
+ };
218
+ const fuzzyMatchReport = (report, keyword) => {
219
+ const tokens = keyword.trim().toLowerCase().split(/\s+/).filter(Boolean);
220
+ if (!tokens.length) {
221
+ return true;
222
+ }
223
+ const haystack = getReportSearchText(report);
224
+ return tokens.every((token) => haystack.includes(token));
225
+ };
226
+ const downloadJson = (name, data) => {
227
+ const blob = new Blob([`${JSON.stringify(data, null, 2)}
228
+ `], {
229
+ type: "application/json;charset=utf-8"
230
+ });
231
+ const url = URL.createObjectURL(blob);
232
+ const anchor = document.createElement("a");
233
+ anchor.href = url;
234
+ anchor.download = name;
235
+ anchor.click();
236
+ URL.revokeObjectURL(url);
237
+ };
238
+ const formatCurrentLoadValue = (value) => {
239
+ if (value === false) {
240
+ return "false";
241
+ }
242
+ if (value === true) {
243
+ return "true";
244
+ }
245
+ if (typeof value === "number") {
246
+ return String(value);
247
+ }
248
+ return value || void 0;
249
+ };
250
+ const getConfigSignature = (config) => JSON.stringify(normalizeObservabilityDevtoolsConfig(config));
251
+ const getLoadingTraceTabKey = (tabId) => typeof tabId === "number" ? String(tabId) : "unknown";
252
+ const LoadingTrace = ({ tabId, resetKey = 0 }) => {
253
+ var _a, _b;
254
+ const { t } = useTranslation();
255
+ const [config, setConfig] = useState(
256
+ DEFAULT_OBSERVABILITY_DEVTOOLS_CONFIG
257
+ );
258
+ const [savedConfig, setSavedConfig] = useState(
259
+ DEFAULT_OBSERVABILITY_DEVTOOLS_CONFIG
260
+ );
261
+ const [stored, setStored] = useState(false);
262
+ const [reports, setReports] = useState([]);
263
+ const [scopes, setScopes] = useState([]);
264
+ const [hasUserObservabilityPlugin, setHasUserObservabilityPlugin] = useState(false);
265
+ const [selectedTraceId, setSelectedTraceId] = useState();
266
+ const [busy, setBusy] = useState(false);
267
+ const [statusText, setStatusText] = useState("");
268
+ const [showConfigPanel, setShowConfigPanel] = useState(false);
269
+ const [reportKeyword, setReportKeyword] = useState("");
270
+ const refreshTimersRef = useRef([]);
271
+ const userPluginPollTimerRef = useRef(
272
+ null
273
+ );
274
+ const tabCacheRef = useRef(/* @__PURE__ */ new Map());
275
+ const activeTabKey = useMemo(() => getLoadingTraceTabKey(tabId), [tabId]);
276
+ const activeTabKeyRef = useRef(activeTabKey);
277
+ const resetKeyRef = useRef(resetKey);
278
+ const filteredReports = useMemo(
279
+ () => reports.filter((report) => fuzzyMatchReport(report, reportKeyword)),
280
+ [reports, reportKeyword]
281
+ );
282
+ const selectedReport = useMemo(
283
+ () => filteredReports.find((report) => report.traceId === selectedTraceId) || filteredReports[0],
284
+ [filteredReports, selectedTraceId]
285
+ );
286
+ const latestReport = reports[0];
287
+ const isObservabilityEnabled = stored && config.enabled !== false;
288
+ const isConfigDirty = useMemo(
289
+ () => getConfigSignature(config) !== getConfigSignature(savedConfig),
290
+ [config, savedConfig]
291
+ );
292
+ const levelOptions = useMemo(
293
+ () => [
294
+ {
295
+ label: t("loadingTrace.config.verbose"),
296
+ value: "verbose"
297
+ },
298
+ {
299
+ label: t("loadingTrace.config.summary"),
300
+ value: "summary"
301
+ },
302
+ {
303
+ label: t("loadingTrace.config.error"),
304
+ value: "error"
305
+ }
306
+ ],
307
+ [t]
308
+ );
309
+ const shouldShowApplyButton = !isObservabilityEnabled || isConfigDirty;
310
+ const emptyDescription = useMemo(() => {
311
+ if (!hasUserObservabilityPlugin && !isObservabilityEnabled) {
312
+ return t("loadingTrace.emptyEnableChrome");
313
+ }
314
+ return t("loadingTrace.empty");
315
+ }, [hasUserObservabilityPlugin, isObservabilityEnabled, t]);
316
+ const sourceStateLabel = isObservabilityEnabled ? "ON" : hasUserObservabilityPlugin ? "CUSTOM" : "OFF";
317
+ const eventCount = useMemo(
318
+ () => reports.reduce(
319
+ (count, report) => {
320
+ var _a2;
321
+ return count + (((_a2 = report.events) == null ? void 0 : _a2.length) || 0);
322
+ },
323
+ 0
324
+ ),
325
+ [reports]
326
+ );
327
+ const applyTabCache = useCallback(
328
+ (tabKey, update) => {
329
+ const current = tabCacheRef.current.get(tabKey) || {
330
+ reports: [],
331
+ selectedTraceId: void 0
332
+ };
333
+ const next = typeof update === "function" ? update(current) : update;
334
+ tabCacheRef.current.set(tabKey, next);
335
+ if (activeTabKeyRef.current === tabKey) {
336
+ setReports(next.reports);
337
+ setSelectedTraceId(next.selectedTraceId);
338
+ }
339
+ return next;
340
+ },
341
+ []
342
+ );
343
+ const clearTabCache = useCallback(
344
+ (tabKey) => applyTabCache(tabKey, {
345
+ reports: [],
346
+ selectedTraceId: void 0
347
+ }),
348
+ [applyTabCache]
349
+ );
350
+ const refreshSnapshot = useCallback(
351
+ (..._0) => __async(void 0, [..._0], function* (targetTabKey = activeTabKeyRef.current) {
352
+ var _a2;
353
+ const snapshot = yield readObservabilitySnapshot();
354
+ setConfig(snapshot.config);
355
+ setSavedConfig(snapshot.config);
356
+ setStored(snapshot.stored);
357
+ setScopes(snapshot.scopes);
358
+ setHasUserObservabilityPlugin(snapshot.hasUserObservabilityPlugin);
359
+ const cached = tabCacheRef.current.get(targetTabKey) || {
360
+ reports: [],
361
+ selectedTraceId: void 0
362
+ };
363
+ const mergedReports = mergeObservabilityReports(
364
+ cached.reports,
365
+ snapshot.reports
366
+ );
367
+ const nextCache = applyTabCache(targetTabKey, {
368
+ reports: mergedReports,
369
+ selectedTraceId: cached.selectedTraceId || ((_a2 = snapshot.reports[0]) == null ? void 0 : _a2.traceId)
370
+ });
371
+ return __spreadProps(__spreadValues({}, snapshot), {
372
+ reports: nextCache.reports
373
+ });
374
+ }),
375
+ [applyTabCache]
376
+ );
377
+ const clearScheduledRefresh = useCallback(() => {
378
+ refreshTimersRef.current.forEach((timer) => clearTimeout(timer));
379
+ refreshTimersRef.current = [];
380
+ }, []);
381
+ const scheduleRefreshBurst = useCallback(() => {
382
+ clearScheduledRefresh();
383
+ const delays = [200, 600, 1200, 2400];
384
+ const targetTabKey = activeTabKeyRef.current;
385
+ refreshTimersRef.current = delays.map(
386
+ (delay, index) => setTimeout(() => __async(void 0, null, function* () {
387
+ const snapshot = yield refreshSnapshot(targetTabKey);
388
+ const isLast = index === delays.length - 1;
389
+ if (snapshot.reports.length) {
390
+ setStatusText(t("loadingTrace.status.synced"));
391
+ clearScheduledRefresh();
392
+ return;
393
+ }
394
+ if (isLast) {
395
+ setStatusText(t("loadingTrace.status.noReports"));
396
+ }
397
+ }), delay)
398
+ );
399
+ }, [clearScheduledRefresh, refreshSnapshot, t]);
400
+ useEffect(() => {
401
+ activeTabKeyRef.current = activeTabKey;
402
+ const cached = tabCacheRef.current.get(activeTabKey);
403
+ setReports((cached == null ? void 0 : cached.reports) || []);
404
+ setSelectedTraceId(cached == null ? void 0 : cached.selectedTraceId);
405
+ setReportKeyword("");
406
+ }, [activeTabKey]);
407
+ useEffect(() => {
408
+ if (resetKey === resetKeyRef.current) {
409
+ return;
410
+ }
411
+ resetKeyRef.current = resetKey;
412
+ clearScheduledRefresh();
413
+ clearTabCache(activeTabKeyRef.current);
414
+ setStatusText(t("loadingTrace.status.noReports"));
415
+ }, [clearScheduledRefresh, clearTabCache, resetKey, t]);
416
+ useEffect(() => {
417
+ let cancelled = false;
418
+ const load = () => __async(void 0, null, function* () {
419
+ try {
420
+ const pageConfig = yield readObservabilityConfig();
421
+ if (!cancelled) {
422
+ setConfig(pageConfig);
423
+ setSavedConfig(pageConfig);
424
+ }
425
+ const snapshot = yield refreshSnapshot();
426
+ if (!cancelled) {
427
+ setStatusText(
428
+ snapshot.stored ? t("loadingTrace.status.enabled") : snapshot.hasUserObservabilityPlugin ? t("loadingTrace.status.userPlugin") : t("loadingTrace.status.disabled")
429
+ );
430
+ }
431
+ } catch (error) {
432
+ if (!cancelled) {
433
+ setStatusText(t("loadingTrace.status.unavailable"));
434
+ }
435
+ }
436
+ });
437
+ void load();
438
+ return () => {
439
+ cancelled = true;
440
+ clearScheduledRefresh();
441
+ };
442
+ }, [clearScheduledRefresh, refreshSnapshot, t, tabId]);
443
+ useEffect(() => {
444
+ if (userPluginPollTimerRef.current) {
445
+ clearInterval(userPluginPollTimerRef.current);
446
+ userPluginPollTimerRef.current = null;
447
+ }
448
+ if (!hasUserObservabilityPlugin) {
449
+ return;
450
+ }
451
+ let polling = false;
452
+ userPluginPollTimerRef.current = setInterval(() => __async(void 0, null, function* () {
453
+ if (polling) {
454
+ return;
455
+ }
456
+ polling = true;
457
+ try {
458
+ const snapshot = yield refreshSnapshot(activeTabKeyRef.current);
459
+ if (snapshot.reports.length) {
460
+ setStatusText(t("loadingTrace.status.synced"));
461
+ }
462
+ } finally {
463
+ polling = false;
464
+ }
465
+ }), 1500);
466
+ return () => {
467
+ if (userPluginPollTimerRef.current) {
468
+ clearInterval(userPluginPollTimerRef.current);
469
+ userPluginPollTimerRef.current = null;
470
+ }
471
+ };
472
+ }, [hasUserObservabilityPlugin, refreshSnapshot, t]);
473
+ useEffect(() => {
474
+ const onMessage = (message, sender) => {
475
+ var _a2, _b2;
476
+ if ((message == null ? void 0 : message.type) !== MESSAGE_OBSERVABILITY_DEVTOOLS_EVENT) {
477
+ return;
478
+ }
479
+ const senderTabId = (_a2 = sender == null ? void 0 : sender.tab) == null ? void 0 : _a2.id;
480
+ const messageTabKey = getLoadingTraceTabKey(senderTabId || tabId);
481
+ const isCurrentTabMessage = !tabId || !senderTabId || senderTabId === tabId;
482
+ const payload = message.data;
483
+ if ((payload == null ? void 0 : payload.config) && isCurrentTabMessage) {
484
+ const nextConfig = normalizeObservabilityDevtoolsConfig(payload.config);
485
+ setConfig(nextConfig);
486
+ setSavedConfig(nextConfig);
487
+ setStored(payload.config.enabled !== false);
488
+ }
489
+ if ((payload == null ? void 0 : payload.kind) === "installed" && isCurrentTabMessage) {
490
+ setStatusText(t("loadingTrace.status.enabled"));
491
+ scheduleRefreshBurst();
492
+ }
493
+ if ((_b2 = payload == null ? void 0 : payload.report) == null ? void 0 : _b2.traceId) {
494
+ const report = __spreadProps(__spreadValues({}, payload.report), {
495
+ __scope: payload.scope || payload.report.__scope
496
+ });
497
+ applyTabCache(messageTabKey, (current) => ({
498
+ reports: mergeObservabilityReports(current.reports, [report]),
499
+ selectedTraceId: current.selectedTraceId || report.traceId
500
+ }));
501
+ if (isCurrentTabMessage) {
502
+ clearScheduledRefresh();
503
+ setStatusText(t("loadingTrace.status.synced"));
504
+ }
505
+ }
506
+ };
507
+ chrome.runtime.onMessage.addListener(onMessage);
508
+ return () => chrome.runtime.onMessage.removeListener(onMessage);
509
+ }, [applyTabCache, clearScheduledRefresh, scheduleRefreshBurst, tabId, t]);
510
+ const updateConfig = (patch) => {
511
+ setConfig(
512
+ (current) => normalizeObservabilityDevtoolsConfig(__spreadValues(__spreadValues({}, current), patch))
513
+ );
514
+ };
515
+ const applyAndReload = () => __async(void 0, null, function* () {
516
+ setBusy(true);
517
+ try {
518
+ const nextConfig = normalizeObservabilityDevtoolsConfig(__spreadProps(__spreadValues({}, config), {
519
+ enabled: true
520
+ }));
521
+ yield applyObservabilityConfig(nextConfig);
522
+ setConfig(nextConfig);
523
+ setSavedConfig(nextConfig);
524
+ setStored(true);
525
+ clearTabCache(activeTabKeyRef.current);
526
+ setStatusText(t("loadingTrace.status.reloading"));
527
+ yield reloadInspectedPage();
528
+ scheduleRefreshBurst();
529
+ } finally {
530
+ setBusy(false);
531
+ }
532
+ });
533
+ const confirmApply = () => {
534
+ Modal.confirm({
535
+ title: isObservabilityEnabled ? t("loadingTrace.confirm.updateTitle") : t("loadingTrace.confirm.observeTitle"),
536
+ content: t("loadingTrace.confirm.content"),
537
+ okText: t("loadingTrace.actions.confirm"),
538
+ cancelText: t("loadingTrace.actions.cancel"),
539
+ onOk: () => applyAndReload()
540
+ });
541
+ };
542
+ const disableAndReload = () => __async(void 0, null, function* () {
543
+ setBusy(true);
544
+ try {
545
+ yield disableObservabilityConfig();
546
+ clearScheduledRefresh();
547
+ setStored(false);
548
+ clearTabCache(activeTabKeyRef.current);
549
+ setStatusText(t("loadingTrace.status.disabled"));
550
+ yield reloadInspectedPage();
551
+ } finally {
552
+ setBusy(false);
553
+ }
554
+ });
555
+ const handleRefresh = () => __async(void 0, null, function* () {
556
+ setBusy(true);
557
+ try {
558
+ const snapshot = yield refreshSnapshot();
559
+ setStatusText(
560
+ snapshot.reports.length ? t("loadingTrace.status.synced") : t("loadingTrace.status.noReports")
561
+ );
562
+ } finally {
563
+ setBusy(false);
564
+ }
565
+ });
566
+ const handleExport = () => {
567
+ downloadJson(`mf-observability-${Date.now()}.json`, {
568
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
569
+ config,
570
+ scopes,
571
+ reports
572
+ });
573
+ };
574
+ const currentLoadRows = useMemo(() => {
575
+ var _a2, _b2, _c, _d;
576
+ if (!selectedReport) {
577
+ return [];
578
+ }
579
+ const rows = [
580
+ {
581
+ labelKey: "consumer",
582
+ value: selectedReport.hostName
583
+ }
584
+ ];
585
+ if (selectedReport.shared) {
586
+ rows.push(
587
+ {
588
+ labelKey: "shared",
589
+ value: selectedReport.shared.name
590
+ },
591
+ {
592
+ labelKey: "provider",
593
+ value: selectedReport.shared.provider
594
+ },
595
+ {
596
+ labelKey: "requiredVersion",
597
+ value: selectedReport.shared.requiredVersion
598
+ },
599
+ {
600
+ labelKey: "selectedVersion",
601
+ value: selectedReport.shared.selectedVersion
602
+ },
603
+ {
604
+ labelKey: "availableVersions",
605
+ value: (_a2 = selectedReport.shared.availableVersions) == null ? void 0 : _a2.join(", ")
606
+ }
607
+ );
608
+ } else {
609
+ rows.push(
610
+ {
611
+ labelKey: "request",
612
+ value: selectedReport.requestId
613
+ },
614
+ {
615
+ labelKey: "producer",
616
+ value: ((_b2 = selectedReport.remote) == null ? void 0 : _b2.alias) || ((_c = selectedReport.remote) == null ? void 0 : _c.name)
617
+ },
618
+ {
619
+ labelKey: "remoteName",
620
+ value: (_d = selectedReport.remote) == null ? void 0 : _d.name
621
+ },
622
+ {
623
+ labelKey: "expose",
624
+ value: selectedReport.expose
625
+ }
626
+ );
627
+ }
628
+ return rows.filter((row) => formatCurrentLoadValue(row.value));
629
+ }, [selectedReport]);
630
+ return /* @__PURE__ */ jsxs("div", { className: styles.wrapper, children: [
631
+ /* @__PURE__ */ jsxs("section", { className: styles.toolbar, children: [
632
+ /* @__PURE__ */ jsxs("div", { className: styles.titleGroup, children: [
633
+ /* @__PURE__ */ jsx("span", { className: styles.title, children: t("loadingTrace.title") }),
634
+ statusText ? /* @__PURE__ */ jsx("span", { className: styles.subtitle, children: statusText }) : null
635
+ ] }),
636
+ /* @__PURE__ */ jsxs("div", { className: styles.actions, children: [
637
+ /* @__PURE__ */ jsx(
638
+ Button,
639
+ {
640
+ className: `${styles.configButton} ${showConfigPanel ? styles.configButtonActive : ""}`,
641
+ shape: "circle",
642
+ icon: /* @__PURE__ */ jsx(IconSettings, {}),
643
+ "aria-pressed": showConfigPanel,
644
+ title: t("loadingTrace.actions.config"),
645
+ onClick: () => setShowConfigPanel((visible) => !visible)
646
+ }
647
+ ),
648
+ shouldShowApplyButton ? /* @__PURE__ */ jsx(
649
+ Button,
650
+ {
651
+ className: styles.primaryAction,
652
+ icon: /* @__PURE__ */ jsx(IconPlayArrow, {}),
653
+ loading: busy,
654
+ onClick: confirmApply,
655
+ children: isObservabilityEnabled ? t("loadingTrace.actions.updateConfig") : t("loadingTrace.actions.observeNow")
656
+ }
657
+ ) : null,
658
+ isObservabilityEnabled ? /* @__PURE__ */ jsx(Button, { loading: busy, onClick: disableAndReload, children: t("loadingTrace.actions.disable") }) : null,
659
+ /* @__PURE__ */ jsx(Button, { icon: /* @__PURE__ */ jsx(IconRefresh, {}), loading: busy, onClick: handleRefresh, children: t("loadingTrace.actions.refresh") }),
660
+ /* @__PURE__ */ jsx(
661
+ Button,
662
+ {
663
+ icon: /* @__PURE__ */ jsx(IconDownload, {}),
664
+ disabled: !reports.length,
665
+ onClick: handleExport,
666
+ children: t("loadingTrace.actions.export")
667
+ }
668
+ )
669
+ ] })
670
+ ] }),
671
+ showConfigPanel ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("section", { className: styles.configGrid, children: [
672
+ /* @__PURE__ */ jsxs("label", { className: styles.field, children: [
673
+ /* @__PURE__ */ jsx(
674
+ FieldLabel,
675
+ {
676
+ label: t("loadingTrace.config.level"),
677
+ tip: t("loadingTrace.config.levelTip")
678
+ }
679
+ ),
680
+ /* @__PURE__ */ jsx(
681
+ SegmentedControl,
682
+ {
683
+ value: config.level,
684
+ options: levelOptions,
685
+ onChange: (level) => updateConfig({ level })
686
+ }
687
+ )
688
+ ] }),
689
+ /* @__PURE__ */ jsxs("label", { className: styles.field, children: [
690
+ /* @__PURE__ */ jsx(
691
+ FieldLabel,
692
+ {
693
+ label: t("loadingTrace.config.console"),
694
+ tip: t("loadingTrace.config.consoleTip")
695
+ }
696
+ ),
697
+ /* @__PURE__ */ jsx(
698
+ Switch,
699
+ {
700
+ checked: config.console,
701
+ onChange: (checked) => updateConfig({ console: checked })
702
+ }
703
+ )
704
+ ] })
705
+ ] }) }) : null,
706
+ /* @__PURE__ */ jsxs(Fragment, { children: [
707
+ /* @__PURE__ */ jsxs("section", { className: styles.stats, children: [
708
+ /* @__PURE__ */ jsxs("div", { children: [
709
+ /* @__PURE__ */ jsxs("span", { className: styles.statValueWithHelp, children: [
710
+ /* @__PURE__ */ jsx("span", { className: styles.statValue, children: sourceStateLabel }),
711
+ sourceStateLabel === "CUSTOM" ? /* @__PURE__ */ jsx(
712
+ "span",
713
+ {
714
+ className: `${styles.inlineHelpIcon} ${styles.statHelpIcon}`,
715
+ "data-tip": t("loadingTrace.stats.customTip"),
716
+ tabIndex: 0,
717
+ "aria-label": t("loadingTrace.stats.customTip"),
718
+ children: /* @__PURE__ */ jsx(IconQuestionCircle, {})
719
+ }
720
+ ) : null
721
+ ] }),
722
+ /* @__PURE__ */ jsx("span", { className: styles.statLabel, children: t("loadingTrace.stats.state") })
723
+ ] }),
724
+ /* @__PURE__ */ jsxs("div", { children: [
725
+ /* @__PURE__ */ jsx("span", { className: styles.statValue, children: reports.length }),
726
+ /* @__PURE__ */ jsx("span", { className: styles.statLabel, children: t("loadingTrace.stats.reports") })
727
+ ] }),
728
+ /* @__PURE__ */ jsxs("div", { children: [
729
+ /* @__PURE__ */ jsx("span", { className: styles.statValue, children: eventCount }),
730
+ /* @__PURE__ */ jsx("span", { className: styles.statLabel, children: t("loadingTrace.stats.events") })
731
+ ] }),
732
+ /* @__PURE__ */ jsxs("div", { children: [
733
+ /* @__PURE__ */ jsx("span", { className: styles.statValue, children: ((_a = latestReport == null ? void 0 : latestReport.summary) == null ? void 0 : _a.outcome) || "-" }),
734
+ /* @__PURE__ */ jsx("span", { className: styles.statLabel, children: t("loadingTrace.stats.latest") })
735
+ ] })
736
+ ] }),
737
+ /* @__PURE__ */ jsx(
738
+ "section",
739
+ {
740
+ className: `${styles.viewer} ${reports.length ? "" : styles.viewerEmpty}`,
741
+ children: reports.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
742
+ /* @__PURE__ */ jsxs("div", { className: styles.reportList, children: [
743
+ /* @__PURE__ */ jsx("div", { className: styles.reportFilter, children: /* @__PURE__ */ jsx(
744
+ Input,
745
+ {
746
+ className: styles.reportSearch,
747
+ prefix: /* @__PURE__ */ jsx(IconSearch, {}),
748
+ allowClear: true,
749
+ placeholder: t("loadingTrace.reports.search"),
750
+ value: reportKeyword,
751
+ onChange: (value) => setReportKeyword(value)
752
+ }
753
+ ) }),
754
+ filteredReports.length ? filteredReports.map((report) => {
755
+ const state = getReportState(report);
756
+ return /* @__PURE__ */ jsxs(
757
+ "button",
758
+ {
759
+ type: "button",
760
+ className: `${styles.reportItem} ${(selectedReport == null ? void 0 : selectedReport.traceId) === report.traceId ? styles.activeReport : ""}`,
761
+ onClick: () => applyTabCache(activeTabKeyRef.current, (current) => __spreadProps(__spreadValues({}, current), {
762
+ selectedTraceId: report.traceId
763
+ })),
764
+ children: [
765
+ /* @__PURE__ */ jsx("span", { className: styles.reportTitle, children: getReportTitle(report) }),
766
+ /* @__PURE__ */ jsx("span", { className: styles.reportTagRow, children: /* @__PURE__ */ jsx(
767
+ "span",
768
+ {
769
+ className: `${styles.statusTag} ${styles[`statusTag${state}`]}`,
770
+ children: t(`loadingTrace.reports.${state}`)
771
+ }
772
+ ) }),
773
+ /* @__PURE__ */ jsx("span", { className: styles.reportMeta, children: formatTime(report.updatedAt) })
774
+ ]
775
+ },
776
+ report.traceId
777
+ );
778
+ }) : /* @__PURE__ */ jsx("div", { className: styles.emptyPanel, children: /* @__PURE__ */ jsx(Empty, { description: t("loadingTrace.reports.noMatch") }) })
779
+ ] }),
780
+ /* @__PURE__ */ jsx("div", { className: styles.timeline, children: selectedReport ? /* @__PURE__ */ jsxs(Fragment, { children: [
781
+ (() => {
782
+ const limitedObservability = getLimitedObservabilityLabel(selectedReport);
783
+ const observabilityScopeLabel = getObservabilityReportScopeLabel(selectedReport);
784
+ return /* @__PURE__ */ jsxs("div", { className: styles.reportHeader, children: [
785
+ /* @__PURE__ */ jsxs("div", { children: [
786
+ /* @__PURE__ */ jsx("span", { className: styles.reportHeading, children: getReportTitle(selectedReport) }),
787
+ /* @__PURE__ */ jsx("span", { className: styles.traceId, children: selectedReport.traceId })
788
+ ] }),
789
+ /* @__PURE__ */ jsxs("div", { className: styles.tags, children: [
790
+ /* @__PURE__ */ jsx(
791
+ "span",
792
+ {
793
+ className: `${styles.statusTag} ${styles[`statusTag${getReportState(selectedReport)}`]}`,
794
+ children: t(
795
+ `loadingTrace.reports.${getReportState(selectedReport)}`
796
+ )
797
+ }
798
+ ),
799
+ observabilityScopeLabel ? /* @__PURE__ */ jsx("span", { className: styles.limitedTag, children: /* @__PURE__ */ jsx("span", { children: observabilityScopeLabel }) }) : null,
800
+ limitedObservability ? /* @__PURE__ */ jsxs("span", { className: styles.limitedTag, children: [
801
+ /* @__PURE__ */ jsx("span", { children: t("loadingTrace.reports.limited") }),
802
+ /* @__PURE__ */ jsx(
803
+ "span",
804
+ {
805
+ className: styles.inlineHelpIcon,
806
+ "data-tip": t(
807
+ `loadingTrace.reports.${limitedObservability}Tip`
808
+ ),
809
+ tabIndex: 0,
810
+ "aria-label": t(
811
+ `loadingTrace.reports.${limitedObservability}Tip`
812
+ ),
813
+ children: /* @__PURE__ */ jsx(IconQuestionCircle, {})
814
+ }
815
+ )
816
+ ] }) : null
817
+ ] })
818
+ ] });
819
+ })(),
820
+ currentLoadRows.length ? /* @__PURE__ */ jsxs("div", { className: styles.currentLoad, children: [
821
+ /* @__PURE__ */ jsxs("div", { className: styles.currentLoadHeader, children: [
822
+ /* @__PURE__ */ jsx("span", { className: styles.currentLoadTitle, children: t("loadingTrace.currentLoad.title") }),
823
+ /* @__PURE__ */ jsx("span", { className: styles.currentLoadSummary, children: selectedReport.shared ? t("loadingTrace.currentLoad.sharedReport") : t("loadingTrace.currentLoad.remoteReport") })
824
+ ] }),
825
+ /* @__PURE__ */ jsx("div", { className: styles.currentLoadRows, children: currentLoadRows.map((row) => /* @__PURE__ */ jsxs(
826
+ "div",
827
+ {
828
+ className: styles.currentLoadRow,
829
+ children: [
830
+ /* @__PURE__ */ jsx("span", { className: styles.currentLoadLabel, children: t(`loadingTrace.currentLoad.${row.labelKey}`) }),
831
+ /* @__PURE__ */ jsx("span", { className: styles.currentLoadValue, children: formatCurrentLoadValue(row.value) })
832
+ ]
833
+ },
834
+ row.labelKey
835
+ )) })
836
+ ] }) : null,
837
+ ((_b = selectedReport.diagnosis) == null ? void 0 : _b.title) ? /* @__PURE__ */ jsx("div", { className: styles.diagnosis, children: selectedReport.diagnosis.title }) : null,
838
+ selectedReport.loadedBefore ? /* @__PURE__ */ jsxs("div", { className: styles.loadedBefore, children: [
839
+ /* @__PURE__ */ jsxs("div", { className: styles.loadedBeforeHeader, children: [
840
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeTitle, children: t("loadingTrace.loadedBefore.title") }),
841
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeSummary, children: t("loadingTrace.loadedBefore.consumerCount", {
842
+ count: selectedReport.loadedBefore.consumers.length
843
+ }) })
844
+ ] }),
845
+ /* @__PURE__ */ jsxs("div", { className: styles.loadedBeforeTags, children: [
846
+ /* @__PURE__ */ jsx(
847
+ "span",
848
+ {
849
+ className: `${styles.loadedBeforeTag} ${styles.loadedBeforeTagSuccess}`,
850
+ children: t("loadingTrace.loadedBefore.producerLoaded")
851
+ }
852
+ ),
853
+ /* @__PURE__ */ jsx(
854
+ "span",
855
+ {
856
+ className: `${styles.loadedBeforeTag} ${selectedReport.loadedBefore.expose ? styles.loadedBeforeTagSuccess : styles.loadedBeforeTagNeutral}`,
857
+ children: selectedReport.loadedBefore.expose ? t("loadingTrace.loadedBefore.exposeLoaded") : t("loadingTrace.loadedBefore.exposeNotLoaded")
858
+ }
859
+ )
860
+ ] }),
861
+ /* @__PURE__ */ jsx("div", { className: styles.loadedBeforeConsumers, children: selectedReport.loadedBefore.consumers.map(
862
+ (consumer, index) => {
863
+ var _a2;
864
+ return /* @__PURE__ */ jsxs(
865
+ "div",
866
+ {
867
+ className: styles.loadedBeforeConsumer,
868
+ children: [
869
+ /* @__PURE__ */ jsxs("div", { className: styles.loadedBeforeRow, children: [
870
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeLabel, children: t("loadingTrace.loadedBefore.consumer") }),
871
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeName, children: consumer.name || t(
872
+ "loadingTrace.loadedBefore.unknownConsumer"
873
+ ) })
874
+ ] }),
875
+ /* @__PURE__ */ jsxs("div", { className: styles.loadedBeforeRow, children: [
876
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeLabel, children: t("loadingTrace.loadedBefore.status") }),
877
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeMeta, children: [
878
+ consumer.remoteEntryExports ? t(
879
+ "loadingTrace.loadedBefore.entryReady"
880
+ ) : t(
881
+ "loadingTrace.loadedBefore.entryMissing"
882
+ ),
883
+ consumer.containerInitialized ? t(
884
+ "loadingTrace.loadedBefore.initReady"
885
+ ) : t(
886
+ "loadingTrace.loadedBefore.initMissing"
887
+ )
888
+ ].join(" · ") })
889
+ ] }),
890
+ /* @__PURE__ */ jsxs("div", { className: styles.loadedBeforeRow, children: [
891
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeLabel, children: t("loadingTrace.loadedBefore.exposes") }),
892
+ /* @__PURE__ */ jsx("span", { className: styles.loadedBeforeExposes, children: ((_a2 = consumer.exposes) == null ? void 0 : _a2.length) ? consumer.exposes.join(", ") : t(
893
+ "loadingTrace.loadedBefore.noExposes"
894
+ ) })
895
+ ] })
896
+ ]
897
+ },
898
+ `${consumer.name || "consumer"}-${index}`
899
+ );
900
+ }
901
+ ) })
902
+ ] }) : null,
903
+ /* @__PURE__ */ jsx("div", { className: styles.eventList, children: (selectedReport.events || []).map((event, index) => /* @__PURE__ */ jsxs(
904
+ "div",
905
+ {
906
+ className: styles.eventItem,
907
+ children: [
908
+ /* @__PURE__ */ jsx("div", { className: styles.eventTime, children: formatTime(event.timestamp) }),
909
+ /* @__PURE__ */ jsxs("div", { className: styles.eventBody, children: [
910
+ /* @__PURE__ */ jsxs("div", { className: styles.eventMain, children: [
911
+ /* @__PURE__ */ jsx("span", { className: styles.phase, children: event.phase }),
912
+ /* @__PURE__ */ jsx(
913
+ "span",
914
+ {
915
+ className: `${styles.eventStatusTag} ${styles[`eventStatusTag${getEventStatusState(
916
+ event.status
917
+ )}`]}`,
918
+ children: event.status
919
+ }
920
+ ),
921
+ event.recovered ? /* @__PURE__ */ jsx("span", { className: styles.eventRecoveredTag, children: t("loadingTrace.reports.eventRecovered") }) : null,
922
+ event.duration !== void 0 ? /* @__PURE__ */ jsxs("span", { className: styles.duration, children: [
923
+ event.duration,
924
+ "ms"
925
+ ] }) : null
926
+ ] }),
927
+ /* @__PURE__ */ jsx("div", { className: styles.eventMeta, children: event.message || event.lifecycle || event.requestId || "-" }),
928
+ event.errorMessage ? /* @__PURE__ */ jsx("div", { className: styles.error, children: event.errorCode ? `${event.errorCode}: ${event.errorMessage}` : event.errorMessage }) : null
929
+ ] })
930
+ ]
931
+ },
932
+ `${event.traceId}-${event.phase}-${event.timestamp}-${index}`
933
+ )) })
934
+ ] }) : null })
935
+ ] }) : /* @__PURE__ */ jsx("div", { className: styles.emptyPanel, children: /* @__PURE__ */ jsx(Empty, { description: emptyDescription }) })
936
+ }
937
+ )
938
+ ] })
939
+ ] });
940
+ };
941
+ var LoadingTrace_default = LoadingTrace;
942
+ export {
943
+ LoadingTrace_default as default
944
+ };