Files
stats/packages/db/src/engine/normalize.ts
Carl-Gerhard Lindesvärd ed1c57dbb8 feat: share dashboard & reports, sankey report, new widgets
* fix: prompt card shadows on light mode

* fix: handle past_due and unpaid from polar

* wip

* wip

* wip 1

* fix: improve types for chart/reports

* wip share
2026-01-14 09:21:18 +01:00

67 lines
2.1 KiB
TypeScript

import { alphabetIds } from '@openpanel/constants';
import type {
IChartEvent,
IChartEventItem,
IReportInput,
IReportInputWithDates,
} from '@openpanel/validation';
import { getChartStartEndDate } from '../services/chart.service';
import { getSettingsForProject } from '../services/organization.service';
import type { SeriesDefinition } from './types';
export type NormalizedInput = Awaited<ReturnType<typeof normalize>>;
/**
* Normalize a chart input into a clean structure with dates and normalized series
*/
export async function normalize(
input: IReportInput,
): Promise<IReportInputWithDates & { series: SeriesDefinition[] }> {
const { timezone } = await getSettingsForProject(input.projectId);
const { startDate, endDate } = getChartStartEndDate(
{
range: input.range,
startDate: input.startDate ?? undefined,
endDate: input.endDate ?? undefined,
},
timezone,
);
// Get series from input (handles both 'series' and 'events' fields)
// The schema preprocessing should have already converted 'events' to 'series', but handle both for safety
const rawSeries = (input as any).series ?? (input as any).events ?? [];
// Normalize each series item
const normalizedSeries: SeriesDefinition[] = rawSeries.map(
(item: any, index: number) => {
// If item already has type field, it's the new format
if (item && typeof item === 'object' && 'type' in item) {
return {
...item,
id: item.id ?? alphabetIds[index] ?? `series-${index}`,
} as SeriesDefinition;
}
// Old format without type field - assume it's an event
const event = item as Partial<IChartEvent>;
return {
type: 'event',
id: event.id ?? alphabetIds[index] ?? `series-${index}`,
name: event.name || 'unknown_event',
segment: event.segment ?? 'event',
filters: event.filters ?? [],
displayName: event.displayName,
property: event.property,
} as SeriesDefinition;
},
);
return {
...input,
series: normalizedSeries,
startDate,
endDate,
};
}