Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions components/webui/client/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,12 @@ const EslintConfig = [
"new-cap": [
"error",
{
// TypeBox imports
capIsNewExceptions: [
// TypeBox imports
"Decode",
"Encode",
"Type.Literal",
"Type.Optional",
"Type.Transform",
"Type.Union",
"Value.Parse",
],
capIsNewExceptionPattern: "^(Type|Value)\\.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Nit: restrict the exemption to PascalCase members

Prevents accidentally exempting non-factory members.

-                    capIsNewExceptionPattern: "^(Type|Value)\\.",
+                    capIsNewExceptionPattern: "^(Type|Value)\\.[A-Z]",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
capIsNewExceptionPattern: "^(Type|Value)\\.",
capIsNewExceptionPattern: "^(Type|Value)\\.[A-Z]",
🤖 Prompt for AI Agents
In components/webui/client/eslint.config.mjs around line 39, the current
capIsNewExceptionPattern ("^(Type|Value)\\.") is too broad and may exempt
non-factory members; change the pattern to require PascalCase names before the
dot (e.g., require the identifier to start with an uppercase letter followed by
letters/digits) so only PascalCase members are exempted — update the pattern
accordingly to something that matches an initial uppercase letter then
alphanumerics before the dot (for example: start with ^, then [A-Z] followed by
[A-Za-z0-9]*, then \\.), and replace the existing value with that stricter
regex.

},
],
},
Expand Down
31 changes: 9 additions & 22 deletions components/webui/client/src/api/presto-search/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
import {
type PrestoQueryJob,
type PrestoQueryJobCreation,
} from "@webui/common/schemas/presto-search";
import axios, {AxiosResponse} from "axios";


// eslint-disable-next-line no-warning-comments
// TODO: Replace with shared type from the `@common` directory once refactoring is completed.
// Currently, server schema types require typebox dependency so they cannot be moved to the
// `@common` directory with current implementation.
type PrestoQueryJobCreationSchema = {
queryString: string;
};

type PrestoQueryJobSchema = {
searchJobId: string;
};


/**
* Sends post request to server to submit presto query.
*
* @param payload
* @return
*/
const submitQuery = async (
payload: PrestoQueryJobCreationSchema
): Promise<AxiosResponse<PrestoQueryJobSchema>> => {
payload: PrestoQueryJobCreation
): Promise<AxiosResponse<PrestoQueryJob>> => {
Comment on lines +15 to +16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Make submitQuery non-async for consistency and type the axios call.

submitQuery is marked async but doesn’t await; other functions here aren’t async. Also, keep the axios generic explicit.

Apply:

-const submitQuery = async (
-    payload: PrestoQueryJobCreation
-): Promise<AxiosResponse<PrestoQueryJob>> => {
+const submitQuery = (
+    payload: PrestoQueryJobCreation
+): Promise<AxiosResponse<PrestoQueryJob>> => {
   console.log("Submitting query:", JSON.stringify(payload));
-
-    return axios.post<PrestoQueryJob>("/api/presto-search/query", payload);
+  return axios.post<PrestoQueryJob>("/api/presto-search/query", payload);
 }

Also applies to: 19-19

🤖 Prompt for AI Agents
In components/webui/client/src/api/presto-search/index.ts around lines 15-16
(and also line 19), change submitQuery to be a non-async function and add
explicit axios generics: update the function signature to return
Promise<AxiosResponse<PrestoQueryJob>> without the async keyword, and call
axios.post with the generic type parameter (e.g.
axios.post<PrestoQueryJob>(...)) so the response is properly typed; ensure you
remove any unused await and keep the rest of the implementation unchanged.

console.log("Submitting query:", JSON.stringify(payload));

return axios.post<PrestoQueryJobSchema>("/api/presto-search/query", payload);
return axios.post<PrestoQueryJob>("/api/presto-search/query", payload);
};


Expand All @@ -36,7 +27,7 @@ const submitQuery = async (
* @return
*/
const cancelQuery = async (
payload: PrestoQueryJobSchema
payload: PrestoQueryJob
): Promise<AxiosResponse<null>> => {
Comment on lines +30 to 31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Type the void responses and consider making logging conditional.

Add axios generics for null responses; optionally guard logs behind a dev flag to avoid noisy consoles in prod.

 const cancelQuery = async (
     payload: PrestoQueryJob
 ): Promise<AxiosResponse<null>> => {
   console.log("Cancelling query:", JSON.stringify(payload));
 
-  return axios.post("/api/presto-search/cancel", payload);
+  return axios.post<null>("/api/presto-search/cancel", payload);
 };
 
-const clearQueryResults = (payload: PrestoQueryJob): Promise<AxiosResponse<null>> => {
+const clearQueryResults = (payload: PrestoQueryJob): Promise<AxiosResponse<null>> => {
   console.log("Clearing query:", JSON.stringify(payload));
 
-  return axios.delete("/api/presto-search/results", {data: payload});
+  return axios.delete<null>("/api/presto-search/results", { data: payload });
 };

Also applies to: 34-35, 44-48

🤖 Prompt for AI Agents
In components/webui/client/src/api/presto-search/index.ts around lines 30-31
(and similarly for 34-35, 44-48), the function Axios calls lack explicit
generics for null responses and console logging is unconditional; update the
Axios call signatures to use AxiosResponse<null> (or
AxiosResponse<YourNullType>) generics where responses are empty, and wrap any
console.log/console.error calls with a development flag (e.g., if
(process.env.NODE_ENV !== 'production') or a isDev constant) so logs are
silenced in production; ensure TypeScript signatures and returned Promise types
match the axios generics and adjust any callers if needed.

console.log("Cancelling query:", JSON.stringify(payload));

Expand All @@ -50,16 +41,12 @@ const cancelQuery = async (
* @param payload
* @return
*/
const clearQueryResults = (payload: PrestoQueryJobSchema): Promise<AxiosResponse<null>> => {
const clearQueryResults = (payload: PrestoQueryJob): Promise<AxiosResponse<null>> => {
console.log("Clearing query:", JSON.stringify(payload));

return axios.delete("/api/presto-search/results", {data: payload});
};

export type {
PrestoQueryJobCreationSchema,
PrestoQueryJobSchema,
};

export {
cancelQuery,
Expand Down
41 changes: 9 additions & 32 deletions components/webui/client/src/api/search/index.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,20 @@
import {
type QueryJob,
type QueryJobCreation,
} from "@webui/common/schemas/search";
import axios, {AxiosResponse} from "axios";

import {Nullable} from "../../typings/common";


// eslint-disable-next-line no-warning-comments
// TODO: Replace with shared type from the `@common` directory once refactoring is completed.
// Currently, server schema types require typebox dependency so they cannot be moved to the
// `@common` directory with current implementation.
type QueryJobSchema = {
searchJobId: string;
aggregationJobId: string;
};

// eslint-disable-next-line no-warning-comments
// TODO: Replace with shared type from the `@common` directory once refactoring is completed.
// Currently, server schema types require typebox dependency so they cannot be moved to the
// `@common` directory with current implementation.
type QueryJobCreationSchema = {
dataset: Nullable<string>;
ignoreCase: boolean;
queryString: string;
timeRangeBucketSizeMillis: number;
timestampBegin: number;
timestampEnd: number;
};

/**
* Sends post request to server to submit query.
*
* @param payload
* @return
*/
const submitQuery = (payload: QueryJobCreationSchema): Promise<AxiosResponse<QueryJobSchema>> => {
const submitQuery = (payload: QueryJobCreation): Promise<AxiosResponse<QueryJob>> => {
console.log("Submitting query:", JSON.stringify(payload));

return axios.post<QueryJobSchema>("/api/search/query", payload);
return axios.post<QueryJob>("/api/search/query", payload);
};
Comment on lines +14 to 18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Type axios responses for null-returning endpoints.

Keep response types explicit to strengthen inference and catch regressions.

-const submitQuery = (payload: QueryJobCreation): Promise<AxiosResponse<QueryJob>> => {
+const submitQuery = (payload: QueryJobCreation): Promise<AxiosResponse<QueryJob>> => {
   console.log("Submitting query:", JSON.stringify(payload));
-  return axios.post<QueryJob>("/api/search/query", payload);
+  return axios.post<QueryJob>("/api/search/query", payload);
 };
 
-const cancelQuery = (payload: QueryJob): Promise<AxiosResponse<null>> => {
+const cancelQuery = (payload: QueryJob): Promise<AxiosResponse<null>> => {
   console.log("Cancelling query:", JSON.stringify(payload));
-  return axios.post("/api/search/cancel", payload);
+  return axios.post<null>("/api/search/cancel", payload);
 };
 
-const clearQueryResults = (payload: QueryJob): Promise<AxiosResponse<null>> => {
+const clearQueryResults = (payload: QueryJob): Promise<AxiosResponse<null>> => {
   console.log("Clearing query:", JSON.stringify(payload));
-  return axios.delete("/api/search/results", {data: payload});
+  return axios.delete<null>("/api/search/results", { data: payload });
 };

Also applies to: 26-30, 38-42

🤖 Prompt for AI Agents
In components/webui/client/src/api/search/index.ts around lines 14-18 (and
similarly update the functions at 26-30 and 38-42), the axios response types are
declared as concrete models but the endpoints can return null; change the return
type generics to include null (e.g. QueryJob | null) and update the function
signatures to return Promise<AxiosResponse<... | null>> so TypeScript accurately
models nullable responses and improves inference; ensure any related
imports/types are preserved.


/**
Expand All @@ -43,7 +23,7 @@ const submitQuery = (payload: QueryJobCreationSchema): Promise<AxiosResponse<Que
* @param payload
* @return
*/
const cancelQuery = (payload: QueryJobSchema): Promise<AxiosResponse<null>> => {
const cancelQuery = (payload: QueryJob): Promise<AxiosResponse<null>> => {
console.log("Cancelling query:", JSON.stringify(payload));

return axios.post("/api/search/cancel", payload);
Expand All @@ -55,15 +35,12 @@ const cancelQuery = (payload: QueryJobSchema): Promise<AxiosResponse<null>> => {
* @param payload
* @return
*/
const clearQueryResults = (payload: QueryJobSchema): Promise<AxiosResponse<null>> => {
const clearQueryResults = (payload: QueryJob): Promise<AxiosResponse<null>> => {
console.log("Clearing query:", JSON.stringify(payload));

return axios.delete("/api/search/results", {data: payload});
};
export type {
QueryJobCreationSchema,
QueryJobSchema,
};

export {
cancelQuery,
clearQueryResults,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
ClientToServerEvents,
ServerToClientEvents,
} from "@webui/common";
} from "@webui/common/socket";
import {Socket} from "socket.io-client";

import {MongoSocketCursor} from "./MongoSocketCursor.js";
Expand Down
5 changes: 2 additions & 3 deletions components/webui/client/src/api/socket/MongoSocketCursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import {
QueryId,
Response,
ServerToClientEvents,
} from "@webui/common";
} from "@webui/common/socket";
import {Nullable} from "@webui/common/utility-types";
import {Socket} from "socket.io-client";

import {Nullable} from "../../typings/common";


/**
* A cursor-like object receiving MongoDB documents over a socket connection.
Expand Down
5 changes: 2 additions & 3 deletions components/webui/client/src/api/socket/SocketSingleton.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {
ClientToServerEvents,
ServerToClientEvents,
} from "@webui/common";
} from "@webui/common/socket";
import {Nullable} from "@webui/common/utility-types";
import {
io,
Socket,
} from "socket.io-client";

import {Nullable} from "../../typings/common";


let sharedSocket: Nullable<Socket<ServerToClientEvents, ClientToServerEvents>> = null;

Expand Down
3 changes: 2 additions & 1 deletion components/webui/client/src/api/socket/useCursor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
useState,
} from "react";

import {Nullable} from "../../typings/common";
import {Nullable} from "@webui/common/utility-types";

import {MongoSocketCursor} from "./MongoSocketCursor.js";


Expand Down
8 changes: 3 additions & 5 deletions components/webui/client/src/api/stream-files/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import {QUERY_JOB_TYPE} from "@webui/common/query";
import {Nullable} from "@webui/common/utility-types";
import axios, {
AxiosProgressEvent,
AxiosResponse,
} from "axios";
import {Nullable} from "src/typings/common";

import {
ExtractStreamResp,
QUERY_JOB_TYPE,
} from "../../typings/query";
import {ExtractStreamResp} from "../../typings/query";


interface SubmitExtractStreamJobProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Nullable} from "@webui/common/utility-types";
import {
Progress,
theme,
} from "antd";
import {Nullable} from "src/typings/common";

import styles from "./index.module.css";
import InputWithCaseSensitive, {InputWithCaseSensitiveProps} from "./InputWithCaseSensitive";
Expand Down
2 changes: 1 addition & 1 deletion components/webui/client/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {CLP_QUERY_ENGINES} from "@webui/common";
import {CLP_QUERY_ENGINES} from "@webui/common/config";

import {settings} from "../settings";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Nullable} from "src/typings/common";
import {Nullable} from "@webui/common/utility-types";

import {DashboardCard} from "../../../components/DashboardCard";
import Stat from "../../../components/Stat";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Nullable} from "src/typings/common";
import {Nullable} from "@webui/common/utility-types";

import {DashboardCard} from "../../../components/DashboardCard";
import Stat from "../../../components/Stat";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Nullable} from "src/typings/common";
import {Nullable} from "@webui/common/utility-types";

import {querySql} from "../../../api/sql";
import {SqlTableSuffix} from "../../../config/sql-table-suffix";
Expand Down
2 changes: 1 addition & 1 deletion components/webui/client/src/pages/IngestPage/Jobs/sql.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Nullable} from "src/typings/common";
import {Nullable} from "@webui/common/utility-types";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm Nullable semantics and path resolution

Good move to centralize. Please confirm the new Nullable equals the old definition (e.g., T | null vs T | null | undefined) to avoid subtle runtime/type mismatches for duration and start_time. Also ensure @webui/* path mapping resolves in the client package’s tsconfig.

Run:


🏁 Script executed:

#!/bin/bash
# Find all Nullable definitions
rg -nP --type=ts --type=tsx '\btype\s+Nullable\s*<'

# Find any remaining non-common Nullable imports
rg -nP --type=ts --type=tsx 'import\s*{\s*Nullable\s*}.*from\s*["'\''](?!@webui/common/utility-types)["'\''][^"'\'';]+["'\'']'

# Show configured path mappings
fd -a tsconfig.json | xargs -I{} sh -c 'echo "== {} =="; jq -r ".compilerOptions.paths?[@\"@webui/*\"]? // \"(no mapping)\"" "{}" 2>/dev/null'

Length of output: 300


🏁 Script executed:

#!/bin/bash
grep -R "type Nullable" -n components/webui
grep -R "import.*Nullable.*from" -n components/webui --include=*.ts --include=*.tsx | grep -v "@webui/common/utility-types"
file=$(find components/webui/common -type f -name 'utility-types.ts' | head -n1)
echo "=== $file ==="
sed -n '1,200p' "$file"
echo "=== client tsconfig ==="
sed -n '1,200p' components/webui/client/tsconfig.json

Length of output: 588


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' components/webui/client/tsconfig/tsconfig.app.json
sed -n '1,200p' components/webui/client/tsconfig/tsconfig.node.json

Length of output: 1019


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' components/webui/client/tsconfig/tsconfig.base.json

Length of output: 586


Confirm centralized Nullable semantics and add tsconfig path mapping

  • Central Nullable<T> is defined as T | null; verify this matches the previous behaviour (e.g. if you relied on T | undefined) and adjust accordingly.
  • In components/webui/client/tsconfig/tsconfig.base.json, under compilerOptions add or update:
    {
      "baseUrl": "../",
      "paths": {
        "@webui/*": ["../*"]
      }
      // …other options…
    }
    to ensure imports like @webui/common/utility-types resolve correctly.
🤖 Prompt for AI Agents
In components/webui/client/src/pages/IngestPage/Jobs/sql.ts at line 1, the
import uses Nullable from @webui/common/utility-types — confirm that the
centralized Nullable<T> is defined as T | null and if previous code relied on T
| undefined update the centralized type to T | null | undefined (or adjust call
sites) so semantics remain the same; then add/update
components/webui/client/tsconfig/tsconfig.base.json under compilerOptions to
include baseUrl set to "../" and a paths mapping "@webui/*": ["../*"] so imports
like @webui/common/utility-types resolve correctly.


import {settings} from "../../../settings";
import {COMPRESSION_JOBS_TABLE_COLUMN_NAMES} from "../sqlConfig";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
useState,
} from "react";

import {Nullable} from "src/typings/common";
import {Nullable} from "@webui/common/utility-types";

import SqlEditor, {SqlEditorRef} from "../../../../../components/SqlEditor";
import useSearchStore from "../../../SearchState/index";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
type PrestoQueryJob,
type PrestoQueryJobCreation,
} from "@webui/common/schemas/presto-search";

import {
cancelQuery,
clearQueryResults,
type PrestoQueryJobCreationSchema,
type PrestoQueryJobSchema,
submitQuery,
} from "../../../../api/presto-search";
import useSearchStore from "../../SearchState";
Expand Down Expand Up @@ -39,7 +42,7 @@ const handlePrestoClearResults = () => {
*
* @param payload
*/
const handlePrestoQuerySubmit = (payload: PrestoQueryJobCreationSchema) => {
const handlePrestoQuerySubmit = (payload: PrestoQueryJobCreation) => {
const {updateSearchJobId, updateSearchUiState, searchUiState} = useSearchStore.getState();

// User should NOT be able to submit a new query while an existing query is in progress.
Expand Down Expand Up @@ -78,7 +81,7 @@ const handlePrestoQuerySubmit = (payload: PrestoQueryJobCreationSchema) => {
*
* @param payload
*/
const handlePrestoQueryCancel = (payload: PrestoQueryJobSchema) => {
const handlePrestoQueryCancel = (payload: PrestoQueryJob) => {
const {searchUiState, updateSearchUiState} = useSearchStore.getState();
if (searchUiState !== SEARCH_UI_STATE.QUERYING) {
console.error("Cannot cancel query if there is no ongoing query.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const CancelButton = () => {
return;
}
handleQueryCancel(
{searchJobId, aggregationJobId}
{
searchJobId: Number(searchJobId),
aggregationJobId: Number(aggregationJobId),
}
);
}, [searchJobId,
aggregationJobId]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const handleSubmit = (ev: React.FormEvent<HTMLFormElement>) => {
const SearchControls = () => {
/* eslint-disable-next-line no-warning-comments */
// TODO: Remove flag and related logic when the new guide UI is fully implemented.
const isGuidedEnabled = "true" === import.meta.env[`VITE_GUIDED_DEV`];
const isGuidedEnabled = "true" === import.meta.env["VITE_GUIDED_DEV"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Prefer typed env access and explicit boolean coercion.
Using bracket access bypasses Vite’s typing; dot access catches typos at compile time.

-    const isGuidedEnabled = "true" === import.meta.env["VITE_GUIDED_DEV"];
+    const isGuidedEnabled = import.meta.env.VITE_GUIDED_DEV === "true";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isGuidedEnabled = "true" === import.meta.env["VITE_GUIDED_DEV"];
const isGuidedEnabled = import.meta.env.VITE_GUIDED_DEV === "true";
🤖 Prompt for AI Agents
In components/webui/client/src/pages/SearchPage/SearchControls/index.tsx around
line 35, replace the bracket env access with typed dot access and perform an
explicit boolean coercion; specifically, change the current
import.meta.env["VITE_GUIDED_DEV"] usage to import.meta.env.VITE_GUIDED_DEV and
compare it strictly to the string "true" (e.g. import.meta.env.VITE_GUIDED_DEV
=== "true") so the value is typed by Vite and converted to a boolean reliably.


return (
<form onSubmit={handleSubmit}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
type QueryJob,
type QueryJobCreation,
} from "@webui/common/schemas/search";
import {message} from "antd";

import {
cancelQuery,
clearQueryResults,
QueryJobCreationSchema,
QueryJobSchema,
submitQuery,
} from "../../../api/search";
import {
Expand Down Expand Up @@ -40,7 +42,10 @@ const handleClearResults = () => {
}

clearQueryResults(
{searchJobId, aggregationJobId}
{
searchJobId: Number(searchJobId),
aggregationJobId: Number(aggregationJobId),
}
).catch((err: unknown) => {
Comment on lines 44 to 49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validate numeric ID conversions to avoid NaN payloads.
Guard against invalid stored IDs before calling the API. Uses the project’s negation guideline.

-    clearQueryResults(
-        {
-            searchJobId: Number(searchJobId),
-            aggregationJobId: Number(aggregationJobId),
-        }
-    ).catch((err: unknown) => {
+    const sj = Number(searchJobId);
+    const aj = Number(aggregationJobId);
+    if (false == Number.isFinite(sj) || false == Number.isFinite(aj)) {
+        console.error("Cannot clear results: job IDs are not valid numbers.", {
+            searchJobId,
+            aggregationJobId,
+        });
+        return;
+    }
+    clearQueryResults({searchJobId: sj, aggregationJobId: aj}).catch((err: unknown) => {
         console.error("Failed to clear query results:", err);
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
clearQueryResults(
{searchJobId, aggregationJobId}
{
searchJobId: Number(searchJobId),
aggregationJobId: Number(aggregationJobId),
}
).catch((err: unknown) => {
const sj = Number(searchJobId);
const aj = Number(aggregationJobId);
if (false == Number.isFinite(sj) || false == Number.isFinite(aj)) {
console.error("Cannot clear results: job IDs are not valid numbers.", {
searchJobId,
aggregationJobId,
});
return;
}
clearQueryResults({ searchJobId: sj, aggregationJobId: aj }).catch((err: unknown) => {
console.error("Failed to clear query results:", err);
});
🤖 Prompt for AI Agents
In
components/webui/client/src/pages/SearchPage/SearchControls/search-requests.ts
around lines 44-49, the Number(...) conversions for searchJobId and
aggregationJobId may produce NaN and send an invalid payload; validate the
converted IDs before calling clearQueryResults by parsing/converting the raw
stored values, checking Number.isFinite(id) (and optionally id >= 0 per project
rules), and then either set the payload properties to undefined/omit them or
return early and skip the API call if required; follow the project's negation
guideline when checking invalid values (use explicit comparisons rather than
relying on falsy checks) and ensure clearQueryResults is only invoked with
confirmed numeric IDs.

console.error("Failed to clear query results:", err);
});
Expand All @@ -51,7 +56,7 @@ const handleClearResults = () => {
*
* @param payload
*/
const handleQuerySubmit = (payload: QueryJobCreationSchema) => {
const handleQuerySubmit = (payload: QueryJobCreation) => {
const store = useSearchStore.getState();

// User should NOT be able to submit a new query while an existing query is in progress.
Expand Down Expand Up @@ -95,8 +100,8 @@ const handleQuerySubmit = (payload: QueryJobCreationSchema) => {
submitQuery(payload)
.then((result) => {
const {searchJobId, aggregationJobId} = result.data;
store.updateSearchJobId(searchJobId);
store.updateAggregationJobId(aggregationJobId);
store.updateSearchJobId(searchJobId.toString());
store.updateAggregationJobId(aggregationJobId.toString());
store.updateSearchUiState(SEARCH_UI_STATE.QUERYING);
console.debug(
"Search job created - ",
Expand All @@ -116,7 +121,7 @@ const handleQuerySubmit = (payload: QueryJobCreationSchema) => {
*
* @param payload
*/
const handleQueryCancel = (payload: QueryJobSchema) => {
const handleQueryCancel = (payload: QueryJob) => {
const store = useSearchStore.getState();

if (store.searchUiState !== SEARCH_UI_STATE.QUERYING) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
useMemo,
} from "react";

import type {PrestoSearchResult} from "@webui/common";
import type {PrestoSearchResult} from "@webui/common/presto";

import VirtualTable from "../../../../../../components/VirtualTable";
import useSearchStore from "../../../../SearchState/index";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {PrestoSearchResult} from "@webui/common";
import type {PrestoSearchResult} from "@webui/common/presto";

import MongoSocketCollection from "../../../../../../api/socket/MongoSocketCollection";
import {useCursor} from "../../../../../../api/socket/useCursor";
Expand Down
Loading