This commit is contained in:
Carl-Gerhard Lindesvärd
2025-11-21 11:21:17 +01:00
parent dd71fd4e11
commit 06fb6c4f3c
40 changed files with 2944 additions and 1972 deletions

View File

@@ -88,9 +88,21 @@ export const zChartBreakdown = z.object({
// Support both old format (array of events without type) and new format (array of event/formula items)
// Preprocess to normalize: if item has 'type' field, use discriminated union; otherwise, add type: 'event'
export const zChartEvents = z.preprocess((val) => {
if (!Array.isArray(val)) return val;
return val.map((item: any) => {
export const zChartSeries = z.preprocess((val) => {
if (!val) return val;
let processedVal = val;
// If the input is an object with numeric keys, convert it to an array
if (typeof val === 'object' && val !== null && !Array.isArray(val)) {
const keys = Object.keys(val).sort(
(a, b) => Number.parseInt(a) - Number.parseInt(b),
);
processedVal = keys.map((key) => (val as any)[key]);
}
if (!Array.isArray(processedVal)) return processedVal;
return processedVal.map((item: any) => {
// If item already has type field, return as-is
if (item && typeof item === 'object' && 'type' in item) {
return item;
@@ -101,7 +113,14 @@ export const zChartEvents = z.preprocess((val) => {
}
return item;
});
}, z.array(zChartEventItem));
}, z
.array(zChartEventItem)
.describe(
'Array of series (events or formulas) to be tracked and displayed in the chart',
));
// Keep zChartEvents as an alias for backward compatibility during migration
export const zChartEvents = zChartSeries;
export const zChartBreakdowns = z.array(zChartBreakdown);
export const zChartType = z.enum(objectToZodEnums(chartTypes));
@@ -116,7 +135,7 @@ export const zRange = z.enum(objectToZodEnums(timeWindows));
export const zCriteria = z.enum(['on_or_after', 'on']);
export const zChartInput = z.object({
export const zChartInputBase = z.object({
chartType: zChartType
.default('linear')
.describe('What type of chart should be displayed'),
@@ -125,8 +144,8 @@ export const zChartInput = z.object({
.describe(
'The time interval for data aggregation (e.g., day, week, month)',
),
events: zChartEvents.describe(
'Array of events to be tracked and displayed in the chart',
series: zChartSeries.describe(
'Array of series (events or formulas) to be tracked and displayed in the chart',
),
breakdowns: zChartBreakdowns
.default([])
@@ -183,7 +202,15 @@ export const zChartInput = z.object({
.describe('Time window in hours for funnel analysis'),
});
export const zReportInput = zChartInput.extend({
export const zChartInput = z.preprocess((val) => {
if (val && typeof val === 'object' && 'events' in val && !('series' in val)) {
// Migrate old 'events' field to 'series'
return { ...val, series: val.events };
}
return val;
}, zChartInputBase);
export const zReportInput = zChartInputBase.extend({
name: z.string().describe('The user-defined name for the report'),
lineType: zLineType.describe('The visual style of the line in the chart'),
unit: z

View File

@@ -8,6 +8,7 @@ import type {
zChartFormula,
zChartInput,
zChartInputAI,
zChartSeries,
zChartType,
zCriteria,
zLineType,
@@ -28,6 +29,9 @@ export type IChartProps = z.infer<typeof zReportInput> & {
export type IChartEvent = z.infer<typeof zChartEvent>;
export type IChartFormula = z.infer<typeof zChartFormula>;
export type IChartEventItem = z.infer<typeof zChartEventItem>;
export type IChartSeries = z.infer<typeof zChartSeries>;
// Backward compatibility alias
export type IChartEvents = IChartSeries;
export type IChartEventSegment = z.infer<typeof zChartEventSegment>;
export type IChartEventFilter = IChartEvent['filters'][number];
export type IChartEventFilterValue =
@@ -49,7 +53,7 @@ export type IGetChartDataInput = {
projectId: string;
startDate: string;
endDate: string;
} & Omit<IChartInput, 'events' | 'name' | 'startDate' | 'endDate' | 'range'>;
} & Omit<IChartInput, 'series' | 'name' | 'startDate' | 'endDate' | 'range'>;
export type ICriteria = z.infer<typeof zCriteria>;
export type PreviousValue =
@@ -81,6 +85,7 @@ export type IChartSerie = {
event: {
id?: string;
name: string;
breakdowns?: Record<string, string>;
};
metrics: Metrics;
data: {