@localstack/appinspector-ui 1.0.133 → 1.0.135

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
@@ -15549,14 +15549,9 @@ var newSpanBackgroundColor = {
15549
15549
  var LABEL_BEGINNING_OF_STREAM = "This is the beginning of the stream";
15550
15550
  var LABEL_END_OF_STREAM = "This is the end of the stream";
15551
15551
  var LABEL_NO_SPANS = "There are no operations";
15552
- var LABEL_LOAD_OLDER = "Load older operations";
15553
- var LABEL_LOAD_NEWER = "Load newer operations";
15554
15552
  var STICK_TO_EDGE_THRESHOLD_PX = 4;
15555
15553
  var StreamBoundaryRow = ({ colSpan, label }) => /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)("span", { children: label }) }) });
15556
- var LoadSpansRow = ({ colSpan, fetching, label, onFetch }) => /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsxs)(import_material7.TableCell, { colSpan, sx: { textAlign: "center" }, children: [
15557
- !fetching && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.Button, { onClick: onFetch, sx: { my: 1 }, children: label }),
15558
- fetching && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.CircularProgress, { size: 24, sx: { m: 2 } })
15559
- ] }) });
15554
+ var LoadingRow = ({ colSpan }) => /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan, sx: { textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.CircularProgress, { size: 24, sx: { m: 2 } }) }) });
15560
15555
  var SpansDataGridRow = (0, import_react38.memo)(
15561
15556
  ({ isNew, onSpanClick, row }) => {
15562
15557
  const theme = (0, import_material7.useTheme)();
@@ -15623,14 +15618,10 @@ var SpansDataGrid = ({
15623
15618
  hasMoreForward,
15624
15619
  licenseLimit,
15625
15620
  onClearSpans,
15626
- onFetchBackward,
15627
- onFetchForward,
15628
15621
  onOrderChange,
15629
15622
  onSpanClick,
15630
- onToggleStream,
15631
15623
  order: order2,
15632
15624
  spans,
15633
- streamPaused,
15634
15625
  systemLimit,
15635
15626
  totalCount,
15636
15627
  warningCount
@@ -15798,21 +15789,6 @@ var SpansDataGrid = ({
15798
15789
  ) })
15799
15790
  ] }),
15800
15791
  /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.Box, { sx: { flexGrow: 1 } }),
15801
- /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(
15802
- import_material7.FormControlLabel,
15803
- {
15804
- control: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(
15805
- import_material7.Button,
15806
- {
15807
- onClick: onToggleStream,
15808
- startIcon: streamPaused ? /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_icons_material3.PlayArrowOutlined, {}) : /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_icons_material3.PauseOutlined, {}),
15809
- variant: "text",
15810
- children: streamPaused ? "Resume Stream" : "Pause Stream"
15811
- }
15812
- ),
15813
- label: ""
15814
- }
15815
- ),
15816
15792
  /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(
15817
15793
  import_material7.FormControlLabel,
15818
15794
  {
@@ -15875,7 +15851,7 @@ var SpansDataGrid = ({
15875
15851
  (spans === void 0 || clearingSpans) && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan: columnCount, sx: { fontStyle: "italic", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.CircularProgress, { size: 48, sx: { m: 4 } }) }) }),
15876
15852
  !clearingSpans && spans?.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_NO_SPANS }),
15877
15853
  !clearingSpans && order2 === "newest_first" && /* @__PURE__ */ (0, import_jsx_runtime127.jsxs)(import_jsx_runtime127.Fragment, { children: [
15878
- hasRows && hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingForward, label: LABEL_LOAD_NEWER, onFetch: onFetchForward }),
15854
+ hasRows && hasMoreForward && fetchingForward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadingRow, { colSpan: columnCount }),
15879
15855
  hasRows && !hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_END_OF_STREAM }),
15880
15856
  hasRows && paddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan: columnCount, sx: { border: 0, height: paddingTop, p: 0 } }) }),
15881
15857
  hasRows && virtualItems.map((virtualItem) => {
@@ -15884,12 +15860,12 @@ var SpansDataGrid = ({
15884
15860
  return /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(SpansDataGridRow, { isNew, onSpanClick, row }, row.original.span_id);
15885
15861
  }),
15886
15862
  hasRows && paddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan: columnCount, sx: { border: 0, height: paddingBottom, p: 0 } }) }),
15887
- hasRows && hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingBackward, label: LABEL_LOAD_OLDER, onFetch: onFetchBackward }),
15863
+ hasRows && hasMoreBackward && fetchingBackward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadingRow, { colSpan: columnCount }),
15888
15864
  hasRows && !hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_BEGINNING_OF_STREAM })
15889
15865
  ] }),
15890
15866
  !clearingSpans && order2 === "oldest_first" && /* @__PURE__ */ (0, import_jsx_runtime127.jsxs)(import_jsx_runtime127.Fragment, { children: [
15891
15867
  hasRows && !hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_BEGINNING_OF_STREAM }),
15892
- hasRows && hasMoreBackward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingBackward, label: LABEL_LOAD_OLDER, onFetch: onFetchBackward }),
15868
+ hasRows && hasMoreBackward && fetchingBackward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadingRow, { colSpan: columnCount }),
15893
15869
  hasRows && paddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan: columnCount, sx: { border: 0, height: paddingTop, p: 0 } }) }),
15894
15870
  hasRows && virtualItems.map((virtualItem) => {
15895
15871
  const row = displayRows[virtualItem.index];
@@ -15897,7 +15873,7 @@ var SpansDataGrid = ({
15897
15873
  return /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(SpansDataGridRow, { isNew, onSpanClick, row }, row.original.span_id);
15898
15874
  }),
15899
15875
  hasRows && paddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(import_material7.TableCell, { colSpan: columnCount, sx: { border: 0, height: paddingBottom, p: 0 } }) }),
15900
- hasRows && hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadSpansRow, { colSpan: columnCount, fetching: fetchingForward, label: LABEL_LOAD_NEWER, onFetch: onFetchForward }),
15876
+ hasRows && hasMoreForward && fetchingForward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(LoadingRow, { colSpan: columnCount }),
15901
15877
  hasRows && !hasMoreForward && /* @__PURE__ */ (0, import_jsx_runtime127.jsx)(StreamBoundaryRow, { colSpan: columnCount, label: LABEL_END_OF_STREAM })
15902
15878
  ] })
15903
15879
  ] })
@@ -15936,14 +15912,10 @@ var SpansList = (props) => {
15936
15912
  hasMoreForward: props.hasMoreForward,
15937
15913
  licenseLimit: props.licenseLimit,
15938
15914
  onClearSpans: props.onClearSpans,
15939
- onFetchBackward: props.onFetchBackward,
15940
- onFetchForward: props.onFetchForward,
15941
15915
  onOrderChange: props.onOrderChange,
15942
15916
  onSpanClick: props.onSpanClick,
15943
- onToggleStream: props.onToggleStream,
15944
15917
  order: props.order,
15945
15918
  spans: props.spans,
15946
- streamPaused: props.streamPaused,
15947
15919
  systemLimit: props.systemLimit,
15948
15920
  totalCount: props.totalCount,
15949
15921
  warningCount: props.warningCount
@@ -15958,11 +15930,10 @@ var import_material9 = require("@mui/material");
15958
15930
  var import_react39 = require("react");
15959
15931
  var import_jsx_runtime129 = require("react/jsx-runtime");
15960
15932
  var StatusMessage = ({
15961
- error,
15962
15933
  localstackVersion,
15963
15934
  onEnable,
15964
15935
  onRetry,
15965
- status
15936
+ phase
15966
15937
  }) => {
15967
15938
  const [enabling, setEnabling] = (0, import_react39.useState)(false);
15968
15939
  const [enableError, setEnableError] = (0, import_react39.useState)();
@@ -15978,8 +15949,23 @@ var StatusMessage = ({
15978
15949
  setEnabling(false);
15979
15950
  }
15980
15951
  };
15981
- const isBelowMinimum = localstackVersion !== void 0 && checkEmulatorVersion(localstackVersion) === "below-minimum";
15982
- if (isBelowMinimum || error instanceof AppInspectorNotFoundError) {
15952
+ if (phase === "CHECKING_STATUS" || phase === "CONNECTING_WS") {
15953
+ return /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
15954
+ import_material9.Box,
15955
+ {
15956
+ sx: {
15957
+ alignItems: "center",
15958
+ display: "flex",
15959
+ flexDirection: "column",
15960
+ gap: 2,
15961
+ justifyContent: "center",
15962
+ p: 4
15963
+ },
15964
+ children: /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.CircularProgress, { size: 32 })
15965
+ }
15966
+ );
15967
+ }
15968
+ if (phase === "INCOMPATIBLE") {
15983
15969
  return /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
15984
15970
  import_material9.Box,
15985
15971
  {
@@ -15999,7 +15985,7 @@ var StatusMessage = ({
15999
15985
  sx: { maxWidth: 600, width: "100%" },
16000
15986
  children: [
16001
15987
  /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.AlertTitle, { sx: { fontWeight: "bold" }, children: "App Inspector Not Available" }),
16002
- /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Typography, { sx: { mb: 2 }, variant: "body2", children: isBelowMinimum ? `App Inspector requires LocalStack ${MINIMUM_EMULATOR_VERSION} or later. You are running version ${localstackVersion}. Please update LocalStack.` : `App Inspector requires LocalStack ${MINIMUM_EMULATOR_VERSION} or later. Please update LocalStack.` }),
15988
+ /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Typography, { sx: { mb: 2 }, variant: "body2", children: localstackVersion === void 0 ? `App Inspector requires LocalStack ${MINIMUM_EMULATOR_VERSION} or later. Please update LocalStack.` : `App Inspector requires LocalStack ${MINIMUM_EMULATOR_VERSION} or later. You are running version ${localstackVersion}. Please update LocalStack.` }),
16003
15989
  /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Typography, { sx: { mb: 1 }, variant: "body2", children: /* @__PURE__ */ (0, import_jsx_runtime129.jsx)("strong", { children: "Update LocalStack:" }) }),
16004
15990
  /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16005
15991
  import_material9.Box,
@@ -16014,11 +16000,10 @@ var StatusMessage = ({
16014
16000
  children: "localstack update docker-images"
16015
16001
  }
16016
16002
  ),
16017
- /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Box, { sx: { display: "flex", gap: 1, mt: 2 }, children: onRetry && /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16003
+ onRetry && /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Box, { sx: { display: "flex", gap: 1, mt: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16018
16004
  import_material9.Button,
16019
16005
  {
16020
16006
  "aria-label": "Check App Inspector status again",
16021
- disabled: enabling,
16022
16007
  onClick: onRetry,
16023
16008
  variant: "outlined",
16024
16009
  children: "Check Again"
@@ -16030,7 +16015,7 @@ var StatusMessage = ({
16030
16015
  }
16031
16016
  );
16032
16017
  }
16033
- if (error instanceof ConnectionError) {
16018
+ if (phase === "UNREACHABLE") {
16034
16019
  return /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16035
16020
  import_material9.Box,
16036
16021
  {
@@ -16092,7 +16077,7 @@ var StatusMessage = ({
16092
16077
  }
16093
16078
  );
16094
16079
  }
16095
- if (error instanceof AppInspectorDisabledError || status?.status === "DISABLED") {
16080
+ if (phase === "DISABLED") {
16096
16081
  return /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16097
16082
  import_material9.Box,
16098
16083
  {
@@ -16147,102 +16132,99 @@ var StatusMessage = ({
16147
16132
  }
16148
16133
  );
16149
16134
  }
16150
- if (error) {
16151
- return /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16152
- import_material9.Box,
16153
- {
16154
- sx: {
16155
- alignItems: "center",
16156
- display: "flex",
16157
- flexDirection: "column",
16158
- gap: 2,
16159
- justifyContent: "center",
16160
- p: 4
16161
- },
16162
- children: /* @__PURE__ */ (0, import_jsx_runtime129.jsxs)(
16163
- import_material9.Alert,
16164
- {
16165
- icon: /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_icons_material4.ErrorOutline, { fontSize: "large" }),
16166
- severity: "error",
16167
- sx: { maxWidth: 600, width: "100%" },
16168
- children: [
16169
- /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.AlertTitle, { sx: { fontWeight: "bold" }, children: "Error" }),
16170
- /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Typography, { sx: { mb: 2 }, variant: "body2", children: error.message }),
16171
- onRetry && /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_material9.Box, { sx: { display: "flex", justifyContent: "flex-start", mt: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(
16172
- import_material9.Button,
16173
- {
16174
- "aria-label": "Retry operation",
16175
- onClick: onRetry,
16176
- variant: "outlined",
16177
- children: "Retry"
16178
- }
16179
- ) })
16180
- ]
16181
- }
16182
- )
16183
- }
16184
- );
16185
- }
16186
16135
  return /* @__PURE__ */ (0, import_jsx_runtime129.jsx)(import_jsx_runtime129.Fragment, {});
16187
16136
  };
16188
16137
 
16189
16138
  // src/hooks/status-provider.tsx
16190
16139
  var import_react41 = require("react");
16191
16140
 
16192
- // src/hooks/use-status.tsx
16141
+ // src/hooks/use-connection-state-machine.ts
16193
16142
  var import_react40 = require("react");
16194
- var useStatus = () => {
16143
+ var POLL_INTERVAL_MS = 5e3;
16144
+ function useConnectionStateMachine() {
16195
16145
  const api = useAppInspectorApi();
16146
+ const [phase, setPhase] = (0, import_react40.useState)("CHECKING_STATUS");
16196
16147
  const [checking, setChecking] = (0, import_react40.useState)(true);
16197
16148
  const [status, setStatus] = (0, import_react40.useState)();
16198
- const [error, setError] = (0, import_react40.useState)();
16199
- const hasFetchedReference = (0, import_react40.useRef)(false);
16200
- const abortControllerReference = (0, import_react40.useRef)(null);
16201
- const checkStatus = (0, import_react40.useCallback)(async () => {
16202
- if (abortControllerReference.current !== null) {
16203
- abortControllerReference.current.abort();
16149
+ const [statusError, setStatusError] = (0, import_react40.useState)();
16150
+ const abortControllerRef = (0, import_react40.useRef)(null);
16151
+ const dispatchStatus = (0, import_react40.useCallback)((result, error) => {
16152
+ if (result === void 0) {
16153
+ setStatus(void 0);
16154
+ setStatusError(error);
16155
+ setPhase(error instanceof AppInspectorNotFoundError ? "INCOMPATIBLE" : "UNREACHABLE");
16156
+ return;
16157
+ }
16158
+ setStatus(result);
16159
+ setStatusError(void 0);
16160
+ if (checkEmulatorVersion(result.localstackVersion) === "below-minimum") {
16161
+ setPhase("INCOMPATIBLE");
16162
+ return;
16163
+ }
16164
+ setPhase(result.status === "ENABLED" ? "CONNECTING_WS" : "DISABLED");
16165
+ }, []);
16166
+ const runCheck = (0, import_react40.useCallback)(async () => {
16167
+ if (abortControllerRef.current !== null) {
16168
+ abortControllerRef.current.abort();
16204
16169
  }
16205
16170
  const abortController = new AbortController();
16206
- abortControllerReference.current = abortController;
16171
+ abortControllerRef.current = abortController;
16207
16172
  setChecking(true);
16208
16173
  try {
16209
- const response = await api.getStatus();
16174
+ const result = await api.getStatus();
16210
16175
  if (!abortController.signal.aborted) {
16211
- setStatus(response);
16212
- setError(void 0);
16176
+ dispatchStatus(result);
16213
16177
  }
16214
- } catch (error_) {
16178
+ } catch (error) {
16215
16179
  if (!abortController.signal.aborted) {
16216
- setError(error_ instanceof Error ? error_ : new Error("Unknown error"));
16217
- setStatus(void 0);
16180
+ dispatchStatus(void 0, error instanceof Error ? error : new Error("Unknown error"));
16218
16181
  }
16219
16182
  } finally {
16220
16183
  if (!abortController.signal.aborted) {
16221
16184
  setChecking(false);
16222
16185
  }
16223
16186
  }
16224
- }, [api]);
16187
+ }, [api, dispatchStatus]);
16225
16188
  (0, import_react40.useEffect)(() => {
16226
- if (!hasFetchedReference.current) {
16227
- hasFetchedReference.current = true;
16228
- void checkStatus();
16229
- }
16230
- }, [checkStatus]);
16231
- return { checking, checkStatus, error, status };
16232
- };
16189
+ void runCheck();
16190
+ }, [runCheck]);
16191
+ (0, import_react40.useEffect)(() => {
16192
+ if (phase !== "UNREACHABLE" && phase !== "DISABLED") return;
16193
+ const intervalId = globalThis.setInterval(() => {
16194
+ void runCheck();
16195
+ }, POLL_INTERVAL_MS);
16196
+ return () => {
16197
+ globalThis.clearInterval(intervalId);
16198
+ };
16199
+ }, [phase, runCheck]);
16200
+ const checkStatus = (0, import_react40.useCallback)(() => {
16201
+ void runCheck();
16202
+ }, [runCheck]);
16203
+ const onWsOpen = (0, import_react40.useCallback)(() => {
16204
+ setPhase("LIVE");
16205
+ }, []);
16206
+ const onWsClose = (0, import_react40.useCallback)(() => {
16207
+ setPhase("CHECKING_STATUS");
16208
+ void runCheck();
16209
+ }, [runCheck]);
16210
+ const wsEnabled = phase === "CONNECTING_WS" || phase === "LIVE";
16211
+ return {
16212
+ checking,
16213
+ checkStatus,
16214
+ onWsClose,
16215
+ onWsOpen,
16216
+ phase,
16217
+ status,
16218
+ statusError,
16219
+ wsEnabled
16220
+ };
16221
+ }
16233
16222
 
16234
16223
  // src/hooks/status-provider.tsx
16235
16224
  var import_jsx_runtime130 = require("react/jsx-runtime");
16236
16225
  var AppInspectorStatusContext = (0, import_react41.createContext)(void 0);
16237
16226
  var StatusProvider = ({ children }) => {
16238
- const { checking, checkStatus, error, status } = useStatus();
16239
- const reportDisabled = (0, import_react41.useCallback)(() => {
16240
- void checkStatus();
16241
- }, [checkStatus]);
16242
- const value = (0, import_react41.useMemo)(
16243
- () => ({ checking, checkStatus, reportDisabled, status, statusError: error }),
16244
- [checking, checkStatus, reportDisabled, status, error]
16245
- );
16227
+ const value = useConnectionStateMachine();
16246
16228
  return /* @__PURE__ */ (0, import_jsx_runtime130.jsx)(AppInspectorStatusContext.Provider, { value, children });
16247
16229
  };
16248
16230
  var useAppInspectorStatus = () => {
@@ -18710,14 +18692,21 @@ var AppInspectorContextProvider = (props) => {
18710
18692
 
18711
18693
  // src/hooks/use-spans-ws.tsx
18712
18694
  function useSpansWebSocket(options) {
18713
- const { onMessage } = options;
18695
+ const { enabled, onClose, onMessage, onOpen } = options;
18714
18696
  const onMessageRef = (0, import_react46.useRef)(onMessage);
18697
+ const onOpenRef = (0, import_react46.useRef)(onOpen);
18698
+ const onCloseRef = (0, import_react46.useRef)(onClose);
18715
18699
  (0, import_react46.useEffect)(() => {
18716
18700
  onMessageRef.current = onMessage;
18717
18701
  }, [onMessage]);
18702
+ (0, import_react46.useEffect)(() => {
18703
+ onOpenRef.current = onOpen;
18704
+ }, [onOpen]);
18705
+ (0, import_react46.useEffect)(() => {
18706
+ onCloseRef.current = onClose;
18707
+ }, [onClose]);
18718
18708
  const [connected, setConnected] = (0, import_react46.useState)(false);
18719
18709
  const wsRef = (0, import_react46.useRef)(void 0);
18720
- const reconnectRef = (0, import_react46.useRef)(void 0);
18721
18710
  const { localstackEndpoint } = useAppInspector();
18722
18711
  const connect = (0, import_react46.useCallback)(() => {
18723
18712
  if (wsRef.current !== void 0) return;
@@ -18726,19 +18715,22 @@ function useSpansWebSocket(options) {
18726
18715
  const ws = new WebSocket(url);
18727
18716
  wsRef.current = ws;
18728
18717
  ws.addEventListener("open", () => {
18718
+ if (wsRef.current !== ws) return;
18729
18719
  setConnected(true);
18720
+ onOpenRef.current();
18730
18721
  });
18731
18722
  ws.addEventListener("message", () => {
18723
+ if (wsRef.current !== ws) return;
18732
18724
  onMessageRef.current();
18733
18725
  });
18734
18726
  ws.addEventListener("close", () => {
18727
+ if (wsRef.current !== ws) return;
18735
18728
  setConnected(false);
18736
18729
  wsRef.current = void 0;
18737
- reconnectRef.current = globalThis.setTimeout(() => {
18738
- connect();
18739
- }, 2e3);
18730
+ onCloseRef.current();
18740
18731
  });
18741
18732
  ws.addEventListener("error", () => {
18733
+ if (wsRef.current !== ws) return;
18742
18734
  try {
18743
18735
  ws.close();
18744
18736
  } catch {
@@ -18746,26 +18738,34 @@ function useSpansWebSocket(options) {
18746
18738
  });
18747
18739
  }, [localstackEndpoint]);
18748
18740
  (0, import_react46.useEffect)(() => {
18741
+ if (!enabled) {
18742
+ if (wsRef.current !== void 0) {
18743
+ wsRef.current.close();
18744
+ wsRef.current = void 0;
18745
+ setConnected(false);
18746
+ }
18747
+ return;
18748
+ }
18749
18749
  connect();
18750
18750
  return () => {
18751
- if (reconnectRef.current !== void 0) clearTimeout(reconnectRef.current);
18752
18751
  if (wsRef.current !== void 0) {
18753
18752
  try {
18754
18753
  wsRef.current.close();
18755
18754
  } catch {
18756
18755
  }
18757
18756
  wsRef.current = void 0;
18757
+ setConnected(false);
18758
18758
  }
18759
18759
  };
18760
- }, [connect]);
18760
+ }, [enabled, connect]);
18761
18761
  return { connected };
18762
18762
  }
18763
18763
 
18764
18764
  // src/hooks/use-spans.ts
18765
- var PAGE_SIZE = 30;
18765
+ var PAGE_SIZE = 100;
18766
18766
  var useSpans = () => {
18767
18767
  const api = useAppInspectorApi();
18768
- const { reportDisabled } = useAppInspectorStatus();
18768
+ const { onWsClose, onWsOpen, wsEnabled } = useAppInspectorStatus();
18769
18769
  const [spans, setSpans] = (0, import_react47.useState)();
18770
18770
  const [fetchError, setFetchError] = (0, import_react47.useState)();
18771
18771
  const [fetchingForward, setFetchingForward] = (0, import_react47.useState)(false);
@@ -18843,37 +18843,35 @@ var useSpans = () => {
18843
18843
  setClearingSpans(false);
18844
18844
  }
18845
18845
  }, [clearingSpans, api]);
18846
- const [streamPaused, setStreamPaused] = (0, import_react47.useState)(false);
18847
- const toggleStream = (0, import_react47.useCallback)(() => {
18848
- setStreamPaused((previous) => !previous);
18849
- }, []);
18850
18846
  (0, import_react47.useEffect)(() => {
18851
- if (hasMoreForward === true && !fetchingForward && !streamPaused) {
18847
+ if (hasMoreForward === true && !fetchingForward) {
18852
18848
  void paginationBufferRef.current.fetchForward();
18853
18849
  }
18854
- }, [hasMoreForward, fetchingForward, streamPaused]);
18850
+ }, [hasMoreForward, fetchingForward]);
18851
+ (0, import_react47.useEffect)(() => {
18852
+ if (hasMoreBackward === true && !fetchingBackward && !fetchingForward) {
18853
+ void paginationBufferRef.current.fetchBackward();
18854
+ }
18855
+ }, [hasMoreBackward, fetchingBackward, fetchingForward]);
18855
18856
  useSpansWebSocket({
18857
+ enabled: wsEnabled,
18858
+ onClose: onWsClose,
18856
18859
  onMessage: () => {
18857
18860
  if (clearingSpans) {
18858
18861
  return;
18859
18862
  }
18860
18863
  if (!hasMoreForward) {
18861
- if (streamPaused) {
18862
- paginationBufferRef.current.checkIfThereAreMoreItemsForward();
18863
- } else {
18864
- void paginationBufferRef.current.fetchForward();
18865
- }
18864
+ void paginationBufferRef.current.fetchForward();
18866
18865
  }
18866
+ },
18867
+ onOpen: () => {
18868
+ onWsOpen();
18869
+ fetchForward();
18867
18870
  }
18868
18871
  });
18869
18872
  const clearFetchError = (0, import_react47.useCallback)(() => {
18870
18873
  setFetchError(void 0);
18871
18874
  }, []);
18872
- (0, import_react47.useEffect)(() => {
18873
- if (fetchError instanceof AppInspectorDisabledError || fetchError instanceof ConnectionError) {
18874
- reportDisabled();
18875
- }
18876
- }, [fetchError, reportDisabled]);
18877
18875
  return {
18878
18876
  clearFetchError,
18879
18877
  clearingSpans,
@@ -18888,9 +18886,7 @@ var useSpans = () => {
18888
18886
  hasMoreForward,
18889
18887
  licenseLimit,
18890
18888
  spans,
18891
- streamPaused,
18892
18889
  systemLimit,
18893
- toggleStream,
18894
18890
  totalCount,
18895
18891
  warningCount
18896
18892
  };
@@ -31117,7 +31113,7 @@ var QueryStatus = {
31117
31113
  var import_material17 = require("@mui/material");
31118
31114
  var import_react53 = require("react");
31119
31115
  var import_jsx_runtime139 = require("react/jsx-runtime");
31120
- var POLL_INTERVAL_MS = 1e3;
31116
+ var POLL_INTERVAL_MS2 = 1e3;
31121
31117
  async function pollQueryResults(client, queryId) {
31122
31118
  return client.send(new GetQueryResultsCommand({ queryId }));
31123
31119
  }
@@ -31178,7 +31174,7 @@ function useLambdaInvokeLogs(functionName2, requestId, region, startTimeNano, en
31178
31174
  setError(new Error(`Query ended with status: ${status}`));
31179
31175
  setLoading(false);
31180
31176
  } else {
31181
- pollTimerRef.current = setTimeout(() => void poll(), POLL_INTERVAL_MS);
31177
+ pollTimerRef.current = setTimeout(() => void poll(), POLL_INTERVAL_MS2);
31182
31178
  }
31183
31179
  } catch (error_) {
31184
31180
  if (!cancelled) {
@@ -31986,90 +31982,75 @@ var TraceGraphView = ({
31986
31982
  fetchError,
31987
31983
  fetchSpans,
31988
31984
  handleClose,
31989
- handleEnable,
31990
31985
  handleEventSelect,
31991
- handleRetry,
31992
31986
  loading,
31993
31987
  navigateToSpansList,
31994
31988
  open,
31995
31989
  selectedEvent,
31996
31990
  spanId,
31997
31991
  spans,
31998
- status,
31999
- statusError,
32000
31992
  traceId
32001
- }) => {
32002
- const shouldShowStatusMessage = Boolean(statusError) || status?.status === "DISABLED";
32003
- return /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)(
32004
- import_material23.Box,
32005
- {
32006
- "data-testid": TRACE_GRAPH_PAGE_TEST_ID,
32007
- sx: {
32008
- alignItems: "center",
32009
- display: "flex",
32010
- flexDirection: "column",
32011
- flexGrow: 1,
32012
- gap: 2,
32013
- overflow: "hidden"
32014
- },
32015
- children: [
32016
- /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)(import_material23.Box, { sx: { display: "flex", width: "100%" }, children: [
32017
- /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_material23.Button, { onClick: () => {
32018
- navigateToSpansList();
32019
- }, startIcon: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_icons_material13.ArrowBack, {}), children: "Go back" }),
32020
- /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_material23.Box, { sx: { flexGrow: 1 } })
32021
- ] }),
32022
- /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
32023
- import_material23.Paper,
32024
- {
32025
- sx: {
32026
- display: "flex",
32027
- flexGrow: 1,
32028
- overflow: "hidden",
32029
- position: "relative",
32030
- width: "100%"
32031
- },
32032
- children: shouldShowStatusMessage ? /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
32033
- StatusMessage,
31993
+ }) => /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)(
31994
+ import_material23.Box,
31995
+ {
31996
+ "data-testid": TRACE_GRAPH_PAGE_TEST_ID,
31997
+ sx: {
31998
+ alignItems: "center",
31999
+ display: "flex",
32000
+ flexDirection: "column",
32001
+ flexGrow: 1,
32002
+ gap: 2,
32003
+ overflow: "hidden"
32004
+ },
32005
+ children: [
32006
+ /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)(import_material23.Box, { sx: { display: "flex", width: "100%" }, children: [
32007
+ /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_material23.Button, { onClick: () => {
32008
+ navigateToSpansList();
32009
+ }, startIcon: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_icons_material13.ArrowBack, {}), children: "Go back" }),
32010
+ /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_material23.Box, { sx: { flexGrow: 1 } })
32011
+ ] }),
32012
+ /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)(
32013
+ import_material23.Paper,
32014
+ {
32015
+ sx: {
32016
+ display: "flex",
32017
+ flexGrow: 1,
32018
+ overflow: "hidden",
32019
+ position: "relative",
32020
+ width: "100%"
32021
+ },
32022
+ children: [
32023
+ /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(Main, { open, children: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
32024
+ import_material23.Box,
32034
32025
  {
32035
- error: statusError,
32036
- onEnable: handleEnable,
32037
- onRetry: handleRetry,
32038
- status
32039
- }
32040
- ) : /* @__PURE__ */ (0, import_jsx_runtime145.jsxs)(import_jsx_runtime145.Fragment, { children: [
32041
- /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(Main, { open, children: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
32042
- import_material23.Box,
32043
- {
32044
- sx: {
32045
- height: "100%",
32046
- overflow: "auto"
32047
- },
32048
- children: traceId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_react62.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
32049
- TraceGraph,
32050
- {
32051
- initialFocusEventId: spanId,
32052
- onEventSelect: handleEventSelect,
32053
- onRefresh: () => {
32054
- fetchSpans();
32055
- },
32056
- spans: {
32057
- data: spans,
32058
- error: fetchError,
32059
- loading
32060
- }
32026
+ sx: {
32027
+ height: "100%",
32028
+ overflow: "auto"
32029
+ },
32030
+ children: traceId !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(import_react62.ReactFlowProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(
32031
+ TraceGraph,
32032
+ {
32033
+ initialFocusEventId: spanId,
32034
+ onEventSelect: handleEventSelect,
32035
+ onRefresh: () => {
32036
+ fetchSpans();
32037
+ },
32038
+ spans: {
32039
+ data: spans,
32040
+ error: fetchError,
32041
+ loading
32061
32042
  }
32062
- ) })
32063
- }
32064
- ) }),
32065
- /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(StyledDrawer, { anchor: "right", open, variant: "persistent", children: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(EventDetails, { onClose: handleClose, selectedEvent }) })
32066
- ] })
32067
- }
32068
- )
32069
- ]
32070
- }
32071
- );
32072
- };
32043
+ }
32044
+ ) })
32045
+ }
32046
+ ) }),
32047
+ /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(StyledDrawer, { anchor: "right", open, variant: "persistent", children: /* @__PURE__ */ (0, import_jsx_runtime145.jsx)(EventDetails, { onClose: handleClose, selectedEvent }) })
32048
+ ]
32049
+ }
32050
+ )
32051
+ ]
32052
+ }
32053
+ );
32073
32054
  async function fetchConnectedTraces(api, traceIds, allSpans = /* @__PURE__ */ new Map(), processedTraceIds = /* @__PURE__ */ new Set()) {
32074
32055
  const newTraceIds = traceIds.filter((id2) => !processedTraceIds.has(id2));
32075
32056
  if (newTraceIds.length === 0) {
@@ -32134,24 +32115,11 @@ var TraceGraphPage = ({ onClose, spanId, traceId }) => {
32134
32115
  spansReference.current = spans;
32135
32116
  }
32136
32117
  }, [spans, setSelectedEvent, spanId]);
32137
- const { checkStatus, reportDisabled, status, statusError } = useAppInspectorStatus();
32138
- (0, import_react63.useEffect)(() => {
32139
- if (fetchError instanceof AppInspectorDisabledError || fetchError instanceof ConnectionError) {
32140
- reportDisabled();
32141
- }
32142
- }, [fetchError, reportDisabled]);
32143
- const handleEnable = (0, import_react63.useCallback)(async () => {
32144
- await api.setStatus({ status: "ENABLED" });
32145
- void checkStatus();
32146
- }, [api, checkStatus]);
32147
32118
  const handleEventSelect = (0, import_react63.useCallback)((spanId2) => {
32148
32119
  const span = spans?.find((s) => s.span_id === spanId2);
32149
32120
  setSelectedEvent(span);
32150
32121
  setOpen(true);
32151
32122
  }, [spans]);
32152
- const handleRetry = (0, import_react63.useCallback)(() => {
32153
- void checkStatus();
32154
- }, [checkStatus]);
32155
32123
  const navigateToSpansList = (0, import_react63.useCallback)(() => {
32156
32124
  onClose?.();
32157
32125
  }, [onClose]);
@@ -32163,17 +32131,13 @@ var TraceGraphPage = ({ onClose, spanId, traceId }) => {
32163
32131
  handleClose: () => {
32164
32132
  setOpen(false);
32165
32133
  },
32166
- handleEnable,
32167
32134
  handleEventSelect,
32168
- handleRetry,
32169
32135
  loading,
32170
32136
  navigateToSpansList,
32171
32137
  open,
32172
32138
  selectedEvent,
32173
32139
  spanId: spanId ?? void 0,
32174
32140
  spans,
32175
- status,
32176
- statusError,
32177
32141
  traceId
32178
32142
  }
32179
32143
  );
@@ -32188,7 +32152,6 @@ var SpansListPage = () => {
32188
32152
  clearingSpans,
32189
32153
  clearSpans,
32190
32154
  errorCount,
32191
- fetchBackward,
32192
32155
  fetchError,
32193
32156
  fetchForward,
32194
32157
  fetchingBackward,
@@ -32197,13 +32160,11 @@ var SpansListPage = () => {
32197
32160
  hasMoreForward,
32198
32161
  licenseLimit,
32199
32162
  spans,
32200
- streamPaused,
32201
32163
  systemLimit,
32202
- toggleStream,
32203
32164
  totalCount,
32204
32165
  warningCount
32205
32166
  } = useSpans();
32206
- const { checking, checkStatus, status, statusError } = useAppInspectorStatus();
32167
+ const { checkStatus, phase, status, statusError } = useAppInspectorStatus();
32207
32168
  const clearSpansSync = (0, import_react64.useCallback)(() => {
32208
32169
  void clearSpans();
32209
32170
  }, [clearSpans]);
@@ -32218,13 +32179,13 @@ var SpansListPage = () => {
32218
32179
  setSelectedSpanId(span.span_id);
32219
32180
  }, []);
32220
32181
  const handleRetry = (0, import_react64.useCallback)(() => {
32221
- void checkStatus();
32182
+ checkStatus();
32222
32183
  fetchForward();
32223
32184
  }, [checkStatus, fetchForward]);
32224
32185
  const handleEnable = (0, import_react64.useCallback)(async () => {
32225
32186
  await api.setStatus({ status: "ENABLED" });
32226
32187
  clearFetchError();
32227
- void checkStatus();
32188
+ checkStatus();
32228
32189
  }, [api, checkStatus, clearFetchError]);
32229
32190
  const isDelayedRefetchRef = (0, import_react64.useRef)(false);
32230
32191
  const delayedRefetchTimerRef = (0, import_react64.useRef)();
@@ -32247,27 +32208,42 @@ var SpansListPage = () => {
32247
32208
  clearTimeout(delayedRefetchTimerRef.current);
32248
32209
  };
32249
32210
  }, [fetchingForward, fetchForward]);
32250
- const shouldShowStatusMessage = Boolean(statusError) || status?.status === "DISABLED";
32251
- if (versionCompatibility === "below-minimum") {
32252
- return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32253
- StatusMessage,
32254
- {
32255
- localstackVersion,
32256
- onRetry: handleRetry
32257
- }
32258
- );
32259
- }
32260
- if (shouldShowStatusMessage) {
32261
- return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32262
- StatusMessage,
32263
- {
32264
- error: statusError,
32265
- localstackVersion,
32266
- onEnable: handleEnable,
32267
- onRetry: handleRetry,
32268
- status
32269
- }
32270
- );
32211
+ switch (phase) {
32212
+ case "CHECKING_STATUS":
32213
+ case "CONNECTING_WS": {
32214
+ return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(StatusMessage, { phase });
32215
+ }
32216
+ case "DISABLED": {
32217
+ return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32218
+ StatusMessage,
32219
+ {
32220
+ onEnable: handleEnable,
32221
+ phase
32222
+ }
32223
+ );
32224
+ }
32225
+ case "INCOMPATIBLE": {
32226
+ return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32227
+ StatusMessage,
32228
+ {
32229
+ localstackVersion,
32230
+ onRetry: handleRetry,
32231
+ phase
32232
+ }
32233
+ );
32234
+ }
32235
+ case "LIVE": {
32236
+ break;
32237
+ }
32238
+ case "UNREACHABLE": {
32239
+ return /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32240
+ StatusMessage,
32241
+ {
32242
+ onRetry: handleRetry,
32243
+ phase
32244
+ }
32245
+ );
32246
+ }
32271
32247
  }
32272
32248
  return /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(import_jsx_runtime146.Fragment, { children: [
32273
32249
  /* @__PURE__ */ (0, import_jsx_runtime146.jsxs)(
@@ -32286,7 +32262,7 @@ var SpansListPage = () => {
32286
32262
  width: "100%"
32287
32263
  },
32288
32264
  children: [
32289
- !checking && /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32265
+ /* @__PURE__ */ (0, import_jsx_runtime146.jsx)(
32290
32266
  EmulatorVersionBanner,
32291
32267
  {
32292
32268
  compatibility: bannerDismissed && versionCompatibility === "warning" ? "ok" : versionCompatibility,
@@ -32308,14 +32284,11 @@ var SpansListPage = () => {
32308
32284
  hasMoreForward,
32309
32285
  licenseLimit,
32310
32286
  onClearSpans: clearSpansSync,
32311
- onFetchBackward: fetchBackward,
32312
32287
  onFetchForward: fetchForward,
32313
32288
  onOrderChange: setOrder,
32314
32289
  onSpanClick: navigateToSpan,
32315
- onToggleStream: toggleStream,
32316
32290
  order: order2,
32317
32291
  spans,
32318
- streamPaused,
32319
32292
  systemLimit,
32320
32293
  totalCount,
32321
32294
  warningCount