@objectstack/service-analytics 9.2.0 → 9.4.0
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/index.cjs +33 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -452,7 +452,10 @@ type CompareTo = DatasetCompareTo;
|
|
|
452
452
|
* - applies measure-scoped filters via supplementary grouped queries,
|
|
453
453
|
* - evaluates derived measures (ratio/sum/difference/product) row-by-row (Q1),
|
|
454
454
|
* - shifts the query for `compareTo` (previousPeriod / previousYear) and
|
|
455
|
-
* attaches `<measure>__compare` columns
|
|
455
|
+
* attaches `<measure>__compare` columns,
|
|
456
|
+
* - computes server-side totals (`selection.totals.groupings`, #1753) by
|
|
457
|
+
* re-running the selection per dimension subset, so matrix subtotals and
|
|
458
|
+
* the grand total use each measure's true aggregate.
|
|
456
459
|
*
|
|
457
460
|
* RLS/tenant scoping is NOT handled here — it is enforced inside the strategy
|
|
458
461
|
* via the StrategyContext read-scope hook (D-C). This layer is pure query
|
|
@@ -478,6 +481,7 @@ declare class DatasetExecutor {
|
|
|
478
481
|
* applied per request (ADR-0021 D-C).
|
|
479
482
|
*/
|
|
480
483
|
execute(compiled: CompiledDataset, selection: DatasetSelection, context?: ExecutionContext): Promise<AnalyticsResult>;
|
|
484
|
+
private executeSelection;
|
|
481
485
|
private buildQuery;
|
|
482
486
|
private runCompare;
|
|
483
487
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -452,7 +452,10 @@ type CompareTo = DatasetCompareTo;
|
|
|
452
452
|
* - applies measure-scoped filters via supplementary grouped queries,
|
|
453
453
|
* - evaluates derived measures (ratio/sum/difference/product) row-by-row (Q1),
|
|
454
454
|
* - shifts the query for `compareTo` (previousPeriod / previousYear) and
|
|
455
|
-
* attaches `<measure>__compare` columns
|
|
455
|
+
* attaches `<measure>__compare` columns,
|
|
456
|
+
* - computes server-side totals (`selection.totals.groupings`, #1753) by
|
|
457
|
+
* re-running the selection per dimension subset, so matrix subtotals and
|
|
458
|
+
* the grand total use each measure's true aggregate.
|
|
456
459
|
*
|
|
457
460
|
* RLS/tenant scoping is NOT handled here — it is enforced inside the strategy
|
|
458
461
|
* via the StrategyContext read-scope hook (D-C). This layer is pure query
|
|
@@ -478,6 +481,7 @@ declare class DatasetExecutor {
|
|
|
478
481
|
* applied per request (ADR-0021 D-C).
|
|
479
482
|
*/
|
|
480
483
|
execute(compiled: CompiledDataset, selection: DatasetSelection, context?: ExecutionContext): Promise<AnalyticsResult>;
|
|
484
|
+
private executeSelection;
|
|
481
485
|
private buildQuery;
|
|
482
486
|
private runCompare;
|
|
483
487
|
}
|
package/dist/index.js
CHANGED
|
@@ -986,6 +986,33 @@ var DatasetExecutor = class {
|
|
|
986
986
|
* applied per request (ADR-0021 D-C).
|
|
987
987
|
*/
|
|
988
988
|
async execute(compiled, selection, context) {
|
|
989
|
+
const result = await this.executeSelection(compiled, selection, context);
|
|
990
|
+
const groupings = selection.totals?.groupings;
|
|
991
|
+
if (groupings?.length) {
|
|
992
|
+
const selected = new Set(selection.dimensions ?? []);
|
|
993
|
+
const totals = [];
|
|
994
|
+
for (const grouping of groupings) {
|
|
995
|
+
const unknown = grouping.filter((d) => !selected.has(d));
|
|
996
|
+
if (unknown.length) {
|
|
997
|
+
throw new Error(
|
|
998
|
+
`[dataset-executor] totals grouping [${grouping.join(", ")}] is not a subset of the selected dimensions \u2014 unknown: ${unknown.join(", ")}.`
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
const sub = await this.executeSelection(compiled, {
|
|
1002
|
+
...selection,
|
|
1003
|
+
dimensions: grouping,
|
|
1004
|
+
totals: void 0,
|
|
1005
|
+
order: void 0,
|
|
1006
|
+
limit: void 0,
|
|
1007
|
+
offset: void 0
|
|
1008
|
+
}, context);
|
|
1009
|
+
totals.push({ dimensions: grouping, rows: sub.rows });
|
|
1010
|
+
}
|
|
1011
|
+
result.totals = totals;
|
|
1012
|
+
}
|
|
1013
|
+
return result;
|
|
1014
|
+
}
|
|
1015
|
+
async executeSelection(compiled, selection, context) {
|
|
989
1016
|
const derivedByName = new Map(compiled.derived.map((d) => [d.name, d]));
|
|
990
1017
|
const selectedDerived = selection.measures.map((m) => derivedByName.get(m)).filter((d) => !!d);
|
|
991
1018
|
const baseMeasures = /* @__PURE__ */ new Set();
|
|
@@ -1534,6 +1561,12 @@ var AnalyticsService = class {
|
|
|
1534
1561
|
if (dims.length) {
|
|
1535
1562
|
try {
|
|
1536
1563
|
await resolveDimensionLabels(dataset.object, dims, result.rows, this.labelResolver);
|
|
1564
|
+
for (const total of result.totals ?? []) {
|
|
1565
|
+
const subset = dims.filter((d) => total.dimensions.includes(d.name));
|
|
1566
|
+
if (subset.length) {
|
|
1567
|
+
await resolveDimensionLabels(dataset.object, subset, total.rows, this.labelResolver);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1537
1570
|
} catch (e) {
|
|
1538
1571
|
this.logger?.warn?.(`[Analytics] dimension label resolution failed for "${dataset.name}": ${String(e?.message ?? e)}`);
|
|
1539
1572
|
}
|