This page lists the v4 changes that break plugins, custom code and Admin API clients. Run the codemods first, then search for the code they do not change, then work through the sections that apply to your project.
| Codemod | Change |
|---|---|
npx vendure codemod role-assignments [path] | Role assignments |
A codemod makes the edits that have one right answer. Where the replacement depends on what your code is meant to do, it adds a // TODO(vendure-v4): comment naming the replacement instead.
Done when: each codemod has run, and rg "TODO\(vendure-v4\)" lists only comments you still have to work through.
The codemods do not change the code below. Search your project for each pattern and update every match.
| Match | What to do |
|---|---|
RoleChangeEvent | Subscribe to RoleAssignmentEvent. See Events. |
getCustomerRole, CUSTOMER_ROLE_CODE, CUSTOMER_ROLE_DESCRIPTION | Remove. There is no Customer role. See . |
getChannelsForRole, assignRoleToChannel, assertActiveUserCanGrantRoles, createApiKeyUser(, createAdministratorAndUser( | See Services. |
user_roles_role, role_channels_channel in SQL | Query the role_assignment table. See Entities. |
implements SessionCacheStrategy | Check that it stores globalPermissions. See Sessions and permission checks. |
roleIds in Admin API calls | Works on the active Channel only. Move multi-channel clients to assignRolesToUser. See Admin API. |
Done when: every match is updated, and npx tsc --noEmit passes.
User.roles and Role.channels are removed, and Roles are granted per Channel through RoleAssignment rows. The main breaks:
RoleAssignmentService.resolveUserRoles(), and grant or revoke them with RoleAssignmentService.assign() / remove().RoleChangeEvent is replaced by RoleAssignmentEvent. The codemod does not rewrite it.RoleService.getCustomerRole() is removed. There is no Customer role.Role.channels and channelIds on the Role inputs are removed, and Role.channel returns the owning Channel. createRole creates the Role on the active Channel. The deprecated roleIds inputs now apply to the active Channel only. Use assignRolesToUser and removeRolesFromUser instead.CreateRole, ReadRole, UpdateRole and DeleteRole permissions on the Channel that owns the Role.BaseAuthResolver.publiclyAccessibleUser() takes the RequestContext as its first argument. Only relevant if you extend the auth resolvers.For the full list, and what stays the same, see Updating your code.
The default cart pricing now uses the buyer price. Without custom strategies, the prices do not change.
DefaultOrderItemPriceCalculationStrategy needs init(). Vendure calls it for the configured strategy. If your code creates the strategy with new and calls calculateUnitPrice() directly, call init(injector) first.OrderItemPriceCalculationStrategy now also runs for setCustomerForOrder, setCustomerForDraftOrder, setOrderCustomer and the login of a guest. A line that has no price for the new customer keeps its current price.OrderItemPriceCalculationStrategy.calculateUnitPrice() has an optional last argument, options?: { buyer?: Buyer }. Vendure does not pass it, so existing strategies work without changes. A StrategyLayer can pass options.buyer to inner, and the default strategy then prices the line for that buyer and not for the customer of the order. A custom strategy that calls calculateBuyerPriceForOrder() should pass buyer: options?.buyer to it. A layer that calls inner with its own argument list should pass options on. See the buyer.DefaultOrderItemPriceCalculationStrategy is now exported from @vendure/core. You can extend or wrap it directly.Architecture reviews, custom plugin work, migrations, ongoing support. Get a hand from the team that builds Vendure.
Talk to the team