Loading documentation...
How chart reads call the `get_fire_data` RPC, catalog caching, and TypeScript types.
get_fire_data, catalog, and generated typesFor route-level inventory, see app-routes.md. /atlas chapter detail: atlas-route.md.
@/lib/data-model)| Name | Role |
|---|---|
getCatalog() | Load catalog metadata (request-deduped + 'use cache'). |
FireDataQuery | App query intent (what to ask get_fire_data). |
patchFireDataQuery() | Console controls — merge a control change into query state. |
resolveFireDataRequest(catalog, { query }) | Sync query + build GetFireDataArgs. |
getCachedFireData(args) | Cached RPC read ('use cache' + tag invalidation). |
fireDataQueryFromSearchParams / fireDataQueryToSearchParams | Tier-2 URL ↔ FireDataQuery (/dashboard, /atlas). |
chart-pivot.ts re-exports | Presentation helpers after RPC rows — pivotWideByPeriod, rowsToCategoryTotals, buildDrilldownTree, pivotCategoryTotals, … (/simple, /explore, /atlas). |
Default read path (mental model): Materialised chart data in fire_data flows through Postgres get_fire_data → getCachedFireData. **/explore only** adds exceptions: **native-only** catalog slices (getCachedNativeFireData, no fact_*` write) and BRASK passthrough (live form HTML, no RPC) — see below.
One server read pattern (Tier 2 + Explore ingested branch):
import { getCatalog, resolveFireDataRequest, getCachedFireData } from '@/lib/data-model' const catalog = await getCatalog() const { args } = resolveFireDataRequest(catalog, { query }) const rows = await getCachedFireData(args)
Catalog to client console: server page calls getCatalog(), passes catalog prop to client components (no React context).
components/fire-data/console)Tier-2 routes with full console chrome use the same drawer/toolbar stack; they differ in URL bridge, route preset (console-config.ts), and layout chrome. /explore uses the same components with url="explore" (Tier 1 bridge).
| Piece | Role |
|---|---|
Console | Inline or mobile drawer host; passes resolved config to toolbar. |
ConsoleToolbar | Composes catalog-driven controls into inline grid or drawer stack. |
StandardCodesCollapsible | Standard koder — categories.standard_code → p_cat_standard; flat filters.standard_code → per-axis p_* (dashboard/atlas when showStandardCodes). |
FireDataAxisFilterSection | Filtre — native or standard tokens per filter axis (filters catalog). |
console-config.ts | DEFAULT_CONSOLE_CONFIG + ROUTE_CONSOLE_CONFIG (dashboard, atlas, explore presets). |
ConsoleShell | Unified URL shell: Tier-2 (url="tier2") or Explore (url="explore") + route preset. |
ConsoleChrome | Optional sticky top bar with scroll-aware translucent background (chrome="sticky"). |
ConsoleSheetProvider | Mobile drawer open state; bottom nav retap on /explore and /atlas toggles the sheet (no in-page console trigger). |
Client import rule: 'use client' modules must not import runtime values from @/lib/data-model barrel (pulls 'use cache'). Use @/lib/data-model/fire-data-query-url, fire-data-query, or fire-data-ui directly — see lib/data-model/README.md.
Standard koder vs Filtre: components/fire-data/console/README.md. Catalog option/patch helpers live in fire-data-ui.ts (categoryStandardCodeOptions, filterStandardCodeOptions, …).
fire-data-query-url.ts)Used by /dashboard and /atlas (ConsoleShell url="tier2"). Filter-axis keys mirror RPC shape (no separate filter_standard):
| URL key | FireDataQuery field |
|---|---|
sources, dim_code / dim_codes, year_start, year_end, granularity, metric | p_sources, p_dim_codes, dates, p_granularity, p_metric |
fire_type, building_type, region, building_age | p_fire_type, p_building_type, p_region, p_building_age |
cat_standard | p_cat_standard (categories.standard_code) |
cat_dims | categoryDims — presentational only (which selected dimensions render as category series instead of one SUM series); pruned to ⊆ p_dim_codes and not sent to get_fire_data. |
/simple is Tier 2 for reads (getCatalog → resolveFireDataRequest → getCachedFireData via load-dashboard-data.ts) but uses a narrow URL — ?interval= only (last_6_months | last_365_days | last_5_years | all_time), not this codec or ConsoleShell.
/explore uses Tier 1 — SliceParams + slice-params-bridge.ts, not this codec.
| Tier | Routes | Bridge / notes |
|---|---|---|
| 1 — Explore | /explore only | SliceParams ↔ FireDataQuery via slice-params-bridge.ts. Probe/ingest/slice_hash — explore-fire-data-slice-probe-and-ingest.md. Exceptions: getCachedNativeFireData, BRASK passthrough (mode=native). |
| 2 — Analytics | /dashboard, /atlas, /simple | Shared read: getCatalog → resolveFireDataRequest → getCachedFireData. Full Tier-2 console + URL: /dashboard (loadDashboardFireDataSnapshot, route="dashboard"), /atlas (fetchAtlas*, route="atlas" — atlas-route.md). /simple: same read stack; fetchSimpleDashboardData + ?interval= toolbar; category bar panels + optional buildDrilldownTree drilldown (SIMPLE_PANEL_SORT on totals). |
| Placeholder | /analytics | Presentation-only page; charts discontinued until reintroduced on the read path. See charts-correlation-crosstab.md. |
getFireData / get_fire_dataTS wrapper: lib/data-model/queries.ts — getFireData (uncached, internal/scripts/ingest) and getCachedFireData (Server Component chart reads on ingested slices).
Grain: p_granularity branches the RPC — year → fact_yearly only; sub-year (day · week · month · quarter) → fact_daily only + sources.supports_subyear (yearly totals are never derived from daily rows inside SQL). conceptual-tables-and-grain.md.
Native live read (Explore exception): lib/data-model/native/queries.ts — getCachedNativeFireData for catalog slices where every category row has is_native_only = true (SSB dim 7 Nøkkeltall; BRIS DSB dim 8 Strømkilde (utstyr)). Slice arg cat_codes may be a subset (Explore cat_standard group, SSB only — see explore doc); fire_type_codes / region_codes carry the selected filters.id values so providers with those axes fetch and tag per filter (no filter → one unfiltered fetch tagged NULL, mirroring fact-row semantics). Tags native:${source_id}:${dim_code} and native:all:all; no fact_* write. Provider registry: lib/data-model/native/registry.ts (source 5 → PxWeb table 12058, source 4 → BRIS /restrictedaggregation).
Cache: 'use cache' with cacheTag — fact:${source_id}:${dim_code}:${metric} (count | kr), blanket fact:${source_id}:${dim_code}, fact:all:all, and catalog. Ingest calls revalidateTag on matching tags. Requires cacheComponents: true in next.config.js. Auth I/O is behind Suspense in app/(main)/layout.tsx and app/(docs)/docs/layout.tsx. Chart routes read searchParams inside Suspense children (no export const dynamic = 'force-dynamic').
Generated RPC shape: types/fire_data.database.types.ts. App narrows required dates in lib/data-model/types.ts as GetFireDataArgs. Ingest Insert aliases (FactYearlyInsert, …) live in the same file — see postgres-contract-rls-and-keys.md for column layout.
Shared chart card: SeriesChartCard — page-agnostic Recharts card (line / stacked area / stacked bar / table + optional pie, interactive legend, injected series meta, time or categorical x-axis). ExploreCharts is a thin time/catalog adapter (line + pie only). BRASK passthrough uses BraskPassthroughCharts with full chart-type select.
Chart bucket alignment (ingested path): get_fire_data returns period as YYYY-MM-DD (date_trunc on the sub-year branch; make_date(year, 1, 1) on yearly). enumerateBucketPeriods builds a dense X-axis list that mirrors those SQL anchors (e.g. ISO Monday for week; quarter starts 01 / 04 / 07 / 10). ExploreCharts pivots with pivotWideByPeriod; buckets with no RPC rows stay undefined so Recharts draws gaps, not zero-fill. Tick labels: formatChartPeriod (+ formatChartValue for tooltips).
BRASK live passthrough (Explore only): lib/data-model/adapters/brask-passthrough.ts — fetchBraskPassthrough / getCachedBraskPassthrough (tags brask-passthrough:…). Activated when source_id=1 and mode=native; skips probe/ingest. Console: PassthroughToggle, BraskPassthroughControls.
Daily coverage gating: explore-fire-data-slice-probe-and-ingest.md.
p_breakdown_axes (facet projection + hierarchy blocks)get_fire_data projects filter-axis columns (fire_type_code, building_type_code, …) only when the matching axis name appears in p_breakdown_axes. Console facet filters (p_fire_type, …) normally drive that list via breakdownAxesFromFacetParams inside syncFireDataFacets.
Hierarchy dashboard blocks declare breakdown steps in block options (breakdownSteps → breakdownStepsToQueryPatch). Those axes must reach the RPC even when the console has no facet selection for them. syncFireDataFacets therefore unions explicit p_breakdown_axes from the merged query with facet-derived axes — it does not replace the explicit list.
Snapshot resolution merges options into the read on every resolve (mergeHierarchyBlockQueryPatch in resolve-snapshots.ts and client canvas). See dashboard-route.md (Hierarchy block).
p_metric (one numeric column per response)Each get_fire_data call sums either fact_*.value (p_metric=count) or fact_*.value_kr (p_metric=kr) into the single value field on GetFireDataRow. Cache tags include the metric (fact:${source_id}:${dim_code}:${metric}).
Most blocks use one metric end-to-end (snapshot.query.p_metric → formatChartValue). The bubble timeline block can encode count on one axis and kr on another; resolveDashboardSnapshots then fetches both metrics for that block’s patch hash and merges rows (mergeDualMetricRows in lens-contract.ts). Details: dashboard-route.md (Bubble timeline block).
lib/data-model/fire-data-query.ts — FireDataQuery, patchFireDataQuery, resolveFireDataRequest (also re-exported from barrel).lib/data-model/queries.ts — RPC + cache implementation.lib/data-model/chart-pivot.ts — row → chart structures (re-exported from barrel for routes).lib/data-model/client.ts — Supabase factories (ingestion only).Regenerate types/fire_data.database.types.ts when migrations change RPC args; reconcile this doc with postgres-contract-rls-and-keys.md. Run npm run verify:docs after doc or @see changes.