@happyvertical/smrt-reports 0.57.31 → 0.57.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/compiler.js CHANGED
@@ -1,171 +1,2 @@
1
- import { getRuntimeReportOptions } from "./decorators.js";
2
- import { ObjectRegistry } from "@happyvertical/smrt-core";
3
- import { toSnakeCase } from "@happyvertical/smrt-core/utils";
4
- //#region src/compiler.ts
5
- var REPORT_BASE_FIELDS = /* @__PURE__ */ new Set([
6
- "id",
7
- "slug",
8
- "context",
9
- "created_at",
10
- "updated_at",
11
- "createdAt",
12
- "updatedAt",
13
- "refreshedAt"
14
- ]);
15
- function sourceClassName(source) {
16
- if (typeof source === "string") return source;
17
- return source.name;
18
- }
19
- function reportOptionsFromRegistry(reportCtor) {
20
- return (ObjectRegistry.getClassByConstructor(reportCtor) ?? ObjectRegistry.getClass(reportCtor.name))?.config?.report;
21
- }
22
- function getReportOptions(reportCtor) {
23
- const options = getRuntimeReportOptions(reportCtor) ?? reportOptionsFromRegistry(reportCtor);
24
- if (!options?.source) throw new Error(`${reportCtor.name} is missing @report({ source }) metadata. Decorate the report class with @report({ source: SourceClass }).`);
25
- return options;
26
- }
27
- function getRegisteredClassName(ctor) {
28
- const registered = ObjectRegistry.getClassByConstructor(ctor) ?? ObjectRegistry.getClass(ctor.name);
29
- return registered?.qualifiedName ?? registered?.name ?? ctor.name;
30
- }
31
- function resolveTableName(className) {
32
- const tableName = ObjectRegistry.getTableName(className);
33
- if (!tableName) throw new Error(`No SMRT table registered for ${className}. Ensure the class is decorated with @smrt() and its manifest is loaded.`);
34
- return tableName;
35
- }
36
- function parseWhereKey(key) {
37
- const trimmed = key.trim();
38
- const operators = [
39
- " is not null",
40
- " is null",
41
- " not in",
42
- " like",
43
- " in",
44
- " !=",
45
- " >=",
46
- " <=",
47
- " >",
48
- " <",
49
- " ="
50
- ];
51
- const lower = trimmed.toLowerCase();
52
- for (const operator of operators) if (lower.endsWith(operator)) return {
53
- field: trimmed.slice(0, -operator.length).trim(),
54
- suffix: operator
55
- };
56
- return {
57
- field: trimmed,
58
- suffix: ""
59
- };
60
- }
61
- function normalizeConditionKey(key, mapField) {
62
- const { field, suffix } = parseWhereKey(key);
63
- const mapped = mapField(field);
64
- return suffix ? `${mapped}${suffix}` : mapped;
65
- }
66
- function normalizeWhere(where, mapField) {
67
- if (!where) return void 0;
68
- if (Array.isArray(where)) return where.map((andGroup) => andGroup.map((condition) => Object.fromEntries(Object.entries(condition).map(([key, value]) => [normalizeConditionKey(key, mapField), value]))));
69
- return Object.fromEntries(Object.entries(where).map(([key, value]) => [normalizeConditionKey(key, mapField), value]));
70
- }
71
- function readReportMetadata(field) {
72
- return field?._meta?.__report ?? field?.__report;
73
- }
74
- function isReportSystemField(fieldName, field) {
75
- return REPORT_BASE_FIELDS.has(fieldName) || field?._meta?.__smrtSystemField || field?._meta?.__tenancy?.isTenantIdField;
76
- }
77
- async function buildReportDefinition(reportCtor) {
78
- const options = getReportOptions(reportCtor);
79
- const reportClassName = getRegisteredClassName(reportCtor);
80
- const sourceName = sourceClassName(options.source);
81
- const sourceTable = resolveTableName(sourceName);
82
- const fields = await ObjectRegistry.getAllFields(reportClassName);
83
- const reportFields = [];
84
- for (const [fieldName, field] of fields.entries()) {
85
- const report = readReportMetadata(field);
86
- if (!report) {
87
- if (!isReportSystemField(fieldName, field) && !field?.transient) throw new Error(`Report field ${reportCtor.name}.${fieldName} is neither a grouping key nor an aggregate. Add @groupBy(), a time-bucket decorator, or an aggregate decorator.`);
88
- continue;
89
- }
90
- reportFields.push({
91
- fieldName,
92
- columnName: toSnakeCase(fieldName),
93
- type: field.type,
94
- report
95
- });
96
- }
97
- return {
98
- reportClassName,
99
- sourceClassName: sourceName,
100
- sourceTable,
101
- fields: reportFields,
102
- where: options.where,
103
- having: options.having,
104
- refresh: options.refresh
105
- };
106
- }
107
- function sourceColumn(field) {
108
- const report = field.report;
109
- if (!report) throw new Error(`Report field ${field.fieldName} is missing metadata`);
110
- if (report.kind === "group") return toSnakeCase(report.sourceColumn ?? field.fieldName);
111
- if (report.kind === "bucket") return toSnakeCase(report.sourceColumn);
112
- if (report.kind === "aggregate") {
113
- if (!report.column) return "";
114
- return toSnakeCase(report.column);
115
- }
116
- return "";
117
- }
118
- function getReportGroupingColumns(definition) {
119
- const columns = definition.fields.filter((field) => field.report?.kind === "group" || field.report?.kind === "bucket").map((field) => field.columnName ?? toSnakeCase(field.fieldName));
120
- return columns.length > 0 ? columns : ["id"];
121
- }
122
- function compileReportDefinition(definition) {
123
- const select = [];
124
- const groupBy = [];
125
- const reportFieldToColumn = /* @__PURE__ */ new Map();
126
- for (const field of definition.fields) {
127
- const outputColumn = field.columnName ?? toSnakeCase(field.fieldName);
128
- reportFieldToColumn.set(field.fieldName, outputColumn);
129
- reportFieldToColumn.set(outputColumn, outputColumn);
130
- const report = field.report;
131
- if (!report) continue;
132
- if (report.kind === "group") {
133
- select.push({
134
- column: sourceColumn(field),
135
- as: outputColumn
136
- });
137
- groupBy.push(outputColumn);
138
- continue;
139
- }
140
- if (report.kind === "bucket") {
141
- select.push({
142
- bucket: report.unit,
143
- column: sourceColumn(field),
144
- as: outputColumn
145
- });
146
- groupBy.push(outputColumn);
147
- continue;
148
- }
149
- select.push({
150
- fn: report.fn,
151
- column: report.column ? sourceColumn(field) : void 0,
152
- as: outputColumn,
153
- distinct: report.distinct
154
- });
155
- }
156
- if (select.length === 0) throw new Error(`${definition.reportClassName} has no report fields. Add @groupBy(), a time-bucket decorator, or an aggregate decorator.`);
157
- return {
158
- from: definition.sourceTable,
159
- select,
160
- groupBy,
161
- where: normalizeWhere(definition.where, (field) => toSnakeCase(field)),
162
- having: normalizeWhere(definition.having, (field) => reportFieldToColumn.get(field) ?? toSnakeCase(field))
163
- };
164
- }
165
- async function compileReportSpec(reportCtor) {
166
- return compileReportDefinition(await buildReportDefinition(reportCtor));
167
- }
168
- //#endregion
169
- export { buildReportDefinition, compileReportDefinition, compileReportSpec, getReportGroupingColumns };
170
-
171
- //# sourceMappingURL=compiler.js.map
1
+ import { a as getReportGroupingColumns, i as compileReportSpec, n as buildReportDefinition, r as compileReportDefinition, t as REPORT_SOURCE_ALIAS } from "./chunks/compiler-IUB2YNgM.js";
2
+ export { REPORT_SOURCE_ALIAS, buildReportDefinition, compileReportDefinition, compileReportSpec, getReportGroupingColumns };
@@ -1,7 +1,13 @@
1
- import type { ReportAggregateFn, ReportOptions } from './types.js';
1
+ import type { ReportAggregateFn, ReportOperand, ReportOptions } from './types.js';
2
2
  export declare function report(options: ReportOptions): <T extends abstract new (...args: any[]) => any>(ctor: T) => T;
3
3
  export declare function getRuntimeReportOptions(ctor: Function): ReportOptions | undefined;
4
- export declare function groupBy(sourceColumn?: string): PropertyDecorator;
4
+ /**
5
+ * Group by a source column (`'status'`), a joined model's column
6
+ * (`'wo.title'`), or a value computed from each row (`{ expr }`).
7
+ */
8
+ export declare function groupBy(sourceColumnOrExpr?: string | {
9
+ expr: ReportOperand;
10
+ }): PropertyDecorator;
5
11
  export declare const minute: (sourceColumn: string) => PropertyDecorator;
6
12
  export declare const hour: (sourceColumn: string) => PropertyDecorator;
7
13
  export declare const day: (sourceColumn: string) => PropertyDecorator;
@@ -9,29 +15,23 @@ export declare const week: (sourceColumn: string) => PropertyDecorator;
9
15
  export declare const month: (sourceColumn: string) => PropertyDecorator;
10
16
  export declare const quarter: (sourceColumn: string) => PropertyDecorator;
11
17
  export declare const year: (sourceColumn: string) => PropertyDecorator;
12
- export interface AggregateDecoratorOptions {
18
+ export interface AggregateMeasureOptions {
19
+ distinct?: boolean;
20
+ /** Aggregate a computed value of each row instead of a column. */
21
+ expr?: ReportOperand;
22
+ /** Aggregate only the rows this predicate holds for (a filtered count or sum). */
23
+ filter?: ReportOperand;
24
+ }
25
+ export interface AggregateDecoratorOptions extends AggregateMeasureOptions {
13
26
  fn: ReportAggregateFn;
14
27
  column?: string;
15
- distinct?: boolean;
16
28
  }
17
29
  export declare function aggregate(options: AggregateDecoratorOptions): PropertyDecorator;
18
- export declare const sum: (column?: string, options?: {
19
- distinct?: boolean;
20
- }) => PropertyDecorator;
21
- export declare const avg: (column?: string, options?: {
22
- distinct?: boolean;
23
- }) => PropertyDecorator;
24
- export declare const min: (column?: string, options?: {
25
- distinct?: boolean;
26
- }) => PropertyDecorator;
27
- export declare const max: (column?: string, options?: {
28
- distinct?: boolean;
29
- }) => PropertyDecorator;
30
+ export declare const sum: (columnOrOptions?: string | AggregateMeasureOptions, options?: AggregateMeasureOptions) => PropertyDecorator;
31
+ export declare const avg: (columnOrOptions?: string | AggregateMeasureOptions, options?: AggregateMeasureOptions) => PropertyDecorator;
32
+ export declare const min: (columnOrOptions?: string | AggregateMeasureOptions, options?: AggregateMeasureOptions) => PropertyDecorator;
33
+ export declare const max: (columnOrOptions?: string | AggregateMeasureOptions, options?: AggregateMeasureOptions) => PropertyDecorator;
30
34
  export declare function count(): PropertyDecorator;
31
- export declare function count(column: string, options?: {
32
- distinct?: boolean;
33
- }): PropertyDecorator;
34
- export declare function count(options: {
35
- distinct?: boolean;
36
- }): PropertyDecorator;
35
+ export declare function count(column: string, options?: AggregateMeasureOptions): PropertyDecorator;
36
+ export declare function count(options: AggregateMeasureOptions): PropertyDecorator;
37
37
  //# sourceMappingURL=decorators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,iBAAiB,EAGjB,aAAa,EAEd,MAAM,YAAY,CAAC;AAIpB,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,IACnC,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,CAAC,KAAG,CAAC,CAIpE;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,QAAQ,GACb,aAAa,GAAG,SAAS,CAE3B;AAsBD,wBAAgB,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAEhE;AAaD,eAAO,MAAM,MAAM,GAAI,cAAc,MAAM,sBAAmC,CAAC;AAC/E,eAAO,MAAM,IAAI,GAAI,cAAc,MAAM,sBAAiC,CAAC;AAC3E,eAAO,MAAM,GAAG,GAAI,cAAc,MAAM,sBAAgC,CAAC;AACzE,eAAO,MAAM,IAAI,GAAI,cAAc,MAAM,sBAAiC,CAAC;AAC3E,eAAO,MAAM,KAAK,GAAI,cAAc,MAAM,sBAAkC,CAAC;AAC7E,eAAO,MAAM,OAAO,GAAI,cAAc,MAAM,sBACX,CAAC;AAClC,eAAO,MAAM,IAAI,GAAI,cAAc,MAAM,sBAAiC,CAAC;AAE3E,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,iBAAiB,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,yBAAyB,GACjC,iBAAiB,CAOnB;AAOD,eAAO,MAAM,GAAG,YAJG,MAAM,YAAW;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,sBAId,CAAC;AAC7C,eAAO,MAAM,GAAG,YALG,MAAM,YAAW;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,sBAKd,CAAC;AAC7C,eAAO,MAAM,GAAG,YANG,MAAM,YAAW;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,sBAMd,CAAC;AAC7C,eAAO,MAAM,GAAG,YAPG,MAAM,YAAW;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,sBAOd,CAAC;AAE7C,wBAAgB,KAAK,IAAI,iBAAiB,CAAC;AAC3C,wBAAgB,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/B,iBAAiB,CAAC;AACrB,wBAAgB,KAAK,CAAC,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,iBAAiB,CAAC"}
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,iBAAiB,EAGjB,aAAa,EACb,aAAa,EAEd,MAAM,YAAY,CAAC;AAIpB,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,IACnC,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,CAAC,KAAG,CAAC,CAIpE;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,QAAQ,GACb,aAAa,GAAG,SAAS,CAE3B;AAsBD;;;GAGG;AACH,wBAAgB,OAAO,CACrB,kBAAkB,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACpD,iBAAiB,CAWnB;AAaD,eAAO,MAAM,MAAM,GAAI,cAAc,MAAM,sBAAmC,CAAC;AAC/E,eAAO,MAAM,IAAI,GAAI,cAAc,MAAM,sBAAiC,CAAC;AAC3E,eAAO,MAAM,GAAG,GAAI,cAAc,MAAM,sBAAgC,CAAC;AACzE,eAAO,MAAM,IAAI,GAAI,cAAc,MAAM,sBAAiC,CAAC;AAC3E,eAAO,MAAM,KAAK,GAAI,cAAc,MAAM,sBAAkC,CAAC;AAC7E,eAAO,MAAM,OAAO,GAAI,cAAc,MAAM,sBACX,CAAC;AAClC,eAAO,MAAM,IAAI,GAAI,cAAc,MAAM,sBAAiC,CAAC;AAE3E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,kFAAkF;IAClF,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,yBAA0B,SAAQ,uBAAuB;IACxE,EAAE,EAAE,iBAAiB,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,yBAAyB,GACjC,iBAAiB,CASnB;AAeD,eAAO,MAAM,GAAG,qBAXM,MAAM,GAAG,uBAAuB,YACzC,uBAAuB,sBAUQ,CAAC;AAC7C,eAAO,MAAM,GAAG,qBAZM,MAAM,GAAG,uBAAuB,YACzC,uBAAuB,sBAWQ,CAAC;AAC7C,eAAO,MAAM,GAAG,qBAbM,MAAM,GAAG,uBAAuB,YACzC,uBAAuB,sBAYQ,CAAC;AAC7C,eAAO,MAAM,GAAG,qBAdM,MAAM,GAAG,uBAAuB,YACzC,uBAAuB,sBAaQ,CAAC;AAE7C,wBAAgB,KAAK,IAAI,iBAAiB,CAAC;AAC3C,wBAAgB,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,uBAAuB,GAChC,iBAAiB,CAAC;AACrB,wBAAgB,KAAK,CAAC,OAAO,EAAE,uBAAuB,GAAG,iBAAiB,CAAC"}
@@ -18,10 +18,14 @@ function registerReportField(metadata) {
18
18
  });
19
19
  });
20
20
  }
21
- function groupBy(sourceColumn) {
21
+ function groupBy(sourceColumnOrExpr) {
22
+ if (typeof sourceColumnOrExpr === "object" && sourceColumnOrExpr !== null) return registerReportField({
23
+ kind: "group",
24
+ expr: sourceColumnOrExpr.expr
25
+ });
22
26
  return registerReportField({
23
27
  kind: "group",
24
- sourceColumn
28
+ sourceColumn: sourceColumnOrExpr
25
29
  });
26
30
  }
27
31
  function bucket(unit, sourceColumn) {
@@ -43,15 +47,19 @@ function aggregate(options) {
43
47
  kind: "aggregate",
44
48
  fn: options.fn,
45
49
  column: options.column,
50
+ ...options.expr ? { expr: options.expr } : {},
51
+ ...options.filter ? { filter: options.filter } : {},
46
52
  distinct: options.distinct
47
53
  });
48
54
  }
49
55
  function aggregateDecorator(fn) {
50
- return (column, options = {}) => aggregate({
51
- fn,
52
- column,
53
- distinct: options.distinct
54
- });
56
+ return (columnOrOptions, options = {}) => {
57
+ return aggregate({
58
+ fn,
59
+ column: typeof columnOrOptions === "string" ? columnOrOptions : void 0,
60
+ ...typeof columnOrOptions === "object" ? columnOrOptions : options
61
+ });
62
+ };
55
63
  }
56
64
  var sum = aggregateDecorator("sum");
57
65
  var avg = aggregateDecorator("avg");
@@ -61,7 +69,7 @@ function count(columnOrOptions, options = {}) {
61
69
  return aggregate({
62
70
  fn: "count",
63
71
  column: typeof columnOrOptions === "string" ? columnOrOptions : void 0,
64
- distinct: (typeof columnOrOptions === "object" ? columnOrOptions : options).distinct
72
+ ...typeof columnOrOptions === "object" ? columnOrOptions : options
65
73
  });
66
74
  }
67
75
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","names":[],"sources":["../src/decorators.ts"],"sourcesContent":["import {\n ObjectRegistry,\n registerCompatibleFieldDecorator,\n} from '@happyvertical/smrt-core';\nimport type {\n ReportAggregateFieldMetadata,\n ReportAggregateFn,\n ReportBucketFieldMetadata,\n ReportFieldMetadata,\n ReportOptions,\n ReportTimeBucketUnit,\n} from './types.js';\n\nconst reportOptionsByConstructor = new WeakMap<Function, ReportOptions>();\n\nexport function report(options: ReportOptions) {\n return <T extends abstract new (...args: any[]) => any>(ctor: T): T => {\n reportOptionsByConstructor.set(ctor, options);\n return ctor;\n };\n}\n\nexport function getRuntimeReportOptions(\n ctor: Function,\n): ReportOptions | undefined {\n return reportOptionsByConstructor.get(ctor);\n}\n\nfunction registerReportField(metadata: ReportFieldMetadata) {\n return ((targetOrValue: any, propertyKeyOrContext: any) => {\n registerCompatibleFieldDecorator(\n targetOrValue,\n propertyKeyOrContext,\n (className, propertyKey, ctor) => {\n const options = {\n __report: metadata,\n };\n ObjectRegistry.registerFieldDecorator(\n className,\n propertyKey,\n options,\n ctor,\n );\n },\n );\n }) as PropertyDecorator;\n}\n\nexport function groupBy(sourceColumn?: string): PropertyDecorator {\n return registerReportField({ kind: 'group', sourceColumn });\n}\n\nfunction bucket(\n unit: ReportTimeBucketUnit,\n sourceColumn: string,\n): PropertyDecorator {\n return registerReportField({\n kind: 'bucket',\n unit,\n sourceColumn,\n } satisfies ReportBucketFieldMetadata);\n}\n\nexport const minute = (sourceColumn: string) => bucket('minute', sourceColumn);\nexport const hour = (sourceColumn: string) => bucket('hour', sourceColumn);\nexport const day = (sourceColumn: string) => bucket('day', sourceColumn);\nexport const week = (sourceColumn: string) => bucket('week', sourceColumn);\nexport const month = (sourceColumn: string) => bucket('month', sourceColumn);\nexport const quarter = (sourceColumn: string) =>\n bucket('quarter', sourceColumn);\nexport const year = (sourceColumn: string) => bucket('year', sourceColumn);\n\nexport interface AggregateDecoratorOptions {\n fn: ReportAggregateFn;\n column?: string;\n distinct?: boolean;\n}\n\nexport function aggregate(\n options: AggregateDecoratorOptions,\n): PropertyDecorator {\n return registerReportField({\n kind: 'aggregate',\n fn: options.fn,\n column: options.column,\n distinct: options.distinct,\n } satisfies ReportAggregateFieldMetadata);\n}\n\nfunction aggregateDecorator(fn: ReportAggregateFn) {\n return (column?: string, options: { distinct?: boolean } = {}) =>\n aggregate({ fn, column, distinct: options.distinct });\n}\n\nexport const sum = aggregateDecorator('sum');\nexport const avg = aggregateDecorator('avg');\nexport const min = aggregateDecorator('min');\nexport const max = aggregateDecorator('max');\n\nexport function count(): PropertyDecorator;\nexport function count(\n column: string,\n options?: { distinct?: boolean },\n): PropertyDecorator;\nexport function count(options: { distinct?: boolean }): PropertyDecorator;\nexport function count(\n columnOrOptions?: string | { distinct?: boolean },\n options: { distinct?: boolean } = {},\n): PropertyDecorator {\n const column =\n typeof columnOrOptions === 'string' ? columnOrOptions : undefined;\n const resolvedOptions =\n typeof columnOrOptions === 'object' ? columnOrOptions : options;\n return aggregate({\n fn: 'count',\n column,\n distinct: resolvedOptions.distinct,\n });\n}\n"],"mappings":";;AAaA,IAAM,6CAA6B,IAAI,QAAiC;AAEjE,SAAS,OAAO,SAAwB;CAC7C,QAAwD,SAAe;EACrE,2BAA2B,IAAI,MAAM,OAAO;EAC5C,OAAO;CACT;AACF;AAEO,SAAS,wBACd,MAC2B;CAC3B,OAAO,2BAA2B,IAAI,IAAI;AAC5C;AAEA,SAAS,oBAAoB,UAA+B;CAC1D,SAAS,eAAoB,yBAA8B;EACzD,iCACE,eACA,uBACC,WAAW,aAAa,SAAS;GAChC,MAAM,UAAU,EACd,UAAU,SACZ;GACA,eAAe,uBACb,WACA,aACA,SACA,IACF;EACF,CACF;CACF;AACF;AAEO,SAAS,QAAQ,cAA0C;CAChE,OAAO,oBAAoB;EAAE,MAAM;EAAS;CAAa,CAAC;AAC5D;AAEA,SAAS,OACP,MACA,cACmB;CACnB,OAAO,oBAAoB;EACzB,MAAM;EACN;EACA;CACF,CAAqC;AACvC;AAEO,IAAM,UAAU,iBAAyB,OAAO,UAAU,YAAY;AACtE,IAAM,QAAQ,iBAAyB,OAAO,QAAQ,YAAY;AAClE,IAAM,OAAO,iBAAyB,OAAO,OAAO,YAAY;AAChE,IAAM,QAAQ,iBAAyB,OAAO,QAAQ,YAAY;AAClE,IAAM,SAAS,iBAAyB,OAAO,SAAS,YAAY;AACpE,IAAM,WAAW,iBACtB,OAAO,WAAW,YAAY;AACzB,IAAM,QAAQ,iBAAyB,OAAO,QAAQ,YAAY;AAQlE,SAAS,UACd,SACmB;CACnB,OAAO,oBAAoB;EACzB,MAAM;EACN,IAAI,QAAQ;EACZ,QAAQ,QAAQ;EAChB,UAAU,QAAQ;CACpB,CAAwC;AAC1C;AAEA,SAAS,mBAAmB,IAAuB;CACjD,QAAQ,QAAiB,UAAkC,CAAC,MAC1D,UAAU;EAAE;EAAI;EAAQ,UAAU,QAAQ;CAAS,CAAC;AACxD;AAEO,IAAM,MAAM,mBAAmB,KAAK;AACpC,IAAM,MAAM,mBAAmB,KAAK;AACpC,IAAM,MAAM,mBAAmB,KAAK;AACpC,IAAM,MAAM,mBAAmB,KAAK;AAQpC,SAAS,MACd,iBACA,UAAkC,CAAC,GAChB;CAKnB,OAAO,UAAU;EACf,IAAI;EACJ,QALA,OAAO,oBAAoB,WAAW,kBAAkB,KAAA;EAMxD,WAJA,OAAO,oBAAoB,WAAW,kBAAkB,QAAA,CAI9B;CAC5B,CAAC;AACH"}
1
+ {"version":3,"file":"decorators.js","names":[],"sources":["../src/decorators.ts"],"sourcesContent":["import {\n ObjectRegistry,\n registerCompatibleFieldDecorator,\n} from '@happyvertical/smrt-core';\nimport type {\n ReportAggregateFieldMetadata,\n ReportAggregateFn,\n ReportBucketFieldMetadata,\n ReportFieldMetadata,\n ReportOperand,\n ReportOptions,\n ReportTimeBucketUnit,\n} from './types.js';\n\nconst reportOptionsByConstructor = new WeakMap<Function, ReportOptions>();\n\nexport function report(options: ReportOptions) {\n return <T extends abstract new (...args: any[]) => any>(ctor: T): T => {\n reportOptionsByConstructor.set(ctor, options);\n return ctor;\n };\n}\n\nexport function getRuntimeReportOptions(\n ctor: Function,\n): ReportOptions | undefined {\n return reportOptionsByConstructor.get(ctor);\n}\n\nfunction registerReportField(metadata: ReportFieldMetadata) {\n return ((targetOrValue: any, propertyKeyOrContext: any) => {\n registerCompatibleFieldDecorator(\n targetOrValue,\n propertyKeyOrContext,\n (className, propertyKey, ctor) => {\n const options = {\n __report: metadata,\n };\n ObjectRegistry.registerFieldDecorator(\n className,\n propertyKey,\n options,\n ctor,\n );\n },\n );\n }) as PropertyDecorator;\n}\n\n/**\n * Group by a source column (`'status'`), a joined model's column\n * (`'wo.title'`), or a value computed from each row (`{ expr }`).\n */\nexport function groupBy(\n sourceColumnOrExpr?: string | { expr: ReportOperand },\n): PropertyDecorator {\n if (typeof sourceColumnOrExpr === 'object' && sourceColumnOrExpr !== null) {\n return registerReportField({\n kind: 'group',\n expr: sourceColumnOrExpr.expr,\n });\n }\n return registerReportField({\n kind: 'group',\n sourceColumn: sourceColumnOrExpr,\n });\n}\n\nfunction bucket(\n unit: ReportTimeBucketUnit,\n sourceColumn: string,\n): PropertyDecorator {\n return registerReportField({\n kind: 'bucket',\n unit,\n sourceColumn,\n } satisfies ReportBucketFieldMetadata);\n}\n\nexport const minute = (sourceColumn: string) => bucket('minute', sourceColumn);\nexport const hour = (sourceColumn: string) => bucket('hour', sourceColumn);\nexport const day = (sourceColumn: string) => bucket('day', sourceColumn);\nexport const week = (sourceColumn: string) => bucket('week', sourceColumn);\nexport const month = (sourceColumn: string) => bucket('month', sourceColumn);\nexport const quarter = (sourceColumn: string) =>\n bucket('quarter', sourceColumn);\nexport const year = (sourceColumn: string) => bucket('year', sourceColumn);\n\nexport interface AggregateMeasureOptions {\n distinct?: boolean;\n /** Aggregate a computed value of each row instead of a column. */\n expr?: ReportOperand;\n /** Aggregate only the rows this predicate holds for (a filtered count or sum). */\n filter?: ReportOperand;\n}\n\nexport interface AggregateDecoratorOptions extends AggregateMeasureOptions {\n fn: ReportAggregateFn;\n column?: string;\n}\n\nexport function aggregate(\n options: AggregateDecoratorOptions,\n): PropertyDecorator {\n return registerReportField({\n kind: 'aggregate',\n fn: options.fn,\n column: options.column,\n ...(options.expr ? { expr: options.expr } : {}),\n ...(options.filter ? { filter: options.filter } : {}),\n distinct: options.distinct,\n } satisfies ReportAggregateFieldMetadata);\n}\n\nfunction aggregateDecorator(fn: ReportAggregateFn) {\n return (\n columnOrOptions?: string | AggregateMeasureOptions,\n options: AggregateMeasureOptions = {},\n ) => {\n const column =\n typeof columnOrOptions === 'string' ? columnOrOptions : undefined;\n const resolved =\n typeof columnOrOptions === 'object' ? columnOrOptions : options;\n return aggregate({ fn, column, ...resolved });\n };\n}\n\nexport const sum = aggregateDecorator('sum');\nexport const avg = aggregateDecorator('avg');\nexport const min = aggregateDecorator('min');\nexport const max = aggregateDecorator('max');\n\nexport function count(): PropertyDecorator;\nexport function count(\n column: string,\n options?: AggregateMeasureOptions,\n): PropertyDecorator;\nexport function count(options: AggregateMeasureOptions): PropertyDecorator;\nexport function count(\n columnOrOptions?: string | AggregateMeasureOptions,\n options: AggregateMeasureOptions = {},\n): PropertyDecorator {\n const column =\n typeof columnOrOptions === 'string' ? columnOrOptions : undefined;\n const resolvedOptions =\n typeof columnOrOptions === 'object' ? columnOrOptions : options;\n return aggregate({ fn: 'count', column, ...resolvedOptions });\n}\n"],"mappings":";;AAcA,IAAM,6CAA6B,IAAI,QAAiC;AAEjE,SAAS,OAAO,SAAwB;CAC7C,QAAwD,SAAe;EACrE,2BAA2B,IAAI,MAAM,OAAO;EAC5C,OAAO;CACT;AACF;AAEO,SAAS,wBACd,MAC2B;CAC3B,OAAO,2BAA2B,IAAI,IAAI;AAC5C;AAEA,SAAS,oBAAoB,UAA+B;CAC1D,SAAS,eAAoB,yBAA8B;EACzD,iCACE,eACA,uBACC,WAAW,aAAa,SAAS;GAChC,MAAM,UAAU,EACd,UAAU,SACZ;GACA,eAAe,uBACb,WACA,aACA,SACA,IACF;EACF,CACF;CACF;AACF;AAMO,SAAS,QACd,oBACmB;CACnB,IAAI,OAAO,uBAAuB,YAAY,uBAAuB,MACnE,OAAO,oBAAoB;EACzB,MAAM;EACN,MAAM,mBAAmB;CAC3B,CAAC;CAEH,OAAO,oBAAoB;EACzB,MAAM;EACN,cAAc;CAChB,CAAC;AACH;AAEA,SAAS,OACP,MACA,cACmB;CACnB,OAAO,oBAAoB;EACzB,MAAM;EACN;EACA;CACF,CAAqC;AACvC;AAEO,IAAM,UAAU,iBAAyB,OAAO,UAAU,YAAY;AACtE,IAAM,QAAQ,iBAAyB,OAAO,QAAQ,YAAY;AAClE,IAAM,OAAO,iBAAyB,OAAO,OAAO,YAAY;AAChE,IAAM,QAAQ,iBAAyB,OAAO,QAAQ,YAAY;AAClE,IAAM,SAAS,iBAAyB,OAAO,SAAS,YAAY;AACpE,IAAM,WAAW,iBACtB,OAAO,WAAW,YAAY;AACzB,IAAM,QAAQ,iBAAyB,OAAO,QAAQ,YAAY;AAelE,SAAS,UACd,SACmB;CACnB,OAAO,oBAAoB;EACzB,MAAM;EACN,IAAI,QAAQ;EACZ,QAAQ,QAAQ;EAChB,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;EAC7C,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACnD,UAAU,QAAQ;CACpB,CAAwC;AAC1C;AAEA,SAAS,mBAAmB,IAAuB;CACjD,QACE,iBACA,UAAmC,CAAC,MACjC;EAKH,OAAO,UAAU;GAAE;GAAI,QAHrB,OAAO,oBAAoB,WAAW,kBAAkB,KAAA;GAG3B,GAD7B,OAAO,oBAAoB,WAAW,kBAAkB;EACf,CAAC;CAC9C;AACF;AAEO,IAAM,MAAM,mBAAmB,KAAK;AACpC,IAAM,MAAM,mBAAmB,KAAK;AACpC,IAAM,MAAM,mBAAmB,KAAK;AACpC,IAAM,MAAM,mBAAmB,KAAK;AAQpC,SAAS,MACd,iBACA,UAAmC,CAAC,GACjB;CAKnB,OAAO,UAAU;EAAE,IAAI;EAAS,QAH9B,OAAO,oBAAoB,WAAW,kBAAkB,KAAA;EAGlB,GADtC,OAAO,oBAAoB,WAAW,kBAAkB;CACC,CAAC;AAC9D"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export type { ReportAdapterDescriptor, ReportAdapterOptions, ReportBackgroundQue
3
3
  export { buildReportAdapterDescriptor, buildReportDrilldownQuery, queryReportMaterializedRows, reportMaterializedRowKey, splitReportFilterScopes, } from './adapter.js';
4
4
  export { bucketExpr, buildAggregate, } from './aggregate.js';
5
5
  export { buildReportDefinition, compileReportDefinition, compileReportSpec, getReportGroupingColumns, } from './compiler.js';
6
+ export type { AggregateDecoratorOptions, AggregateMeasureOptions, } from './decorators.js';
6
7
  export { aggregate, avg, count, day, getRuntimeReportOptions, groupBy, hour, max, min, minute, month, quarter, report, sum, week, year, } from './decorators.js';
7
8
  export type { AppliedReportRefresh, ApplyReportRefreshOptions, PreviewReportRefreshOptions, ReportLifecycleOptions, ReportLifecycleRun, ReportLifecycleSnapshot, ReportLifecycleState, ReportRefreshActionContext, ReportRefreshActionHost, ReportRefreshJobHandle, ReportRefreshOutcome, ReportRefreshPreview, } from './lifecycle.js';
8
9
  export { applyReportRefresh, getReportLifecycle, previewReportRefresh, reportRefreshOutcome, } from './lifecycle.js';
@@ -27,7 +28,7 @@ export { parseRuntimeReportTime, resolveRuntimeReportTimeRange, runtimeReportBuc
27
28
  export type { EnqueueReportRefreshOptions, EnsureReportSchedulesOptions, ReportExecutionPrincipalReference, ReportRefreshExecutionAuditEvent, ReportRefreshExecutionAuthority, ReportRefreshExecutionAuthorityContext, ReportRefreshExecutionAuthorityHost, ReportRefreshInterceptorOptions, ReportRefreshJobArgs, ReportScheduleInfo, ReportScheduleRunnerConfig, ReportScheduleRunnerEvents, } from './scheduler.js';
28
29
  export { enqueueReportRefresh, ensureReportRefreshSchedules, ReportScheduleRunner, registerReportRefreshExecutionAuthorityHost, registerReportRefreshInterceptor, registerReportRefreshJobIntegritySigner, SmrtPrincipalReportRefreshTask, SmrtReportRefreshTask, } from './scheduler.js';
29
30
  export { assertReportTablesReady, REPORT_LOCKS_TABLE, REPORT_REFRESH_TASKS_TABLE, REPORT_RUNS_TABLE, REPORT_RUNTIME_TABLES, REPORT_SCHEDULER_TABLES, REPORT_SCHEDULES_TABLE, REPORT_WATERMARKS_TABLE, SmrtReportLock, SmrtReportLockCollection, SmrtReportRun, SmrtReportRunCollection, SmrtReportSchedule, SmrtReportScheduleCollection, SmrtReportWatermark, SmrtReportWatermarkCollection, scopeKeyForTenant, } from './state.js';
30
- export type { AggregateBuildResult, AggregateSelectExpr, AggregateSpec, ReportAggregateFieldMetadata, ReportAggregateFn, ReportBucketFieldMetadata, ReportDefinition, ReportFieldDefinition, ReportFieldMetadata, ReportGroupFieldMetadata, ReportOptions, ReportRefreshConfig, ReportRefreshMode, ReportRefreshOptions, ReportRefreshResult, ReportRefreshTrigger, ReportSource, ReportTimeBucketUnit, } from './types.js';
31
+ export type { AggregateBuildResult, AggregateSelectExpr, AggregateSpec, ReportAggregateFieldMetadata, ReportAggregateFn, ReportBucketFieldMetadata, ReportDefinition, ReportFieldDefinition, ReportFieldMetadata, ReportGroupFieldMetadata, ReportJoinDefinition, ReportJoinOptions, ReportOperand, ReportOptions, ReportRefreshConfig, ReportRefreshMode, ReportRefreshOptions, ReportRefreshResult, ReportRefreshTrigger, ReportRelatedFieldPolicy, ReportSource, ReportTimeBucketUnit, } from './types.js';
31
32
  export type { AppliedReportExport, ReportBackgroundExportTask, ReportExportActionContext, ReportExportActionHost, ReportExportArtifact, ReportExportFormat, ReportExportLimits, ReportExportPreview, ReportExportProgress, ReportExportReadPlan, ReportExportRequest, ReportExportSnapshot, ReportExportSnapshotBinding, ReportExportSnapshotContext, ReportSavedView, ReportSavedViewColumn, ReportSavedViewDisplay, ReportSavedViewGrouping, ReportSavedViewPinnedSide, } from './views.js';
32
33
  export { applyReportExport, createReportExportPageRequest, createReportExportRequest, createReportExportSnapshot, migrateReportSavedView, normalizeReportSavedView, previewReportExport, ReportSurfaceValidationError, reportDefinitionFingerprint, restoreReportSavedView, validateReportExportArtifact, validateReportExportExecution, validateReportExportRequest, verifyReportExportSnapshot, } from './views.js';
33
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { aggregate, avg, count, day, getRuntimeReportOptions, groupBy, hour, max, min, minute, month, quarter, report, sum, week, year } from "./decorators.js";
2
- import { buildReportDefinition, compileReportDefinition, compileReportSpec, getReportGroupingColumns } from "./compiler.js";
2
+ import { a as getReportGroupingColumns, c as tenantColumn, i as compileReportSpec, n as buildReportDefinition, r as compileReportDefinition, s as fieldPolicy } from "./chunks/compiler-IUB2YNgM.js";
3
3
  import { REPORT_LOCKS_TABLE, REPORT_REFRESH_TASKS_TABLE, REPORT_RUNS_TABLE, REPORT_RUNTIME_TABLES, REPORT_SCHEDULER_TABLES, REPORT_SCHEDULES_TABLE, REPORT_WATERMARKS_TABLE, SmrtReportLock, SmrtReportLockCollection, SmrtReportRun, SmrtReportRunCollection, SmrtReportSchedule, SmrtReportScheduleCollection, SmrtReportWatermark, SmrtReportWatermarkCollection, assertReportTablesReady, scopeKeyForTenant } from "./state.js";
4
- import { adapterTypeFromDb, refreshReport, reportRowIdentity, tenantColumn } from "./refresh.js";
4
+ import { adapterTypeFromDb, refreshReport, reportRowIdentity } from "./refresh.js";
5
5
  import { ReportScheduleRunner, SmrtPrincipalReportRefreshTask, SmrtReportRefreshTask, enqueueReportRefresh, ensureReportRefreshSchedules, registerReportRefreshExecutionAuthorityHost, registerReportRefreshInterceptor, registerReportRefreshJobIntegritySigner } from "./scheduler.js";
6
6
  import { bucketExpr, buildAggregate } from "./aggregate.js";
7
7
  import { C as runtimeReportSpecDigest, S as parseRuntimeReportSpec, _ as RUNTIME_REPORT_HAVING_OPS, a as runRuntimeReportInMemory, b as RUNTIME_REPORT_SPEC_VERSION, c as coerceRuntimeReportValue, d as planRuntimeReportColumns, f as resolveRuntimeReportFieldPolicy, g as RUNTIME_REPORT_FILTER_OPS, h as RUNTIME_REPORT_CHART_TYPES, i as describeRuntimeReportMemorySource, l as humanizeRuntimeReportName, m as RUNTIME_REPORT_BUCKETS, n as resolveRuntimeReportTimeRange, o as describeRuntimeReportSourceFields, p as unknownRuntimeReportField, r as runtimeReportBucketForSpan, s as assertRuntimeReportFilterOperator, t as parseRuntimeReportTime, u as normalizeRuntimeReportCell, v as RUNTIME_REPORT_LIMITS, w as serializeRuntimeReportSpec, x as RuntimeReportError, y as RUNTIME_REPORT_MEASURE_FNS } from "./chunks/runtime-time-D7JZ1e4J.js";
@@ -213,14 +213,6 @@ var SENSITIVITIES = /* @__PURE__ */ new Set([
213
213
  function registeredClass(ctor) {
214
214
  return ObjectRegistry.getClassByConstructor(ctor) ?? ObjectRegistry.getClass(ctor.name);
215
215
  }
216
- function fieldPolicy(field) {
217
- const meta = field?._meta ?? {};
218
- const sensitivity = [field?.sensitivity, meta.sensitivity].find((value) => typeof value === "string");
219
- return {
220
- sensitive: field?.sensitive === true || meta.sensitive === true || sensitivity === "sensitive" || sensitivity === "secret",
221
- readPermission: typeof field?.readPermission === "string" ? field.readPermission : typeof meta.readPermission === "string" ? meta.readPermission : void 0
222
- };
223
- }
224
216
  function descriptorMetadata(field) {
225
217
  const metadata = field?._meta ?? {};
226
218
  const format = [field?.format, metadata.format].find((value) => typeof value === "string" && value.length > 0);
@@ -243,6 +235,34 @@ function queryType(type) {
243
235
  default: return "string";
244
236
  }
245
237
  }
238
+ function canonical(value) {
239
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
240
+ if (value && typeof value === "object") {
241
+ const object = value;
242
+ return `{${Object.keys(object).filter((key) => object[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(object[key])}`).join(",")}}`;
243
+ }
244
+ return JSON.stringify(value ?? null);
245
+ }
246
+ function columnSemantics(field, joins) {
247
+ const report = field.report;
248
+ if (!report) return void 0;
249
+ const expr = report.kind === "aggregate" || report.kind === "group" ? report.expr : void 0;
250
+ const filter = report.kind === "aggregate" ? report.filter : void 0;
251
+ const text = canonical([expr, filter]);
252
+ const aliases = new Set([...text.matchAll(/"col":"([a-z][a-z0-9_]*)\./g)].map((match) => match[1]));
253
+ const own = report.kind === "group" ? report.sourceColumn : report.kind === "bucket" ? report.sourceColumn : report.column;
254
+ if (own?.includes(".")) aliases.add(own.split(".")[0]);
255
+ const used = joins.filter((join) => aliases.has(join.alias)).map((join) => ({ ...join }));
256
+ if (!expr && !filter && used.length === 0) return void 0;
257
+ return canonical({
258
+ expr,
259
+ filter,
260
+ joins: used
261
+ });
262
+ }
263
+ function columnRef(ref) {
264
+ return ref.split(".").map(toSnakeCase).join(".");
265
+ }
246
266
  function configuredTenantField(configured) {
247
267
  return configured ? toSnakeCase(configured) : void 0;
248
268
  }
@@ -255,15 +275,16 @@ function isColumnBackedField(field) {
255
275
  "manyToMany"
256
276
  ].includes(field.type ?? "");
257
277
  }
258
- function reportColumn(field, registryField) {
278
+ function reportColumn(field, registryField, joins = []) {
259
279
  const policy = fieldPolicy(registryField);
260
- if (policy.sensitive || policy.readPermission || !isColumnBackedField(registryField)) return;
280
+ const relatedRestricted = (field.related ?? []).some((related) => related.sensitive || related.readPermission);
281
+ if (policy.sensitive || policy.readPermission || relatedRestricted || !isColumnBackedField(registryField)) return;
261
282
  const id = field.columnName ?? toSnakeCase(field.fieldName);
262
283
  const report = field.report;
263
284
  if (!report) return void 0;
264
285
  const type = queryType(field.type ?? registryField?.type);
265
286
  const filterOperators = filterOperatorsFor(type);
266
- return {
287
+ const base = {
267
288
  id,
268
289
  fieldName: field.fieldName,
269
290
  label: registryField?.description || labelFor(field.fieldName),
@@ -282,18 +303,21 @@ function reportColumn(field, registryField) {
282
303
  ...report.kind !== "aggregate" ? ["facet"] : [],
283
304
  ...report.kind === "aggregate" ? ["aggregate"] : report.kind === "group" ? ["group"] : []
284
305
  ],
285
- ...report.kind === "group" ? { sourceColumn: toSnakeCase(report.sourceColumn ?? field.fieldName) } : {},
306
+ ...report.kind === "group" && !report.expr ? { sourceColumn: columnRef(report.sourceColumn ?? field.fieldName) } : {},
286
307
  ...report.kind === "bucket" ? {
287
308
  bucket: report.unit,
288
- sourceColumn: toSnakeCase(report.sourceColumn)
309
+ sourceColumn: columnRef(report.sourceColumn)
289
310
  } : {},
290
311
  ...report.kind === "aggregate" ? {
291
312
  aggregate: report.fn,
292
- ...report.column ? { sourceColumn: toSnakeCase(report.column) } : {},
313
+ ...report.column ? { sourceColumn: columnRef(report.column) } : {},
293
314
  ...report.distinct === void 0 ? {} : { distinct: report.distinct }
294
315
  } : {},
295
316
  ...descriptorMetadata(registryField)
296
317
  };
318
+ const semantics = columnSemantics(field, joins);
319
+ if (semantics) base.semantics = semantics;
320
+ return base;
297
321
  }
298
322
  function identityColumn() {
299
323
  return {
@@ -526,7 +550,7 @@ function drilldownDescriptor(columns, sourceClassName) {
526
550
  return {
527
551
  id: "drilldown",
528
552
  sourceClassName,
529
- fields: columns.filter((column) => (column.kind === "group" || column.kind === "bucket") && typeof column.sourceColumn === "string").map((column) => ({
553
+ fields: columns.filter((column) => (column.kind === "group" || column.kind === "bucket") && typeof column.sourceColumn === "string" && !column.sourceColumn.includes(".")).map((column) => ({
530
554
  id: column.id,
531
555
  sourceColumn: column.sourceColumn,
532
556
  kind: column.kind,
@@ -545,7 +569,7 @@ async function buildReportAdapterDescriptor(reportCtor, options = {}) {
545
569
  const registered = registeredClass(reportCtor);
546
570
  const fields = await ObjectRegistry.getAllFields(definition.reportClassName);
547
571
  const tenantField = configuredTenantField(registered?.tenantScopedConfig?.field);
548
- const columns = [identityColumn(), ...definition.fields.map((field) => reportColumn(field, fields.get(field.fieldName))).filter((field) => Boolean(field))].sort((left, right) => left.id.localeCompare(right.id));
572
+ const columns = [identityColumn(), ...definition.fields.map((field) => reportColumn(field, fields.get(field.fieldName), definition.joins)).filter((field) => Boolean(field))].sort((left, right) => left.id.localeCompare(right.id));
549
573
  const schema = {
550
574
  version: 1,
551
575
  identityField: "id",
@@ -597,6 +621,11 @@ async function buildReportAdapterDescriptor(reportCtor, options = {}) {
597
621
  },
598
622
  dataTable,
599
623
  drilldown: drilldownDescriptor(columns, definition.sourceClassName),
624
+ ...definition.joins?.length ? { semantics: canonical({
625
+ joins: definition.joins,
626
+ where: definition.where,
627
+ having: definition.having
628
+ }) } : {},
600
629
  refresh: refreshDescriptor(definition.refresh, options.refreshPermission)
601
630
  };
602
631
  }
@@ -604,6 +633,9 @@ function publicFieldMap(descriptor) {
604
633
  return new Map(descriptor.columns.map((column) => [column.id, column.fieldName]));
605
634
  }
606
635
  async function buildReportDrilldownQuery(reportCtor, row, options = {}) {
636
+ const definition = await buildReportDefinition(reportCtor);
637
+ const unbindable = definition.fields.find((field) => field.report?.kind === "group" && (field.report.expr || field.report.sourceColumn?.includes(".")) || field.report?.kind === "bucket" && field.report.sourceColumn.includes("."));
638
+ if (unbindable) throw new DataQueryValidationError(`Report drilldown is not available for ${definition.reportClassName}: ${unbindable.fieldName} groups by a joined or computed value`, "DATA_QUERY_UNSUPPORTED");
607
639
  const descriptor = await buildReportAdapterDescriptor(reportCtor, options);
608
640
  const constraints = descriptor.drilldown.fields.map((field) => {
609
641
  if (!Object.hasOwn(row, field.id)) throw new DataQueryValidationError(`Report drilldown row is missing grouping field: ${field.id}`, "DATA_QUERY_RESULT_INVALID");
@@ -2009,9 +2041,11 @@ function reportDefinitionFingerprint(descriptor) {
2009
2041
  sourceColumn: column.sourceColumn ?? null,
2010
2042
  bucket: column.bucket ?? null,
2011
2043
  aggregate: column.aggregate ?? null,
2012
- distinct: column.distinct ?? null
2044
+ distinct: column.distinct ?? null,
2045
+ ...column.semantics ? { semantics: column.semantics } : {}
2013
2046
  })),
2014
- schema: descriptor.schema
2047
+ schema: descriptor.schema,
2048
+ ...descriptor.semantics ? { semantics: descriptor.semantics } : {}
2015
2049
  };
2016
2050
  return "rv1_" + createHash("sha256").update(stable(definition), "utf8").digest("base64url");
2017
2051
  }