@localstack/appinspector-ui 1.0.37 → 1.0.39

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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/pages/spans-list-page.tsx
2
2
  import { Box as Box18 } from "@mui/material";
3
- import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMemo7, useRef as useRef4, useState as useState10 } from "react";
3
+ import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3, useState as useState9 } from "react";
4
4
 
5
5
  // src/api/use-api.tsx
6
6
  import { createContext, useContext } from "react";
@@ -24,101 +24,114 @@ import { Alert, Box as Box4, Button as Button2 } from "@mui/material";
24
24
  import { Cached, DeleteForeverOutlined, Search } from "@mui/icons-material";
25
25
  import { Box as Box3, Button, FormControlLabel, Grid, Paper, Switch, TextField, Tooltip as Tooltip2, Typography as Typography2 } from "@mui/material";
26
26
  import { DataGrid } from "@mui/x-data-grid";
27
- import { useCallback, useMemo as useMemo2, useState as useState2 } from "react";
28
-
29
- // src/components/cells/responsive-timestamp-cell.tsx
30
- import { useEffect, useMemo, useRef, useState } from "react";
31
-
32
- // src/utils/time.ts
33
- function unixNanoToDate(unixNanoString) {
34
- if (!unixNanoString) return void 0;
35
- const milliseconds = Number(BigInt(unixNanoString) / BigInt("1000000"));
36
- return new Date(milliseconds);
37
- }
27
+ import { useCallback, useMemo, useState } from "react";
38
28
 
39
29
  // src/components/cells/responsive-timestamp-cell.tsx
30
+ import { memo } from "react";
40
31
  import { jsx as jsx2 } from "react/jsx-runtime";
41
- var ResponsiveTimestampCell = ({ locale, value }) => {
42
- const [columnWidth, setColumnWidth] = useState(0);
43
- const cellReference = useRef(null);
44
- useEffect(() => {
45
- const updateWidth = () => {
46
- if (cellReference.current) {
47
- const width = cellReference.current.offsetWidth;
48
- setColumnWidth(width);
49
- }
50
- };
51
- updateWidth();
52
- window.addEventListener("resize", updateWidth);
53
- if (cellReference.current) {
54
- const resizeObserver = new ResizeObserver(updateWidth);
55
- resizeObserver.observe(cellReference.current);
56
- return () => {
57
- resizeObserver.disconnect();
58
- window.removeEventListener("resize", updateWidth);
59
- };
32
+ var ResponsiveTimestampCell = memo(({ date, locale }) => {
33
+ const format = new Intl.DateTimeFormat(locale, {
34
+ day: "2-digit",
35
+ fractionalSecondDigits: 3,
36
+ hour: "2-digit",
37
+ hour12: false,
38
+ minute: "2-digit",
39
+ month: "2-digit",
40
+ second: "2-digit",
41
+ year: "numeric"
42
+ });
43
+ const formattedTime = format.format(date);
44
+ return /* @__PURE__ */ jsx2("div", { style: { width: "100%" }, children: formattedTime });
45
+ });
46
+
47
+ // src/utils/logger.ts
48
+ var getIsDevelopment = () => {
49
+ try {
50
+ return false;
51
+ } catch {
52
+ return false;
53
+ }
54
+ };
55
+ var isDevelopment = getIsDevelopment();
56
+ var logger = {
57
+ debug: (message, data) => {
58
+ if (isDevelopment) {
59
+ console.debug(`[DEBUG] ${message}`, data === void 0 ? "" : data);
60
60
  }
61
- }, []);
62
- const formattedTime = useMemo(() => {
63
- if (!value) return;
64
- const date = unixNanoToDate(value);
65
- if (!date) return;
66
- if (columnWidth < 100) {
67
- const formatter = new Intl.DateTimeFormat(locale, {
68
- hour: "2-digit",
69
- hour12: false,
70
- minute: "2-digit",
71
- second: "2-digit"
72
- });
73
- return formatter.format(date);
74
- } else if (columnWidth < 160) {
75
- const formatter = new Intl.DateTimeFormat(locale, {
76
- hour: "2-digit",
77
- hour12: false,
78
- minute: "2-digit",
79
- second: "2-digit"
80
- });
81
- const timeString = formatter.format(date);
82
- const ms = date.getMilliseconds().toString().padStart(3, "0");
83
- return `${timeString}:${ms}`;
84
- } else {
85
- const dateFormatter = new Intl.DateTimeFormat(locale, {
86
- day: "2-digit",
87
- month: "2-digit",
88
- year: "numeric"
89
- });
90
- const timeFormatter = new Intl.DateTimeFormat(locale, {
91
- hour: "2-digit",
92
- hour12: false,
93
- minute: "2-digit",
94
- second: "2-digit"
95
- });
96
- const dateString = dateFormatter.format(date);
97
- const timeString = timeFormatter.format(date);
98
- const ms = date.getMilliseconds().toString().padStart(3, "0");
99
- return `${dateString} - ${timeString}:${ms}`;
61
+ },
62
+ error: (message, data) => {
63
+ if (isDevelopment) {
64
+ console.error(`[ERROR] ${message}`, data === void 0 ? "" : data);
100
65
  }
101
- }, [value, columnWidth, locale]);
102
- if (!formattedTime) return /* @__PURE__ */ jsx2("span", { children: "N/A" });
103
- return /* @__PURE__ */ jsx2("div", { ref: cellReference, style: { width: "100%" }, children: formattedTime });
66
+ },
67
+ info: (message, data) => {
68
+ if (isDevelopment) {
69
+ console.info(`[INFO] ${message}`, data === void 0 ? "" : data);
70
+ }
71
+ },
72
+ warn: (message, data) => {
73
+ if (isDevelopment) {
74
+ console.warn(`[WARN] ${message}`, data === void 0 ? "" : data);
75
+ }
76
+ }
77
+ };
78
+ var createScopedLogger = (scope) => ({
79
+ debug: (message, data) => {
80
+ logger.debug(`[${scope}] ${message}`, data);
81
+ },
82
+ error: (message, data) => {
83
+ logger.error(`[${scope}] ${message}`, data);
84
+ },
85
+ info: (message, data) => {
86
+ logger.info(`[${scope}] ${message}`, data);
87
+ },
88
+ warn: (message, data) => {
89
+ logger.warn(`[${scope}] ${message}`, data);
90
+ }
91
+ });
92
+
93
+ // src/utils/search-in-object.ts
94
+ var searchInObject = (object, searchTerm, skipKeys = []) => {
95
+ if (!object) return false;
96
+ if (!searchTerm || searchTerm.trim() === "") return true;
97
+ const normalizedSearchTerm = searchTerm.toLowerCase().trim();
98
+ if (typeof object === "string") {
99
+ return object.toLowerCase().includes(normalizedSearchTerm);
100
+ }
101
+ if (typeof object === "number") {
102
+ return String(object).toLowerCase().includes(normalizedSearchTerm);
103
+ }
104
+ if (typeof object === "boolean") {
105
+ return String(object).toLowerCase().includes(normalizedSearchTerm);
106
+ }
107
+ if (Array.isArray(object)) {
108
+ return object.some((item) => searchInObject(item, searchTerm, skipKeys));
109
+ }
110
+ if (typeof object === "object") {
111
+ return Object.entries(object).filter(([key]) => !skipKeys.includes(key)).some(([, value]) => searchInObject(value, searchTerm, skipKeys));
112
+ }
113
+ return false;
104
114
  };
105
115
 
106
116
  // src/components/cells/service-cell.tsx
107
117
  import { Box as Box2, Divider, Typography, useTheme } from "@mui/material";
118
+ import { memo as memo6 } from "react";
108
119
 
109
120
  // src/components/aws-service-icon/aws-service-icon.tsx
110
121
  import { Tooltip } from "@mui/material";
122
+ import { memo as memo4 } from "react";
111
123
 
112
124
  // src/utils/wrap-in-component.tsx
113
- var WrapInComponent = ({ children, wrap, wrapperFn }) => {
125
+ import { memo as memo2 } from "react";
126
+ var WrapInComponent = memo2(({ children, wrap, wrapperFn }) => {
114
127
  if (wrap) {
115
128
  return wrapperFn(children);
116
129
  }
117
130
  return children;
118
- };
131
+ });
119
132
 
120
133
  // src/components/aws-service-icon/icons/index.tsx
121
- import { memo } from "react";
134
+ import { memo as memo3 } from "react";
122
135
 
123
136
  // src/types/service-names.ts
124
137
  var SERVICE_NAME = {
@@ -2433,7 +2446,7 @@ var ICONS_MAP = {
2433
2446
  [SERVICE_NAME.WAFV2]: wafv2_default,
2434
2447
  [SERVICE_NAME.XRAY]: xray_default
2435
2448
  };
2436
- var AwsServiceIconBase = memo((props) => {
2449
+ var AwsServiceIconBase = memo3((props) => {
2437
2450
  const Icon = ICONS_MAP[props.service] ?? ICONS_MAP.infrastructure;
2438
2451
  return /* @__PURE__ */ jsx121(Icon, { ...props });
2439
2452
  });
@@ -2442,7 +2455,7 @@ var supportedServiceNames = Object.keys(ICONS_MAP);
2442
2455
  // src/components/aws-service-icon/aws-service-icon.tsx
2443
2456
  import { jsx as jsx122 } from "react/jsx-runtime";
2444
2457
  var sizes = { large: [32, 32], medium: [22, 22], small: [11, 11] };
2445
- var AwsServiceIcon = ({ hideTooltip, service, size = "medium", title }) => {
2458
+ var AwsServiceIcon = memo4(({ hideTooltip, service, size = "medium", title }) => {
2446
2459
  const [width, height] = sizes[size];
2447
2460
  return /* @__PURE__ */ jsx122(
2448
2461
  WrapInComponent,
@@ -2452,12 +2465,13 @@ var AwsServiceIcon = ({ hideTooltip, service, size = "medium", title }) => {
2452
2465
  children: /* @__PURE__ */ jsx122(AwsServiceIconBase, { height, service, style: { display: "block" }, width })
2453
2466
  }
2454
2467
  );
2455
- };
2468
+ });
2456
2469
 
2457
2470
  // src/components/cells/pill-cell.tsx
2458
2471
  import { Box } from "@mui/material";
2472
+ import { memo as memo5 } from "react";
2459
2473
  import { jsx as jsx123 } from "react/jsx-runtime";
2460
- var PillCell = ({
2474
+ var PillCell = memo5(({
2461
2475
  backgroundColor,
2462
2476
  children,
2463
2477
  height = "24px",
@@ -2486,11 +2500,11 @@ var PillCell = ({
2486
2500
  children
2487
2501
  }
2488
2502
  );
2489
- };
2503
+ });
2490
2504
 
2491
2505
  // src/components/cells/service-cell.tsx
2492
2506
  import { Fragment, jsx as jsx124, jsxs as jsxs119 } from "react/jsx-runtime";
2493
- var ServiceCell = ({
2507
+ var ServiceCell = memo6(({
2494
2508
  height = "24px",
2495
2509
  resource,
2496
2510
  selected,
@@ -2563,77 +2577,8 @@ var ServiceCell = ({
2563
2577
  )
2564
2578
  ] }) : void 0
2565
2579
  ] }) });
2566
- };
2567
- ServiceCell.displayName = "ServiceCell";
2568
-
2569
- // src/utils/logger.ts
2570
- var getIsDevelopment = () => {
2571
- try {
2572
- return false;
2573
- } catch {
2574
- return false;
2575
- }
2576
- };
2577
- var isDevelopment = getIsDevelopment();
2578
- var logger = {
2579
- debug: (message, data) => {
2580
- if (isDevelopment) {
2581
- console.debug(`[DEBUG] ${message}`, data === void 0 ? "" : data);
2582
- }
2583
- },
2584
- error: (message, data) => {
2585
- if (isDevelopment) {
2586
- console.error(`[ERROR] ${message}`, data === void 0 ? "" : data);
2587
- }
2588
- },
2589
- info: (message, data) => {
2590
- if (isDevelopment) {
2591
- console.info(`[INFO] ${message}`, data === void 0 ? "" : data);
2592
- }
2593
- },
2594
- warn: (message, data) => {
2595
- if (isDevelopment) {
2596
- console.warn(`[WARN] ${message}`, data === void 0 ? "" : data);
2597
- }
2598
- }
2599
- };
2600
- var createScopedLogger = (scope) => ({
2601
- debug: (message, data) => {
2602
- logger.debug(`[${scope}] ${message}`, data);
2603
- },
2604
- error: (message, data) => {
2605
- logger.error(`[${scope}] ${message}`, data);
2606
- },
2607
- info: (message, data) => {
2608
- logger.info(`[${scope}] ${message}`, data);
2609
- },
2610
- warn: (message, data) => {
2611
- logger.warn(`[${scope}] ${message}`, data);
2612
- }
2613
2580
  });
2614
-
2615
- // src/utils/search-in-object.ts
2616
- var searchInObject = (object, searchTerm, skipKeys = []) => {
2617
- if (!object) return false;
2618
- if (!searchTerm || searchTerm.trim() === "") return true;
2619
- const normalizedSearchTerm = searchTerm.toLowerCase().trim();
2620
- if (typeof object === "string") {
2621
- return object.toLowerCase().includes(normalizedSearchTerm);
2622
- }
2623
- if (typeof object === "number") {
2624
- return String(object).toLowerCase().includes(normalizedSearchTerm);
2625
- }
2626
- if (typeof object === "boolean") {
2627
- return String(object).toLowerCase().includes(normalizedSearchTerm);
2628
- }
2629
- if (Array.isArray(object)) {
2630
- return object.some((item) => searchInObject(item, searchTerm, skipKeys));
2631
- }
2632
- if (typeof object === "object") {
2633
- return Object.entries(object).filter(([key]) => !skipKeys.includes(key)).some(([, value]) => searchInObject(value, searchTerm, skipKeys));
2634
- }
2635
- return false;
2636
- };
2581
+ ServiceCell.displayName = "ServiceCell";
2637
2582
 
2638
2583
  // src/components/spans-list/spans-data-grid.tsx
2639
2584
  import { Fragment as Fragment2, jsx as jsx125, jsxs as jsxs120 } from "react/jsx-runtime";
@@ -2641,12 +2586,6 @@ var resourceNameComparator = (v1 = "", v2 = "") => {
2641
2586
  return v1.localeCompare(v2);
2642
2587
  };
2643
2588
  var columns = [
2644
- // {
2645
- // field: 'status',
2646
- // renderHeader: () => null,
2647
- // width: 50,
2648
- // renderCell: (parameters) => <StatusCell span={parameters.row} />,
2649
- // },
2650
2589
  {
2651
2590
  field: "trace_id",
2652
2591
  headerName: "Trace",
@@ -2670,7 +2609,7 @@ var columns = [
2670
2609
  {
2671
2610
  field: "start_time_unix_nano",
2672
2611
  headerName: "Time",
2673
- renderCell: (parameters) => /* @__PURE__ */ jsx125(ResponsiveTimestampCell, { value: parameters.value }),
2612
+ renderCell: (parameters) => /* @__PURE__ */ jsx125(ResponsiveTimestampCell, { date: parameters.value?.startTime }),
2674
2613
  type: "string",
2675
2614
  width: 180
2676
2615
  },
@@ -2722,8 +2661,8 @@ var SpansDataGrid = ({
2722
2661
  // setRows,
2723
2662
  sortingOption = defaultSortingOption
2724
2663
  }) => {
2725
- const [searchTerm, setSearchTerm] = useState2(() => localStorage.getItem("spansSearchTerm") ?? "");
2726
- const [sortModel, setSortModel] = useState2(() => {
2664
+ const [searchTerm, setSearchTerm] = useState(() => localStorage.getItem("spansSearchTerm") ?? "");
2665
+ const [sortModel, setSortModel] = useState(() => {
2727
2666
  const savedSorting = localStorage.getItem("spansSortModel");
2728
2667
  if (savedSorting) {
2729
2668
  try {
@@ -2758,8 +2697,8 @@ var SpansDataGrid = ({
2758
2697
  },
2759
2698
  [searchTerm]
2760
2699
  );
2761
- const filtersToApply = useMemo2(() => [filterSpansBySearchTerm], [filterSpansBySearchTerm]);
2762
- const filteredRows = useMemo2(
2700
+ const filtersToApply = useMemo(() => [filterSpansBySearchTerm], [filterSpansBySearchTerm]);
2701
+ const filteredRows = useMemo(
2763
2702
  () => rows.filter((row) => filtersToApply.every((filter) => filter(row))),
2764
2703
  [filtersToApply, rows]
2765
2704
  );
@@ -3181,9 +3120,9 @@ var StatusMessage = ({
3181
3120
  };
3182
3121
 
3183
3122
  // src/hooks/use-local-storage.tsx
3184
- import { useCallback as useCallback2, useEffect as useEffect2, useState as useState3 } from "react";
3123
+ import { useCallback as useCallback2, useEffect, useState as useState2 } from "react";
3185
3124
  function useLocalStorage(key, initialValue) {
3186
- const [storedValue, setStoredValue] = useState3(() => {
3125
+ const [storedValue, setStoredValue] = useState2(() => {
3187
3126
  try {
3188
3127
  const item = globalThis.localStorage.getItem(key);
3189
3128
  return item ? JSON.parse(item) : initialValue;
@@ -3204,7 +3143,7 @@ function useLocalStorage(key, initialValue) {
3204
3143
  console.error(`Error setting localStorage key "${key}":`, error);
3205
3144
  }
3206
3145
  }, [key]);
3207
- useEffect2(() => {
3146
+ useEffect(() => {
3208
3147
  const handleStorageChange = (event) => {
3209
3148
  if (event.key === key && event.newValue !== null) {
3210
3149
  try {
@@ -3223,14 +3162,14 @@ function useLocalStorage(key, initialValue) {
3223
3162
  }
3224
3163
 
3225
3164
  // src/hooks/use-status.tsx
3226
- import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
3165
+ import { useCallback as useCallback3, useEffect as useEffect2, useRef, useState as useState3 } from "react";
3227
3166
  var useStatus = () => {
3228
3167
  const api = useAppInspectorApi();
3229
- const [checking, setChecking] = useState4(true);
3230
- const [status, setStatus] = useState4();
3231
- const [error, setError] = useState4();
3232
- const hasFetchedReference = useRef2(false);
3233
- const abortControllerReference = useRef2(null);
3168
+ const [checking, setChecking] = useState3(true);
3169
+ const [status, setStatus] = useState3();
3170
+ const [error, setError] = useState3();
3171
+ const hasFetchedReference = useRef(false);
3172
+ const abortControllerReference = useRef(null);
3234
3173
  const checkStatus = useCallback3(async () => {
3235
3174
  if (abortControllerReference.current) {
3236
3175
  abortControllerReference.current.abort();
@@ -3255,7 +3194,7 @@ var useStatus = () => {
3255
3194
  }
3256
3195
  }
3257
3196
  }, [api]);
3258
- useEffect3(() => {
3197
+ useEffect2(() => {
3259
3198
  if (!hasFetchedReference.current) {
3260
3199
  hasFetchedReference.current = true;
3261
3200
  void checkStatus();
@@ -3269,11 +3208,11 @@ import { ArrowBack } from "@mui/icons-material";
3269
3208
  import { Box as Box17, Button as Button5, Drawer, Paper as Paper2 } from "@mui/material";
3270
3209
  import { styled } from "@mui/material/styles";
3271
3210
  import { ReactFlowProvider } from "@xyflow/react";
3272
- import { useCallback as useCallback4, useEffect as useEffect6, useState as useState9 } from "react";
3211
+ import { useCallback as useCallback4, useEffect as useEffect5, useState as useState8 } from "react";
3273
3212
 
3274
3213
  // src/components/event-details/event-details.tsx
3275
3214
  import { Box as Box13, Chip as Chip3, Divider as Divider2, Stack, Typography as Typography9 } from "@mui/material";
3276
- import { useMemo as useMemo5 } from "react";
3215
+ import { useMemo as useMemo4 } from "react";
3277
3216
 
3278
3217
  // src/utils/iam-utils.ts
3279
3218
  function determinePermissionStatus(payload) {
@@ -3469,6 +3408,17 @@ var getEventGroupsByType = (events) => {
3469
3408
  return groups;
3470
3409
  };
3471
3410
 
3411
+ // src/utils/time.ts
3412
+ function unixNanoToDate(unixNanoString) {
3413
+ const milliseconds = unixNanoToMilliseconds(unixNanoString);
3414
+ if (!milliseconds) return void 0;
3415
+ return new Date(milliseconds);
3416
+ }
3417
+ function unixNanoToMilliseconds(unixNanoString) {
3418
+ if (!unixNanoString) return void 0;
3419
+ return Number(BigInt(unixNanoString) / BigInt("1000000"));
3420
+ }
3421
+
3472
3422
  // src/components/event-details/event-details-header.tsx
3473
3423
  import { Close } from "@mui/icons-material";
3474
3424
  import { Box as Box6, IconButton, Typography as Typography4 } from "@mui/material";
@@ -3507,7 +3457,7 @@ import { Box as Box12 } from "@mui/material";
3507
3457
  // src/components/event-details/event-detail.tsx
3508
3458
  import { KeyboardArrowDown as KeyboardArrowDown2, KeyboardArrowRight as KeyboardArrowRight2 } from "@mui/icons-material";
3509
3459
  import { Box as Box10, Grid as Grid3, IconButton as IconButton3, Typography as Typography7 } from "@mui/material";
3510
- import { useEffect as useEffect4, useMemo as useMemo4, useRef as useRef3, useState as useState6 } from "react";
3460
+ import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef2, useState as useState5 } from "react";
3511
3461
 
3512
3462
  // src/components/status-icon.tsx
3513
3463
  import { Cancel, CheckCircle, Error as Error2, Info, RemoveCircle } from "@mui/icons-material";
@@ -3658,7 +3608,7 @@ var IAMEventDetail = ({ event }) => {
3658
3608
  // src/components/event-details/iam-permission-detail.tsx
3659
3609
  import { KeyboardArrowDown, KeyboardArrowRight } from "@mui/icons-material";
3660
3610
  import { Box as Box9, Chip as Chip2, IconButton as IconButton2, Typography as Typography6 } from "@mui/material";
3661
- import { useMemo as useMemo3, useState as useState5 } from "react";
3611
+ import { useMemo as useMemo2, useState as useState4 } from "react";
3662
3612
  import { jsx as jsx131, jsxs as jsxs125 } from "react/jsx-runtime";
3663
3613
  var getChipColors = (status) => {
3664
3614
  const isAllowed = status === "explicitly_allowed" || status === "implicitly_allowed";
@@ -3668,8 +3618,8 @@ var getChipColors = (status) => {
3668
3618
  };
3669
3619
  };
3670
3620
  var IAMPermissionItem = ({ event }) => {
3671
- const [isOpen, setIsOpen] = useState5(false);
3672
- const parsedData = useMemo3(() => {
3621
+ const [isOpen, setIsOpen] = useState4(false);
3622
+ const parsedData = useMemo2(() => {
3673
3623
  const payloadString = event.attributes?.payload;
3674
3624
  if (!payloadString) {
3675
3625
  return;
@@ -3739,15 +3689,15 @@ var DetailRow2 = ({ content, label }) => /* @__PURE__ */ jsxs126(Grid3, { contai
3739
3689
  ) : content })
3740
3690
  ] });
3741
3691
  var EventMessage = ({ event }) => {
3742
- const [isOpen, setIsOpen] = useState6(false);
3743
- const [isOverflowing, setIsOverflowing] = useState6(false);
3744
- const textReference = useRef3(null);
3745
- const parsedMessage = useMemo4(() => parseEventMessage(event), [event]);
3746
- const isIAMPolicyEvent = useMemo4(
3692
+ const [isOpen, setIsOpen] = useState5(false);
3693
+ const [isOverflowing, setIsOverflowing] = useState5(false);
3694
+ const textReference = useRef2(null);
3695
+ const parsedMessage = useMemo3(() => parseEventMessage(event), [event]);
3696
+ const isIAMPolicyEvent = useMemo3(
3747
3697
  () => event.event_type === "iam.policy_evaluation" && event.attributes?.payload && typeof event.attributes.payload === "string",
3748
3698
  [event]
3749
3699
  );
3750
- useEffect4(() => {
3700
+ useEffect3(() => {
3751
3701
  const checkOverflow = () => {
3752
3702
  const element = textReference.current;
3753
3703
  if (element) {
@@ -3760,11 +3710,11 @@ var EventMessage = ({ event }) => {
3760
3710
  window.removeEventListener("resize", checkOverflow);
3761
3711
  };
3762
3712
  }, [parsedMessage.headline]);
3763
- const hasAdditionalContent = useMemo4(
3713
+ const hasAdditionalContent = useMemo3(
3764
3714
  () => parsedMessage.message || parsedMessage.details || isIAMPolicyEvent,
3765
3715
  [parsedMessage.message, parsedMessage.details, isIAMPolicyEvent]
3766
3716
  );
3767
- const shouldShowToggle = useMemo4(
3717
+ const shouldShowToggle = useMemo3(
3768
3718
  () => isOverflowing || hasAdditionalContent,
3769
3719
  [isOverflowing, hasAdditionalContent]
3770
3720
  );
@@ -3906,10 +3856,10 @@ var EventDetail = ({
3906
3856
  // src/components/event-details/toggle-section.tsx
3907
3857
  import { KeyboardArrowDown as KeyboardArrowDown3, KeyboardArrowRight as KeyboardArrowRight3 } from "@mui/icons-material";
3908
3858
  import { Box as Box11, Typography as Typography8 } from "@mui/material";
3909
- import { useState as useState7 } from "react";
3859
+ import { useState as useState6 } from "react";
3910
3860
  import { jsx as jsx133, jsxs as jsxs127 } from "react/jsx-runtime";
3911
3861
  var ToggleSection = ({ children, headline, initialOpen = true }) => {
3912
- const [isOpen, setIsOpen] = useState7(initialOpen);
3862
+ const [isOpen, setIsOpen] = useState6(initialOpen);
3913
3863
  return /* @__PURE__ */ jsxs127(Box11, { sx: { mt: 4 }, children: [
3914
3864
  /* @__PURE__ */ jsx133(
3915
3865
  Box11,
@@ -3985,7 +3935,7 @@ var EventSection = ({
3985
3935
  // src/components/event-details/event-details.tsx
3986
3936
  import { Fragment as Fragment5, jsx as jsx135, jsxs as jsxs129 } from "react/jsx-runtime";
3987
3937
  var EventDetails = ({ onClose, selectedEvent }) => {
3988
- const attributes = useMemo5(() => {
3938
+ const attributes = useMemo4(() => {
3989
3939
  const attributes2 = Object.entries(selectedEvent?.attributes ?? {});
3990
3940
  return attributes2.filter(([key]) => key !== "localstack.aws.account_id" && key !== "localstack.aws.service");
3991
3941
  }, [selectedEvent?.attributes]);
@@ -4085,21 +4035,21 @@ function renderKeyValue(key, value) {
4085
4035
  import "@xyflow/react/dist/base.css";
4086
4036
  import { Alert as Alert3, Button as Button4, useTheme as useTheme2 } from "@mui/material";
4087
4037
  import { Background, ReactFlow, useNodesState, useReactFlow as useReactFlow2 } from "@xyflow/react";
4088
- import { useEffect as useEffect5, useState as useState8 } from "react";
4038
+ import { useEffect as useEffect4, useState as useState7 } from "react";
4089
4039
 
4090
4040
  // src/components/trace-graph/service-node.tsx
4091
4041
  import { Box as Box15, Stack as Stack2, Typography as Typography10 } from "@mui/material";
4092
4042
  import "@xyflow/react/dist/style.css";
4093
4043
  import { Handle, Position } from "@xyflow/react";
4094
- import { memo as memo2 } from "react";
4044
+ import { memo as memo7 } from "react";
4095
4045
 
4096
4046
  // src/components/trace-graph/problem-indicator.tsx
4097
4047
  import { Error as ErrorIcon2, Info as Info2, Warning as Warning2 } from "@mui/icons-material";
4098
4048
  import { Box as Box14, Tooltip as Tooltip3 } from "@mui/material";
4099
- import { useMemo as useMemo6 } from "react";
4049
+ import { useMemo as useMemo5 } from "react";
4100
4050
  import { jsx as jsx136 } from "react/jsx-runtime";
4101
4051
  var ProblemIndicator = ({ error }) => {
4102
- const icon = useMemo6(() => {
4052
+ const icon = useMemo5(() => {
4103
4053
  switch (error.level) {
4104
4054
  case "error": {
4105
4055
  return /* @__PURE__ */ jsx136(ErrorIcon2, { sx: { color: "#d32f2f", fontSize: "14px" } });
@@ -4112,7 +4062,7 @@ var ProblemIndicator = ({ error }) => {
4112
4062
  }
4113
4063
  }
4114
4064
  }, [error.level]);
4115
- const color = useMemo6(() => {
4065
+ const color = useMemo5(() => {
4116
4066
  switch (error.level) {
4117
4067
  case "error": {
4118
4068
  return "#d32f2f";
@@ -4151,7 +4101,7 @@ var handleStyle = {
4151
4101
  borderColor: "lightgray",
4152
4102
  opacity: 0
4153
4103
  };
4154
- var ServiceNode = memo2(({ data, selected }) => {
4104
+ var ServiceNode = memo7(({ data, selected }) => {
4155
4105
  const hasErrors = (data.event.errors && data.event.errors.length > 0) ?? false;
4156
4106
  return /* @__PURE__ */ jsxs130(Box15, { sx: { maxWidth: 200 }, children: [
4157
4107
  /* @__PURE__ */ jsxs130(
@@ -4332,7 +4282,7 @@ var calculateCenterX = (focusNodeX, viewPortPixelWidth, minX, maxX) => {
4332
4282
  import { Add, FitScreen, Remove } from "@mui/icons-material";
4333
4283
  import { Box as Box16, IconButton as IconButton4 } from "@mui/material";
4334
4284
  import { useReactFlow, useStore } from "@xyflow/react";
4335
- import { memo as memo3 } from "react";
4285
+ import { memo as memo8 } from "react";
4336
4286
 
4337
4287
  // node_modules/zustand/esm/shallow.mjs
4338
4288
  function shallow$1(objA, objB) {
@@ -4379,7 +4329,7 @@ var selector = (s) => ({
4379
4329
  maxZoomReached: s.transform[2] >= s.maxZoom,
4380
4330
  minZoomReached: s.transform[2] <= s.minZoom
4381
4331
  });
4382
- var Controls = memo3(() => {
4332
+ var Controls = memo8(() => {
4383
4333
  const { maxZoomReached, minZoomReached } = useStore(selector, shallow$1);
4384
4334
  const { fitView, zoomIn, zoomOut } = useReactFlow();
4385
4335
  const onZoomInHandler = () => {
@@ -4452,10 +4402,10 @@ var TraceGraph = ({
4452
4402
  viewPortPixelWidth
4453
4403
  }) => {
4454
4404
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
4455
- const [edges, setEdges] = useState8([]);
4456
- const [initialViewSet, setInitialViewSet] = useState8(false);
4405
+ const [edges, setEdges] = useState7([]);
4406
+ const [initialViewSet, setInitialViewSet] = useState7(false);
4457
4407
  const { fitView, setCenter } = useReactFlow2();
4458
- useEffect5(() => {
4408
+ useEffect4(() => {
4459
4409
  const spansMap = /* @__PURE__ */ new Map();
4460
4410
  const rootSpans = [];
4461
4411
  for (const span of spans.data ?? []) {
@@ -4490,7 +4440,7 @@ var TraceGraph = ({
4490
4440
  setNodes(layoutedNodes);
4491
4441
  setEdges(layoutedEdges);
4492
4442
  }, [spans.data, initialFocusEventId, setNodes]);
4493
- useEffect5(() => {
4443
+ useEffect4(() => {
4494
4444
  const shouldSetInitialView = !spans.loading && nodes.length > 0 && !initialViewSet;
4495
4445
  if (shouldSetInitialView) {
4496
4446
  if (initialFocusEventId) {
@@ -4536,6 +4486,7 @@ var TraceGraph = ({
4536
4486
  maxZoom: 1.5,
4537
4487
  minZoom: 0.1,
4538
4488
  nodes,
4489
+ nodesDraggable: false,
4539
4490
  nodeTypes,
4540
4491
  onNodeClick: (_event, node) => {
4541
4492
  onEventSelect(node.data.event);
@@ -4679,10 +4630,10 @@ var TraceGraphView = ({
4679
4630
  };
4680
4631
  var TraceGraphPage = ({ onClose, spanId, traceId }) => {
4681
4632
  const api = useAppInspectorApi();
4682
- const [spans, setSpans] = useState9();
4683
- const [loading, setLoading] = useState9(false);
4633
+ const [spans, setSpans] = useState8();
4634
+ const [loading, setLoading] = useState8(false);
4684
4635
  const [includeReadOperations] = useLocalStorage("includeReadOperations", false);
4685
- const [fetchError, setFetchError] = useState9();
4636
+ const [fetchError, setFetchError] = useState8();
4686
4637
  const fetchSpans = useCallback4(async () => {
4687
4638
  setLoading(true);
4688
4639
  try {
@@ -4699,12 +4650,12 @@ var TraceGraphPage = ({ onClose, spanId, traceId }) => {
4699
4650
  setLoading(false);
4700
4651
  }
4701
4652
  }, [api, includeReadOperations, traceId]);
4702
- useEffect6(() => {
4653
+ useEffect5(() => {
4703
4654
  void fetchSpans();
4704
4655
  }, [fetchSpans]);
4705
- const [open, setOpen] = useState9(true);
4706
- const [selectedEvent, setSelectedEvent] = useState9();
4707
- const [viewPortPixelWidth, setViewPortPixelWidth] = useState9(0);
4656
+ const [open, setOpen] = useState8(true);
4657
+ const [selectedEvent, setSelectedEvent] = useState8();
4658
+ const [viewPortPixelWidth, setViewPortPixelWidth] = useState8(0);
4708
4659
  const { checkStatus, error: statusError, status } = useStatus();
4709
4660
  const calculateDrawerWidth = useCallback4(() => {
4710
4661
  const percentageMatch = /(\d+)%/.exec(DRAWER_WIDTH);
@@ -4714,7 +4665,7 @@ var TraceGraphPage = ({ onClose, spanId, traceId }) => {
4714
4665
  }
4715
4666
  return 0;
4716
4667
  }, [open]);
4717
- useEffect6(() => {
4668
+ useEffect5(() => {
4718
4669
  const updateViewportWidth = () => {
4719
4670
  const totalWidth = window.innerWidth;
4720
4671
  const drawerPixelWidth = open ? calculateDrawerWidth() : 0;
@@ -4767,22 +4718,22 @@ import { Fragment as Fragment8, jsx as jsx141, jsxs as jsxs134 } from "react/jsx
4767
4718
  var spansPerPageOptions = [25, 50, 100];
4768
4719
  var SpansListPage = () => {
4769
4720
  const api = useAppInspectorApi();
4770
- const [spans, setSpans] = useState10();
4771
- const [loading, setLoading] = useState10(false);
4772
- const hasFetched = useRef4(false);
4721
+ const [spans, setSpans] = useState9();
4722
+ const [loading, setLoading] = useState9(false);
4723
+ const hasFetched = useRef3(false);
4773
4724
  const [includeReadOperations, setIncludeReadOperations] = useLocalStorage("includeReadOperations", false);
4774
- const mapPageToNextCursor = useRef4({});
4775
- const [page, setPage] = useState10(0);
4776
- const [pageSize, setPageSize] = useState10(100);
4777
- const [spanCount, setSpanCount] = useState10(0);
4778
- const queryOptions = useMemo7(() => {
4725
+ const mapPageToNextCursor = useRef3({});
4726
+ const [page, setPage] = useState9(0);
4727
+ const [pageSize, setPageSize] = useState9(100);
4728
+ const [spanCount, setSpanCount] = useState9(0);
4729
+ const queryOptions = useMemo6(() => {
4779
4730
  return {
4780
4731
  is_write_operation: includeReadOperations ? void 0 : true,
4781
4732
  limit: pageSize,
4782
4733
  pagination_token: mapPageToNextCursor.current[page - 1]
4783
4734
  };
4784
4735
  }, [includeReadOperations, pageSize, page]);
4785
- const [fetchError, setFetchError] = useState10();
4736
+ const [fetchError, setFetchError] = useState9();
4786
4737
  const { checkStatus, error: statusError, status } = useStatus();
4787
4738
  const fetchSpans = useCallback5(async () => {
4788
4739
  setLoading(true);
@@ -4804,18 +4755,18 @@ var SpansListPage = () => {
4804
4755
  const fetchSpansSync = useCallback5(() => {
4805
4756
  void fetchSpans();
4806
4757
  }, [fetchSpans]);
4807
- useEffect7(() => {
4758
+ useEffect6(() => {
4808
4759
  if (hasFetched.current) return;
4809
4760
  if (status?.status !== "ENABLED") return;
4810
4761
  hasFetched.current = true;
4811
4762
  void fetchSpans();
4812
4763
  }, [fetchSpans, status]);
4813
- useEffect7(() => {
4764
+ useEffect6(() => {
4814
4765
  if (!hasFetched.current) return;
4815
4766
  void fetchSpans();
4816
4767
  }, [fetchSpans]);
4817
- const [selectedTraceId, setSelectedTraceId] = useState10();
4818
- const [selectedSpanId, setSelectedSpanId] = useState10();
4768
+ const [selectedTraceId, setSelectedTraceId] = useState9();
4769
+ const [selectedSpanId, setSelectedSpanId] = useState9();
4819
4770
  const navigateToSpan = useCallback5((span) => {
4820
4771
  setSelectedTraceId(span.trace_id);
4821
4772
  setSelectedSpanId(span.span_id);
@@ -4905,7 +4856,7 @@ var routes = {
4905
4856
 
4906
4857
  // src/context.tsx
4907
4858
  import { createContext as createContext2, useContext as useContext2 } from "react";
4908
- import { useCallback as useCallback6, useMemo as useMemo8 } from "react";
4859
+ import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
4909
4860
 
4910
4861
  // src/constants/error-messages.ts
4911
4862
  var ERROR_MESSAGES = {
@@ -5014,7 +4965,15 @@ var createApiClient = ({ localstackEndpoint }) => {
5014
4965
  },
5015
4966
  getSpans: async (request) => {
5016
4967
  const endpoint = buildSpansEndpoint(request);
5017
- return makeRequest({ endpoint, localstackEndpoint });
4968
+ const response = await makeRequest({ endpoint, localstackEndpoint });
4969
+ return {
4970
+ ...response,
4971
+ spans: response.spans.map((span) => ({
4972
+ ...span,
4973
+ endTime: unixNanoToDate(span.end_time_unix_nano),
4974
+ startTime: unixNanoToDate(span.start_time_unix_nano)
4975
+ }))
4976
+ };
5018
4977
  },
5019
4978
  getStatus: async () => {
5020
4979
  return makeRequest({
@@ -5029,7 +4988,7 @@ var createApiClient = ({ localstackEndpoint }) => {
5029
4988
  import { jsx as jsx142 } from "react/jsx-runtime";
5030
4989
  var AppInspectorContext = createContext2(void 0);
5031
4990
  var AppInspectorContextProvider = (props) => {
5032
- const api = useMemo8(() => {
4991
+ const api = useMemo7(() => {
5033
4992
  return false ? createApiClientMock() : createApiClient({ localstackEndpoint: props.localstackEndpoint });
5034
4993
  }, [props.localstackEndpoint]);
5035
4994
  const resolveLink = useCallback6(
@@ -5044,7 +5003,7 @@ var AppInspectorContextProvider = (props) => {
5044
5003
  },
5045
5004
  [props.routePrefix]
5046
5005
  );
5047
- const contextValue = useMemo8(
5006
+ const contextValue = useMemo7(
5048
5007
  () => ({
5049
5008
  linkComponent: props.linkComponent,
5050
5009
  localstackEndpoint: props.localstackEndpoint,