fix(analytics): improve formatting and readability in input validation and error handling

This commit is contained in:
Nawaz Dhandala
2026-03-11 18:46:28 +00:00
parent 818f6a3788
commit 484dbabc3c
3 changed files with 17 additions and 11 deletions

View File

@@ -278,7 +278,8 @@ export default class AnalyticsDatabaseService<
throw new BadDataException("aggregationType is required");
}
const allowedAggregationTypes: Array<string> = Object.values(AggregationType);
const allowedAggregationTypes: Array<string> =
Object.values(AggregationType);
if (!allowedAggregationTypes.includes(aggregateBy.aggregationType)) {
throw new BadDataException(
`Invalid aggregationType: ${aggregateBy.aggregationType}. Allowed values: ${allowedAggregationTypes.join(", ")}`,
@@ -295,13 +296,19 @@ export default class AnalyticsDatabaseService<
throw new BadDataException("aggregateColumnName is required");
}
if (!this.model.getTableColumn(aggregateBy.aggregateColumnName.toString())) {
if (
!this.model.getTableColumn(aggregateBy.aggregateColumnName.toString())
) {
throw new BadDataException(
`Invalid aggregateColumnName: ${aggregateBy.aggregateColumnName.toString()}`,
);
}
if (!this.model.getTableColumn(aggregateBy.aggregationTimestampColumnName.toString())) {
if (
!this.model.getTableColumn(
aggregateBy.aggregationTimestampColumnName.toString(),
)
) {
throw new BadDataException(
`Invalid aggregationTimestampColumnName: ${aggregateBy.aggregationTimestampColumnName.toString()}`,
);

View File

@@ -223,8 +223,10 @@ describe("AnalyticsDatabaseService", () => {
return undefined!;
});
// The base getException method is async and throws without await in the
// catch block, creating unhandled rejections. Override to throw synchronously.
/*
* The base getException method is async and throws without await in the
* catch block, creating unhandled rejections. Override to throw synchronously.
*/
(service as any).getException = (error: Error): never => {
throw error;
};
@@ -234,7 +236,7 @@ describe("AnalyticsDatabaseService", () => {
jest.restoreAllMocks();
});
const makeAggregateBy = (overrides: Record<string, unknown> = {}): any => {
const makeAggregateBy: (overrides?: Record<string, unknown>) => any = (overrides: Record<string, unknown> = {}): any => {
return {
aggregationType: AggregationType.Sum,
aggregateColumnName: "column_2",
@@ -264,9 +266,7 @@ describe("AnalyticsDatabaseService", () => {
test("should reject invalid aggregationType (arbitrary string)", async () => {
await expect(
service.aggregateBy(
makeAggregateBy({ aggregationType: "INVALID" }),
),
service.aggregateBy(makeAggregateBy({ aggregationType: "INVALID" })),
).rejects.toThrow("Invalid aggregationType");
});

View File

@@ -112,8 +112,7 @@ const MermaidDiagram: FunctionComponent<{ chart: string }> = ({
} catch (error) {
if (containerRef.current) {
const errorMessage: string = String(error);
const errorEl: HTMLPreElement =
document.createElement("pre");
const errorEl: HTMLPreElement = document.createElement("pre");
errorEl.className = "text-red-500";
errorEl.textContent = `Error rendering diagram: ${errorMessage}`;
containerRef.current.innerHTML = "";