Kaizen
Browse modulesInsightsinsights/serverClasses

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 as SavedReportNotFoundError — 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.totalRows is 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 sort has 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

ParameterType
depsExportServiceDeps

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

ParameterTypeDescription
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.columnsstring[]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.schemaVersion1-
definition.sort{ by: string; direction: "asc" | "desc"; }[]-
definition.subjectstring-
definition.timezonestring-
definition.totals?boolean-
formatExportFormat-
ctxExportDefinitionContext-

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

ParameterType
idstring
formatExportFormat
ctxExportSavedReportContext

Returns

Promise<ExportFile>

On this page