@objectstack/service-analytics 9.10.0 → 10.0.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.d.cts CHANGED
@@ -227,6 +227,17 @@ interface AnalyticsServiceConfig {
227
227
  * provided, `queryDataset` validates that every declared `include` exists.
228
228
  */
229
229
  relationshipResolver?: RelationshipResolver;
230
+ /**
231
+ * ADR-0053 currency chain — resolve a measure's SOURCE FIELD currency
232
+ * metadata so a monetary measure that omits an explicit `currency` falls back
233
+ * to the field's declared currency, then the tenant default (`ctx.currency`).
234
+ * Returns the source field's `type` and (fixed-mode) `defaultCurrency`;
235
+ * `undefined` for an unknown field. Non-`currency` fields never get a code.
236
+ */
237
+ measureCurrency?: (object: string, field: string) => {
238
+ type?: string;
239
+ defaultCurrency?: string;
240
+ } | undefined;
230
241
  /** Pre-defined datasets to compile + register at construction (ADR-0021). */
231
242
  datasets?: Dataset[];
232
243
  /**
@@ -276,6 +287,7 @@ declare class AnalyticsService implements IAnalyticsService {
276
287
  private readonly datasetRegistry;
277
288
  /** Optional object-graph resolver used when compiling datasets. */
278
289
  private readonly relationshipResolver?;
290
+ private readonly measureCurrency?;
279
291
  /** Optional dimension display-label resolver (select options / lookup names). */
280
292
  private readonly labelResolver?;
281
293
  /** ADR-0037 P3: pending-seed row resolver for draft data preview. */
package/dist/index.d.ts CHANGED
@@ -227,6 +227,17 @@ interface AnalyticsServiceConfig {
227
227
  * provided, `queryDataset` validates that every declared `include` exists.
228
228
  */
229
229
  relationshipResolver?: RelationshipResolver;
230
+ /**
231
+ * ADR-0053 currency chain — resolve a measure's SOURCE FIELD currency
232
+ * metadata so a monetary measure that omits an explicit `currency` falls back
233
+ * to the field's declared currency, then the tenant default (`ctx.currency`).
234
+ * Returns the source field's `type` and (fixed-mode) `defaultCurrency`;
235
+ * `undefined` for an unknown field. Non-`currency` fields never get a code.
236
+ */
237
+ measureCurrency?: (object: string, field: string) => {
238
+ type?: string;
239
+ defaultCurrency?: string;
240
+ } | undefined;
230
241
  /** Pre-defined datasets to compile + register at construction (ADR-0021). */
231
242
  datasets?: Dataset[];
232
243
  /**
@@ -276,6 +287,7 @@ declare class AnalyticsService implements IAnalyticsService {
276
287
  private readonly datasetRegistry;
277
288
  /** Optional object-graph resolver used when compiling datasets. */
278
289
  private readonly relationshipResolver?;
290
+ private readonly measureCurrency?;
279
291
  /** Optional dimension display-label resolver (select options / lookup names). */
280
292
  private readonly labelResolver?;
281
293
  /** ADR-0037 P3: pending-seed row resolver for draft data preview. */
package/dist/index.js CHANGED
@@ -1456,6 +1456,7 @@ var AnalyticsService = class {
1456
1456
  }
1457
1457
  this.readScopeProvider = config.getReadScope;
1458
1458
  this.relationshipResolver = config.relationshipResolver;
1459
+ this.measureCurrency = config.measureCurrency;
1459
1460
  this.labelResolver = config.labelResolver;
1460
1461
  this.draftRowsResolver = config.draftRowsResolver;
1461
1462
  if (config.datasets) {
@@ -1633,8 +1634,21 @@ var AnalyticsService = class {
1633
1634
  }
1634
1635
  throw err;
1635
1636
  }
1636
- if (this.labelResolver && selection.dimensions?.length) {
1637
- const dims = selection.dimensions.map((name) => dataset.dimensions?.find((d) => d.name === name)).filter((d) => !!d?.field).map((d) => ({ name: d.name, field: d.field, type: d.type, dateGranularity: d.dateGranularity }));
1637
+ const selectedDims = (selection.dimensions ?? []).map((name) => dataset.dimensions?.find((d) => d.name === name)).filter((d) => !!d);
1638
+ const drillDims = selectedDims.filter((d) => !!d.field && d.type !== "date");
1639
+ if (drillDims.length && result.rows.length) {
1640
+ result.object = dataset.object;
1641
+ result.dimensionFields = Object.fromEntries(
1642
+ drillDims.map((d) => [d.name, d.field])
1643
+ );
1644
+ result.drillRawRows = result.rows.map((row) => {
1645
+ const raw = {};
1646
+ for (const d of drillDims) raw[d.name] = row[d.name];
1647
+ return raw;
1648
+ });
1649
+ }
1650
+ if (this.labelResolver && selectedDims.length) {
1651
+ const dims = selectedDims.filter((d) => !!d.field).map((d) => ({ name: d.name, field: d.field, type: d.type, dateGranularity: d.dateGranularity }));
1638
1652
  if (dims.length) {
1639
1653
  try {
1640
1654
  await resolveDimensionLabels(dataset.object, dims, result.rows, this.labelResolver);
@@ -1656,6 +1670,25 @@ var AnalyticsService = class {
1656
1670
  if (!m) continue;
1657
1671
  if (f.label == null && typeof m.label === "string") f.label = m.label;
1658
1672
  if (f.format == null && m.format) f.format = m.format;
1673
+ const fc = f;
1674
+ const mc = m;
1675
+ if (fc.currency == null) {
1676
+ const meta = m.field ? this.measureCurrency?.(dataset.object, m.field) : void 0;
1677
+ const monetary = !!mc.currency || meta?.type === "currency";
1678
+ if (monetary) {
1679
+ const resolved = mc.currency ?? meta?.defaultCurrency ?? context?.currency;
1680
+ if (resolved) fc.currency = resolved;
1681
+ }
1682
+ }
1683
+ }
1684
+ }
1685
+ if (result.fields?.length && selectedDims.length) {
1686
+ const dimByName = new Map(selectedDims.map((d) => [d.name, d]));
1687
+ const dimByField = new Map(selectedDims.filter((d) => !!d.field).map((d) => [d.field, d]));
1688
+ for (const f of result.fields) {
1689
+ if (f.label != null) continue;
1690
+ const d = dimByName.get(f.name) ?? dimByField.get(f.name);
1691
+ if (d && typeof d.label === "string") f.label = d.label;
1659
1692
  }
1660
1693
  }
1661
1694
  return result;
@@ -2044,6 +2077,11 @@ var AnalyticsServicePlugin = class {
2044
2077
  coerceTemporalFilterValue,
2045
2078
  relationshipResolver,
2046
2079
  labelResolver,
2080
+ // ADR-0053 — source-field currency metadata for the measure currency chain.
2081
+ measureCurrency: (object, field) => {
2082
+ const f = dataEngine()?.getObject?.(object)?.fields?.[field];
2083
+ return f ? { type: f.type, defaultCurrency: f.currencyConfig?.defaultCurrency } : void 0;
2084
+ },
2047
2085
  draftRowsResolver
2048
2086
  };
2049
2087
  if (autoBridgedReadScope) {