@localstack/appinspector-ui 1.0.59 → 1.0.61

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.cjs CHANGED
@@ -77,7 +77,7 @@ module.exports = __toCommonJS(index_exports);
77
77
 
78
78
  // src/pages/spans-list-page.tsx
79
79
  var import_material20 = require("@mui/material");
80
- var import_react61 = require("react");
80
+ var import_react62 = require("react");
81
81
 
82
82
  // src/components/spans-list/spans-list.tsx
83
83
  var import_material5 = require("@mui/material");
@@ -12148,6 +12148,16 @@ var newSpanBackgroundColor = {
12148
12148
  dark: "#887b02",
12149
12149
  light: "#ffde7b"
12150
12150
  };
12151
+ var LABEL_BEGINNING_OF_STREAM = "This is the beginning of the stream";
12152
+ var LABEL_END_OF_STREAM = "This is the end of the stream";
12153
+ var LABEL_NO_SPANS = "There are no spans";
12154
+ var LABEL_LOAD_OLDER = "Load older spans";
12155
+ var LABEL_LOAD_NEWER = "Load newer spans";
12156
+ var StreamBoundaryRow = ({ colSpan, label }) => /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableCell, { colSpan, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)("span", { children: label }) }) });
12157
+ var LoadSpansRow = ({ colSpan, fetching, label, onFetch }) => /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_material4.TableCell, { colSpan, sx: { textAlign: "center" }, children: [
12158
+ !fetching && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.Button, { onClick: onFetch, sx: { my: 1 }, children: label }),
12159
+ fetching && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.CircularProgress, { size: 24, sx: { m: 2 } })
12160
+ ] }) });
12151
12161
  var SpansDataGridRow = (0, import_react40.memo)(
12152
12162
  ({ row }) => {
12153
12163
  const theme = (0, import_material4.useTheme)();
@@ -12203,11 +12213,15 @@ var SpansDataGridRow = (0, import_react40.memo)(
12203
12213
  var SpansDataGrid = ({
12204
12214
  clearingSpans,
12205
12215
  fetchingBackward,
12216
+ fetchingForward,
12206
12217
  hasMoreBackward,
12207
12218
  hasMoreForward,
12208
12219
  onClearSpans,
12209
12220
  onFetchBackward,
12221
+ onFetchForward,
12222
+ onOrderChange,
12210
12223
  onSpanClick,
12224
+ order: order2,
12211
12225
  spans
12212
12226
  }) => {
12213
12227
  const columns = (0, import_react40.useMemo)(() => [
@@ -12297,6 +12311,23 @@ var SpansDataGrid = ({
12297
12311
  return /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_jsx_runtime124.Fragment, { children: [
12298
12312
  /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.Grid, { item: true, xs: 12, children: /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_material4.Box, { sx: { alignItems: "center", display: "flex", gap: "0.5rem" }, children: [
12299
12313
  /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.Box, { sx: { flexGrow: 1 } }),
12314
+ /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(
12315
+ import_material4.FormControlLabel,
12316
+ {
12317
+ control: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(
12318
+ import_material4.Button,
12319
+ {
12320
+ onClick: () => {
12321
+ onOrderChange(order2 === "newest_first" ? "oldest_first" : "newest_first");
12322
+ },
12323
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_icons_material.SwapVertOutlined, {}),
12324
+ variant: "text",
12325
+ children: order2 === "newest_first" ? "Newest First" : "Oldest First"
12326
+ }
12327
+ ),
12328
+ label: ""
12329
+ }
12330
+ ),
12300
12331
  /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(
12301
12332
  import_material4.FormControlLabel,
12302
12333
  {
@@ -12354,21 +12385,30 @@ var SpansDataGrid = ({
12354
12385
  }) }),
12355
12386
  /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_material4.TableBody, { children: [
12356
12387
  spans === void 0 && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.CircularProgress, { size: 48, sx: { m: 4 } }) }) }),
12357
- spans?.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)("span", { children: "There are no spans" }) }) }),
12358
- hasRows && !hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)("span", { children: "This is the beginning of the stream" }) }) }),
12359
- hasRows && hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_material4.TableCell, { colSpan: columnCount, sx: { textAlign: "center" }, children: [
12360
- !fetchingBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(
12361
- import_material4.Button,
12362
- {
12363
- onClick: onFetchBackward,
12364
- sx: { my: 1 },
12365
- children: "Load older spans"
12388
+ spans?.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_NO_SPANS }),
12389
+ order2 === "newest_first" && /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_jsx_runtime124.Fragment, { children: [
12390
+ hasRows && hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingForward, label: LABEL_LOAD_NEWER, onFetch: onFetchForward }),
12391
+ hasRows && !hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_END_OF_STREAM }),
12392
+ hasRows && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(AnimatePresence, { initial: false, children: (() => {
12393
+ const reversed = [];
12394
+ for (let index2 = rows.length - 1; index2 >= 0; index2--) {
12395
+ const row = rows.at(index2);
12396
+ reversed.push(
12397
+ /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(SpansDataGridRow, { row }, row.original.span_id)
12398
+ );
12366
12399
  }
12367
- ),
12368
- fetchingBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.CircularProgress, { size: 24, sx: { m: 2 } })
12369
- ] }) }),
12370
- hasRows && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(AnimatePresence, { initial: false, children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(SpansDataGridRow, { row }, row.original.span_id)) }),
12371
- hasRows && !hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(import_material4.TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime124.jsx)("span", { children: "This is the end of the stream" }) }) })
12400
+ return reversed;
12401
+ })() }),
12402
+ hasRows && hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingBackward, label: LABEL_LOAD_OLDER, onFetch: onFetchBackward }),
12403
+ hasRows && !hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_BEGINNING_OF_STREAM })
12404
+ ] }),
12405
+ order2 === "oldest_first" && /* @__PURE__ */ (0, import_jsx_runtime124.jsxs)(import_jsx_runtime124.Fragment, { children: [
12406
+ hasRows && !hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_BEGINNING_OF_STREAM }),
12407
+ hasRows && hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingBackward, label: LABEL_LOAD_OLDER, onFetch: onFetchBackward }),
12408
+ hasRows && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(AnimatePresence, { initial: false, children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(SpansDataGridRow, { row }, row.original.span_id)) }),
12409
+ hasRows && hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingForward, label: LABEL_LOAD_NEWER, onFetch: onFetchForward }),
12410
+ hasRows && !hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime124.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_END_OF_STREAM })
12411
+ ] })
12372
12412
  ] })
12373
12413
  ]
12374
12414
  }
@@ -12405,7 +12445,9 @@ var SpansList = (props) => {
12405
12445
  onClearSpans: props.onClearSpans,
12406
12446
  onFetchBackward: props.onFetchBackward,
12407
12447
  onFetchForward: props.onFetchForward,
12448
+ onOrderChange: props.onOrderChange,
12408
12449
  onSpanClick: props.onSpanClick,
12450
+ order: props.order,
12409
12451
  refetching: props.refetching,
12410
12452
  spans: props.spans
12411
12453
  }
@@ -12710,18 +12752,63 @@ var StatusMessage = ({
12710
12752
  return /* @__PURE__ */ (0, import_jsx_runtime126.jsx)(import_jsx_runtime126.Fragment, {});
12711
12753
  };
12712
12754
 
12755
+ // src/hooks/use-local-storage.tsx
12756
+ var import_react41 = require("react");
12757
+ function useLocalStorage(key, initialValue) {
12758
+ const [storedValue, setStoredValue] = (0, import_react41.useState)(() => {
12759
+ try {
12760
+ const item = globalThis.localStorage.getItem(key);
12761
+ return item ? JSON.parse(item) : initialValue;
12762
+ } catch (error) {
12763
+ console.error(`Error reading localStorage key "${key}":`, error);
12764
+ return initialValue;
12765
+ }
12766
+ });
12767
+ const setValue = (0, import_react41.useCallback)((value) => {
12768
+ try {
12769
+ setStoredValue((previousState) => {
12770
+ const next = typeof value === "function" ? value(previousState) : value;
12771
+ globalThis.localStorage.setItem(key, JSON.stringify(next));
12772
+ globalThis.dispatchEvent(new StorageEvent("storage", {
12773
+ key,
12774
+ newValue: JSON.stringify(next)
12775
+ }));
12776
+ return next;
12777
+ });
12778
+ } catch (error) {
12779
+ console.error(`Error setting localStorage key "${key}":`, error);
12780
+ }
12781
+ }, [key]);
12782
+ (0, import_react41.useEffect)(() => {
12783
+ const handleStorageChange = (event) => {
12784
+ if (event.key === key && event.newValue !== null) {
12785
+ try {
12786
+ setStoredValue(JSON.parse(event.newValue));
12787
+ } catch (error) {
12788
+ console.error(`Error parsing localStorage key "${key}":`, error);
12789
+ }
12790
+ }
12791
+ };
12792
+ globalThis.addEventListener("storage", handleStorageChange);
12793
+ return () => {
12794
+ globalThis.removeEventListener("storage", handleStorageChange);
12795
+ };
12796
+ }, [key]);
12797
+ return [storedValue, setValue];
12798
+ }
12799
+
12713
12800
  // src/hooks/use-spans.ts
12714
- var import_react46 = require("react");
12801
+ var import_react47 = require("react");
12715
12802
 
12716
12803
  // src/api/use-api.tsx
12717
- var import_react41 = require("react");
12804
+ var import_react42 = require("react");
12718
12805
  var import_jsx_runtime127 = require("react/jsx-runtime");
12719
- var AppInspectorApiContext = (0, import_react41.createContext)(void 0);
12806
+ var AppInspectorApiContext = (0, import_react42.createContext)(void 0);
12720
12807
  var ApiProvider = (props) => {
12721
12808
  return /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(AppInspectorApiContext.Provider, { value: props.api, children: props.children });
12722
12809
  };
12723
12810
  var useAppInspectorApi = () => {
12724
- const api = (0, import_react41.useContext)(AppInspectorApiContext);
12811
+ const api = (0, import_react42.useContext)(AppInspectorApiContext);
12725
12812
  if (!api) {
12726
12813
  throw new Error("useAppInspectorApi must be used within AppInspectorApiProvider");
12727
12814
  }
@@ -12729,15 +12816,15 @@ var useAppInspectorApi = () => {
12729
12816
  };
12730
12817
 
12731
12818
  // src/hooks/use-status.tsx
12732
- var import_react42 = require("react");
12819
+ var import_react43 = require("react");
12733
12820
  var useStatus = () => {
12734
12821
  const api = useAppInspectorApi();
12735
- const [checking, setChecking] = (0, import_react42.useState)(true);
12736
- const [status, setStatus] = (0, import_react42.useState)();
12737
- const [error, setError] = (0, import_react42.useState)();
12738
- const hasFetchedReference = (0, import_react42.useRef)(false);
12739
- const abortControllerReference = (0, import_react42.useRef)(null);
12740
- const checkStatus = (0, import_react42.useCallback)(async () => {
12822
+ const [checking, setChecking] = (0, import_react43.useState)(true);
12823
+ const [status, setStatus] = (0, import_react43.useState)();
12824
+ const [error, setError] = (0, import_react43.useState)();
12825
+ const hasFetchedReference = (0, import_react43.useRef)(false);
12826
+ const abortControllerReference = (0, import_react43.useRef)(null);
12827
+ const checkStatus = (0, import_react43.useCallback)(async () => {
12741
12828
  if (abortControllerReference.current !== null) {
12742
12829
  abortControllerReference.current.abort();
12743
12830
  }
@@ -12761,7 +12848,7 @@ var useStatus = () => {
12761
12848
  }
12762
12849
  }
12763
12850
  }, [api]);
12764
- (0, import_react42.useEffect)(() => {
12851
+ (0, import_react43.useEffect)(() => {
12765
12852
  if (!hasFetchedReference.current) {
12766
12853
  hasFetchedReference.current = true;
12767
12854
  void checkStatus();
@@ -12919,11 +13006,11 @@ var createPaginationBuffer = (options) => {
12919
13006
  };
12920
13007
 
12921
13008
  // src/hooks/use-spans-ws.tsx
12922
- var import_react45 = require("react");
13009
+ var import_react46 = require("react");
12923
13010
 
12924
13011
  // src/context.tsx
12925
- var import_react43 = require("react");
12926
13012
  var import_react44 = require("react");
13013
+ var import_react45 = require("react");
12927
13014
 
12928
13015
  // src/utils/time.ts
12929
13016
  function unixNanoToDate(unixNanoString) {
@@ -13116,19 +13203,19 @@ var createApiClient = ({ localstackEndpoint }) => {
13116
13203
 
13117
13204
  // src/context.tsx
13118
13205
  var import_jsx_runtime128 = require("react/jsx-runtime");
13119
- var AppInspectorContext = (0, import_react43.createContext)(void 0);
13206
+ var AppInspectorContext = (0, import_react44.createContext)(void 0);
13120
13207
  var useAppInspector = () => {
13121
- const context = (0, import_react43.useContext)(AppInspectorContext);
13208
+ const context = (0, import_react44.useContext)(AppInspectorContext);
13122
13209
  if (!context) {
13123
13210
  throw new Error("@localstack-studio/ui: components must be used within a <AppInspectorContextProvider>");
13124
13211
  }
13125
13212
  return context;
13126
13213
  };
13127
13214
  var AppInspectorContextProvider = (props) => {
13128
- const api = (0, import_react44.useMemo)(() => {
13215
+ const api = (0, import_react45.useMemo)(() => {
13129
13216
  return false ? createApiClientMock() : createApiClient({ localstackEndpoint: props.localstackEndpoint });
13130
13217
  }, [props.localstackEndpoint]);
13131
- const resolveLink = (0, import_react44.useCallback)(
13218
+ const resolveLink = (0, import_react45.useCallback)(
13132
13219
  (options) => {
13133
13220
  if (options.to === "settings") {
13134
13221
  return `${props.routePrefix}/settings`;
@@ -13140,7 +13227,7 @@ var AppInspectorContextProvider = (props) => {
13140
13227
  },
13141
13228
  [props.routePrefix]
13142
13229
  );
13143
- const contextValue = (0, import_react44.useMemo)(
13230
+ const contextValue = (0, import_react45.useMemo)(
13144
13231
  () => ({
13145
13232
  linkComponent: props.linkComponent,
13146
13233
  localstackEndpoint: props.localstackEndpoint,
@@ -13154,15 +13241,15 @@ var AppInspectorContextProvider = (props) => {
13154
13241
  // src/hooks/use-spans-ws.tsx
13155
13242
  function useSpansWebSocket(options) {
13156
13243
  const { onMessage } = options;
13157
- const onMessageRef = (0, import_react45.useRef)(onMessage);
13158
- (0, import_react45.useEffect)(() => {
13244
+ const onMessageRef = (0, import_react46.useRef)(onMessage);
13245
+ (0, import_react46.useEffect)(() => {
13159
13246
  onMessageRef.current = onMessage;
13160
13247
  }, [onMessage]);
13161
- const [connected, setConnected] = (0, import_react45.useState)(false);
13162
- const wsRef = (0, import_react45.useRef)(void 0);
13163
- const reconnectRef = (0, import_react45.useRef)(void 0);
13248
+ const [connected, setConnected] = (0, import_react46.useState)(false);
13249
+ const wsRef = (0, import_react46.useRef)(void 0);
13250
+ const reconnectRef = (0, import_react46.useRef)(void 0);
13164
13251
  const { localstackEndpoint } = useAppInspector();
13165
- const connect = (0, import_react45.useCallback)(() => {
13252
+ const connect = (0, import_react46.useCallback)(() => {
13166
13253
  if (wsRef.current !== void 0) return;
13167
13254
  const url = new URL(getAppInspectorApiUrl(localstackEndpoint, API_ENDPOINTS.WEBSOCKET_SPANS));
13168
13255
  url.protocol = globalThis.location.protocol === "https:" ? "wss" : "ws";
@@ -13188,7 +13275,7 @@ function useSpansWebSocket(options) {
13188
13275
  }
13189
13276
  });
13190
13277
  }, [localstackEndpoint]);
13191
- (0, import_react45.useEffect)(() => {
13278
+ (0, import_react46.useEffect)(() => {
13192
13279
  connect();
13193
13280
  return () => {
13194
13281
  if (reconnectRef.current !== void 0) clearTimeout(reconnectRef.current);
@@ -13208,12 +13295,12 @@ function useSpansWebSocket(options) {
13208
13295
  var PAGE_SIZE = 30;
13209
13296
  var useSpans = () => {
13210
13297
  const api = useAppInspectorApi();
13211
- const [spans, setSpans] = (0, import_react46.useState)();
13212
- const [fetchError, setFetchError] = (0, import_react46.useState)();
13213
- const [fetchingForward, setFetchingForward] = (0, import_react46.useState)(false);
13214
- const [fetchingBackward, setFetchingBackward] = (0, import_react46.useState)(false);
13215
- const [refetching, setRefetching] = (0, import_react46.useState)(false);
13216
- const paginationBuffer = (0, import_react46.useRef)(createPaginationBuffer({
13298
+ const [spans, setSpans] = (0, import_react47.useState)();
13299
+ const [fetchError, setFetchError] = (0, import_react47.useState)();
13300
+ const [fetchingForward, setFetchingForward] = (0, import_react47.useState)(false);
13301
+ const [fetchingBackward, setFetchingBackward] = (0, import_react47.useState)(false);
13302
+ const [refetching, setRefetching] = (0, import_react47.useState)(false);
13303
+ const paginationBuffer = (0, import_react47.useRef)(createPaginationBuffer({
13217
13304
  async fetchPage(token) {
13218
13305
  const response = await api.getSpans({
13219
13306
  limit: PAGE_SIZE,
@@ -13248,20 +13335,20 @@ var useSpans = () => {
13248
13335
  return a2.start_time_unix_nano < b2.start_time_unix_nano ? -1 : 1;
13249
13336
  }
13250
13337
  }));
13251
- const [hasMoreBackward, setHasMoreBackward] = (0, import_react46.useState)();
13252
- const [hasMoreForward, setHasMoreForward] = (0, import_react46.useState)();
13253
- const fetchForward = (0, import_react46.useCallback)(() => {
13338
+ const [hasMoreBackward, setHasMoreBackward] = (0, import_react47.useState)();
13339
+ const [hasMoreForward, setHasMoreForward] = (0, import_react47.useState)();
13340
+ const fetchForward = (0, import_react47.useCallback)(() => {
13254
13341
  paginationBuffer.current.fetchForward();
13255
13342
  }, []);
13256
- const fetchBackward = (0, import_react46.useCallback)(() => {
13343
+ const fetchBackward = (0, import_react47.useCallback)(() => {
13257
13344
  paginationBuffer.current.fetchBackward();
13258
13345
  }, []);
13259
- (0, import_react46.useEffect)(() => {
13346
+ (0, import_react47.useEffect)(() => {
13260
13347
  fetchForward();
13261
13348
  }, [fetchForward]);
13262
13349
  const { checkStatus, error: statusError, status } = useStatus();
13263
- const [clearingSpans, setClearingSpans] = (0, import_react46.useState)(false);
13264
- const clearSpans = (0, import_react46.useCallback)(async () => {
13350
+ const [clearingSpans, setClearingSpans] = (0, import_react47.useState)(false);
13351
+ const clearSpans = (0, import_react47.useCallback)(async () => {
13265
13352
  setClearingSpans(true);
13266
13353
  try {
13267
13354
  await api.deleteSpans();
@@ -13300,12 +13387,12 @@ var useSpans = () => {
13300
13387
  var import_icons_material11 = require("@mui/icons-material");
13301
13388
  var import_material19 = require("@mui/material");
13302
13389
  var import_styles = require("@mui/material/styles");
13303
- var import_react59 = require("@xyflow/react");
13304
- var import_react60 = require("react");
13390
+ var import_react60 = require("@xyflow/react");
13391
+ var import_react61 = require("react");
13305
13392
 
13306
13393
  // src/components/event-details/event-details.tsx
13307
13394
  var import_material14 = require("@mui/material");
13308
- var import_react50 = require("react");
13395
+ var import_react51 = require("react");
13309
13396
 
13310
13397
  // src/utils/iam-utils.ts
13311
13398
  function determinePermissionStatus(payload) {
@@ -13539,7 +13626,7 @@ var import_material13 = require("@mui/material");
13539
13626
  // src/components/event-details/event-detail.tsx
13540
13627
  var import_icons_material7 = require("@mui/icons-material");
13541
13628
  var import_material11 = require("@mui/material");
13542
- var import_react48 = require("react");
13629
+ var import_react49 = require("react");
13543
13630
 
13544
13631
  // src/components/status-icon.tsx
13545
13632
  var import_icons_material4 = require("@mui/icons-material");
@@ -13690,7 +13777,7 @@ var IAMEventDetail = ({ event }) => {
13690
13777
  // src/components/event-details/iam-permission-detail.tsx
13691
13778
  var import_icons_material6 = require("@mui/icons-material");
13692
13779
  var import_material10 = require("@mui/material");
13693
- var import_react47 = require("react");
13780
+ var import_react48 = require("react");
13694
13781
  var import_jsx_runtime132 = require("react/jsx-runtime");
13695
13782
  var getChipColors = (status) => {
13696
13783
  const isAllowed = status === "explicitly_allowed" || status === "implicitly_allowed";
@@ -13700,8 +13787,8 @@ var getChipColors = (status) => {
13700
13787
  };
13701
13788
  };
13702
13789
  var IAMPermissionItem = ({ event }) => {
13703
- const [isOpen, setIsOpen] = (0, import_react47.useState)(false);
13704
- const parsedData = (0, import_react47.useMemo)(() => {
13790
+ const [isOpen, setIsOpen] = (0, import_react48.useState)(false);
13791
+ const parsedData = (0, import_react48.useMemo)(() => {
13705
13792
  const payloadString = event.attributes?.payload;
13706
13793
  if (!payloadString) {
13707
13794
  return;
@@ -13771,15 +13858,15 @@ var DetailRow2 = ({ content, label }) => /* @__PURE__ */ (0, import_jsx_runtime1
13771
13858
  ) : content })
13772
13859
  ] });
13773
13860
  var EventMessage = ({ event }) => {
13774
- const [isOpen, setIsOpen] = (0, import_react48.useState)(false);
13775
- const [isOverflowing, setIsOverflowing] = (0, import_react48.useState)(false);
13776
- const textReference = (0, import_react48.useRef)(null);
13777
- const parsedMessage = (0, import_react48.useMemo)(() => parseEventMessage(event), [event]);
13778
- const isIAMPolicyEvent = (0, import_react48.useMemo)(
13861
+ const [isOpen, setIsOpen] = (0, import_react49.useState)(false);
13862
+ const [isOverflowing, setIsOverflowing] = (0, import_react49.useState)(false);
13863
+ const textReference = (0, import_react49.useRef)(null);
13864
+ const parsedMessage = (0, import_react49.useMemo)(() => parseEventMessage(event), [event]);
13865
+ const isIAMPolicyEvent = (0, import_react49.useMemo)(
13779
13866
  () => event.event_type === "iam.policy_evaluation" && event.attributes?.payload && typeof event.attributes.payload === "string",
13780
13867
  [event]
13781
13868
  );
13782
- (0, import_react48.useEffect)(() => {
13869
+ (0, import_react49.useEffect)(() => {
13783
13870
  const checkOverflow = () => {
13784
13871
  const element = textReference.current;
13785
13872
  if (element) {
@@ -13792,11 +13879,11 @@ var EventMessage = ({ event }) => {
13792
13879
  window.removeEventListener("resize", checkOverflow);
13793
13880
  };
13794
13881
  }, [parsedMessage.headline]);
13795
- const hasAdditionalContent = (0, import_react48.useMemo)(
13882
+ const hasAdditionalContent = (0, import_react49.useMemo)(
13796
13883
  () => parsedMessage.message || parsedMessage.details || isIAMPolicyEvent,
13797
13884
  [parsedMessage.message, parsedMessage.details, isIAMPolicyEvent]
13798
13885
  );
13799
- const shouldShowToggle = (0, import_react48.useMemo)(
13886
+ const shouldShowToggle = (0, import_react49.useMemo)(
13800
13887
  () => isOverflowing || hasAdditionalContent,
13801
13888
  [isOverflowing, hasAdditionalContent]
13802
13889
  );
@@ -13938,10 +14025,10 @@ var EventDetail = ({
13938
14025
  // src/components/event-details/toggle-section.tsx
13939
14026
  var import_icons_material8 = require("@mui/icons-material");
13940
14027
  var import_material12 = require("@mui/material");
13941
- var import_react49 = require("react");
14028
+ var import_react50 = require("react");
13942
14029
  var import_jsx_runtime134 = require("react/jsx-runtime");
13943
14030
  var ToggleSection = ({ children, headline, initialOpen = true }) => {
13944
- const [isOpen, setIsOpen] = (0, import_react49.useState)(initialOpen);
14031
+ const [isOpen, setIsOpen] = (0, import_react50.useState)(initialOpen);
13945
14032
  return /* @__PURE__ */ (0, import_jsx_runtime134.jsxs)(import_material12.Box, { sx: { mt: 4 }, children: [
13946
14033
  /* @__PURE__ */ (0, import_jsx_runtime134.jsx)(
13947
14034
  import_material12.Box,
@@ -14031,7 +14118,7 @@ var ATTRIBUTE_NAME_TRANSFORMATIONS = {
14031
14118
  "localstack.aws.service.response": "Response"
14032
14119
  };
14033
14120
  var EventDetails = ({ onClose, selectedEvent }) => {
14034
- const attributes = (0, import_react50.useMemo)(() => {
14121
+ const attributes = (0, import_react51.useMemo)(() => {
14035
14122
  const attributes2 = Object.entries(selectedEvent?.attributes ?? {});
14036
14123
  return attributes2.filter(([key]) => !ATTRIBUTES_TO_EXCLUDE.has(key));
14037
14124
  }, [selectedEvent?.attributes]);
@@ -14140,22 +14227,22 @@ function renderKeyValue(key, value) {
14140
14227
  // src/components/trace-graph/trace-graph.tsx
14141
14228
  var import_base = require("@xyflow/react/dist/base.css");
14142
14229
  var import_material18 = require("@mui/material");
14143
- var import_react57 = require("@xyflow/react");
14144
- var import_react58 = require("react");
14230
+ var import_react58 = require("@xyflow/react");
14231
+ var import_react59 = require("react");
14145
14232
 
14146
14233
  // src/components/trace-graph/service-node.tsx
14147
14234
  var import_material16 = require("@mui/material");
14148
14235
  var import_style = require("@xyflow/react/dist/style.css");
14149
- var import_react52 = require("@xyflow/react");
14150
- var import_react53 = require("react");
14236
+ var import_react53 = require("@xyflow/react");
14237
+ var import_react54 = require("react");
14151
14238
 
14152
14239
  // src/components/trace-graph/problem-indicator.tsx
14153
14240
  var import_icons_material9 = require("@mui/icons-material");
14154
14241
  var import_material15 = require("@mui/material");
14155
- var import_react51 = require("react");
14242
+ var import_react52 = require("react");
14156
14243
  var import_jsx_runtime137 = require("react/jsx-runtime");
14157
14244
  var ProblemIndicator = ({ error }) => {
14158
- const icon = (0, import_react51.useMemo)(() => {
14245
+ const icon = (0, import_react52.useMemo)(() => {
14159
14246
  switch (error.level) {
14160
14247
  case "error": {
14161
14248
  return /* @__PURE__ */ (0, import_jsx_runtime137.jsx)(import_icons_material9.Error, { sx: { color: "#d32f2f", fontSize: "14px" } });
@@ -14168,7 +14255,7 @@ var ProblemIndicator = ({ error }) => {
14168
14255
  }
14169
14256
  }
14170
14257
  }, [error.level]);
14171
- const color2 = (0, import_react51.useMemo)(() => {
14258
+ const color2 = (0, import_react52.useMemo)(() => {
14172
14259
  switch (error.level) {
14173
14260
  case "error": {
14174
14261
  return "#d32f2f";
@@ -14207,7 +14294,7 @@ var handleStyle = {
14207
14294
  borderColor: "lightgray",
14208
14295
  opacity: 0
14209
14296
  };
14210
- var ServiceNode = (0, import_react53.memo)(({ data, selected }) => {
14297
+ var ServiceNode = (0, import_react54.memo)(({ data, selected }) => {
14211
14298
  const hasErrors = (data.event.errors && data.event.errors.length > 0) ?? false;
14212
14299
  return /* @__PURE__ */ (0, import_jsx_runtime138.jsxs)(import_material16.Box, { sx: { maxWidth: 200 }, children: [
14213
14300
  /* @__PURE__ */ (0, import_jsx_runtime138.jsxs)(
@@ -14231,8 +14318,8 @@ var ServiceNode = (0, import_react53.memo)(({ data, selected }) => {
14231
14318
  },
14232
14319
  tabIndex: 0,
14233
14320
  children: [
14234
- /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_react52.Handle, { position: import_react52.Position.Left, style: handleStyle, type: "target" }),
14235
- /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_react52.Handle, { position: import_react52.Position.Right, style: handleStyle, type: "source" }),
14321
+ /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_react53.Handle, { position: import_react53.Position.Left, style: handleStyle, type: "target" }),
14322
+ /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(import_react53.Handle, { position: import_react53.Position.Right, style: handleStyle, type: "source" }),
14236
14323
  /* @__PURE__ */ (0, import_jsx_runtime138.jsx)(
14237
14324
  ServiceCell,
14238
14325
  {
@@ -14292,7 +14379,7 @@ var ServiceNode = (0, import_react53.memo)(({ data, selected }) => {
14292
14379
 
14293
14380
  // src/components/trace-graph/utils.ts
14294
14381
  var import_dagre = __toESM(require("@dagrejs/dagre"), 1);
14295
- var import_react54 = require("@xyflow/react");
14382
+ var import_react55 = require("@xyflow/react");
14296
14383
  var generateNodesAndEdges = (event, parentId) => {
14297
14384
  const nodes = [];
14298
14385
  const edges = [];
@@ -14308,8 +14395,8 @@ var generateNodesAndEdges = (event, parentId) => {
14308
14395
  id: event.span_id,
14309
14396
  position: { x: 0, y: 0 },
14310
14397
  // Will be set by layout
14311
- sourcePosition: import_react54.Position.Right,
14312
- targetPosition: import_react54.Position.Left,
14398
+ sourcePosition: import_react55.Position.Right,
14399
+ targetPosition: import_react55.Position.Left,
14313
14400
  type: "service"
14314
14401
  });
14315
14402
  if (parentId) {
@@ -14319,7 +14406,7 @@ var generateNodesAndEdges = (event, parentId) => {
14319
14406
  markerEnd: {
14320
14407
  color: "lightgray",
14321
14408
  height: 16,
14322
- type: import_react54.MarkerType.Arrow,
14409
+ type: import_react55.MarkerType.Arrow,
14323
14410
  width: 16
14324
14411
  },
14325
14412
  source: parentId,
@@ -14372,8 +14459,8 @@ var getLayoutedNodesAndEdges = (inputNodes, inputEdges) => {
14372
14459
  // src/components/trace-graph/xyflow/controls.tsx
14373
14460
  var import_icons_material10 = require("@mui/icons-material");
14374
14461
  var import_material17 = require("@mui/material");
14375
- var import_react55 = require("@xyflow/react");
14376
- var import_react56 = require("react");
14462
+ var import_react56 = require("@xyflow/react");
14463
+ var import_react57 = require("react");
14377
14464
 
14378
14465
  // node_modules/zustand/esm/shallow.mjs
14379
14466
  function shallow$1(objA, objB) {
@@ -14420,9 +14507,9 @@ var selector = (s) => ({
14420
14507
  maxZoomReached: s.transform[2] >= s.maxZoom,
14421
14508
  minZoomReached: s.transform[2] <= s.minZoom
14422
14509
  });
14423
- var Controls = (0, import_react56.memo)(() => {
14424
- const { maxZoomReached, minZoomReached } = (0, import_react55.useStore)(selector, shallow$1);
14425
- const { fitView, zoomIn, zoomOut } = (0, import_react55.useReactFlow)();
14510
+ var Controls = (0, import_react57.memo)(() => {
14511
+ const { maxZoomReached, minZoomReached } = (0, import_react56.useStore)(selector, shallow$1);
14512
+ const { fitView, zoomIn, zoomOut } = (0, import_react56.useReactFlow)();
14426
14513
  const onZoomInHandler = () => {
14427
14514
  void zoomIn();
14428
14515
  };
@@ -14491,9 +14578,9 @@ var TraceGraph = ({
14491
14578
  onRefresh,
14492
14579
  spans
14493
14580
  }) => {
14494
- const [nodes, setNodes, onNodesChange] = (0, import_react57.useNodesState)([]);
14495
- const [edges, setEdges] = (0, import_react58.useState)([]);
14496
- (0, import_react58.useEffect)(() => {
14581
+ const [nodes, setNodes, onNodesChange] = (0, import_react58.useNodesState)([]);
14582
+ const [edges, setEdges] = (0, import_react59.useState)([]);
14583
+ (0, import_react59.useEffect)(() => {
14497
14584
  const spansMap = /* @__PURE__ */ new Map();
14498
14585
  const rootSpans = [];
14499
14586
  for (const span of spans.data ?? []) {
@@ -14552,7 +14639,7 @@ var TraceGraph = ({
14552
14639
  }
14553
14640
  ),
14554
14641
  /* @__PURE__ */ (0, import_jsx_runtime140.jsxs)(
14555
- import_react57.ReactFlow,
14642
+ import_react58.ReactFlow,
14556
14643
  {
14557
14644
  "data-testid": "trace-graph",
14558
14645
  edges,
@@ -14571,7 +14658,7 @@ var TraceGraph = ({
14571
14658
  children: [
14572
14659
  /* @__PURE__ */ (0, import_jsx_runtime140.jsx)(Controls, {}),
14573
14660
  /* @__PURE__ */ (0, import_jsx_runtime140.jsx)(
14574
- import_react57.Background,
14661
+ import_react58.Background,
14575
14662
  {
14576
14663
  bgColor: theme.palette.background.paper,
14577
14664
  color: theme.palette.text.disabled
@@ -14676,7 +14763,7 @@ var TraceGraphView = ({
14676
14763
  height: "100%",
14677
14764
  overflow: "auto"
14678
14765
  },
14679
- children: traceId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime141.jsx)(import_react59.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime141.jsx)(
14766
+ children: traceId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime141.jsx)(import_react60.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime141.jsx)(
14680
14767
  TraceGraph,
14681
14768
  {
14682
14769
  initialFocusEventId: spanId,
@@ -14737,10 +14824,10 @@ async function fetchConnectedTraces(api, traceIds, allSpans = /* @__PURE__ */ ne
14737
14824
  }
14738
14825
  var TraceGraphPage = ({ onClose, spanId, traceId }) => {
14739
14826
  const api = useAppInspectorApi();
14740
- const [spans, setSpans] = (0, import_react60.useState)();
14741
- const [loading, setLoading] = (0, import_react60.useState)(false);
14742
- const [fetchError, setFetchError] = (0, import_react60.useState)();
14743
- const fetchSpans = (0, import_react60.useCallback)(async () => {
14827
+ const [spans, setSpans] = (0, import_react61.useState)();
14828
+ const [loading, setLoading] = (0, import_react61.useState)(false);
14829
+ const [fetchError, setFetchError] = (0, import_react61.useState)();
14830
+ const fetchSpans = (0, import_react61.useCallback)(async () => {
14744
14831
  setLoading(true);
14745
14832
  try {
14746
14833
  const spans2 = await fetchConnectedTraces(api, [traceId]);
@@ -14753,28 +14840,28 @@ var TraceGraphPage = ({ onClose, spanId, traceId }) => {
14753
14840
  setLoading(false);
14754
14841
  }
14755
14842
  }, [api, traceId]);
14756
- (0, import_react60.useEffect)(() => {
14843
+ (0, import_react61.useEffect)(() => {
14757
14844
  void fetchSpans();
14758
14845
  }, [fetchSpans]);
14759
- const [open, setOpen] = (0, import_react60.useState)(true);
14760
- const [selectedEvent, setSelectedEvent] = (0, import_react60.useState)(() => spans?.find((span) => span.span_id === spanId));
14761
- const spansReference = (0, import_react60.useRef)();
14762
- (0, import_react60.useEffect)(() => {
14846
+ const [open, setOpen] = (0, import_react61.useState)(true);
14847
+ const [selectedEvent, setSelectedEvent] = (0, import_react61.useState)(() => spans?.find((span) => span.span_id === spanId));
14848
+ const spansReference = (0, import_react61.useRef)();
14849
+ (0, import_react61.useEffect)(() => {
14763
14850
  if (!spansReference.current && spans) {
14764
14851
  setSelectedEvent(spans.find((span) => span.span_id === spanId));
14765
14852
  spansReference.current = spans;
14766
14853
  }
14767
14854
  }, [spans, setSelectedEvent, spanId]);
14768
14855
  const { checkStatus, error: statusError, status } = useStatus();
14769
- const handleEventSelect = (0, import_react60.useCallback)((spanId2) => {
14856
+ const handleEventSelect = (0, import_react61.useCallback)((spanId2) => {
14770
14857
  const span = spans?.find((s) => s.span_id === spanId2);
14771
14858
  setSelectedEvent(span);
14772
14859
  setOpen(true);
14773
14860
  }, [spans]);
14774
- const handleRetry = (0, import_react60.useCallback)(() => {
14861
+ const handleRetry = (0, import_react61.useCallback)(() => {
14775
14862
  void checkStatus();
14776
14863
  }, [checkStatus]);
14777
- const navigateToSpansList = (0, import_react60.useCallback)(() => {
14864
+ const navigateToSpansList = (0, import_react61.useCallback)(() => {
14778
14865
  onClose?.();
14779
14866
  }, [onClose]);
14780
14867
  return /* @__PURE__ */ (0, import_jsx_runtime141.jsx)(
@@ -14819,16 +14906,17 @@ var SpansListPage = () => {
14819
14906
  status,
14820
14907
  statusError
14821
14908
  } = useSpans();
14822
- const clearSpansSync = (0, import_react61.useCallback)(() => {
14909
+ const clearSpansSync = (0, import_react62.useCallback)(() => {
14823
14910
  void clearSpans();
14824
14911
  }, [clearSpans]);
14825
- const [selectedTraceId, setSelectedTraceId] = (0, import_react61.useState)();
14826
- const [selectedSpanId, setSelectedSpanId] = (0, import_react61.useState)();
14827
- const navigateToSpan = (0, import_react61.useCallback)((span) => {
14912
+ const [order2, setOrder] = useLocalStorage("spans-order", "oldest_first");
14913
+ const [selectedTraceId, setSelectedTraceId] = (0, import_react62.useState)();
14914
+ const [selectedSpanId, setSelectedSpanId] = (0, import_react62.useState)();
14915
+ const navigateToSpan = (0, import_react62.useCallback)((span) => {
14828
14916
  setSelectedTraceId(span.trace_id);
14829
14917
  setSelectedSpanId(span.span_id);
14830
14918
  }, []);
14831
- const handleRetry = (0, import_react61.useCallback)(() => {
14919
+ const handleRetry = (0, import_react62.useCallback)(() => {
14832
14920
  void checkStatus();
14833
14921
  }, [checkStatus]);
14834
14922
  const shouldShowStatusMessage = Boolean(statusError) || status?.status === "DISABLED";
@@ -14867,7 +14955,9 @@ var SpansListPage = () => {
14867
14955
  onClearSpans: clearSpansSync,
14868
14956
  onFetchBackward: fetchBackward,
14869
14957
  onFetchForward: fetchForward,
14958
+ onOrderChange: setOrder,
14870
14959
  onSpanClick: navigateToSpan,
14960
+ order: order2,
14871
14961
  refetching,
14872
14962
  spans
14873
14963
  }