Skip to content

Latest commit

 

History

History
1309 lines (953 loc) · 42.3 KB

File metadata and controls

1309 lines (953 loc) · 42.3 KB

Changelog — @objectstack/service-analytics

16.1.0

Patch Changes

  • Updated dependencies [9e45b63]
  • Updated dependencies [b20201f]
    • @objectstack/spec@16.1.0
    • @objectstack/core@16.1.0

16.0.0

Minor Changes

  • a9459e6: Analytics drill metadata now snapshots raw grouped values for totals/subtotal rows too (#3214). The ADR-0021 D2 drill sidecar (drillRawRows, #2080) only covered result.rows, but the totals rows added in #1753 carry dimension values and go through the same label resolution — which overwrote their stored value (select option value, lookup/master_detail FK id) with the display label, leaving a subtotal drill nothing to exact-match on.

    queryDataset now also emits drillRawTotals, aligned to result.totals by index (drillRawTotals[i][j]result.totals[i].rows[j]), captured in the same pre-label-resolution pass. Each map is restricted to the drillable dimensions the grouping actually groups by, so the grand-total grouping ([]) contributes an empty map per row. Purely additive result props (same as #2080) — no spec-contract change.

  • dd9f223: feat(analytics): scope a datetime date-bucket drill to the reference-tz midnight instants (#1752 follow-up)

    Closes the one gap left by the initial #1752 change: a datetime date dimension bucketed under a non-UTC reference timezone previously fell back to a superset drill (its bucket boundary is that tz's midnight instant, which YYYY-MM-DD calendar bounds can't express).

    • @objectstack/core adds zonedDateStartToUtcMs(ymd, tz) — the UTC instant at which a calendar day begins in a reference timezone (the inverse of calendarPartsInTz). DST-safe: the offset is read from the platform tz database via Intl, with a two-pass resolution for the rare offset-boundary case; an unset/'UTC'/invalid zone returns plain UTC midnight.
    • @objectstack/service-analytics now emits drillRanges bounds per the field's temporal type (ADR-0053): a datetime field → ISO instant bounds at the reference tz's midnight (works under any tz, incl. DST); a date field → YYYY-MM-DD calendar bounds (tz-naive, exact under any tz). An unknown field type is still emitted only under UTC and omitted (superset) under a non-UTC tz.

    No objectui change is needed — the client already forwards whatever bound values the server sends into the drill filter and the filter[field][gte|lt] URL.

  • 290e2f0: feat(analytics): emit a half-open date-range drill scope for granularity-bucketed date dimensions (#1752)

    A report/dashboard cell grouped by a dateGranularity date dimension ("2026-Q2") covers a SPAN of records, so drilling it needs a range (>= start AND < nextStart), which the equality drill contract (drillRawRows) can't express — date dims were therefore excluded from drill metadata and a drill landed on an unscoped superset.

    • @objectstack/core adds bucketKeyToCalendarRange(key, granularity), the inverse of bucketDateValue: it turns a canonical bucket key into its half-open [start, end) calendar span (YYYY-MM-DD, end exclusive). Pure, timezone-naive calendar arithmetic; returns null for unbucketable / out-of-range keys so the caller falls back to an unscoped (superset) drill rather than emit a wrong bound.
    • @objectstack/service-analytics emits a drillRanges sidecar (aligned to rows by index — the range companion to drillRawRows) for date + dateGranularity dimensions, computed from the canonical bucket key in the pre-label-resolution snapshot pass. A datetime field under a non-UTC reference timezone is omitted (host drills a superset) until instant-boundary support lands; a tz-naive date field is exact under any timezone (ADR-0053).

    Consumed by objectui's report drill-through to scope the drilled record list to the clicked time bucket.

Patch Changes

  • Updated dependencies [f972574]
  • Updated dependencies [6289ec3]
  • Updated dependencies [22013aa]
  • Updated dependencies [3ad3dd5]
  • Updated dependencies [8efa395]
  • Updated dependencies [3a18b60]
  • Updated dependencies [a8aa34c]
  • Updated dependencies [e057f42]
  • Updated dependencies [a3823b2]
  • Updated dependencies [43a3efb]
  • Updated dependencies [524696a]
  • Updated dependencies [bfa3c3f]
  • Updated dependencies [5e3301d]
  • Updated dependencies [dd9f223]
  • Updated dependencies [46e876c]
  • Updated dependencies [5f05de2]
  • Updated dependencies [021ba4c]
  • Updated dependencies [158aa14]
  • Updated dependencies [62a2117]
  • Updated dependencies [d2723e2]
  • Updated dependencies [fefcd54]
  • Updated dependencies [beaf2de]
  • Updated dependencies [369eb6e]
  • Updated dependencies [06ff734]
  • Updated dependencies [b659111]
  • Updated dependencies [5754a23]
  • Updated dependencies [6c270a6]
  • Updated dependencies [290e2f0]
  • Updated dependencies [668dd17]
  • Updated dependencies [8abf133]
  • Updated dependencies [e0859b1]
  • Updated dependencies [04ecd4e]
  • Updated dependencies [4d5a892]
  • Updated dependencies [16cebeb]
  • Updated dependencies [86d30af]
  • Updated dependencies [8923843]
  • Updated dependencies [a2795f6]
  • Updated dependencies [f16b492]
  • Updated dependencies [4b6fde8]
  • Updated dependencies [2018df9]
  • Updated dependencies [fc5a3a2]
  • Updated dependencies [8ff9210]
    • @objectstack/spec@16.0.0
    • @objectstack/core@16.0.0

16.0.0-rc.1

Patch Changes

  • Updated dependencies [6289ec3]
  • Updated dependencies [8efa395]
  • Updated dependencies [bfa3c3f]
  • Updated dependencies [62a2117]
  • Updated dependencies [06ff734]
    • @objectstack/spec@16.0.0-rc.1
    • @objectstack/core@16.0.0-rc.1

16.0.0-rc.0

Minor Changes

  • a9459e6: Analytics drill metadata now snapshots raw grouped values for totals/subtotal rows too (#3214). The ADR-0021 D2 drill sidecar (drillRawRows, #2080) only covered result.rows, but the totals rows added in #1753 carry dimension values and go through the same label resolution — which overwrote their stored value (select option value, lookup/master_detail FK id) with the display label, leaving a subtotal drill nothing to exact-match on.

    queryDataset now also emits drillRawTotals, aligned to result.totals by index (drillRawTotals[i][j]result.totals[i].rows[j]), captured in the same pre-label-resolution pass. Each map is restricted to the drillable dimensions the grouping actually groups by, so the grand-total grouping ([]) contributes an empty map per row. Purely additive result props (same as #2080) — no spec-contract change.

  • dd9f223: feat(analytics): scope a datetime date-bucket drill to the reference-tz midnight instants (#1752 follow-up)

    Closes the one gap left by the initial #1752 change: a datetime date dimension bucketed under a non-UTC reference timezone previously fell back to a superset drill (its bucket boundary is that tz's midnight instant, which YYYY-MM-DD calendar bounds can't express).

    • @objectstack/core adds zonedDateStartToUtcMs(ymd, tz) — the UTC instant at which a calendar day begins in a reference timezone (the inverse of calendarPartsInTz). DST-safe: the offset is read from the platform tz database via Intl, with a two-pass resolution for the rare offset-boundary case; an unset/'UTC'/invalid zone returns plain UTC midnight.
    • @objectstack/service-analytics now emits drillRanges bounds per the field's temporal type (ADR-0053): a datetime field → ISO instant bounds at the reference tz's midnight (works under any tz, incl. DST); a date field → YYYY-MM-DD calendar bounds (tz-naive, exact under any tz). An unknown field type is still emitted only under UTC and omitted (superset) under a non-UTC tz.

    No objectui change is needed — the client already forwards whatever bound values the server sends into the drill filter and the filter[field][gte|lt] URL.

  • 290e2f0: feat(analytics): emit a half-open date-range drill scope for granularity-bucketed date dimensions (#1752)

    A report/dashboard cell grouped by a dateGranularity date dimension ("2026-Q2") covers a SPAN of records, so drilling it needs a range (>= start AND < nextStart), which the equality drill contract (drillRawRows) can't express — date dims were therefore excluded from drill metadata and a drill landed on an unscoped superset.

    • @objectstack/core adds bucketKeyToCalendarRange(key, granularity), the inverse of bucketDateValue: it turns a canonical bucket key into its half-open [start, end) calendar span (YYYY-MM-DD, end exclusive). Pure, timezone-naive calendar arithmetic; returns null for unbucketable / out-of-range keys so the caller falls back to an unscoped (superset) drill rather than emit a wrong bound.
    • @objectstack/service-analytics emits a drillRanges sidecar (aligned to rows by index — the range companion to drillRawRows) for date + dateGranularity dimensions, computed from the canonical bucket key in the pre-label-resolution snapshot pass. A datetime field under a non-UTC reference timezone is omitted (host drills a superset) until instant-boundary support lands; a tz-naive date field is exact under any timezone (ADR-0053).

    Consumed by objectui's report drill-through to scope the drilled record list to the clicked time bucket.

Patch Changes

  • Updated dependencies [f972574]
  • Updated dependencies [22013aa]
  • Updated dependencies [3ad3dd5]
  • Updated dependencies [3a18b60]
  • Updated dependencies [a8aa34c]
  • Updated dependencies [e057f42]
  • Updated dependencies [a3823b2]
  • Updated dependencies [43a3efb]
  • Updated dependencies [524696a]
  • Updated dependencies [5e3301d]
  • Updated dependencies [dd9f223]
  • Updated dependencies [46e876c]
  • Updated dependencies [5f05de2]
  • Updated dependencies [021ba4c]
  • Updated dependencies [158aa14]
  • Updated dependencies [d2723e2]
  • Updated dependencies [fefcd54]
  • Updated dependencies [beaf2de]
  • Updated dependencies [369eb6e]
  • Updated dependencies [b659111]
  • Updated dependencies [5754a23]
  • Updated dependencies [6c270a6]
  • Updated dependencies [290e2f0]
  • Updated dependencies [668dd17]
  • Updated dependencies [8abf133]
  • Updated dependencies [e0859b1]
  • Updated dependencies [04ecd4e]
  • Updated dependencies [4d5a892]
  • Updated dependencies [16cebeb]
  • Updated dependencies [86d30af]
  • Updated dependencies [8923843]
  • Updated dependencies [a2795f6]
  • Updated dependencies [f16b492]
  • Updated dependencies [4b6fde8]
  • Updated dependencies [2018df9]
  • Updated dependencies [fc5a3a2]
    • @objectstack/spec@16.0.0-rc.0
    • @objectstack/core@16.0.0-rc.0

15.1.1

Patch Changes

  • @objectstack/spec@15.1.1
  • @objectstack/core@15.1.1

15.1.0

Patch Changes

  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [3fe9df1]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [4109153]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [627f225]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
  • Updated dependencies [f531a26]
    • @objectstack/spec@15.1.0
    • @objectstack/core@15.1.0

15.0.0

Patch Changes

  • Updated dependencies [28b7c28]
  • Updated dependencies [13749ec]
  • Updated dependencies [e62c233]
  • Updated dependencies [ed61c9b]
  • Updated dependencies [31d04d4]
    • @objectstack/spec@15.0.0
    • @objectstack/core@15.0.0

14.8.0

Patch Changes

  • Updated dependencies [16b4bf6]
  • Updated dependencies [16b4bf6]
  • Updated dependencies [10e8983]
  • Updated dependencies [607aaf4]
  • Updated dependencies [bb71321]
    • @objectstack/spec@14.8.0
    • @objectstack/core@14.8.0

14.7.0

Patch Changes

  • Updated dependencies [d6a72eb]
    • @objectstack/spec@14.7.0
    • @objectstack/core@14.7.0

14.6.0

Patch Changes

  • Updated dependencies [609cb13]
  • Updated dependencies [ce6d151]
    • @objectstack/spec@14.6.0
    • @objectstack/core@14.6.0

14.5.0

Patch Changes

  • Updated dependencies [526805e]
  • Updated dependencies [d79ca07]
  • Updated dependencies [33ebd34]
  • Updated dependencies [c044f08]
  • Updated dependencies [01274eb]
    • @objectstack/spec@14.5.0
    • @objectstack/core@14.5.0

14.4.0

Patch Changes

  • Updated dependencies [7953832]
  • Updated dependencies [82e745e]
  • Updated dependencies [f3035bd]
  • Updated dependencies [82c0d94]
  • Updated dependencies [7449476]
    • @objectstack/spec@14.4.0
    • @objectstack/core@14.4.0

14.3.0

Patch Changes

  • Updated dependencies [2a71f48]
  • Updated dependencies [02f6af4]
  • Updated dependencies [c1064f1]
    • @objectstack/spec@14.3.0
    • @objectstack/core@14.3.0

14.2.0

Patch Changes

  • Updated dependencies [ac8f029]
  • Updated dependencies [4ab9958]
    • @objectstack/spec@14.2.0
    • @objectstack/core@14.2.0

14.1.0

Patch Changes

  • Updated dependencies [5a8465f]
  • Updated dependencies [7f8620b]
  • Updated dependencies [82ba3a6]
    • @objectstack/spec@14.1.0
    • @objectstack/core@14.1.0

14.0.0

Patch Changes

  • Updated dependencies [0a8e685]
  • Updated dependencies [afa8115]
  • Updated dependencies [80f12ca]
  • Updated dependencies [e2fa074]
  • Updated dependencies [23c8668]
  • Updated dependencies [29f017d]
  • Updated dependencies [216fa9a]
  • Updated dependencies [6c22b12]
    • @objectstack/spec@14.0.0
    • @objectstack/core@14.0.0

13.0.0

Patch Changes

  • Updated dependencies [6d83431]
  • Updated dependencies [01917c2]
  • Updated dependencies [b271691]
  • Updated dependencies [a5a1e41]
  • Updated dependencies [466adf6]
  • Updated dependencies [5be00c3]
  • Updated dependencies [466adf6]
  • Updated dependencies [2bee609]
  • Updated dependencies [fc7e7f7]
    • @objectstack/spec@13.0.0
    • @objectstack/core@13.0.0

12.6.0

Patch Changes

  • Updated dependencies [6cebf22]
  • Updated dependencies [21420d9]
    • @objectstack/spec@12.6.0
    • @objectstack/core@12.6.0

12.5.0

Patch Changes

  • Updated dependencies [8b3d363]
    • @objectstack/spec@12.5.0
    • @objectstack/core@12.5.0

12.4.0

Patch Changes

  • Updated dependencies [60dc3ba]
    • @objectstack/spec@12.4.0
    • @objectstack/core@12.4.0

12.3.0

Patch Changes

  • Updated dependencies [e7eceec]
    • @objectstack/spec@12.3.0
    • @objectstack/core@12.3.0

12.2.0

Patch Changes

  • Updated dependencies [fce8ff4]
  • Updated dependencies [3962023]
  • Updated dependencies [2bb193d]
  • Updated dependencies [0426d27]
  • Updated dependencies [da807f7]
  • Updated dependencies [4f5b791]
    • @objectstack/spec@12.2.0
    • @objectstack/core@12.2.0

12.1.0

Patch Changes

  • Updated dependencies [93e6d02]
    • @objectstack/spec@12.1.0
    • @objectstack/core@12.1.0

12.0.0

Patch Changes

  • Updated dependencies [a8df396]
  • Updated dependencies [e695fe0]
  • Updated dependencies [7c09621]
  • Updated dependencies [7709db4]
  • Updated dependencies [2082109]
  • Updated dependencies [7c09621]
  • Updated dependencies [9860de4]
  • Updated dependencies [069c205]
    • @objectstack/spec@12.0.0
    • @objectstack/core@12.0.0

11.10.0

Patch Changes

  • Updated dependencies [6a9397e]
  • Updated dependencies [c0efe5d]
    • @objectstack/spec@11.10.0
    • @objectstack/core@11.10.0

11.9.0

Patch Changes

  • Updated dependencies [d3595d9]
    • @objectstack/spec@11.9.0
    • @objectstack/core@11.9.0

11.8.0

Patch Changes

  • @objectstack/spec@11.8.0
  • @objectstack/core@11.8.0

11.7.0

Patch Changes

  • Updated dependencies [5178906]
    • @objectstack/spec@11.7.0
    • @objectstack/core@11.7.0

11.6.0

Patch Changes

  • @objectstack/spec@11.6.0
  • @objectstack/core@11.6.0

11.5.0

Patch Changes

  • Updated dependencies [6ee4f04]
  • Updated dependencies [c1e3a65]
    • @objectstack/spec@11.5.0
    • @objectstack/core@11.5.0

11.4.0

Patch Changes

  • Updated dependencies [5821c51]
  • Updated dependencies [a0fce3f]
    • @objectstack/spec@11.4.0
    • @objectstack/core@11.4.0

11.3.0

Patch Changes

  • Updated dependencies [58e8e31]
  • Updated dependencies [b4a5df0]
    • @objectstack/spec@11.3.0
    • @objectstack/core@11.3.0

11.2.0

Patch Changes

  • Updated dependencies [d0f4b13]
  • Updated dependencies [302bdab]
    • @objectstack/spec@11.2.0
    • @objectstack/core@11.2.0

11.1.0

Patch Changes

  • Updated dependencies [ce0b4f6]
  • Updated dependencies [9ccfcd6]
  • Updated dependencies [ecf193f]
  • Updated dependencies [51bec81]
  • Updated dependencies [3e593a7]
  • Updated dependencies [63d5403]
    • @objectstack/core@11.1.0
    • @objectstack/spec@11.1.0

11.0.0

Minor Changes

  • 5eef4cf: feat(analytics): multi-hop relationship joins for datasets (ADR-0071)

    A dataset's include and dimension/measure field paths may now traverse up to 3 to-one relationship hops (account.owner.region), not just one. The compiler expands each declared path into the ordered join chain (one cube.join per path prefix, aliased dot-free as account__owner so it stays a single valid SQL identifier), and the NativeSQLStrategy emits the chained LEFT JOINs. Per-hop tenant/RLS read-scope is enforced for EVERY object in the chain — the alias-driven scope loop already generalizes, so no security path is rewritten.

    Restricted to to-one (lookup / master_detail) relationships, which never fan out — aggregates stay correct with no symmetric-aggregate machinery; to-many traversal is out of scope. Single-hop datasets are byte-for-byte unchanged (the dot-free alias is a no-op for a single segment). Undeclared paths are still rejected (ADR-0021 D-C); paths beyond 3 hops are rejected at both parse and compile time.

Patch Changes

  • 910a8f0: fix(analytics): compare boolean filters/group-by against the real boolean, not stringified '1'

    The analytics filter normalizer stringified boolean true'1', which the ObjectQL strategy then coerced back to the number 1 before calling engine.aggregate. Boolean fields hold a real true/false, so 1 !== true never matched: a metric widget filtered on a boolean field (e.g. { is_critical: true }) always returned 0, and pie/donut/bar charts grouped by a boolean dimension failed to bucket. stringifyForCube now serializes booleans as the tokens 'true'/'false', and a new coerceFilterValueForObjectQL recovers a real boolean for the ObjectQL engine while the SQL path keeps binding 1/0 (better-sqlite3 cannot bind a JS boolean).

  • 715d667: fix(analytics): qualify base-object columns in joined dataset queries

    A dataset that joins a related object (include + a relationship.field dimension/measure) emitted BARE base-table columns in SELECT/GROUP BY while the joined columns were alias-qualified. When the base and joined tables share a column name (e.g. both have status), the query failed at runtime with "ambiguous column name". NativeSQLStrategy now qualifies plain base-column identifiers with the base table when the cube has joins; single-object cubes are unchanged (byte-for-byte identical SQL).

  • Updated dependencies [ab5718a]

  • Updated dependencies [4845c12]

  • Updated dependencies [c1a754a]

  • Updated dependencies [6fbe91f]

  • Updated dependencies [715d667]

  • Updated dependencies [5eef4cf]

  • Updated dependencies [72759e1]

  • Updated dependencies [6c4fbd9]

  • Updated dependencies [ef3ed67]

  • Updated dependencies [cd51229]

  • Updated dependencies [7697a0e]

  • Updated dependencies [e7e04f1]

  • Updated dependencies [cfd5ac4]

  • Updated dependencies [2be5c1f]

  • Updated dependencies [ad143ce]

  • Updated dependencies [5c4a8c8]

  • Updated dependencies [3afaeed]

  • Updated dependencies [8801c02]

  • Updated dependencies [3d04e06]

  • Updated dependencies [4a84c98]

  • Updated dependencies [c715d25]

  • Updated dependencies [aa33b02]

  • Updated dependencies [d980f0d]

  • Updated dependencies [a658523]

  • Updated dependencies [82ff91c]

  • Updated dependencies [638f472]

    • @objectstack/spec@11.0.0
    • @objectstack/core@11.0.0

10.3.0

Patch Changes

  • f73d40a: fix(analytics): log scalar auto-inferred cubes at debug, not warn

    Scalar metric queries (measures only, no dimensions/timeDimensions) over an unregistered cube — the first-class object-metric "metric over an object" path — auto-infer a trivial count/sum cube by design. That auto-infer now logs at debug instead of warn, so boot/render no longer spams No cube registered for "..." for a non-problem. Grouped queries (explicit dimension / time bucket) over an unregistered cube keep the warn, where a forgotten cube registration is a real mistake.

    • @objectstack/spec@10.3.0
    • @objectstack/core@10.3.0

10.2.0

Patch Changes

  • Updated dependencies [b496498]
    • @objectstack/spec@10.2.0
    • @objectstack/core@10.2.0

10.1.0

Minor Changes

  • 49da36e: feat(analytics): correct analytics over federated objects (ADR-0062 Phase 3, D6)

    Analytics over an external (federated) object now aggregates against the correct remote table instead of silently querying the wrong one. The NativeSQLStrategy hand-compiles FROM "<object>" and bare column references, which bypass the driver's physical-table resolution (external.remoteName / remoteSchema / columnMap). It now declines any query whose base or joined object is federated, routing it to the ObjectQLStrategy — whose engine.aggregate() goes through the driver's getBuilder and already honours remoteName/remoteSchema (#2138/#2149). This "reuses the driver's resolution" (D6) rather than re-implementing it.

    Adds an optional StrategyContext.isExternalObject(objectName) hook (reported by the analytics plugin from the object's external block). Purely additive — with no hook, behavior is unchanged for managed objects.

Patch Changes

  • Updated dependencies [49da36e]
  • Updated dependencies [ac79f16]
    • @objectstack/spec@10.1.0
    • @objectstack/core@10.1.0

10.0.0

Minor Changes

  • 70609af: Resolve a monetary measure's display currency via the field→tenant chain.

    A dataset measure-currency now resolves through: explicit measure currency → source-field currencyConfig.defaultCurrency → tenant default (ctx.currency). A measure is monetary iff it declares a currency or aggregates a currency-type field, so count/avg-of-number measures never receive a code. Wires a measureCurrency field-metadata resolver from the data engine's object schema.

  • 3187952: Dataset analytics enrich dimension result fields with their display label (so report/dashboard table headers read "Status" instead of the raw field name) and expose drill-through metadata on the dataset query result: the base object, a drillable dimension→field map, and a parallel drillRawRows array of each row's raw grouped values (captured before label resolution). This lets a host drill a grouped bucket back to its underlying records with an exact-match filter built from the stored value, not the display label. Date dimensions are excluded (a humanized bucket can't be exact-matched).

  • a581385: Propagate a dataset measure's declared currency to the analytics result field.

    Adds an optional DatasetMeasure.currency (ISO 4217) on the semantic layer and carries it onto each measure result field alongside label/format, so a currency-aware client (Intl symbol) can render ¥1,234 / $616,000 from a real currency code instead of a plain number or a $ baked into format. Additive and optional — existing datasets are unaffected.

Patch Changes

  • Updated dependencies [d7ff626]
  • Updated dependencies [2a1b16b]
  • Updated dependencies [e16f2a8]
  • Updated dependencies [e411a82]
  • Updated dependencies [a581385]
  • Updated dependencies [d5f6d29]
  • Updated dependencies [220ce5b]
  • Updated dependencies [3efe334]
  • Updated dependencies [feead7e]
  • Updated dependencies [6ca20b3]
  • Updated dependencies [5f875fe]
  • Updated dependencies [b469950]
    • @objectstack/spec@10.0.0
    • @objectstack/core@10.0.0

9.11.0

Patch Changes

  • Updated dependencies [e7f6539]
  • Updated dependencies [2365d07]
  • Updated dependencies [6595b53]
  • Updated dependencies [fa8964d]
  • Updated dependencies [36138c7]
  • Updated dependencies [a8e4f3b]
  • Updated dependencies [4c213c2]
  • Updated dependencies [2afb612]
    • @objectstack/spec@9.11.0
    • @objectstack/core@9.11.0

9.10.0

Patch Changes

  • db02bd5: Fix dashboard time-series charts / "last N months" KPIs that filter or group by a Field.datetime column silently returning "No rows".

    The analytics NativeSQLStrategy compiles dashboard relative-date tokens ({12_months_ago}, {today}, …) to ISO date strings and binds them directly into raw SQL, bypassing the driver's own filter coercion. Under better-sqlite3 a Field.datetime column is stored as an INTEGER epoch (ms), so assessed_at >= '2025-06-18' became a TEXT-vs-INTEGER affinity compare that is always false — an empty result even though the rows exist. Field.date columns store ISO TEXT and were unaffected.

    The strategy now coerces a temporal comparand to the column's on-disk storage form via a new optional StrategyContext.coerceTemporalFilterValue hook, wired to the driver's public SqlDriver.temporalFilterValue (the single source of truth for the storage convention). Coercion is dialect-correct: SQLite Field.datetime → epoch ms; Field.date text and native-timestamp dialects (Postgres/MySQL) are left unchanged, so Postgres is never handed an epoch integer. Applied to gte/lte/gt/lt/equals, in/notIn, and the dateRange/timeDimension BETWEEN path.

  • fd07027: fix(analytics): make organization timezone actually drive date-dimension bucketing (ADR-0053 Phase 2, #1982)

    Date-bucketed analytics silently ignored the reference timezone end-to-end. Three independent seams were broken:

    • service-analyticsNativeSQLStrategy (priority 10) won every cube/dataset query on a SQL driver, but it groups by the raw column (no date_trunc) and ignores timezone, so a date dimension never bucketed (one row per raw timestamp) and a non-UTC zone was dropped. It now declines queries that carry a timeDimensions[].granularity, handing them to ObjectQLStrategyengine.aggregate (native bucketing when UTC-safe, uniform in-memory bucketing when non-UTC).
    • objectql — the in-memory count aggregation treated the * count-all sentinel (the Cube count measure / a fieldless dataset count, both compiled to sql: '*') as a column name, counting non-null of a non-existent property → 0 for every bucket. The driver's COUNT(*) masked it; the in-memory path (non-UTC date buckets, driver-rest/driver-memory) returned zeros. * is now counted as all rows.
    • restresolveExecCtx never resolved the localization timezone/locale, so /analytics/dataset/query always ran with timezone: 'UTC'. It now resolves them through the settings service (honouring the 4-tier cascade incl. the OS_LOCALIZATION_TIMEZONE env override), mirroring the dispatcher path.
  • Updated dependencies [db02bd5]

  • Updated dependencies [641675d]

  • Updated dependencies [94e9040]

  • Updated dependencies [1f88fd9]

  • Updated dependencies [1f88fd9]

    • @objectstack/spec@9.10.0
    • @objectstack/core@9.10.0

9.9.1

Patch Changes

  • @objectstack/spec@9.9.1
  • @objectstack/core@9.9.1

9.9.0

Minor Changes

  • 9afeb2d: feat(settings): localization settings — platform default timezone, language & formats (ADR-0053 Phase 2)

    Adds a localization SettingsManifest, the missing keystone that makes the Phase 2 reference-timezone actually configurable end-to-end. One declaration gives the full settings stack for free: platform built-in default → globaltenant cascade, a permission-gated settings page, and i18n.

    Keys (organization-level; per-user overrides intentionally out of scope for v1): timezone (UTC), locale (en-US), default_country, date_format, time_format, number_format, first_day_of_week, currency (USD), fiscal_year_start. Benchmarked against Salesforce/Workday "Company Information + Locale".

    Resolver 收编resolveExecutionContext now resolves timezone and locale from the localization settings via the settings service (canonical 4-tier cascade), falling back to a direct tenant-scoped sys_setting read, then UTC / en-US. This replaces the hand-rolled sys_user_preference + tenant-only sys_setting path from #1978 (which bypassed the settings abstraction and is dropped along with the per-user tier). New ExecutionContext.locale.

    Consumer wiring — analytics date bucketing now picks up the resolved org timezone: DatasetExecutor threads ExecutionContext.timezone into the query (precedence: explicit selection tz → request tz → UTC), so #1982's tz-aware buckets fire for a configured org without callers passing a zone. Formula today()/datetime were already wired (#1979/#1980).

    Email datetime rendering (SendTemplateInput.timezone, shipped in #1981) is intentionally not wired here: the only current sendTemplate callers are pre-session auth emails with no org context; business-notification callers can pass the zone when they appear.

  • 601cc11: feat(analytics): timezone-aware date bucketing (ADR-0053 Phase 2)

    Analytics day/week/month/quarter/year buckets now resolve on a reference timezone's calendar days, so a row near a tz day-boundary lands in the bucket a user in that zone would expect — identically on SQLite and Postgres.

    Per ADR-0053 decision D2, bucketing is done in-memory, uniformly for non-UTC zones rather than emitting dialect-specific date_trunc … AT TIME ZONE (SQLite has no tz database and MySQL needs tz tables loaded, so splitting by dialect would shift bucket boundaries for the same data). engine.aggregate({ timezone }) therefore forces the in-memory aggregation path when a non-UTC reference tz is set — the date-range where still goes to the driver, so only matching rows are fetched. UTC / unset keeps the native driver fast path unchanged.

    • New shared calendarPartsInTz / calendarPartsInTzOrUtc util in @objectstack/core (DST-safe via Intl.DateTimeFormat, never hand-rolled offset math; falls back to UTC for an unset/'UTC'/invalid zone).
    • EngineAggregateOptions and the analytics executeAggregate bridge / ObjectQLStrategy thread the reference timezone (sourced from the dataset selection / ExecutionContext) through to applyInMemoryAggregationbucketDateValue, and the draft-preview evaluator's bucketDate.
    • formatDateBucket (dimension labels) stays UTC-only by design: it re-labels values that were already bucketed upstream, so re-applying a timezone there would shift a correct bucket by a day.

Patch Changes

  • Updated dependencies [84249a4]
  • Updated dependencies [11af299]
  • Updated dependencies [d5774b5]
  • Updated dependencies [134043a]
  • Updated dependencies [90108e0]
  • Updated dependencies [9afeb2d]
  • Updated dependencies [6bec07e]
  • Updated dependencies [601cc11]
  • Updated dependencies [575448d]
    • @objectstack/spec@9.9.0
    • @objectstack/core@9.9.0

9.8.0

Patch Changes

  • Updated dependencies [97c55b3]
  • Updated dependencies [1b1f490]
    • @objectstack/spec@9.8.0
    • @objectstack/core@9.8.0

9.7.0

Patch Changes

  • @objectstack/spec@9.7.0
  • @objectstack/core@9.7.0

9.6.0

Patch Changes

  • Updated dependencies [d1e930a]
  • Updated dependencies [71578f2]
  • Updated dependencies [5e3a301]
  • Updated dependencies [5db2742]
    • @objectstack/spec@9.6.0
    • @objectstack/core@9.6.0

9.5.1

Patch Changes

  • Updated dependencies [ee72aae]
    • @objectstack/spec@9.5.1
    • @objectstack/core@9.5.1

9.5.0

Patch Changes

  • Updated dependencies [d08551c]
  • Updated dependencies [707aeed]
  • Updated dependencies [7a103d4]
  • Updated dependencies [4b01250]
    • @objectstack/spec@9.5.0
    • @objectstack/core@9.5.0

9.4.0

Patch Changes

  • Updated dependencies [060467a]
  • Updated dependencies [0856476]
  • Updated dependencies [b678d8c]
  • Updated dependencies [b678d8c]
  • Updated dependencies [b678d8c]
    • @objectstack/spec@9.4.0
    • @objectstack/core@9.4.0

9.3.0

Minor Changes

  • b4765be: Server-side totals for matrix reports (#1753). queryDataset selections accept totals: { groupings: string[][] } — each grouping a subset of selection.dimensions to additionally aggregate by ([] = grand total); the marginal rows come back on AnalyticsResult.totals in request order. Each subtotal/grand total re-runs the full executor pipeline (measure-scoped filters, derived measures, compareTo) grouped only by that subset, so totals use each measure's true aggregate over the underlying rows — an avg total is the average of all rows, never an average of bucket averages (the ADR-0021 line that forbids client-side re-aggregation). Dimension display labels resolve on totals rows the same as the primary grid. A matrix report renderer asks for { groupings: [rowDims, columnDims, []] } and renders the supplied totals row/column.

Patch Changes

  • Updated dependencies [1ada658]
  • Updated dependencies [3219191]
  • Updated dependencies [290f631]
  • Updated dependencies [50b7b47]
  • Updated dependencies [f15d6f6]
  • Updated dependencies [f8684ea]
  • Updated dependencies [b4765be]
    • @objectstack/spec@9.3.0
    • @objectstack/core@9.3.0

9.2.0

Patch Changes

  • Updated dependencies [2f57b75]
  • Updated dependencies [2f57b75]
    • @objectstack/spec@9.2.0
    • @objectstack/core@9.2.0

9.1.0

Patch Changes

  • Updated dependencies [b9062c9]
    • @objectstack/spec@9.1.0
    • @objectstack/core@9.1.0

9.0.1

Patch Changes

  • Updated dependencies [1817845]
    • @objectstack/spec@9.0.1
    • @objectstack/core@9.0.1

9.0.0

Minor Changes

  • 4a0736b: Analytics now renders date dimensions as human bucket labels instead of raw epoch millis, and buckets them by their declared granularity.

    • A date dimension with an explicit dateGranularity is now grouped by that bucket (the executor promotes it to a time dimension), so a "monthly" trend chart shows one point per month rather than one per raw timestamp.
    • Grouped date values are formatted to a sort-stable label per granularity (year2026, quarter2026-Q2, month2026-04, day/week2026-04-15), so charts no longer show 1777632968596.

    Pairs with the dimension display-label resolution (select option labels / lookup names) shipped previously.

  • 2c6864f: Analytics dimensions now render human display labels instead of raw stored values. A select dimension shows its option label (e.g. Backlog rather than backlog), and a lookup/master_detail dimension shows the related record's display name (e.g. an account's name rather than its FK id). queryDataset resolves these server-side, so every dashboard/report chart benefits with no frontend change. Date/number/string dimensions are unaffected, and unresolved values are left as-is.

  • 0bf39f1: queryDataset now carries each measure's display label and format on the result fields, so presentations can show "Tasks" / "$616,000" instead of the raw measure name "task_count" / "616000".

    • AnalyticsResult.fields[] gains optional label? and format?.
    • The dataset executor enriches measure columns from the dataset's measure definitions (matching <name> and <name>__compare).

    The format can't be baked into the numeric row value (charts need the raw number), so the renderer applies it at display time.

Patch Changes

  • Updated dependencies [4c3f693]
  • Updated dependencies [0bf39f1]
  • Updated dependencies [f533f42]
  • Updated dependencies [1c83ee8]
    • @objectstack/spec@9.0.0
    • @objectstack/core@9.0.0

8.0.1

Patch Changes

  • @objectstack/spec@8.0.1
  • @objectstack/core@8.0.1

8.0.0

Patch Changes

  • Updated dependencies [a46c017]
  • Updated dependencies [b990b89]
  • Updated dependencies [99111ec]
  • Updated dependencies [d5a8161]
  • Updated dependencies [5cf1f1b]
  • Updated dependencies [9ef89d4]
  • Updated dependencies [3306d2f]
  • Updated dependencies [c262301]
  • Updated dependencies [bc44195]
  • Updated dependencies [9e2e229]
    • @objectstack/spec@8.0.0
    • @objectstack/core@8.0.0

7.9.0

Patch Changes

  • @objectstack/spec@7.9.0
  • @objectstack/core@7.9.0

7.8.0

Patch Changes

  • Updated dependencies [06f2bbb]
  • Updated dependencies [36719db]
  • Updated dependencies [424ab26]
    • @objectstack/spec@7.8.0
    • @objectstack/core@7.8.0

7.7.0

Patch Changes

  • Updated dependencies [b391955]
  • Updated dependencies [f06b64e]
  • Updated dependencies [023bf93]
    • @objectstack/spec@7.7.0
    • @objectstack/core@7.7.0

7.6.0

Patch Changes

  • Updated dependencies [955d4c8]
  • Updated dependencies [c4a4cbd]
  • Updated dependencies [b046ec2]
  • Updated dependencies [2170ad9]
  • Updated dependencies [02d6359]
  • Updated dependencies [7648242]
  • Updated dependencies [8fa1e7f]
  • Updated dependencies [55866f5]
  • Updated dependencies [60f9c45]
    • @objectstack/spec@7.6.0
    • @objectstack/core@7.6.0

7.5.0

Patch Changes

  • @objectstack/spec@7.5.0
  • @objectstack/core@7.5.0

7.4.1

Patch Changes

  • @objectstack/spec@7.4.1
  • @objectstack/core@7.4.1

7.4.0

Patch Changes

  • Updated dependencies [23c7107]
  • Updated dependencies [c72daad]
  • Updated dependencies [f115182]
  • Updated dependencies [2faf9f2]
  • Updated dependencies [2faf9f2]
  • Updated dependencies [2faf9f2]
  • Updated dependencies [58b450b]
  • Updated dependencies [82eb6cf]
  • Updated dependencies [13d8653]
  • Updated dependencies [ff3d006]
  • Updated dependencies [5e831de]
    • @objectstack/spec@7.4.0
    • @objectstack/core@7.4.0

7.3.0

Patch Changes

  • Updated dependencies [5e7c554]
    • @objectstack/spec@7.3.0
    • @objectstack/core@7.3.0

7.2.1

Patch Changes

  • @objectstack/spec@7.2.1
  • @objectstack/core@7.2.1

7.2.0

Patch Changes

  • @objectstack/spec@7.2.0
  • @objectstack/core@7.2.0

7.1.0

Patch Changes

  • Updated dependencies [47a92f4]
    • @objectstack/spec@7.1.0
    • @objectstack/core@7.1.0

7.0.0

Patch Changes

  • Updated dependencies [74470ad]
  • Updated dependencies [d29617e]
  • Updated dependencies [dc72172]
    • @objectstack/spec@7.0.0
    • @objectstack/core@7.0.0

6.9.0

Patch Changes

  • @objectstack/spec@6.9.0
  • @objectstack/core@6.9.0

6.8.1

Patch Changes

  • @objectstack/spec@6.8.1
  • @objectstack/core@6.8.1

6.8.0

Patch Changes

  • Updated dependencies [6e88f77]
  • Updated dependencies [c8b9f57]
    • @objectstack/spec@6.8.0
    • @objectstack/core@6.8.0

6.7.1

Patch Changes

  • @objectstack/spec@6.7.1
  • @objectstack/core@6.7.1

6.7.0

Patch Changes

  • Updated dependencies [430067b]
  • Updated dependencies [4f9e9d4]
    • @objectstack/spec@6.7.0
    • @objectstack/core@6.7.0

6.6.0

Patch Changes

  • Updated dependencies [a49cfc2]
    • @objectstack/spec@6.6.0
    • @objectstack/core@6.6.0

6.5.1

Patch Changes

  • @objectstack/spec@6.5.1
  • @objectstack/core@6.5.1

6.5.0

Patch Changes

  • @objectstack/spec@6.5.0
  • @objectstack/core@6.5.0

6.4.0

Patch Changes

  • Updated dependencies [f8651cc]
  • Updated dependencies [f8651cc]
  • Updated dependencies [0bf6f9a]
    • @objectstack/spec@6.4.0
    • @objectstack/core@6.4.0

6.3.0

Patch Changes

  • @objectstack/spec@6.3.0
  • @objectstack/core@6.3.0

6.2.0

Patch Changes

  • Updated dependencies [b4c74a9]
    • @objectstack/spec@6.2.0
    • @objectstack/core@6.2.0

6.1.1

Patch Changes

  • @objectstack/spec@6.1.1
  • @objectstack/core@6.1.1

6.1.0

Patch Changes

  • Updated dependencies [93c0589]
    • @objectstack/spec@6.1.0
    • @objectstack/core@6.1.0

6.0.0

Patch Changes

  • Updated dependencies [629a716]
  • Updated dependencies [dbc4f7d]
  • Updated dependencies [944f187]
    • @objectstack/spec@6.0.0
    • @objectstack/core@6.0.0

5.2.0

Patch Changes

  • Updated dependencies [bab2b20]
  • Updated dependencies [fa011d8]
  • Updated dependencies [b806f58]
    • @objectstack/spec@5.2.0
    • @objectstack/core@5.2.0

5.1.0

Patch Changes

  • Updated dependencies [75f4ee6]
  • Updated dependencies [823d559]
    • @objectstack/spec@5.1.0
    • @objectstack/core@5.1.0

5.0.0

Patch Changes

  • Updated dependencies [2f9073a]
    • @objectstack/spec@5.0.0
    • @objectstack/core@5.0.0

4.2.0

Patch Changes

  • Updated dependencies [2869891]
    • @objectstack/spec@4.2.0
    • @objectstack/core@4.2.0

4.1.1

Patch Changes

  • @objectstack/spec@4.1.1
  • @objectstack/core@4.1.1

4.1.0

Patch Changes

  • Updated dependencies [2108c30]
  • Updated dependencies [23db640]
    • @objectstack/spec@4.1.0
    • @objectstack/core@4.1.0

4.0.5

Patch Changes

  • 15e0df6: chore: unify all package versions to a single patch release
  • Updated dependencies [15e0df6]
    • @objectstack/spec@4.0.5
    • @objectstack/core@4.0.5

4.0.4

Patch Changes

  • Updated dependencies [326b66b]
    • @objectstack/spec@4.0.4
    • @objectstack/core@4.0.4

4.0.3

Patch Changes

  • @objectstack/spec@4.0.3
  • @objectstack/core@4.0.3

4.0.2

Patch Changes

  • Updated dependencies [5f659e9]
    • @objectstack/spec@4.0.2
    • @objectstack/core@4.0.2

4.0.0

Patch Changes

  • Updated dependencies [f08ffc3]
  • Updated dependencies [e0b0a78]
    • @objectstack/spec@4.0.0
    • @objectstack/core@4.0.0

3.3.1

Patch Changes

  • @objectstack/spec@3.3.1
  • @objectstack/core@3.3.1

3.2.10

Patch Changes

  • @objectstack/spec@3.3.0
  • @objectstack/core@3.3.0

All notable changes to this package will be documented in this file.

[3.2.9] — 2026-03-22

Added

  • Initial implementation of @objectstack/service-analytics
  • AnalyticsService orchestrator implementing IAnalyticsService
  • Strategy pattern with priority chain:
    • P1 — NativeSQLStrategy: Pushes queries as native SQL to SQL-capable drivers (Postgres, MySQL, etc.)
    • P2 — ObjectQLStrategy: Translates analytics queries into ObjectQL engine.aggregate() calls
    • P3 — InMemoryStrategy: Delegates to any registered IAnalyticsService (e.g., MemoryAnalyticsService)
  • CubeRegistry for auto-discovery and registration of cubes from manifest definitions and object schema inference
  • AnalyticsServicePlugin for kernel plugin lifecycle integration
  • queryCapabilities() driver capability probing for strategy selection
  • generateSql() dry-run SQL generation across all strategies
  • Unit tests covering all strategy branches