Skip to content

Conversation

@odinr
Copy link
Collaborator

@odinr odinr commented Dec 3, 2025

Why

Why is this change needed?
This PR fixes a regression introduced by PR #3639 (AG-Grid 34.3.1 upgrade) that causes an "object is not extensible" error in Vite dev mode. The issue occurs because AG-Grid 34.3.1 changed its internal dependency injection system, making theme injection timing-sensitive. In Vite dev mode with split ESM chunks, provideGlobalGridOptions({ theme }) now happens after AG-Grid has already created and frozen its internal theme instance, causing the error when AG-Grid tries to add _paramsCache.

What is the current behavior?

  • Theme configuration accepts a direct Theme value that is evaluated immediately
  • In Vite dev mode, theme injection happens too late due to chunk loading order
  • Results in "object is not extensible" error when AG-Grid tries to extend the theme object
  • AG Charts components must be imported from ./enterprise export path
  • The issue only manifests in dev mode (production bundling works fine)

What is the new behavior?

  • Theme configuration now accepts a function () => Theme for lazy evaluation
  • Theme is resolved when needed, ensuring correct injection timing even when the provider lives in a separate Vite chunk
  • New dedicated ./charts export path for AG Charts components (AgCharts and AgChartsEnterpriseModule)
  • Charts exports remain available from ./enterprise for backward compatibility (will be removed in future minor release)
  • Fixes the dev mode regression while maintaining backward compatibility

Does this PR introduce a breaking change?
No. While the theme API changes from Theme to () => Theme, this is marked as a minor version bump. The changeset includes migration instructions showing how to update from direct theme values to theme functions. After upgrading, everything will work again without any code changes on the consumer side (the lazy evaluation handles both function and direct value patterns internally). Charts exports are maintained in ./enterprise for backward compatibility.

Additional context

  • Root cause: AG-Grid 34.3.1 introduced stricter bean lifecycle management and earlier object freezing in its DI system, which exposed timing issues in split-chunk scenarios like Vite dev mode
  • The fix ensures compatibility with AG-Grid's improved DI system without overriding its enhancements
  • Cookbook examples have been updated to demonstrate the new theme function API
  • Chart components in cookbooks now use the new ./charts export path
  • All changesets have been created for the affected packages

Related issues
closes: https://github.com/equinor/fusion/issues/747

How to Review This PR

Understanding the Problem

This regression was introduced by PR #3639 (AG-Grid 34.3.1 upgrade). AG-Grid v34 introduced several enhancements to its internal dependency injection system that affect theme injection:

  • Improved bean lifecycle management: Beans (like ThemeImpl) are now initialized more aggressively during early grid core setup, with stricter sealing of objects to prevent runtime mutations outside the DI container.
  • Deferred resolution for globals: Global providers (like our theme injection) are now resolved later in the init sequence, but only if they're available in the same execution context. This makes the system more robust in bundled environments but exposes timing issues in split-chunk scenarios like Vite dev.
  • Enhanced extensibility checks: Objects in the DI graph (e.g., theme params cache) are frozen earlier to enforce immutability, which triggers the "object is not extensible" error if injection misses the window.

In Vite dev mode with split ESM chunks, provideGlobalGridOptions({ theme }) now happens after AG-Grid has already created and frozen its internal theme instance, causing the error when AG-Grid tries to add _paramsCache.

What to Focus On

  1. Theme function API implementation (packages/modules/ag-grid/):

    • Verify that theme?: () => Theme is consistently used throughout the module chain
    • Check that theme is resolved lazily (function called when needed, not at config time)
    • Ensure backward compatibility is maintained (function can wrap direct theme values)
  2. Charts export path (packages/react/ag-grid/):

    • Verify the new ./charts export path works correctly
    • Confirm backward compatibility with ./enterprise exports
    • Check that all chart components are properly exported
  3. Testing considerations:

    • Critical: Test in Vite dev mode (not just production build) - this is where the regression manifests
    • The issue only appears in dev mode with split chunks; production bundling works fine
    • Verify theme injection happens at the correct time in the AG-Grid initialization sequence
    • Testing preset from portal: The fix can be tested by enabling ag-grid in the dev-portal (done in bug fix - see packages/dev-portal/src/config.ts for reference on how to enable modules using the enable* pattern)
    • Theme alteration testing: Test by altering the theme in the Cookbook (see cookbooks/app-react-ag-grid/src/config.ts for the theme override example) to verify the lazy theme function API works correctly and doesn't trigger the "object is not extensible" error
  4. Cookbook examples:

    • Verify cookbook examples demonstrate the new theme function API correctly
    • Check that chart components use the new export path

Key Files to Review

  • packages/modules/ag-grid/src/AgGridConfigurator.interface.ts - Interface change to theme?: () => Theme
  • packages/modules/ag-grid/src/AgGridConfigurator.ts - Lazy theme resolution implementation
  • packages/modules/ag-grid/src/AgGridProvider.ts - Theme getter that calls the function
  • packages/react/ag-grid/src/charts.ts - New charts export path
  • packages/react/ag-grid/src/enterprise.ts - Backward compatibility exports

Checklist

@changeset-bot
Copy link

changeset-bot bot commented Dec 3, 2025

🦋 Changeset detected

Latest commit: 9029ff6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@equinor/fusion-framework-cookbook-app-react-ag-grid Patch
@equinor/fusion-framework-cookbook-app-react-charts Patch
@equinor/fusion-framework-module-ag-grid Minor
@equinor/fusion-framework-react-ag-grid Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added 🐞 bug Something isn't working 👨🏻‍🍳 cookbooks 👾 React 🚀 feature New feature or request 🚧 chore maintaines work, (update deps, workflos ...) 🧨 breaking changes 🧬 Modules labels Dec 3, 2025
@odinr odinr self-assigned this Dec 3, 2025
@odinr odinr marked this pull request as ready for review December 3, 2025 20:30
@odinr odinr requested a review from a team as a code owner December 3, 2025 20:30
Copilot AI review requested due to automatic review settings December 3, 2025 20:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression introduced in AG-Grid 34.3.1 that causes "object is not extensible" errors in Vite dev mode. The fix changes the theme configuration to use lazy evaluation via functions () => Theme instead of direct Theme values, ensuring proper timing with AG-Grid's updated dependency injection system. Additionally, it introduces a new dedicated ./charts export path for AG Charts components.

Key Changes:

  • Theme API converted from Theme to () => Theme for lazy evaluation
  • New ./charts export path added for AgCharts and AgChartsEnterpriseModule
  • Cookbook examples updated to use new chart exports and demonstrate theme function API
  • Dependencies updated: added ag-charts-react and peer dependencies for React 18/19

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/modules/ag-grid/src/AgGridConfigurator.interface.ts Changes theme type from Theme to () => Theme in config interface
packages/modules/ag-grid/src/AgGridConfigurator.ts Updates theme storage and setTheme() to wrap values in functions, imports createTheme from local themes module
packages/modules/ag-grid/src/AgGridProvider.ts Updates theme getter and initialization to call theme function with ?.()
packages/modules/ag-grid/src/module.ts Wraps theme initialization in function for lazy evaluation
packages/react/ag-grid/src/charts.ts New file exporting AgChartsEnterpriseModule and AgCharts from dedicated path
packages/react/ag-grid/src/enterprise.ts Adds AgCharts export for backward compatibility with deprecation note
packages/react/ag-grid/package.json Adds ./charts export path, ag-charts-react dependency, and React peer dependencies
cookbooks/app-react-ag-grid/src/config.ts Adds theme customization example using setTheme() callback
cookbooks/app-react-charts/src/pages/ag-charts/*.tsx Updates chart imports to use new @equinor/fusion-framework-react-ag-grid/charts path
cookbooks/app-react-charts/package.json Removes direct ag-charts dependencies, adds framework ag-grid package
.changeset/*.md Changesets documenting the theme function change, charts export addition, and cookbook updates
pnpm-lock.yaml Dependency resolution updates including ag-grid-react now using React 18 instead of 19
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

@odinr odinr requested a review from AndrejNikolicEq December 3, 2025 20:38
@odinr
Copy link
Collaborator Author

odinr commented Dec 3, 2025

@eikeland and @asbjornhaland - i have assigned the review for @AndrejNikolicEq, but if he still sick tomorrow, please follow up this PR.

Note

well you could have a look anyway, more 👀 = more ♥️

ASAP Zulu release - prevents anyone with AG Grid to render their app dev-mode

odinr and others added 9 commits December 3, 2025 21:51
BREAKING CHANGE: theme configuration now accepts a function () => Theme instead of Theme directly

Fixes #747
Add new ./charts export for AG Charts React components and enterprise module.
Includes AgCharts and AgChartsEnterpriseModule exports.

Fixes #747
Add test theme override demonstrating theme function API with custom parameters.
Migrate chart components to use @equinor/fusion-framework-react-ag-grid/charts
instead of direct ag-charts-react imports.

Fixes #747
- Bump '@types/node' from 24.9.2 to 24.10.1 across various packages.
- Update 'ag-charts-react' and related dependencies to version 12.3.1.
- Adjust 'react' and 'react-dom' versions to 18.3.1.
- Upgrade 'rollup' from 4.52.5 to 4.53.3.
- Remove deprecated esbuild versions and clean up unused packages.

This update ensures compatibility with the latest versions and improves overall project stability.

Signed-off-by: Odin Thomas Rochmann <[email protected]>
Eliminate the unused import of createTheme from AgGridProvider.ts to clean up the codebase and improve readability.

Signed-off-by: Odin Thomas Rochmann <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Change exports in charts.ts to use a wildcard export for ag-charts-react, and remove AgCharts export from enterprise.ts to streamline module usage. This enhances clarity and maintains compatibility with the latest ag-charts updates.

Signed-off-by: Odin Thomas Rochmann <[email protected]>
@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 5.76% 55583 / 964142
🔵 Statements 5.76% 55583 / 964142
🔵 Functions 43.81% 542 / 1237
🔵 Branches 63.65% 965 / 1516
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
cookbooks/app-react-ag-grid/src/config.ts 0% 100% 100% 0% 2-50
cookbooks/app-react-charts/src/pages/ag-charts/AgArea.tsx 0% 100% 100% 0% 2-93
cookbooks/app-react-charts/src/pages/ag-charts/AgBar.tsx 0% 100% 100% 0% 2-91
cookbooks/app-react-charts/src/pages/ag-charts/AgLine.tsx 0% 100% 100% 0% 2-109
cookbooks/app-react-charts/src/pages/ag-charts/AgPie.tsx 0% 100% 100% 0% 2-63
packages/modules/ag-grid/src/AgGridConfigurator.interface.ts 100% 100% 100% 100%
packages/modules/ag-grid/src/AgGridConfigurator.ts 0% 0% 0% 0% 1-59
packages/modules/ag-grid/src/AgGridProvider.ts 0% 0% 0% 0% 1-46
packages/modules/ag-grid/src/module.ts 0% 100% 100% 0% 7-54
packages/react/ag-grid/src/charts.ts 0% 0% 0% 0% 1-2
packages/react/ag-grid/src/enterprise.ts 0% 0% 0% 0% 1-3
Generated in workflow #11354 for commit 9029ff6 by the Vitest Coverage Report Action

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 18 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment on lines 32 to 38
setTheme(valueOrCallback: Theme | ((baseTheme: Theme) => Theme) | null): void {
if (typeof valueOrCallback === 'function') {
this.#theme = valueOrCallback(this.#theme ?? createTheme());
this._set('theme', async () => () => valueOrCallback(this.#theme()));
} else {
this.#theme = valueOrCallback ?? undefined;
this._set('theme', async () => () => valueOrCallback as Theme);
}
}
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setTheme method updates the config via _set() but doesn't update the #theme field. This means subsequent calls to setTheme with a callback will use the old theme function, not the newly set one.

The method should also update #theme:

setTheme(valueOrCallback: Theme | ((baseTheme: Theme) => Theme) | null): void {
  if (typeof valueOrCallback === 'function') {
    this.#theme = () => valueOrCallback(this.#theme());
    this._set('theme', async () => this.#theme);
  } else {
    this.#theme = () => (valueOrCallback ?? createTheme());
    this._set('theme', async () => this.#theme);
  }
}

Copilot uses AI. Check for mistakes.
this._set('theme', async () => () => valueOrCallback(this.#theme()));
} else {
this.#theme = valueOrCallback ?? undefined;
this._set('theme', async () => () => valueOrCallback as Theme);
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When valueOrCallback is null, this code casts it to Theme and wraps it in a function. This will result in () => null, which will cause issues when the theme is used.

The handling of null should either set theme to undefined or to a default theme function:

this._set('theme', async () => valueOrCallback ? () => valueOrCallback as Theme : () => createTheme());

Copilot uses AI. Check for mistakes.
@odinr odinr merged commit 7c57951 into main Dec 4, 2025
14 of 15 checks passed
@odinr odinr deleted the fix/fusion-747 branch December 4, 2025 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🧨 breaking changes 🐞 bug Something isn't working 🚧 chore maintaines work, (update deps, workflos ...) 👨🏻‍🍳 cookbooks 🚀 feature New feature or request 🧬 Modules 👾 React

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants