Migrating from v7 to v8
Start by executing the upgrade script in the root of your project:
npx @comet/upgrade@latest v8
That handles most of the necessary changes.
The following sections go over all necessary changes. All changes handled by the upgrade script are hidden in closed accordions. Refer to the hidden content if you face issues with the upgrade scripts.
You can re-execute individual upgrade scripts if needed: npx @comet/upgrade@latest v8/[upgrade-script-name].ts
General
✅ Upgrade Node to v22
Handled by @comet/upgrade
In development:
npx @comet/upgrade v8/replace-node-with-v22-locally.ts
- 20
+ 22
- "@types/node": "^20.0.0",
+ "@types/node": "^22.0.0",
In pipeline and deployment:
npx @comet/upgrade v8/replace-node-with-v22-in-gitlab-ci-files.ts
Make sure you use Node 22 in your CI files. When using Gitlab CI, check all files in the .gitlab-ci folders. Make sure to extend the correct jobs and replace all images and base images.
- extends: .lint-npm-node20
+ extends: .lint-npm-node22
- BASE_IMAGE: "ubi/s2i-ubi9-nodejs20-minimal"
+ BASE_IMAGE: "ubi/s2i-ubi9-nodejs22-minimal"
- image: eu.gcr.io/vivid-planet/utils/ubi9-nodejs20-minimal:master
+ image: eu.gcr.io/vivid-planet/utils/ubi9-nodejs22-minimal:master
API
✅ Upgrade peer dependencies
NestJS
-
Upgrade all your dependencies to support NestJS v11
Handled by @comet/upgrade
Handled by following upgrade scriptnpx @comet/upgrade v8/update-nest-dependencies.ts
{
"dependencies": {
+ "@apollo/server": "^4.0.0",
- "@nestjs/apollo": "^10.0.0",
- "@nestjs/common": "^9.0.0",
- "@nestjs/config": "^2.0.0",
- "@nestjs/core": "^9.0.0",
- "@nestjs/graphql": "^10.0.0",
- "@nestjs/passport": "^9.0.0",
- "@nestjs/platform-express": "^9.0.0",
+ "@nestjs/apollo": "^13.0.0",
+ "@nestjs/common": "^11.0.0",
+ "@nestjs/core": "^11.0.0",
+ "@nestjs/graphql": "^13.0.0",
+ "@nestjs/passport": "^11.0.0",
+ "@nestjs/platform-express": "^11.0.0",
- "apollo-server-core": "^3.0.0",
- "apollo-server-express": "^3.0.0",
- "express": "^4.0.0",
+ "express": "^5.0.0",
- "graphql": "^15.0.0",
+ "graphql": "^16.10.0",
},
"devDependencies": {
- "@nestjs/cli": "^9.0.0",
- "@nestjs/schematics": "^9.0.0",
- "@nestjs/testing": "^9.0.0",
+ "@nestjs/cli": "^11.0.0",
+ "@nestjs/schematics": "^11.0.0",
+ "@nestjs/testing": "^11.0.0",
- "@types/express": "^4.0.0",
+ "@types/express": "^5.0.0",
}
} -
Update the custom
formatError
function to hide GraphQL field suggestionsHandled by @comet/upgrade
Handled by following upgrade scriptnpx @comet/upgrade v8/update-graphql-format-error.ts
- import { ValidationError } from "apollo-server-express";
+ import { ValidationError } from "@nestjs/apollo";
/* ... */
GraphQLModule.forRootAsync<ApolloDriverConfig>({
/* ... */
useFactory: (moduleRef: ModuleRef) => ({
/* ... */,
formatError: (error) => {
// Disable GraphQL field suggestions in production
if (process.env.NODE_ENV !== "development") {
- if (error instanceof ValidationError) {
+ if (error.extensions?.code === "GRAPHQL_VALIDATION_FAILED") {
return new ValidationError("Invalid request.");
}
}
return error;
},
}),
}), -
You may need to update some of your routes to support Express v5. See the migration guide for more information.
✅ Add NestJS peer dependencies
Peer dependencies defined by NestJS have been added as peer dependencies to @comet/cms-api
.
Handled by @comet/upgrade
npx @comet/upgrade v8/nest-peer-dependencies.ts
To upgrade, install the dependencies in your project:
{
"dependencies": {
+ "class-transformer": "^0.5.1",
- "reflect-metadata": "^0.1.13",
+ "reflect-metadata": "^0.2.2",
- "rxjs": "^7.0.0",
+ "rxjs": "^7.8.1",
}
}
MikroORM
-
Upgrade all your dependencies:
Handled by @comet/upgrade
Handled by following upgrade scriptnpx @comet/upgrade v8/update-mikro-orm-dependencies.ts
{
"dependencies": {
- "@mikro-orm/cli": "^5.9.8",
- "@mikro-orm/core": "^5.9.8",
- "@mikro-orm/migrations": "^5.9.8",
- "@mikro-orm/nestjs": "^5.2.3",
- "@mikro-orm/postgresql": "^5.9.8",
+ "@mikro-orm/cli": "^6.4.0",
+ "@mikro-orm/core": "^6.4.0",
+ "@mikro-orm/migrations": "^6.4.0",
+ "@mikro-orm/nestjs": "^6.0.2",
+ "@mikro-orm/postgresql": "^6.4.0",
},
} -
Follow the official migration guide to upgrade.
Partially handled by upgrade scriptsWe provide upgrade scripts for basic migrations. Please note that these scripts might not cover all necessary migrations.
Changes handled by @comet/upgrade
Remove generic from
BaseEntity
:npx @comet/upgrade v8/mikro-orm-base-entity-generic.ts
Rename
customType
totype
:npx @comet/upgrade v8/mikro-orm-custom-type.ts
Rename
onDelete
todeleteRule
:npx @comet/upgrade v8/mikro-orm-delete-rule.ts
Add a
mikro-orm
script with a dotenv call topackage.json
:npx @comet/upgrade v8/mikro-orm-dotenv.ts
Change all imports from
@mikro-orm/core
to@mikro-orm/postgresql
:npx @comet/upgrade v8/mikro-orm-imports.ts
Wrap config in
defineConfig
:npx @comet/upgrade v8/mikro-orm-ormconfig.ts
✅ class-validator
The class-validator peer dependency has been bumped to v0.14.0.
Handled by @comet/upgrade
npx @comet/upgrade v8/update-class-validator.ts
{
"dependencies": {
- "class-validator": "0.13.2",
+ "class-validator": "^0.14.0",
}
}
✅ Sentry
The Sentry dependency has been bumped to v9.
Handled by @comet/upgrade
npx @comet/upgrade v8/update-sentry.ts
- Upgrade the "@sentry/node" dependency in your
package.json
file:
{
"dependencies": {
- "@sentry/node": "^7.0.0",
+ "@sentry/node": "^9.0.0",
},
}
- Update your
main.ts
file to remove allSentry.Handlers
and addSentry.setupExpressErrorHandler(app)
:
- app.use(Sentry.Handlers.requestHandler());
- app.use(Sentry.Handlers.tracingHandler());
- app.use(Sentry.Handlers.errorHandler());
+ Sentry.setupExpressErrorHandler(app);
None of the other breaking changes in @sentry/node
should affect us. If you still encounter problems, consult the official migration guides:
✅ @kubernetes/client-node
The @kubernetes/client-node
peer dependency has been bumped to v1.
Handled by @comet/upgrade
npx @comet/upgrade v8/update-kubernetes-client-node.ts
{
"dependencies": {
- "@kubernetes/client-node": "^0.18.0",
+ "@kubernetes/client-node": "^1.0.0",
}
}
✅ Add new package @comet/api-generator
Handled by @comet/upgrade
npx @comet/upgrade v8/api-generator-dev-dependencies.ts
The API Generator has been moved into a separate package @comet/api-generator
.
devDependencies: {
+ "@comet/api-generator": "^8.0.0",
}
API Generator - Removed Special status
Field Behavior
Previously, if entities specified a status
enum, it was automatically added to list queries arguments with a default value.
This special handling has been removed. The status
field now behaves like a normal enum. Filtering by status
can be
done with the normal filtering mechanism.
✅ Remove @comet/blocks-api
The @comet/blocks-api
package has been merged into the @comet/cms-api
package.
Handled by @comet/upgrade
To upgrade, perform the following steps:
-
Remove the package:
Handled by following upgrade scriptnpx @comet/upgrade v8/remove-blocks-packages.ts
api/package.json- "@comet/blocks-api": "^7.x.x",
-
Update all your imports from
@comet/blocks-api
to@comet/cms-api
Handled by following upgrade scriptnpx @comet/upgrade v8/merge-blocks-api-into-cms-api.ts
-
Update imports that have been renamed
Handled by following upgrade scriptnpx @comet/upgrade v8/merge-blocks-api-into-cms-api.ts
-
Remove usages of removed export
getFieldKeys
(probably none)
Replace nestjs-console with nest-commander
The nestjs-console package isn't actively maintained anymore. We therefore replace it with nest-command.
The upgrade script will remove the nestjs-console
package and install nest-commander
and @types/inquirer
.
Handled by @comet/upgrade
npx @comet/upgrade v8/replace-nestjs-console-with-nest-commander.ts
- Uninstall
nestjs-console
- Install
nest-commander
and@types/inquirer
You have to perform the following steps manually:
-
Update
api/src/console.ts
to usenest-commander
. Minimum example:import { CommandFactory } from "nest-commander";
import { AppModule } from "./app.module";
import { createConfig } from "./config/config";
const config = createConfig(process.env);
async function bootstrap() {
const appModule = AppModule.forRoot(config);
// @ts-expect-error CommandFactory doesn't except DynamicModule, only Type<any>
await CommandFactory.run(appModule, {
logger: ["error", "warn", "log"],
serviceErrorHandler: async (error) => {
console.error(error);
process.exit(1);
},
});
}
bootstrap(); -
Update your commands to the new
nest-commander
syntax
Migrating nestjs-console commands to nest-commander
This section highlights the necessary changes to convert a nestjs-console command to nest-commander.
-
Replace the
@Console()
decorator with@Command()
:- import { Command, Console } from "nestjs-console";
+ import { Command } from "nest-commander";
- @Injectable()
- @Console()
+ @Command({
+ name: "fixtures",
+ description: "Create fixtures with faker.js",
+ })
export class FixturesConsole {
- @Command({
- command: "fixtures",
- description: "Create fixtures with faker.js",
- })
@CreateRequestContext()
async execute(): Promise<void> {
/* ... */
}
} -
Extend
CommandRunner
:+ import { CommandRunner } from "nest-commander";
- export class FixturesConsole {
+ export class FixturesConsole extends CommandRunner {
/* ... */
} -
Add a
super()
call to the constructor:export class FixturesConsole extends CommandRunner {
constructor(@Inject(CONFIG) private readonly config: Config) {
+ super();
}
} -
Rename the executing function to
run
:export class FixturesConsole extends CommandRunner {
@CreateRequestContext()
- async execute(): Promise<void> {
+ async run(): Promise<void> {
/* ... */
}
} -
If necessary, migrate arguments and options.
Arguments: Move from
command
field intoarguments
field:import-redirects.command.ts@Command({
name: "import-redirects",
+ arguments: "<filepath> [comment]",
description: "Import redirects from a CSV file",
})
export class ImportRedirectsCommand extends CommandRunner {
@Command({
- command: "import-redirects [filepath] [comment]",
description: "Import redirects from csv file",
})
@CreateRequestContext()
- async execute(filepath: string, comment = "Imported"): Promise<void> {
+ async run([filepath, comment = "Imported"]: string[]): Promise<void> {
/* ... */
}
}Options: Use the
@Option()
decorator:refresh-block-index-views.command.ts@Command({
name: "refreshBlockIndexViews",
})
export class RefreshBlockIndexViewsCommand extends CommandRunner {
@Command({
command: "refreshBlockIndexViews",
- options: [
- {
- flags: "-f, --force [boolean]",
- defaultValue: false,
- },
- ],
})
@CreateRequestContext()
- async refreshBlockIndexViews(args: { force: boolean }): Promise<void> {
+ async run(arguments: string[], options: { force?: true }): Promise<void> {
/* ... */
}
+ @Option({
+ flags: "-f, --force",
+ })
+ parseForce() {}
}Review the documentation for more information.
-
Optional: Rename console to command:
- export class FixturesConsole extends CommandRunner {
+ export class FixturesCommand extends CommandRunner {
/* ... */
}
Remove passport
The passport dependencies were removed by the upgrade script.
Handled by @comet/upgrade
npx @comet/upgrade v8/remove-passport.ts
Remove all passport-dependencies and add @nestjs/jwt
{
"dependencies": {
- "@nestjs/passport": "^9.0.0",
- ...other passport dependencies
+ "@nestjs/jwt": "^10.2.0",
}
}
Following steps must be done manually:
Rename the strategy
-factories and wrap them in ...createAuthGuardProviders()
:
- createStaticCredentialsBasicStrategy({ ... }),
- createAuthProxyJwtStrategy({ ... }),
- createStaticCredentialsBasicStrategy({ ... }),
+ ...createAuthGuardProviders(
+ createBasicAuthService({ ... }),
+ createJwtAuthService({ ... }),
+ createSitePreviewAuthService({ ... }),
+ createStaticUserAuthService({ ... }),
+ ),
The configuration of the AuthServices have changed slightly compared to the strategies, however they remain similar. Consulting the code completion should help to adapt.
Replace createAuthResolver
with the class name:
- useClass: createCometAuthGuard([...]),
+ useClass: CometAuthGuard,
CometAuthGuard
does not support Passport strategies anymore. Consider rewriting or wrapping into AuthServiceInterface
. However, you still can use passport strategies in conjunction with the provided AuthGuard
from @nestjs/passport
.
Import JwtModule
from @nestjs/jwt
:
exports: [UserService, AccessControlService],
+ imports: [JwtModule],
Admin
Upgrade peer dependencies
React
The React dependency has been bumped to v18.
-
Upgrade all your dependencies
Handled by @comet/upgrade
Handled by following upgrade scriptnpx @comet/upgrade v8/update-react-dependencies.ts
{
"dependencies": {
- "react": "^17.0.2",
- "react-dom": "^17.0.2",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1"
},
"devDependencies": {
- "@types/react": "^17.0.83",
- "@types/react-dom": "^17.0.26",
+ "@types/react": "^18.3.18",
+ "@types/react-dom": "^18.3.5"
}
} -
Follow the official migration guide to upgrade.
tipUse types-react-codemod to fix potential TypeScript compile errors when upgrading to
@types/react@^18.0.0
.
MUI
The MUI dependencies (@mui/material
, @mui/system
, @mui/utils
, @mui/icons-material
, @mui/lab
) were bumped to v7.
-
Upgrade your MUI dependencies
Handled by @comet/upgrade
Handled by following upgrade scriptnpx @comet/upgrade v8/update-mui-dependencies.ts
- "@mui/icons-material": "^5.0.0",
- "@mui/lab": "^5.0.0-alpha.76",
- "@mui/material": "^5.0.0",
- "@mui/system": "^5.0.0",
- "@mui/utils": "^5.0.0",
+ "@mui/icons-material": "^7.0.0",
+ "@mui/lab": "^7.0.0-beta.9",
+ "@mui/material": "^7.0.0",
+ "@mui/system": "^7.0.0",
+ "@mui/utils": "^7.0.0", -
Execute MUI codemods to update your code
Handled by @comet/upgrade
Handled by following upgrade scriptnpx @comet/upgrade v8/mui-codemods.ts
-
Follow the official migration guides to upgrade:
MUI X (DataGrid)
The MUI dependencies (@mui/x-data-grid
, @mui/x-data-grid-pro
) were bumped to v7.
Handled by @comet/upgrade
In package.json
update the version of the MUI X packages to ^7.22.3
.
npx @comet/upgrade v8/update-mui-x-dependencies.ts
- "@mui/x-data-grid": "^5.x.x",
- "@mui/x-data-grid-pro": "^5.x.x",
- "@mui/x-data-grid-premium": "^5.x.x",
+ "@mui/x-data-grid": "^7.22.3",
+ "@mui/x-data-grid-pro": "^7.22.3",
+ "@mui/x-data-grid-premium": "^7.22.3",
A lots of props have been renamed from MUI, for a detailed look, see the official migration guide v5 -> v6 and migration guide v6 -> v7. There is also a codemod from MUI which handles most of the changes:
npx @comet/upgrade v8/mui-x-codemods.ts
Be aware if you have a date in the data grid, you will need to add a valueGetter
<DataGrid
//other props
columns=[
{
field: "updatedAt",
type: "dateTime",
+ valueGetter: (params, row) => row.updatedAt && new Date(row.updatedAt)
}]
/>
Also, be aware if you have a valueGetter
or valueFormatter
in the data grid, you will need to change the arguments passing to the functions. Previously, arguments were passed as an object. Now, they are passed directly as individual parameters
<DataGrid
//other props
columns=[
{
field: "updatedAt",
type: "dateTime",
- valueGetter: ({params, row}) => row.updatedAt && new Date(row.updatedAt)
+ valueGetter: (params, row) => row.updatedAt && new Date(row.updatedAt)
- valueFormatter: ({value}) => (value ? intl.formatDate(value, { dateStyle: "medium", timeStyle: "short" }) : ""),
+ valueFormatter: (value) => (value ? intl.formatDate(value, { dateStyle: "medium", timeStyle: "short" }) : ""),
}]
/>
✅ Vite / SWC
Handled by @comet/upgrade
npx @comet/upgrade v8/update-swc-dependencies.ts
- "@swc/plugin-emotion": "^3.0.13",
- "@vitejs/plugin-react-swc": "^3.7.2",
+ "@swc/plugin-emotion": "^8.7.2",
+ "@vitejs/plugin-react-swc": "^3.8.0",
✅ Add new package @comet/admin-generator
Handled by @comet/upgrade
npx @comet/upgrade v8/admin-generator-dev-dependencies.ts
The Admin Generator has been moved into a separate package @comet/admin-generator
.
devDependencies: {
+ "@comet/admin-generator": "^8.0.0",
}
✅ Remove @comet/blocks-admin
The @comet/blocks-admin
package has been merged into the @comet/cms-admin
package.
Handled by @comet/upgrade
To upgrade, perform the following steps:
-
Remove the package:
Handled by following upgrade scriptnpx @comet/upgrade v8/remove-blocks-packages.ts
admin/package.json- "@comet/blocks-admin": "^7.x.x",
-
Update all your imports from
@comet/blocks-admin
to@comet/cms-admin
Handled by following upgrade scriptnpx @comet/upgrade v8/merge-blocks-admin-into-cms-admin.ts
-
Update imports that have been renamed
Handled by following upgrade scriptnpx @comet/upgrade v8/merge-blocks-admin-into-cms-admin.ts
Manually remove usages of removed exports CannotPasteBlockDialog
, ClipboardContent
, useBlockClipboard
, Collapsible
, CollapsibleSwitchButtonHeader
, usePromise
, DispatchSetStateAction
, SetStateAction
, and SetStateFn
Use Dispatch<SetStateAction<T>>
from react
instead of DispatchSetStateAction
.
✅ Remove @comet/admin-theme
Handled by @comet/upgrade
npx @comet/upgrade v8/merge-admin-theme-into-admin.ts
npx @comet/upgrade v8/remove-admin-theme-package.ts
The @comet/admin-theme
package has been merged into @comet/admin
, adjust the imports accordingly:
- import { createCometTheme } from "@comet/admin-theme";
+ import { createCometTheme } from "@comet/admin";
const theme = createCometTheme();
✅ Remove @comet/admin-react-select
Handled by @comet/upgrade
npx @comet/upgrade v8/remove-comet-admin-react-select-dependency.ts
- "@comet/admin-react-select": "^7.x.x",
It is recommended to use the AutocompleteField
or the SelectField
components from @comet/admin
instead:
- import { FinalFormReactSelectStaticOptions } from "@comet/admin-react-select";
- <Field name="color" type="text" component={FinalFormReactSelectStaticOptions} fullWidth options={options} />;
+ import { AutocompleteField } from "@comet/admin";
+ <AutocompleteField name="color" label="Color" options={options} fullWidth />;
✅ Merge providers into CometConfigProvider
The separate providers for CMS features (e.g, DamConfigProvider
) have been merged into a CometConfigProvider
.
Handled by @comet/upgrade
npx @comet/upgrade v8/comet-config-provider.ts
Note: This upgrade script is experimental and might not work as expected in your application. Review the result carefully.
Wrap your application with the CometConfigProvider
:
import { CometConfigProvider } from "@comet/cms-admin";
function App() {
return (
<CometConfigProvider
apiUrl={config.apiUrl}
graphQLApiUrl={`${config.apiUrl}/graphql`}
adminUrl={config.adminUrl}
>
{/* Application */}
</CometConfigProvider>
);
}
Move module configs to the new provider:
<CometConfigProvider
apiUrl={config.apiUrl}
graphQLApiUrl={`${config.apiUrl}/graphql`}
adminUrl={config.adminUrl}
+ dam={{
+ ...config.dam,
+ scopeParts: ["domain"],
+ contentGeneration: {
+ generateAltText: true,
+ generateImageTitle: true,
+ },
+ }}
>
{/* Application */}
</CometConfigProvider>
Remove the old config providers:
- <DamConfigProvider>
{/* Application */}
- </DamConfigProvider>
Update usages of renamed exports:
useSitesConfig()
->useSiteConfigs()
useLocale()
->useContentLanguage()
useCmsBlockContext()
->useBlockContext()
Remove the allCategories
prop from PagesPage
:
<PagesPage
path="/pages/pagetree/main-navigation"
- allCategories={pageTreeCategories}
documentTypes={pageTreeDocumentTypes}
category="MainNavigation"
renderContentScopeIndicator={(scope) => <ContentScopeIndicator scope={scope} />}
/>
This upgrade script is experimental and might not work as expected in your application. Review the result carefully.
Add proxy for /dam
URLs
The API now only returns relative URLs for DAM assets.
You must proxy the /dam
URLs in your application to the API.
This must be done for local development and production.
In development:
Add the proxy to your vite config:
//...
server: {
// ...
proxy: process.env.API_URL_INTERNAL
? {
"/dam": {
target: process.env.API_URL_INTERNAL,
changeOrigin: true,
secure: false,
},
}
: undefined,
// ...
},
//...
In production:
Add the proxy to your admin server:
"dependencies": {
// ...
+ "http-proxy-middleware": "^3.0.3"
// ...
},
// ...
app.get("/status/health", (req, res) => {
// ...
});
+ const proxyMiddleware = createProxyMiddleware({
+ target: process.env.API_URL_INTERNAL + "/dam",
+ changeOrigin: true,
+ });
+ app.use("/dam", proxyMiddleware);
// ...
You might also need to add API_URL_INTERNAL
to your values.tpl.yaml
for deployment:
admin:
env:
ADMIN_URL: "https://$ADMIN_DOMAIN"
API_URL: "https://$ADMIN_DOMAIN/api"
+ API_URL_INTERNAL: "http://$APP_NAME-$APP_ENV-api:3000/api"
✅ Rename Menu
and related components to MainNavigation
in @comet/admin
Handled by @comet/upgrade
npx @comet/upgrade v8/rename-menu-components-in-admin.ts
To better differentiate between imports from @comet/admin
and @mui/material
, the following components and related types have been renamed:
Menu
→MainNavigation
MenuProps
→MainNavigationProps
MenuClassKey
→MainNavigationClassKey
MenuItem
→MainNavigationItem
MenuItemProps
→MainNavigationItemProps
MenuItemClassKey
→MainNavigationItemClassKey
MenuCollapsibleItem
→MainNavigationCollapsibleItem
MenuCollapsibleItemProps
→MainNavigationCollapsibleItemProps
MenuCollapsibleItemClassKey
→MainNavigationCollapsibleItemClassKey
IWithMenu
→WithMainNavigation
withMenu
→withMainNavigation
MenuItemAnchorLink
→MainNavigationItemAnchorLink
MenuItemAnchorLinkProps
→MainNavigationItemAnchorLinkProps
MenuItemGroup
→MainNavigationItemGroup
MenuItemGroupClassKey
→MainNavigationItemGroupClassKey
MenuItemGroupProps
→MainNavigationItemGroupProps
MenuItemRouterLink
→MainNavigationItemRouterLink
MenuItemRouterLinkProps
→MainNavigationItemRouterLinkProps
The MenuContext
has been removed, use the new useMainNavigation
hook instead.
Stay on same page after changing scope
The Admin now stays on the same page per default when changing scopes. Perform the following changes:
-
Remove the
path
prop from thePagesPage
componentadmin/src/common/MasterMenu.tsx<PagesPage
- path="/pages/pagetree/main-navigation"
allCategories={pageTreeCategories}
documentTypes={pageTreeDocumentTypes}
category="MainNavigation"
renderContentScopeIndicator={(scope) => <ContentScopeIndicator scope={scope} />}
/> -
Remove the
redirectPathAfterChange
prop from theRedirectsPage
componentadmin/src/common/MasterMenu.tsx{
type: "route",
primary: <FormattedMessage id="menu.redirects" defaultMessage="Redirects" />,
route: {
path: "/system/redirects",
- render: () => <RedirectsPage redirectPathAfterChange="/system/redirects" />,
+ component: RedirectsPage
},
requiredPermission: "pageTree",
}, -
Optional: Remove unnecessary usages of the
useContentScopeConfig
hookexport function ProductsPage() {
const intl = useIntl();
- useContentScopeConfig({ redirectPathAfterChange: "/structured-content/products" });
}
DataGrid-related changes
Update usage of DataGridToolbar
DataGridToolbar
has been simplified to a basic wrapper component. Props and features from the standard Toolbar
component have been removed, along with the density
prop since density is now controlled by the DataGrid
.
The new usage simplifies the component structure - children can now be passed directly without needing to wrap them in ToolbarItem
and ToolbarActions
components:
- <DataGridToolbar density="compact">
+ <DataGridToolbar>
- <ToolbarItem>
<GridToolbarQuickFilter />
- </ToolbarItem>
- <ToolbarItem>
<GridFilterButton />
- </ToolbarItem>
- <ToolbarItem>
<GridColumnsButton />
- </ToolbarItem>
<FillSpace />
- <ToolbarActions>
<Button responsive variant="outlined">
Secondary action
</Button>
<Button responsive startIcon={<AddIcon />}>
Add item
</Button>
- </ToolbarActions>
</DataGridToolbar>
✅ Pass columns instead of apiRef to muiGridSortToGql
Function
Handled by @comet/upgrade
npx @comet/upgrade v8/mui-grid-sort-to-gql.ts
Note: This upgrade script will naively change the second argument of muiGridSortToGql
function to columns
, assuming that columns
is available in the current scope.
The muiGridSortToGql
helper now expects the columns instead of the apiRef
:
const columns : GridColDef[] = [/* column definitions*/];
const dataGridRemote = useDataGridRemote();
const persistentColumnState = usePersistentColumnState("persistent_column_state");
- muiGridSortToGql(dataGridRemote.sortModel, persistentColumnState.apiRef);
+ muiGridSortToGql(dataGridRemote.sortModel, columns);
This upgrade script will naively change the second argument of muiGridSortToGql
function to columns
, assuming that columns
is available in the current scope.
Remove error
prop from DataGrid
The error and onError props were removed - the grid no longer catches errors during rendering. To catch errors that happen during rendering use the error boundary. The components.ErrorOverlay slot was also removed.
Handled by @comet/upgrade
npx @comet/upgrade v8/mui-data-grid-remove-error-prop.ts
Note: Error handling must be implemented manually, the upgrade script simply removes all usages of the error prop on DataGrids and adds a TODO: comment.
This upgrade script simply removes all usages of the error prop on DataGrids and adds a TODO: comment. Error handling must be implemented manually.
The recommended way to handle errors is to use the ErrorBoundary
in the parent component and throw errors where the query error happens.
- const { loading, data, error } = useQuery(/* query parameters */)
- <DataGrid error={error} /* other props */ >
+ const { loading, data, error } = useQuery(/* query parameters */)
+ if (error) {
+ throw error
+ }
+ <DataGrid /* other props */ >
✅ useDataGridRemote
Hook - Return Value
The useDataGridRemote
hook has been changed to match the updated DataGrid props:
- const { pageSize, page, onPageSizeChange } = useDataGridRemote();
+ const { paginationModel, onPaginationModelChange } = useDataGridRemote();
rowCount
must be passedBe aware that you must pass rowCount
to the DataGrid when using the useDataGridRemote
hook. Otherwise, the pagination component will show a NaN
value when used with server-side pagination.
✅ Dialog-related changes
✅ Import Dialog
from @comet/admin
package
Handled by @comet/upgrade
npx @comet/upgrade v8/update-import-of-dialog.ts
- import { Dialog } from "@mui/material";
+ import { Dialog } from "@comet/admin";
✅ Add DialogContent
to EditDialog
Handled by @comet/upgrade
npx @comet/upgrade v8/add-dialog-content-to-edit-dialog.ts
The DialogContent
inside EditDialog
has been removed.
To maintain the existing styling of EditDialog
, such as for forms and text, manually wrap the content with DialogContent
to ensure proper spacing.
For grids or other elements that already handle their own spacing (e.g., DataGrid
), adding DialogContent
is not necessary.
<EditDialog>
//...
+ <DialogContent>
+ //...
+ </DialogContent>
// ...
</EditDialog>
✅ Tooltip-related Changes
✅ Import Tooltip
from @comet/admin
package
Handled by @comet/upgrade
npx @comet/upgrade v8/tooltip-1-update-import.ts
- import { Tooltip } from "@mui/material";
+ import { Tooltip } from "@comet/admin";
✅ Remove trigger
prop from Tooltip
Handled by @comet/upgrade
npx @comet/upgrade v8/tooltip-2-remove-trigger-prop.ts
The trigger
prop has been removed. The combined hover
/focus
trigger is now the only supported behavior.
Example:
<Tooltip
- trigger="hover"
></Tooltip>
Site
✅ Remove graphQLFetch
from sitePreviewRoute
calls
Handled by @comet/upgrade
npx @comet/upgrade v8/remove-graphql-fetch-from-site-preview-route.ts
- return sitePreviewRoute(request, createGraphQLFetch());
+ return sitePreviewRoute(request);
Remove x-relative-dam-urls
header from graphQLClient
// ...
return createGraphQLFetchLibrary(
createFetchWithDefaults(fetch, {
// ...
headers: {
- "x-relative-dam-urls": "1",
// ...
},
}),
`${process.env.API_URL_INTERNAL}/graphql`,
);
ESLint
✅ Upgrade ESLint from v8 to v9 with ESM
Handled by @comet/upgrade
npx @comet/upgrade v8/eslint-dev-dependencies.ts
Update ESLint to v9
package.json
- "eslint": "^8.0.0",
+ "eslint": "^9.0.0",
An ESM compatible ESLint config is required. Delete the related .eslintrc.json
and move the configured rules to the new ESLint flat configuration eslint.config.mjs
.
Migration Guide of ESLint 9.0 can be found here: Migration Guide
admin/eslint.config.mjs
import cometConfig from "@comet/eslint-config/react.js";
/** @type {import('eslint')} */
const config = [
{
ignores: ["schema.json", "src/fragmentTypes.json", "dist/**", "src/**/*.generated.ts"],
},
...cometConfig
];
export default config;
api/eslint.config.mjs
import cometConfig from "@comet/eslint-config/react.js";
/** @type {import('eslint')} */
import cometConfig from "@comet/eslint-config/nestjs.js";
/** @type {import('eslint')} */
const config = [
{
ignores: ["src/db/migrations/**", "dist/**", "src/**/*.generated.ts"],
},
...cometConfig,
];
export default config;
site/eslint.config.mjs
import cometConfig from "@comet/eslint-config/react.js";
/** @type {import('eslint')} */
import cometConfig from "@comet/eslint-config/nextjs.js";
/** @type {import('eslint')} */
const config = [
{
ignores: ["**/**/*.generated.ts", "dist/**", "lang/**", "lang-compiled/**", "lang-extracted/**", ".next/**", "public/**"],
},
...cometConfig,
];
export default config;
If you have custom rules in your .eslintrc.json
, you need to manually move them to the new ESLint flat configuration eslint.config.mjs
.
Upgrade Prettier from v2 to v3
Handled by @comet/upgrade
npx @comet/upgrade v8/prettier-dev-dependencies.ts
- "prettier": "^2.8.1",
+ "prettier": "^3.4.2",
Remove React barrel imports
Importing React
is no longer necessary due to the new JSX transform, which automatically imports the necessary react/jsx-runtime
functions.
Use individual named imports instead, e.g, import { useState } from "react"
.
It is recommended to perform the following steps separately in the admin/
and site/
directories:
-
Replace
import * as React from "react";
withimport React from "react";
in your codebase (This step is optional but improves the results of the codemod). -
Run the codemod to update React imports (option
--force
is required to because of changes of step one above):npx react-codemod update-react-imports --force
-
Run ESLint with the
--fix
option to automatically fix issues:npm run lint:eslint --fix
These steps will help automate the process of updating React imports and fixing linting issues, making the migration smoother. The codemod does not handle all cases, so manual adjustments may still be necessary.
✅ Consistent type imports
Handled by @comet/upgrade
The upgrade script runs eslint with the --fix
option. That will automatically update the imports.
What is the change?
To improve code consistency and readability, we now enforce the ESLint rule @typescript-eslint/consistent-type-imports with the following configuration:
"@typescript-eslint/consistent-type-imports": [
"error",
{
"prefer": "type-imports",
"disallowTypeAnnotations": false,
"fixStyle": "inline-type-imports"
}
]
Why this change?
This rule ensures that TypeScript type-only imports are explicitly marked with import type, leading to multiple benefits:
- Improved Code Clarity It is immediately clear that the imported symbol is used only for TypeScript type checking and not at runtime. Avoids confusion between runtime imports and purely static type definitions.
- Performance & Tree-Shaking TypeScript can optimize build performance since it knows which imports are needed only at compile time. Some bundlers can more effectively remove unused type imports, reducing bundle size.
- Reduced Circular Dependency Issues Circular dependencies can cause hard-to-debug issues in TypeScript projects. Using import type ensures that types do not introduce unintended runtime dependencies.