Follow-on to #4620. A connected store's field metadata should flow from its View rather than being independently (and weakly) declared.
Motivation
A Cube View already reconciles a growing list of config onto its connected stores at connection: digestSpec (cubeRowDigest), projectionOnly (now set/enforced by the View), and - added with calculated fields - a side channel marking view-level calculated field names (Store.setExternalCalculatedFieldNames). Field metadata is the piece still flowing nowhere: connected store fields are today mostly auto-created from grid columns as type: 'auto', so anything reading field metadata off the store (StoreFilterField, filter choosers, display names) sees weaker information than the Cube already has. The calc-names side channel is a narrow shim standing in for real field reconciliation.
Proposed design
On connect (and on updateQuery when the field set changes), the View merges its query fields into the connected store's field list:
- Store fields for view-published data become the query's
CubeField instances (or Fields derived from them) - types, displayNames, and isCalculated flow through.
- App-declared extras are preserved: store-layer
calculatedFn fields composed on top of view rows (e.g. the Store.summaryRecords pct-of-total pattern), and infra fields such as cubeDimension.
Store.generateDataConfig() is deliberately re-runnable and parseStores runs before the connect-time reload, so the timing works with no record migration - the same mechanism setProjectionOnly uses.
The store's evaluation set for calculated fields stays store-layer-only (isCalculated && !isCubeField - a store must never run a (row, ctx) cube fn itself), while the behavioral set (grid repaint, sort staleness handling, filter refresh escalation, read-only columns) becomes derivable from the store's own fields.
What it deletes
Store.setExternalCalculatedFieldNames / _externalCalculatedFieldNames and the lazily-built union in Store.calculatedFieldNames.
View.syncStoreCalculatedFields - the reconciled fields carry the information.
- The
Column.isEditableForRecord gate can return to plain Field.isCalculated.
Open questions
- Conflict rules when an app declares a store field whose name matches a view field (view wins vs. throw).
store.fields visibly changing at connection is a real behavioral surface - grid column/field resolution and filter field specs read it, so this needs its own testing and changelog treatment.
- Whether
CubeField instances are shared by reference or copied into store-appropriate Fields.
Sized as its own PR - deliberately split out of #4636.
Follow-on to #4620. A connected store's field metadata should flow from its View rather than being independently (and weakly) declared.
Motivation
A Cube View already reconciles a growing list of config onto its connected stores at connection:
digestSpec(cubeRowDigest),projectionOnly(now set/enforced by the View), and - added with calculated fields - a side channel marking view-level calculated field names (Store.setExternalCalculatedFieldNames). Field metadata is the piece still flowing nowhere: connected store fields are today mostly auto-created from grid columns astype: 'auto', so anything reading field metadata off the store (StoreFilterField, filter choosers, display names) sees weaker information than the Cube already has. The calc-names side channel is a narrow shim standing in for real field reconciliation.Proposed design
On connect (and on
updateQuerywhen the field set changes), the View merges its query fields into the connected store's field list:CubeFieldinstances (or Fields derived from them) - types,displayNames, andisCalculatedflow through.calculatedFnfields composed on top of view rows (e.g. theStore.summaryRecordspct-of-total pattern), and infra fields such ascubeDimension.Store.generateDataConfig()is deliberately re-runnable andparseStoresruns before the connect-time reload, so the timing works with no record migration - the same mechanismsetProjectionOnlyuses.The store's evaluation set for calculated fields stays store-layer-only (
isCalculated && !isCubeField- a store must never run a(row, ctx)cube fn itself), while the behavioral set (grid repaint, sort staleness handling, filter refresh escalation, read-only columns) becomes derivable from the store's own fields.What it deletes
Store.setExternalCalculatedFieldNames/_externalCalculatedFieldNamesand the lazily-built union inStore.calculatedFieldNames.View.syncStoreCalculatedFields- the reconciled fields carry the information.Column.isEditableForRecordgate can return to plainField.isCalculated.Open questions
store.fieldsvisibly changing at connection is a real behavioral surface - grid column/field resolution and filter field specs read it, so this needs its own testing and changelog treatment.CubeFieldinstances are shared by reference or copied into store-appropriateFields.Sized as its own PR - deliberately split out of #4636.