(normalized: NormalizedInput)
| 10 | * This sets up ConcreteSeries placeholders - actual breakdown expansion happens during fetch |
| 11 | */ |
| 12 | export async function plan(normalized: NormalizedInput): Promise<Plan> { |
| 13 | const { timezone } = await getSettingsForProject(normalized.projectId); |
| 14 | |
| 15 | const concreteSeries: ConcreteSeries[] = []; |
| 16 | |
| 17 | // Create concrete series placeholders for each definition |
| 18 | normalized.series.forEach((definition, index) => { |
| 19 | if (definition.type === 'event') { |
| 20 | const event = definition as IChartEventItem & { type: 'event' }; |
| 21 | |
| 22 | // For events, create a placeholder |
| 23 | // If breakdowns exist, fetch will return multiple series (one per breakdown value) |
| 24 | // If no breakdowns, fetch will return one series |
| 25 | const concrete: ConcreteSeries = { |
| 26 | id: `${slug(event.name)}-${event.id ?? index}`, |
| 27 | definitionId: event.id ?? alphabetIds[index] ?? `series-${index}`, |
| 28 | definitionIndex: index, |
| 29 | name: [event.displayName || event.name], |
| 30 | context: { |
| 31 | event: event.name, |
| 32 | filters: [...event.filters], |
| 33 | }, |
| 34 | data: [], // Will be populated by fetch stage |
| 35 | definition, |
| 36 | }; |
| 37 | concreteSeries.push(concrete); |
| 38 | } else { |
| 39 | // For formulas, we'll create placeholders during compute stage |
| 40 | // Formulas depend on event series, so we skip them here |
| 41 | } |
| 42 | }); |
| 43 | |
| 44 | return { |
| 45 | concreteSeries, |
| 46 | definitions: normalized.series, |
| 47 | input: normalized, |
| 48 | timezone, |
| 49 | }; |
| 50 | } |
no test coverage detected