Skip to main content
Version: 3.x

3.18 -> 3.19

This page lists the highlights for upgrading a project from Front-Commerce 3.18 to 3.19

Update dependencies

Update all your @front-commerce/* dependencies to this version:

pnpm update "@front-commerce/*@3.19.0"

Automated Migration

We provide a codemod to automatically update your codebase to the latest version of Front-Commerce. This tool will update your code when possible.

pnpm run front-commerce migrate --transform 3.19.0

Manual Migration

Sessions Redis Configuration

Starting from version 3.19, the sessions configuration in your front-commerce.config.ts file accepts a redis property via defineRedisConfig. This enables Redis password authentication for session storage.

Automated Migration

The codemod will automatically add the sessions configuration to your project. Run the migration command above to apply this change automatically.

If you prefer to migrate manually, update your front-commerce.config.ts to add the sessions.redis property:

front-commerce.config.ts
- import { defineConfig } from "@front-commerce/core/config";
+ import { defineConfig, defineRedisConfig } from "@front-commerce/core/config";

export default defineConfig({
// ... other configuration
+ sessions: {
+ redis: defineRedisConfig("SESSIONS"),
+ },
// ... other configuration
});

Maintenance Configuration Now Required

Starting from version 3.19, the maintenance configuration is required in your front-commerce.config.ts file because it now includes a redis property for storing maintenance mode state.

Automated Migration

The codemod will automatically add the maintenance configuration to your project. Run the migration command above to apply this change automatically.

If you prefer to migrate manually or need to customize the configuration:

  1. Create the maintenance configuration file at app/config/maintenance.ts:
app/config/maintenance.ts
import {
defineRedisConfig,
type UserConfig,
} from "@front-commerce/core/config";

export default {
force: process.env.FRONT_COMMERCE_MAINTENANCE_MODE_FORCE_ENABLED === "true",
authorizedIps: process.env.FRONT_COMMERCE_MAINTENANCE_MODE_AUTHORIZED_IPS
? process.env.FRONT_COMMERCE_MAINTENANCE_MODE_AUTHORIZED_IPS.split(",")
: [],
authorizedHeader:
process.env.FRONT_COMMERCE_MAINTENANCE_MODE_AUTHORIZED_HEADER,
redis: defineRedisConfig("MAINTENANCE_MODE", {
db:
process.env.FRONT_COMMERCE_CLOUD_REDIS_MAINTENANCE_MODE_DB ||
process.env.FRONT_COMMERCE_REDIS_MAINTENANCE_MODE_DB ||
4,
}),
} satisfies UserConfig["maintenance"];
  1. Update your front-commerce.config.ts to import and use the maintenance configuration:
front-commerce.config.ts
import { defineConfig, defineRedisConfig } from "@front-commerce/core/config";
+ import maintenanceConfig from "./app/config/maintenance";

export default defineConfig({
// ... other configuration
+ maintenance: maintenanceConfig,
sessions: {
redis: defineRedisConfig("SESSIONS"),
},
// ... other configuration
});

Custom External Login Providers

If you have created a custom external login provider, you need to update the parseProfileFromProviderCallback method.

The method signature has changed to return { profile, rawProfile } instead of just Profile. This change enables the new profile and payload transformers feature.

Update your custom provider as follows:

extensions/my-extension/server/SsoProvider.ts
import type {
Profile,
ExternalLoginProvider,
} from "@front-commerce/core/external-login";

class SSOCompanyProvider implements ExternalLoginProvider {
name = "sso-company";

loginRoute(callbackUrl: string): string {
return `https://sso.mycompany.com/login/oauth2?callback=${callbackUrl}`;
}

async parseProfileFromProviderCallback(
- request: Request
- ): Promise<Profile | undefined> {
+ request: Request,
+ callbackUrl: string
+ ): Promise<{ profile: Profile; rawProfile: unknown } | undefined> {
try {
const requestJson = await request.json();
- return {
- email: requestJson.profile.email,
- firstname: requestJson.profile.firstname,
- lastname: requestJson.profile.lastname,
- };
+ return {
+ profile: {
+ email: requestJson.profile.email,
+ firstname: requestJson.profile.firstname,
+ lastname: requestJson.profile.lastname,
+ },
+ rawProfile: requestJson,
+ };
} catch (e) {
return undefined;
}
}
}

The rawProfile should contain the complete response from your OAuth provider. This allows profile transformers to access any additional fields from the provider's response.

tip

Take advantage of this change to implement profile and payload transformers if you need to enrich user profiles or customize customer creation payloads.

Negotiable Quotes: publicConfig.negotiableQuotes removed (Gezy)

The negotiableQuotes configuration has been moved from config.public to config.gezy and is now managed through the permission system. If you have overridden the theme/modules/User/AccountNavigation/AccountNavigation.jsx or theme/layouts/Header/Navigation/AccountNavigation/AccountSubNavigation.jsx file, you need to update your code to replace usePublicConfig / useCompanyPermissions with usePermissions from the new permission system.

theme/modules/User/AccountNavigation/AccountNavigation.jsx
import {
Restricted,
- useCompanyPermissions,
useExtensionFeatureFlags,
- usePublicConfig,
+ usePermissions,
} from "@front-commerce/core/react";
MobileSelector component
-    const publicConfig = usePublicConfig();
- const negotiableQuotesEnabled = publicConfig.negotiableQuotes?.enabled;
+ const { isAllowedTo } = usePermissions();
const customer = useCustomer();
- const { isAllowedTo } = useCompanyPermissions();
MobileSelector component
    const negotiableQuoteRoutes = [
- negotiableQuotesEnabled && {
+ isAllowedTo("negotiableQuote") && {
value: "/user/negotiable-quotes",
label: intl.formatMessage(messages.negotiableQuotesLink),
},
];
DesktopLeftMenu component
-    const publicConfig = usePublicConfig();
- const negotiableQuotesEnabled = publicConfig.negotiableQuotes?.enabled;
const customer = useCustomer();
DesktopLeftMenu component
-        {negotiableQuotesEnabled && (
+ <Restricted to="negotiableQuote">
<AccountNavigationItem
path="/user/negotiable-quotes"
icon="paper"
label={intl.formatMessage(messages.negotiableQuotesLink)}
/>
- )}
+ </Restricted>
theme/layouts/Header/Navigation/AccountNavigation/AccountSubNavigation.jsx
-import { usePublicConfig } from "@front-commerce/core/react";
+import { usePermissions } from "@front-commerce/core/react";
  const customer = useCustomer();
- const publicConfig = usePublicConfig();
- const negotiableQuotesEnabled = publicConfig.negotiableQuotes?.enabled;
+ const { isAllowedTo } = usePermissions();
-            {negotiableQuotesEnabled && (
+ {isAllowedTo("negotiableQuote") && (
<li className="account-sub-navigation__item">
...
</li>
- )}
+ )}

If you used the guardAgainstDisabledNegotiableQuotes or guardAgainstDisabledPublicNegotiableQuote helpers in custom routes, update them to pass app.user instead of app.config:

- guardAgainstDisabledNegotiableQuotes(app.config);
+ guardAgainstDisabledNegotiableQuotes(app.user);

Server Events Redis Environment Variables Renamed

The Redis environment variables for Server Events have been renamed to follow the standardized naming convention used by defineRedisConfig. This homogenization makes configuration more consistent across all Redis-backed features.

Old variable names (deprecated):

  • FRONT_COMMERCE_SERVER_EVENT_REDIS_HOST
  • FRONT_COMMERCE_SERVER_EVENT_REDIS_PORT

New variable names:

  • FRONT_COMMERCE_REDIS_SERVER_EVENT_HOST
  • FRONT_COMMERCE_REDIS_SERVER_EVENT_PORT

Update your environment variables accordingly:

.env
- FRONT_COMMERCE_SERVER_EVENT_REDIS_HOST=redis.example.com
- FRONT_COMMERCE_SERVER_EVENT_REDIS_PORT=6380
+ FRONT_COMMERCE_REDIS_SERVER_EVENT_HOST=redis.example.com
+ FRONT_COMMERCE_REDIS_SERVER_EVENT_PORT=6380

Using Legacy Environment Variables

If you need to continue using the old environment variable names (e.g., for backward compatibility during a gradual migration), you can use the overrides parameter of defineRedisConfig:

app/config/serverEvents.ts
import { defineRedisConfig } from "@front-commerce/core/config";

export default {
redis: defineRedisConfig("SERVER_EVENT", {
// Use legacy env vars as overrides
host:
process.env.FRONT_COMMERCE_SERVER_EVENT_REDIS_HOST ||
process.env.FRONT_COMMERCE_REDIS_SERVER_EVENT_HOST,
port:
process.env.FRONT_COMMERCE_SERVER_EVENT_REDIS_PORT ||
process.env.FRONT_COMMERCE_REDIS_SERVER_EVENT_PORT
? Number(process.env.FRONT_COMMERCE_SERVER_EVENT_REDIS_PORT)
: undefined,
}),
};
note

The defineRedisConfig helper follows a consistent naming pattern for all Redis instances: FRONT_COMMERCE_REDIS_{NAME}_{PROP} (or FRONT_COMMERCE_CLOUD_REDIS_{NAME}_{PROP} for Front-Commerce Cloud environments). This pattern applies to SESSIONS, RATE_LIMITER, SERVER_EVENT, and other Redis configurations.