Class: ExportService
Defined in: server/insights/services/export-service.ts:163
READ-ONLY export of a report definition or a saved report to CSV, XLSX, or PDF. Two separate methods, never a union parameter:
- ExportService.exportDefinition — an ad-hoc (builder) definition.
- ExportService.exportSavedReport — resolves the report through
SavedReportService.get, so org scope, ownership, and private visibility are enforced by the same code path a normal read uses. A private report the caller does not own surfaces asSavedReportNotFoundError— the export path cannot be used to probe for, or read, a report the caller could not open.
Both go through QueryService.run, which validates the definition against
the currently registered model and compiles the tenant predicate in. This
service issues no SQL of its own and never writes — there is no export
history table. RECURRING emailed delivery is layered on top of this method by
@the-kaizen-labs/taproot/insights/scheduling, whose worker calls
ExportService.exportSavedReport and hands the buffer to a consumer
EmailSender — export itself stays a pure read.
Row collection
A grouped/aggregated definition returns its whole result in one snapshot, so
one run suffices. A detail (non-grouped) definition is offset-paginated
at EXPORT_CHUNK_SIZE, so the export pages through it. That stride is the
export's own — it is independent of the interactive MAX_PAGE_SIZE cap so a
wider builder window does not change how many rows a chunk holds in memory.
Two consequences, both deliberate:
- The first page's
page.totalRowsis checked against the format cap before any further page is fetched, so an over-cap export fails fast instead of after N queries. - Each page is its own transaction and therefore its own MVCC snapshot, and
OFFSET pagination over a non-unique
sorthas no defined tie order. For a reproducible detail export, sort on something unique (an id) or export a grouped definition — which is one query and one snapshot. Aggregates are always computed in SQL and passed through untouched; this service never sums money in JS.
Constructors
Constructor
new ExportService(deps: ExportServiceDeps): ExportService;Defined in: server/insights/services/export-service.ts:164
Parameters
| Parameter | Type |
|---|---|
deps | ExportServiceDeps |
Returns
ExportService
Methods
exportDefinition()
exportDefinition(
definition: {
aggregations?: {
alias: string;
field?: string;
fn: "min" | "max" | "count" | "avg" | "sum";
}[];
columns: string[];
filter?: FilterNode;
groupBy?: {
bucket?: "year" | "month" | "day" | "week" | "quarter";
field: string;
}[];
schemaVersion: 1;
sort: {
by: string;
direction: "asc" | "desc";
}[];
subject: string;
timezone: string;
totals?: boolean;
},
format: ExportFormat,
ctx: ExportDefinitionContext
): Promise<ExportFile>;Defined in: server/insights/services/export-service.ts:167
Export an ad-hoc definition. Validated + compiled by QueryService.
Parameters
| Parameter | Type | Description |
|---|---|---|
definition | { aggregations?: { alias: string; field?: string; fn: "min" | "max" | "count" | "avg" | "sum"; }[]; columns: string[]; filter?: FilterNode; groupBy?: { bucket?: "year" | "month" | "day" | "week" | "quarter"; field: string; }[]; schemaVersion: 1; sort: { by: string; direction: "asc" | "desc"; }[]; subject: string; timezone: string; totals?: boolean; } | - |
definition.aggregations? | { alias: string; field?: string; fn: "min" | "max" | "count" | "avg" | "sum"; }[] | - |
definition.columns | string[] | The SELECT list — and the ONLY source of output columns, for grouped runs as much as detail runs: the compiler derives its projection from columns alone and never from groupBy/aggregations. So an empty columns has no compilable projection at all (not merely a semantically odd one), which makes it a STRUCTURAL failure and puts the check here rather than in validateDefinition. Keeping it in the schema also means every surface that parses a definition — run input, saved-report create/update, normalizeSavedReportDefinition on read, canned reports in the registry — fails closed without having to remember a second validation pass. |
definition.filter? | FilterNode | - |
definition.groupBy? | { bucket?: "year" | "month" | "day" | "week" | "quarter"; field: string; }[] | - |
definition.schemaVersion | 1 | - |
definition.sort | { by: string; direction: "asc" | "desc"; }[] | - |
definition.subject | string | - |
definition.timezone | string | - |
definition.totals? | boolean | - |
format | ExportFormat | - |
ctx | ExportDefinitionContext | - |
Returns
Promise<ExportFile>
exportSavedReport()
exportSavedReport(
id: string,
format: ExportFormat,
ctx: ExportSavedReportContext
): Promise<ExportFile>;Defined in: server/insights/services/export-service.ts:183
Export a saved report the caller may read. SavedReportNotFoundError /
SavedReportPermissionError from the resolve step propagate unchanged.
Parameters
| Parameter | Type |
|---|---|
id | string |
format | ExportFormat |
ctx | ExportSavedReportContext |
Returns
Promise<ExportFile>