Class: SavedReportsRepository
Defined in: server/insights/saved-reports-repository.ts:112
Base repository providing transaction routing, audit-field helpers, and opt-in activity logging. Extend one of the specialized classes instead of using this directly:
ReadRepository— read-onlyWriteRepository— create + update (append-only)CrudRepository— full CRUD (most common)VersionRepository— parent-child versioning
TClient is the consumer's generated Prisma client (for model accessors on
this.tx). TTx is the transaction handle type (the inner argument of
prisma.$transaction(fn)); it defaults to TClient because modern Prisma
transaction handles are structurally compatible with the top-level client
apart from the $-prefixed control methods.
Extends
BaseRepository<PrismaClient,Tx<PrismaClient>>
Constructors
Constructor
new SavedReportsRepository(prismaClient: PrismaClientLike<Tx<PrismaClient<PrismaClientOptions, never, DefaultArgs>>> & PrismaClient<PrismaClientOptions, never, DefaultArgs>, options?: RepositoryOptions): SavedReportsRepository;Defined in: server/persistence/base-repository.ts:68
Parameters
| Parameter | Type |
|---|---|
prismaClient | PrismaClientLike<Tx<PrismaClient<PrismaClientOptions, never, DefaultArgs>>> & PrismaClient<PrismaClientOptions, never, DefaultArgs> |
options | RepositoryOptions |
Returns
SavedReportsRepository
Inherited from
Properties
ENTITY_TYPE?
protected readonly optional ENTITY_TYPE?: string;Defined in: server/persistence/base-repository.ts:61
Set ENTITY_TYPE in child repositories to enable automatic activity
logging. When set, create/update/delete operations auto-log unless
silenced with .silent. Requires an activity model on the consumer's
Prisma schema.
Inherited from
logger?
protected readonly optional logger?: Logger;Defined in: server/persistence/base-repository.ts:64
Inherited from
prismaClient
protected prismaClient: PrismaClientLike<Tx<PrismaClient<PrismaClientOptions, never, DefaultArgs>>> & PrismaClient<PrismaClientOptions, never, DefaultArgs>;Defined in: server/persistence/base-repository.ts:69
Inherited from
Accessors
actorId
Get Signature
get protected actorId(): string | null | undefined;Defined in: server/persistence/base-repository.ts:76
Returns
string | null | undefined
Inherited from
auditCreate
Get Signature
get protected auditCreate(): {
createdBy: string | null | undefined;
updatedBy: string | null | undefined;
};Defined in: server/persistence/base-repository.ts:90
Returns
{
createdBy: string | null | undefined;
updatedBy: string | null | undefined;
}createdBy
createdBy: string | null | undefined = actorId;updatedBy
updatedBy: string | null | undefined = actorId;Inherited from
auditDelete
Get Signature
get protected auditDelete(): {
deletedAt: Date;
deletedBy: string | null | undefined;
};Defined in: server/persistence/base-repository.ts:99
Returns
{
deletedAt: Date;
deletedBy: string | null | undefined;
}deletedAt
deletedAt: Date;deletedBy
deletedBy: string | null | undefined;Inherited from
auditUpdate
Get Signature
get protected auditUpdate(): {
updatedBy: string | null | undefined;
};Defined in: server/persistence/base-repository.ts:95
Returns
{
updatedBy: string | null | undefined;
}updatedBy
updatedBy: string | null | undefined;Inherited from
silent
Get Signature
get silent(): this;Defined in: server/persistence/base-repository.ts:115
Suppress activity logging for the next mutation call. One-shot: the flag is consumed by the next create/update/delete.
Example
await repo.silent.update(id, data); // no activity logged
await repo.update(id, data); // activity logged normallyReturns
this
Inherited from
tx
Get Signature
get protected tx(): TTx;Defined in: server/persistence/base-repository.ts:86
The current Prisma handle: the active transaction if one is running on this async context, otherwise the raw client.
Returns
TTx
Inherited from
Methods
consumeSilent()
protected consumeSilent(): boolean;Defined in: server/persistence/base-repository.ts:128
Consume and reset the silent flag. Called by template methods.
Returns
boolean
Inherited from
create()
create(input: {
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;
};
description?: string | null;
name: string;
organizationId: string;
subjectKey: string;
userId: string;
visibility?: "public" | "private";
}): Promise<SavedReport>;Defined in: server/insights/saved-reports-repository.ts:232
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { 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; }; description?: string | null; name: string; organizationId: string; subjectKey: string; userId: string; visibility?: "public" | "private"; } | - |
input.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; } | - |
input.definition.aggregations? | { alias: string; field?: string; fn: "min" | "max" | "count" | "avg" | "sum"; }[] | - |
input.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. |
input.definition.filter? | FilterNode | - |
input.definition.groupBy? | { bucket?: "year" | "month" | "day" | "week" | "quarter"; field: string; }[] | - |
input.definition.schemaVersion | 1 | - |
input.definition.sort | { by: string; direction: "asc" | "desc"; }[] | - |
input.definition.subject | string | - |
input.definition.timezone | string | - |
input.definition.totals? | boolean | - |
input.description? | string | null | - |
input.name | string | - |
input.organizationId | string | - |
input.subjectKey | string | - |
input.userId | string | - |
input.visibility? | "public" | "private" | - |
Returns
Promise<SavedReport>
delete()
delete(input: {
id: string;
organizationId: string;
userId: string;
}): Promise<void>;Defined in: server/insights/saved-reports-repository.ts:335
Parameters
| Parameter | Type |
|---|---|
input | { id: string; organizationId: string; userId: string; } |
input.id | string |
input.organizationId | string |
input.userId | string |
Returns
Promise<void>
existsActive()
existsActive(input: {
id: string;
organizationId: string;
}): Promise<boolean>;Defined in: server/insights/saved-reports-repository.ts:170
Whether an active row exists in the organization, deliberately ignoring viewer visibility. The scheduled-delivery worker uses this SYSTEM read to distinguish a deleted report from a still-existing report its actor can no longer read; it must never expose the result to a request caller.
Parameters
| Parameter | Type |
|---|---|
input | { id: string; organizationId: string; } |
input.id | string |
input.organizationId | string |
Returns
Promise<boolean>
get()
get(input: {
id: string;
organizationId: string;
userId: string;
}): Promise<SavedReport>;Defined in: server/insights/saved-reports-repository.ts:147
Parameters
| Parameter | Type |
|---|---|
input | { id: string; organizationId: string; userId: string; } |
input.id | string |
input.organizationId | string |
input.userId | string |
Returns
Promise<SavedReport>
getAuthorizationFields()
getAuthorizationFields(input: {
id: string;
organizationId: string;
userId: string;
}): Promise<SavedReportAuthorizationFields>;Defined in: server/insights/saved-reports-repository.ts:208
The authorization columns for one report — with the stored definition
neither fetched nor parsed.
get ends in toDomain, which runs normalizeSavedReportDefinition and
throws SavedReportValidationError on a definition that no longer
parses. Failing closed is right for a READ; it is fatal as a WRITE
precondition, because delete and updateDefinition are precisely the
operations that exist to remove or repair such a row. Authorizing a write
through get therefore makes a corrupt row unfixable: the recovery paths
fail before they reach the repository at all.
So this method MUST NOT normalize, and must keep definition out of its
select so it cannot start to. That is its contract, not an
optimization — every input an authorization decision needs (existence, org
scope, visibility, ownership) plus subjectKey is a raw column.
Same visibility gate as SavedReportsRepository.get: a non-owner's
PRIVATE row misses the filter and surfaces as
SavedReportNotFoundError (no existence leak). Ownership is left to
the caller to judge from createdBy — the mutating methods still re-check
it authoritatively inside their own transaction via getOwnedOrThrow.
Parameters
| Parameter | Type |
|---|---|
input | { id: string; organizationId: string; userId: string; } |
input.id | string |
input.organizationId | string |
input.userId | string |
Returns
Promise<SavedReportAuthorizationFields>
list()
list(input: {
organizationId: string;
subjectKey?: string;
userId: string;
}): Promise<SavedReport[]>;Defined in: server/insights/saved-reports-repository.ts:130
Parameters
| Parameter | Type |
|---|---|
input | { organizationId: string; subjectKey?: string; userId: string; } |
input.organizationId | string |
input.subjectKey? | string |
input.userId | string |
Returns
Promise<SavedReport[]>
logActivity()
protected logActivity(
_entityId: string,
_action: string,
_metadata?: Record<string, unknown>
): Promise<void>;Defined in: server/persistence/base-repository.ts:140
Log an activity entry.
NOTE: This is not implemented because there's no activity model implemented in taproot yet! https://linear.app/kaizenlabs/issue/ENG-7846/add-activity-log-tables
Parameters
| Parameter | Type |
|---|---|
_entityId | string |
_action | string |
_metadata? | Record<string, unknown> |
Returns
Promise<void>
Inherited from
rename()
rename(input: {
id: string;
name: string;
organizationId: string;
userId: string;
}): Promise<SavedReport>;Defined in: server/insights/saved-reports-repository.ts:287
Parameters
| Parameter | Type |
|---|---|
input | { id: string; name: string; organizationId: string; userId: string; } |
input.id | string |
input.name | string |
input.organizationId | string |
input.userId | string |
Returns
Promise<SavedReport>
setVisibility()
setVisibility(input: {
id: string;
organizationId: string;
userId: string;
visibility: "public" | "private";
}): Promise<SavedReport>;Defined in: server/insights/saved-reports-repository.ts:321
Parameters
| Parameter | Type |
|---|---|
input | { id: string; organizationId: string; userId: string; visibility: "public" | "private"; } |
input.id | string |
input.organizationId | string |
input.userId | string |
input.visibility | "public" | "private" |
Returns
Promise<SavedReport>
updateDefinition()
updateDefinition(input: {
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;
};
description?: string | null;
id: string;
name?: string;
organizationId: string;
userId: string;
}): Promise<SavedReport>;Defined in: server/insights/saved-reports-repository.ts:301
Parameters
| Parameter | Type | Description |
|---|---|---|
input | { 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; }; description?: string | null; id: string; name?: string; organizationId: string; userId: string; } | - |
input.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; } | - |
input.definition.aggregations? | { alias: string; field?: string; fn: "min" | "max" | "count" | "avg" | "sum"; }[] | - |
input.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. |
input.definition.filter? | FilterNode | - |
input.definition.groupBy? | { bucket?: "year" | "month" | "day" | "week" | "quarter"; field: string; }[] | - |
input.definition.schemaVersion | 1 | - |
input.definition.sort | { by: string; direction: "asc" | "desc"; }[] | - |
input.definition.subject | string | - |
input.definition.timezone | string | - |
input.definition.totals? | boolean | - |
input.description? | string | null | - |
input.id | string | - |
input.name? | string | - |
input.organizationId | string | - |
input.userId | string | - |
Returns
Promise<SavedReport>