Releases: medusajs/medusa
v2.3.1
Highlights
Add missing dependency in @medusajs/framework
In @medusajs/framework
uninstalled dependencies are directly imported and resolved through transitive dependencies. However, the glob
package is not a transitive dependency of any production dependency and hence it fails running the server with NODE_ENV=production
.
Bugs
- fix(core-flows): cart validate sales channel by @fPolic in #11024
- fix(cli): fix command description for plugin:db:generate by @shahednasser in #11022
- fix(dashboard): invite UI tweaks by @fPolic in #10999
- fix: missing dependencies in the framework package by @thetutlage in #11049
Documentation
- docs: update payment docs after removing fields by @shahednasser in #10992
- docs: document new migration script option for db:migrate by @shahednasser in #10986
- chore: generate core-flows reference for 2.3.0 by @shahednasser in #11028
- chore: generate types docs reference manually for 2.3.0 by @shahednasser in #11034
- docs: generate references for v2.3.0 by @shahednasser in #11035
- docs: improve content of workflows reference overview page by @shahednasser in #11045
Chores
- chore(framework): update the TSDocs for a plugin in the medusa config by @shahednasser in #10991
- chore(core-flows): general fixes to core-flows TSDocs by @shahednasser in #11046
Other Changes
- docs: fix typo by @gharbi-mohamed-dev in #11043
Full Changelog: v2.3.0...v2.3.1
v1.20.11
Fixes
- fix(admin-ui): remove unsafe access to index by @kasperkristensen in #9355
- fix(product): fix product variant update price with min_quantity and max_quantity by @BeyondOT in #9381
- fix: Abort the admin
develop
command if serve isfalse
by @adevinwild in #7299 - fix: Don't store JWT token in an SSR environment by @devcshort in #9848
Documentation
- docs: Update meilisearch.md by @pavlotsyhanok in #7862
- docs(v1.x): fix incorrect display of route path by @shahednasser in #9383
- docs(v1.x): add redirects to v2 docs by @shahednasser in #9723
- docs(v1.x): update configuration to add /v1 path prefix by @shahednasser in #9731
- docs(v1.x): disable base path from rewrite by @shahednasser in #9763
- docs(v1): remove AI assistant by @shahednasser in #10080
- docs(v1): migrate kapa by @shahednasser in #10199
- docs(v1): remove installation instructions by @shahednasser in #10354
Chores
- chore: Convert to TS by @olivermrbl in #9271
- chore(v1.x): fix v1 links in source code + generate references by @shahednasser in #10777
New Contributors
- @pavlotsyhanok made their first contribution in #7862
- @BeyondOT made their first contribution in #9381
- @devcshort made their first contribution in #9848
Full Changelog: v1.20.10...v1.20.11
v2.3.0
Highlights
Data migrations script
Some features might require data migrations to ensure new functionality works as expected after an upgrade. Typically, these migrations can be dealt with by database migrations within a module. However, this is not the case when the changes affect the data models in several modules. In those scenarios, the data in multiple modules need to be brought to the desired state.
To support this, we've introduced data migration scripts. They are very similar to regular scripts in the sense, that you have access to the dependency container, i.e. all modules. However, instead of running manually, data migration scripts are run automatically as part of running medusa db:migrate
.
How it works
We scour Medusa projects, plugins, and the core for files in the src/migration-scripts
and execute them. The files should export a default function. These scripts are only run once, provided they succeed.
The flow is as follows:
- Find files
- Ensure the
script_migrations
table existsβif not, create it - Identify pending migration scripts (scripts that have not been ran previously)
- Acquire a lock on the table
- Begin loop, for each script
- Insert migration script in the database
- Execute script
- Mark script as finished
- Release lock
This release focuses on putting the foundation in place for data migrations and does not introduce any scripts.
See #10960 for more.
Cart validation hooks
All Cart workflows have been updated to include a hook to perform validation before executing the operation.
For example, in the completeCartWorkflow
you can register a hook like so:
import { completeCartWorkflow } from "@medusajs/medusa/core-flows"
completeCartWorkflow.hooks.validate({ cart } => {
if (!cart.metadata.approved_at) {
throw new Error("Cannot complete unapproved cart")
}
})
Variant Inventory UX upgrade
Warning
Breaking changes
New bulk editors have been added to improve inventory management. One on the product details page, and another on the inventory item list page.
To enable these improvements, we have had to introduce breaking changes to the endpoint updating location levels in batches.
Before
POST /admin/inventory-items/:id/location-levels/batch
{ creates: [ ... ], deletes: [ ... ] }
After
POST /admin/inventory-items/:id/location-levels/batch
{ create: [ ... ], delete: [ ... ], update: [...] }
This brings the endpoint in line with all other batch endpoints.
See #10630 for more.
Payment module changes
Warning
Breaking changes
Data models in the Payment Module have been cleaned up, removing unused fields. This is a breaking change.
The removed fields are region_id
from the Payment Collection entity and cart_id
, order_id
, and customer_id
from the payment entity.
See #10987 for more.
Promotion statuses
The process of creating a promotion is sometimes a lengthy one that requires a campaign to be designed, promotion rules to be drafted, approvals to go through, and time to test it out.
This release introduces statuses on promotions to enable these workflows.
Promotions can now be either active
, inactive
, or draft
. All existing promotions will be set to active
whileas new promotion will start in a draft
state, unless specified otherwise.
See #10950 for more.
Features
- feat: add default retry strategy for redis by @thetutlage in #10880
- feat: remove dead code and refactor the logic of resolving plugins by @thetutlage in #10874
- feat: Merge plugin modules by @thetutlage in #10895
- feat(inventory,dashboard,types,core-flows,js-sdk,medusa): Improve inventory UX by @kasperkristensen in #10630
- feat(admin-bundler,admin-vite-plugin,medusa): Add support for loading Admin Extensions from plugins by @kasperkristensen in #10869
- Feat/plugin develop by @thetutlage in #10926
- feat: add plugin build command by @thetutlage in #10935
- feat: Scaffold plugin in create-medusa-app by @adrien2p in #10908
- feat(cli): Add plugin:publish and plugin:add commands support by @adrien2p in #10938
- feat(medusa,framework,cli,admin-bundler): Integrate admin extensions into medusa build:plugin by @kasperkristensen in #10941
- feat(core, medusa, cli): Enable migration scripts by @adrien2p in #10960
- feat(core-flows): validate hook by @carlos-r-l-rodrigues in #10967
- feat: add support for loading admin extensions from the source by @thetutlage in #10975
- feat: Improvements to payment module and Stripe provider by @sradevski in #10980
- feat: Remove fields from payment models that were leftovers from v1 by @sradevski in #10987
- feat: Add support for listing saved payment methods in module and Stripe by @sradevski in #10994
- feat(promotion,dashboard,types,utils,medusa): Add statuses to promotions by @riqwan in #10950
- Feat(medusa, cli): plugin db generate by @adrien2p in #10988
Bugs
- fix(pricing): PriceLists of type Sale should not override lower prices by @kasperkristensen in #10882
- fix: event-bus-redis processor execute event before subscriber are loaded by @pmc12thsuki in #10823
- fix(pricing): add null conditions for deleted at during price calculations by @riqwan in #10896
- fix(modules): Fix miss leading provider resolution error by @adrien2p in #10900
- fix(types): add missing inventory_items to input of createProductsWorkflow by @shahednasser in #10892
- fix(orchestration): avoid retry when finished by @carlos-r-l-rodrigues in #10913
- fix(core-flows): return refunded when all captured payments have been refunded by @riqwan in #10923
- fix(dashboard, core-flows): improvements to order page on canceled orders by @riqwan in #10888
- fix(core-flows): missing variable of when condition by @carlos-r-l-rodrigues in #10958
- fix: Include is default billing and shipping fields in the address re⦠by @sradevski in #10970
- chore(dashboard,icons): Update icons and switch icon in CategoryTree by @kasperkristensen in #10961
- fix(index): Add type casting to raw order by by @adrien2p in #10899
- fix: Put routes loader error inline by @sradevski in #10912
- fix(framework): Exclude .d.ts files from the glob search and fix insert query by @adrien2p in #10990
- fix(dashboard): delete user messages by @fPolic in #11004
- fix(core-flows,medusa): use deleteRefundReasonsWorkflow in delete /admin/refund-reasons/:id by @shahednasser in #11012
Documentation
- docs: fix divider in API reference + clean up layout by @shahednasser in #10861
- docs: document create-medusa-app new project name argument by @shahednasser in #10834
- docs-util: fixes to OAS generator + generate OAS by @shahednasser in #10867
- docs: document dependencies for auth provider by @shahednasser in #10865
- docs: update recipes following 2.2 release by @shahednasser in #10868
- docs: added Cloudflare R2 guide for Object Storage by @ehtisham-afzal in #10497
- docs: fix typo by @gharbi-mohamed-dev in #10870
- docs: added llms.txt by @shahednasser in #10873
- docs: general fixes and additions by @shahednasser in #10876
- docs-util: fix parsing when function if it has three parameters by @shahednasser in #10878
- docs-util: add warning on request parameters change by @shahednasser in #10881
- docs: add inventory kit conceptual guide by @shahednasser in #10891
- docs: fix colon in api key header by @shahednasser in #10893
- docs: add workflow and js sdk reference pages for commerce modules by @shahednasser in #10898
- docs-util: fix hook input type showing as __type by @shahednasser in #10905
- d...
v2.2.0
Highlights
Passing custom callback to Oauth providers
Warning
Breaking changes
The callback URL for Oauth providers can now be passed in the payload of the authentication request to support use cases like different login pages based on the actor.
For example, you might have a user/github/callback
page and a customer/github/callback
page, and where you redirect to would depend on which actor is doing the authentication.
The request would look as follows:
POST http://localhost:9000/customer/auth/github
{ callback_url: "<some url>" }
This change also adds the state
parameter as defined in the Oauth protocol.
Passing Query Parameters in Callback Validation
Previously, you only passed the code
from the third-party provider (For example, Google) to the callback route. It's now required to pass all query parameters received from the third-party, including state
or error
.
Required actions
If you have overridden the auth module definition in medusa-config.ts
, you will need to pass Modules.CACHE
as a dependency, as the state
is stored temporarily in cache when carrying out the authentication flow:
module.exports = defineConfig({
...
modules: [
{
resolve: "@medusajs/medusa/auth",
dependencies: [Modules.CACHE, ContainerRegistrationKeys.LOGGER],
options: {
providers: [ ... ],
},
},
],
})
If you have a storefront implementation of third-party authentication, make sure to pass all query parameters to the validate callback route. You can also refer to the following updated documentation pages to learn more:
- Storefront Development Guide: Implement Third-Party Social Login
- Conceptual Guide: Third-Party Service Authentication Flow
Custom module types
Container mappings types are generated for modules by inspecting the registered modules. The types are generated and written to your local project in .medusa/types/module-bindings.d.ts
. To generate the types, the module needs be functionally correct, registered in medusa-config.ts
, and the server needs to be started in development mode.
Once the types are generated, your IDEs intellisense should pick them up, e.g. when creating an API Route:
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
export const GET = (req: MedusaRequest, res: MedusaResponse) => {
const brandModule = req.scope.resolve("brand")
await brandModule. // <-------------- Autocompletion should appear
...
}
If you experience issues with generating types for custom modules, please submit an issue, so we can look into it.
Deprecated APIs
Some APIs have been deprecated and/or renamed as part of a housekeeping task in order to be more consistent with naming across tools and modules.
These are:
remoteLink
->link
(deprecated and renamed)remoteQueryConfig
->queryConfig
(deprecated and renamed)remote-query-entry-points.d.ts
->query-entry-points.d.ts
(renaming)
There are no breaking changes in this release, but the deprecated APIs will be removed in a later release, so we recommend updating your code to use the new APIs as soon as possible.
Order cancelation
Canceling an order will also cancel its payments. If the payments are captured, we will attempt to refund an amount equal to the captured amount. If the payments are not captured, they will be canceled immediately.
Other changes
The relationship between stock location and stock location address has been changed to a one-to-one. This change involves a migration, so please apply the latest migrations when upgrading.
Required actions
Run migrations to ensure your server functions as expected after upgrading:
npx medusa db:migrate
Features
- feat(medusa): Add health endpoint for all running modes of medusa by @sradevski in #10737
- feat(create-medusa-app): allow passing project name on command line by @shahednasser in #10755
- feat: deprecate remote link by @thetutlage in #10768
- feat: deprecate remoteQueryConfig in favor of queryConfig by @thetutlage in #10773
- feat: generate modules mappings at runtime by @thetutlage in #10791
- feat(create-medusa-app): improve by adding depth to clone commands by @shahednasser in #10812
- feat(auth-google,auth-github): Allow passing a custom callbackUrl to β¦ by @sradevski in #10829
- feat(dashboard,core-flows,types,utils,medusa): Order cancelations will refund payments by @riqwan in #10667
Bugs
- fix(fulfillment): export schema types by @shahednasser in #10700
- fix: pluralization of words ending in y, where y follows a vowel by @thetutlage in #10697
- fix(medusa,types,js-sdk): fix request query parameter types for store product routes by @shahednasser in #10707
- fix(core-flows): export updateTaxRegionsStep by @shahednasser in #10732
- fix(pricing): pricing context calculations only takes into account existing rule attributes by @riqwan in #10771
- Fix/product variants filter by @thetutlage in #10808
- fix(): Workflow cancellation + gracefully handle non serializable state by @adrien2p in #10674
- fix(core-flow): invalid update quantity in update line item in cart workflow by @daykrm in #10405
- fix(promotion): don't evaluate rule condition if conditions to evaluate is empty by @riqwan in #10795
- fix(stock-location,core-flows,types): updates existing address when updating stock location by @riqwan in #10832
- feat(core-flows,fulfillment, fulfillment-manual, types): make fulfillment typings more specific by @fPolic in #10677
- fix(create-medusa-app): add default storefront url to auth CORS by @shahednasser in #10853
- fix(dashboard): cancel order notifications by @fPolic in #10858
Documentation
- docs: integrate shipstation guide by @shahednasser in #10623
- docs: update typedoc, convert packages to esm, generate references by @shahednasser in #10699
- docs: fix typo in CmsModuleService by @shahednasser in #10702
- docs-util: fix links in references to current page by @shahednasser in #10703
- docs-util: fix query params not retrieved correctly for some routes by @shahednasser in #10708
- docs: split commerce modules sidebars by @shahednasser in #10705
- docs: fix typo in extend core flow by @shahednasser in #10709
- docs: split events reference across modules by @shahednasser in #10711
- docs: split admin widget zone to pages by @shahednasser in #10719
- docs: improve link docs for commerce modules by @shahednasser in #10726
- docs: fix multiple typos in customization chapters by @shahednasser in #10727
- docs: add workflow / step tags by @shahednasser in #10731
- docs: revise commerce modules overview pages by @shahednasser in #10738
- docs: add JS SDK to commerce modules sidebars by @shahednasser in #10740
- chore: improve payment provider tsdocs + generate reference by @shahednasser in #10742
- docs: fix and improve details on sending authenticated requests with API token by @shahednasser in #10744
- docs-util: add publishable api key header parameter to store routes OAS by @shahednasser in #10747
- docs: document how to calculate shipping prices in storefront by @shahednasser in #10748
- docs: allow scroll with keys by @shahednasser in #10752
- docs: update and fix UI props docs by @shahednasser in #10754
- docs: document missing events in reference by @shahednasser in #10779
- docs: update fulfillment provider module docs to reflect CalculatedShippingOptionPrice by @ranjithkumar8352 in #10778
- docs: fix code tabs in production by @shahednasser in #10784
- docs: fix selected variant in storefront guide by @shahednasser in #10785
- chore: fix links t...
v2.1.3
Highlights
Calculated shipping option price
This release introduces dynamically calculated shipping option prices, which comprise three key changes:
- Admin support for creating dynamically priced options
When creating a shipping option, choose the "calculated" price type. Upon sending the request to create the option, our fulfillment module verifies if the provider and method support calculated prices.
- New storefront endpoint to calculate shipping option prices
To display calculated prices on the storefront, use the endpoint below. Calculated shipping options do not include a price in the regular request to retrieve options for a cart. These are calculated separatelyβone request for each option.
POST /store/shipping-options/:id/calculate
{ cart_id: "cart_1234", data: { ... } }
Pass custom data in the data
property of the payload. The data
is passed down to the provider and can be used for the calculation, e.g. distance to destination.
Our Next.js starter has been updated to include this feature. Check it out here.
- Changes to the addShippingMethodToCartWorkflow
When adding a calculated shipping option to a cart, the price is computed dynamically similarly to the calculation endpoint.
Module DML migrations
More core modules have been migrated from MikroORM to DML. These migrations come with non-breaking schema changes, primarily around index renaming and adding default timestamp columns.
Removed orphan deletion
Additionally, we've removed the default orphanRemoval: true
configuration from one-to-one relationships. This is a less aggressive approach to cascade removal, meaning that disconnecting entities in such a relation will not delete the "child" of the association.
Required action
Run migrations to ensure your server functions as expected after upgrading:
npx medusa db:migrate
As part of migrating modules to use DML, we've uncovered a range of minor bugs (not affecting end-users) and improvements. You can read more about those in this PR.
Line items with custom prices
This release allows for custom prices on line items by decoupling variants and line items in the cart and order workflows.
Our core API doesn't support custom prices out of the box, however the underlying addToCartWorkflow
does.
Here's an example of how to use it in a custom API Route:
// POST /store/carts/:id/custom-line-items
import { addToCartWorkflow } from "@medusajs/medusa/core-flows"
async function thirdPartyCallToComputePrice(item: any) {
return {
...item,
unit_price: Math.floor(Math.random() * 900) + 100,
}
}
export const POST = async (req, res) => {
const { id } = req.params
const { items } = req.body
const query = req.scope.resolve("query")
const itemsWithDynamicPrice = await Promise.all(
items.map((item) => {
return thirdPartyCallToComputePrice(item)
})
)
const workflowInput = {
items: itemsWithDynamicPrice,
cart_id: id,
}
await addToCartWorkflow(req.scope).run({
input: workflowInput,
})
const updatedCart = await query.graph({
entity: "cart",
filters: { id },
fields: ["id", "items.*"],
})
res.status(200).json({ cart: updatedCart })
}
Nesting Admin UI Routes under existing domains
This release introduces support for nesting a UI Route under an existing domain in the sidebar instead of in the extensions section.
For example, you can locate Brands under Products:
import { defineRouteConfig } from "@medusajs/admin-sdk"
import { Container, Heading } from "@medusajs/ui"
const NestedProductsPage = () => {
return (
<Container className="divide-y p-0">
<div className="flex items-center justify-between px-6 py-4">
<Heading level="h1">Nested Products Page</Heading>
</div>
</Container>
)
}
export const config = defineRouteConfig({
label: "Nested Products",
nested: "/products",
})
export default NestedProductsPage
This improvement to our existing UI Routes tooling was a community contribution from @eugenepro2.
Features
- feat(core-flows,dashboard,js-sdk,medusa,types): support Fulfillment Options by @fPolic in #10622
- feat: Custom line items by @olivermrbl in #10408
- feat(order, types): Add Credit Line to order module by @riqwan in #10636
- feat(core-flows): pass fields variant details when creating fulfillment by @fPolic in #10665
Bugs
- fix(core-flows): export getItemTaxLinesStep by @shahednasser in #10640
- fix(medusa): Missing metadata field on order by @olivermrbl in #10651
- fix(dashboard): order details status by @fPolic in #10650
- fix(notification): Only use enabled providers for notis by @olivermrbl in #10659
- fix(core-flows): use useQueryGraphStep instead of useQueryStep by @shahednasser in #10643
- fix(core-flows): data passed to to fulfillment provider context by @fPolic in #10660
- fix(core-flows): refresh payment collections upon shipping changes by @riqwan in #10673
- fix(product): updating collections with products fix by @riqwan in #10668
- fix(core-flows): select stock locations for reservation from correct SC by @fPolic in #10661
Documentation
- docs: document float property (for v2.1.2) by @shahednasser in #10575
- docs-util: infer resolved resources in workflow + steps by @shahednasser in #10637
- docs: generate references manually for v2.1.2 by @shahednasser in #10639
- chore: fix redocly circular dependencies by @shahednasser in #10642
- docs: add tags package to generate tags by @shahednasser in #10666
- docs: support generating sidebar items with tags by @shahednasser in #10672
- docs: add tags manually to doc pages by @shahednasser in #10675
- docs: remove duplicate parsed tag items by @shahednasser in #10676
Chores
- chore(types): Keep intelisense while being more loosen by @adrien2p in #10657
- chore: improve tsdocs of fulfillment provider by @shahednasser in #10649
- chore(fulfillment, utils): Migrate module to DML by @adrien2p in #10617
Other Changes
- Add FilterableRefundReason filter by description and label by @vethan in #10606
- feat(dashboard): ability to locate new admin route under existing route by @eugenepro2 in #10587
New Contributors
- @vethan made their first contribution in #10606
- @eugenepro2 made their first contribution in #10587
Full Changelog: v2.1.2...v2.1.3
v2.1.2
Highlights
Breaking changes
The input shape of two core workflows have changed:
updateLineItemInCartWorkflow
export interface UpdateLineItemInCartWorkflowInputDTO {
+ cart_id: string
+ item_id: string
- cart: CartDTO
- item: CartLineItemDTO
update: Partial<UpdateLineItemDTO>
}
addToCartWorkflow
export interface AddToCartWorkflowInputDTO {
+ cart_id: string
- cart: CartDTO
items: CreateCartCreateLineItemDTO[]
}
Patches a regression with the Cart Module
Warning
Schema changes
In an earlier release, we migrated the data models of the Cart Module from MikroORM to our DML. As part of that migration, the tax rate
column on line item tax lines and shipping method tax lines was mistakenly changed from a numeric to an integer. This led to issues with tax rates with decimal points, as they would get rounded to the nearest integer.
In this release, we are changing the rate
column to real
(or float()
in our DML) to be consistent with how tax rates are generally represented across the codebase.
Required action
Run migrations to ensure your server functions as expected after upgrading:
npx medusa db:migrate
Features
- refactor: migration stock location module by @thetutlage in #10471
- refactor: migrate promotion module by @thetutlage in #10410
- feat(core-flows, dashboard, fulfillment, fulfillment-manual, utils, types): create shipping options with calculated prices by @fPolic in #10495
- feat: Migrate customer module to DML by @thetutlage in #10499
- feat(file-s3): Add support for IAM role authentication to file-s3 provider by @sradevski in #10528
- feat: add support for float properties by @thetutlage in #10551
- feat(medusa, core-flows, fulfillment): calculate SO price endpoint by @fPolic in #10532
- Feat/tax dml by @thetutlage in #10525
- feat(types,fulfillment): ability to delete a canceled fulfillment by @riqwan in #10602
- feat(core-flows): calculate SO price on cart ops by @fPolic in #10563
- feat(medusa,pricing): Cart pricing context with customer group by @riqwan in #10579
Bugs
- fix(product): Only apply default order to products if user has not specified one by @kasperkristensen in #10535
- fix(dashboard): Prevent fulfillment provider modal from re-rendering before form submission is complete by @kasperkristensen in #10547
- breaking: pluralization rule for the info word by @thetutlage in #10599
- fix(core-flows): use customer create workflow to reuse the emit event by @riqwan in #10601
- fix(cart): tax rate data type by @carlos-r-l-rodrigues in #10626
Documentation
- docs: documented fetchCredentials options of JS SDK by @shahednasser in #10510
- docs: added restock notification guide by @shahednasser in #10413
- docs: fix page title in reference pagesnot showing + refactor workflows reference by @shahednasser in #10537
- docs: generate references manually for 2.1.1 by @shahednasser in #10534
- docs: regenerate references for core flows by @shahednasser in #10538
- docs: document when-then name by @shahednasser in #10543
- docs: fix typo in code in module isolation documentation by @shahednasser in #10546
- docs: revise recipe examples by @shahednasser in #10545
- docs: revise architectural modules documentation by @shahednasser in #10548
- chore: fixes to tsdocs + docs-util related to providers by @shahednasser in #10555
- docs: fix bugs in API reference by @shahednasser in #10557
- Nits by @MedusaNick in #10558
- docs: fix imports in createBrandStep by @shahednasser in #10567
- docs: clarify that stripe module provider is available in application by @shahednasser in #10577
- docs: add documentation on sending requests to custom routes with JS SDK by @shahednasser in #10582
- docs: updates to contribution guidelines by @shahednasser in #10578
- docs: document many-to-many with extra columns by @shahednasser in #10586
- docs: improve examples in module link direction by @shahednasser in #10590
- docs: add section on updating medusa by @shahednasser in #10589
- docs: document alternatives for conditional operators by @shahednasser in #10588
- docs-util: support @Version tag by @shahednasser in #10591
- chore: fix docs freshness check action by @shahednasser in #10592
- docs: add pivotTable in digital product recipe by @shahednasser in #10605
- docs: add customize stripe integration in next.js guide by @shahednasser in #10583
- docs: small wording fix by @shahednasser in #10616
- docs: remove unnecessary log by @shahednasser in #10619
- docs: add stripe events to provider guide by @shahednasser in #10618
- docs: add example of Table component with pagination by @shahednasser in #10621
- docs: fix expanding of custom relations in customer and product category routes by @shahednasser in #10620
Chores
- chore(payment): Payment module DML by @carlos-r-l-rodrigues in #10553
- chore: small tsdoc update to dml float property. by @shahednasser in #10576
- chore(inventory): convert to dml by @carlos-r-l-rodrigues in #10569
Other Changes
- feat: added Ukrainian translations by @Avia-Code in #10536
New Contributors
- @Avia-Code made their first contribution in #10536
Full Changelog: v2.1.1...v2.1.2
v2.1.1
Highlights
Shipping option rules
We've introduced support for pricing rules on shipping options. Initially, the feature allows you to define prices based on the cart item total. For example, you could have a free shipping option that is only available when the item total is above 100 EUR.
Every time the cart is updated, e.g. with new items, we refresh the shipping methods to ensure the correct price is applied at all times.
You'll find the new setting in the admin dashboard under "Settings > Locations & Shipping > View details > Edit prices (on shipping option)".
New languages
Our admin dashboard has been translated into Japanese.
DML Migrations
Warning
Schema changes
We've migrated our Cart, Sales Channel, API Key, Store, Workflow Engine, and Locking modules to use our Data Model API. These migrations include minor changes to the database schema, primarily around renaming indexes to respect our autogenerated naming conventions.
Read more about each of the schema changes in the PRs below.
Changes to hasOne
As part of our DML work, the behavior of hasOne
has been updated in use cases where it is only defined on one side of the relation. In these cases, the mappedBy
configuration of the hasOne
definition needs to be set to undefined
as it is not present on the other model.
For example:
const email = model.define("email", {
email: model.text(),
isVerified: model.boolean(),
})
const user = model.define("user", {
id: model.number(),
username: model.text(),
email: model.hasOne(() => email, { mappedBy: undefined }), // <------------ Required config
})
Required actions
Run migrations to ensure your server functions as expected after upgrading to v2.1.0:
npx medusa db:migrate
Features
- feat: add support for defining hasOne with FK by @thetutlage in #10441
- refactor: migrate cart module to DML by @thetutlage in #10385
- refactor: migrate sales-channel to DML by @thetutlage in #10452
- refactor: migrate api key module to DML by @thetutlage in #10450
- feat(js-sdk): Make credentials configurable in SDK by @sradevski in #10464
- refactor: migrate store module to DML by @thetutlage in #10467
- feat(core-flows, types): update shipping methods upon cart ops by @riqwan in #10382
- feat(dashboard): SO cart item total rules UI by @kasperkristensen in #10386
Bugs
- fix(dashboard,types): Add missing Metadata form for Region domain and fix payload types by @kasperkristensen in #10449
- fix(core/js-sdk) Add the credentials field in the fetch() only if supported by @sgirones in #10446
- fix(dashboard): Cleanup unsafe accesses to possibly undefined values in order timeline by @kasperkristensen in #10454
- fix(): Deleted default sales channel should be prevented by @adrien2p in #10193
- fix(utils): DML one to one definition by @adrien2p in #10415
- fix(workflows-sdk): name for when/then step by @carlos-r-l-rodrigues in #10459
- fix(framework): add missing query type argument in request types by @shahednasser in #10456
- fix(dashboard): Prevent sending off empty string as handle for product category by @kasperkristensen in #10473
- fix(utils): avoid optional properties on graphql generated file by @carlos-r-l-rodrigues in #10476
- fix(dashboard,types): Fix TS errors by @kasperkristensen in #10457
- fix(promotion, core-flows): updating cart with removed promotion removes adjustments by @riqwan in #10489
- fix(medusa): add query type argument to RequestWithContext by @shahednasser in #10469
- fix(medusa): calculate sales channel availability correctly for variants by @srindom in #10448
Documentation
- docs: add documentation for check constraints by @shahednasser in #10425
- docs: add note about default owner table in many-to-many by @shahednasser in #10426
- docs: generate references manually by @shahednasser in #10438
- docs: revise extend create product by @shahednasser in #10444
- docs: revise query linked records by @shahednasser in #10447
- docs: fix links in extend product guide by @shahednasser in #10472
- docs-util: support new query type argument by @shahednasser in #10468
- docs: revise admin customization pages by @shahednasser in #10466
- docs: revise last chapters of customizations by @shahednasser in #10480
- docs: support detecting broken link cross-projects by @shahednasser in #10483
- docs: fix self hosting deployments not showing by @shahednasser in #10486
- docs: revise main docs outline by @shahednasser in #10502
- docs: fix links to steps in workflow references by @shahednasser in #10503
- docs-util: normalize RelationNullableModifier in model references by @shahednasser in #10505
Chores
- chore(utils): DML#hasOne allow mappedBy to not be defined by @adrien2p in #10442
- chore: locking-postgres provider dml by @carlos-r-l-rodrigues in #10478
- chore(workflow-engine): Migrate to DML by @adrien2p in #10477
Other Changes
New Contributors
Full Changelog: v2.1.0...v2.1.1
v2.1.0
Highlights
Improved order management
We've improved our order management with support for updating email, shipping address, and billing address.
New languages
Our admin dashboard has been translated into Italian.
Support for check constraint in Data Model API
We've added support for Postgres check constraints in our Data Model API.
For example:
const shippingMethod = model.define('ShippingMethod', {
amount: model.bigNumber(),
})
.checks([
(columns) => `${columns.amount} >= 0`
])
DML Migrations
Warning
Schema changes
We've migrated our Pricing, User, and Auth modules to use our Data Model API. These migrations include minor changes to the database schema:
Pricing module
- Added column
operator
toprice_rule
table (defaults toeq
) - Created index on
(operator)
inprice_rule
table - Created index on
(price_id)
inprice_rule
table - Created unique index on
(price_id, attribute, operator)
inprice_rule
table - Changed type of
max_quantity
column inprice
table from numeric to integer - Changed type of
min_quantity
column inprice
table from numeric to integer
Auth module
- Added column
deleted_at
toauth_identity
table - Added column
deleted_at
toprovider_identity
table - Created index on
(deleted_at)
inauth_identity
table - Created index on
(deleted_at)
inprovider_identity
table
User module
- Renamed unique index on
(email)
ininvite
table - Renamed unique index on
(email)
inuser
table
Required actions
Run migrations to ensure your server functions as expected after upgrading to v2.1.0:
npx medusa db:migrate
Features
- feat(pricing,utils,types): add operator field to price rule by @riqwan in #10315
- feat(pricing, types): add price rule operators to price calculations by @riqwan in #10350
- feat(core-flows,types,medusa): ability to update/create custom shipping prices by @riqwan in #10368
- feat(core-flows,framework,medusa): list shipping options pass in cart as pricing context by @riqwan in #10374
- refactor: migrate pricing entities to DML models by @thetutlage in #10335
- feature: add support for check constraints in DML by @thetutlage in #10391
- feat(core-flows,medusa,order,types): update orders by @fPolic in #10373
- feat(admin, js-sdk, types): update order forms by @fPolic in #10418
Bugs
- fix(medusa): remove request body type argument from cancel order transfer routes by @shahednasser in #10327
- fix(product): change export name of ProductImage by @shahednasser in #10326
- fix: Use the correct defaults for the invite token expiry by @sradevski in #10344
- fix: do not initialize FKs to null by @thetutlage in #10337
- fix(order): archive order status update by @fPolic in #10340
- fix: do not rely on model loading order to find an implicit owner by @thetutlage in #10360
- fix(ui,icons,ui-preset): Fix CodeBlock and Command components by @kasperkristensen in #10369
- fix: Ensure tax lines are generated for all items and shipping methods in cart by @olivermrbl in #10372
- fix(stock-location): Fix export of StockLocation module by @kasperkristensen in #10406
- fix(dashboard): Fix broken number input in adjust inventory form by @kasperkristensen in #10416
- fix(dashboard): Add default value to inventory item combobox by @kasperkristensen in #10412
- fix(dashboard): Prevent language ptBR from breaking dashboard by @kasperkristensen in #10422
- fix(framework): Ensure that CORS and Auth middleware is applied for routes only defined in middlewares.ts by @kasperkristensen in #10339
- fix(dashboard): Add Shipping Profile metadata route by @kasperkristensen in #10430
Documentation
- docs: update sanity guide + marketplace recipe to use permanentFailure by @shahednasser in #10310
- docs: update details on retrieving nested categories by @shahednasser in #10317
- docs: add note about actor_type in reset password event in v2.0.7 by @shahednasser in #10322
- docs: update many-to-many docs by @shahednasser in #10323
- docs: generate references manually by @shahednasser in #10325
- docs: revise implement brand module by @shahednasser in #10341
- docs: revised build custom features chapter by @shahednasser in #10338
- docs: revise create brand workflow by @shahednasser in #10346
- docs: changes to deployment + remove admin deployment guides by @shahednasser in #10345
- docs: document permanentFailure by @shahednasser in #10356
- docs: add note about retryInterval making workflow long-running by @shahednasser in #10355
- docs: intro + basic chapter fixes by @shahednasser in #10361
- docs: remove v2 branch of next js starter installation by @shahednasser in #10402
- docs: add missing import to db operations documentation by @shahednasser in #10390
- docs: revise brand API route by @shahednasser in #10352
- docs-util: add user, pricing, and auth as modules with DML by @shahednasser in #10423
- docs: fixes and improvements to Sanity guide by @shahednasser in #10414
Chores
- Fix(dml): DML default/nullable management by @adrien2p in #10363
- chore(utils): Ensure DML name convention follow the same as the class name for simplicity by @adrien2p in #10370
- feat(auth): Migrate auth module to DML by @adrien2p in #10387
- feat(user): Migrate user module to DML by @adrien2p in #10389
- chore(workflows-sdk): add unit test by @carlos-r-l-rodrigues in #10419
Other Changes
- German language corrections by @pixelwiese in #10394
- feat: added Italian translations by @MarcoSan19 in #10362
- Fix French translation typos by @lucienbl in #10348
New Contributors
- @MarcoSan19 made their first contribution in #10362
- @lucienbl made their first contribution in #10348
Full Changelog: v2.0.7...v2.1.0
v2.0.7
Highlights
Order transfers
You can now transfer order ownership between customers. We've added UI support in three places:
- Order details page in Medusa Admin
- Customer details page (Order list) in Medusa Admin
- Self-serve in our Next.js and B2B starters
The high-level flow is as follows:
- Initiate transfer
POST /admin/orders/:id/transfer { customer_id: string }
Send a request to generate a transfer token and emit an event with the order ID.
- Event subscriber
A subscriber picks up the event and emails the orderβs current customer with the token.
- Accept Transfer
Customer accepts the order transfer.
POST /store/orders/:id/transfer/accept { token: string }
Product Module DML migration
Warning
Breaking changes (avoidable)
The Product module now uses our DML for data model definitions instead of MikroORM. This migration introduces improvements and fixes but results in breaking changes to some relationship APIs. These can be avoided through explicit configurations.
Required actions
- Relation ownership on
manyToMany
relation
Previously, the manyToMany
API inferred the owning side of relations based on the order of loading models. If the first-loaded model used mappedBy
, it became the owner. Now, ownership is determined by examining both sides of the relation, before defaulting to the old behavior. This change might lead to unexpected behavior, and we therefore recommend explicitly defining the owner.
Explicitly define the owner using joinColumn
, inverseJoinColumn
, or pivotTable
:
const ProductVariant = model
.define("ProductVariant", {
id: model.id({ prefix: "variant" }).primaryKey(),
...
options: model.manyToMany(() => ProductOptionValue, {
pivotTable: "product_variant_option",
mappedBy: "variants",
joinColumn: "variant_id",
inverseJoinColumn: "option_value_id",
}),
})
- Pivot table naming
Aside from the relation ownership, we have also updated how pivot table names are generated.
Before
We used the model names in alphabetical order and pluralized the last one of them.
Now
We use the model's table names in alphabetical order and pluralize the last one of them.
To avoid issues with your project, explicitly set pivotTable
in manyToMany
relations to match your existing table names:
For example:
const user = model.define('User', () => {
addresses: model.manyToMany(() => Address, { pivotTable: 'address_users' })
})
New languages
Our admin dashboard has been translated into Brazilian Portuguese, French, Thai, and Spanish.
Features
- feat(dashboard): Allow setting a tooltip for disabled action items by @kasperkristensen in #10234
- feat(dashboard, js-sdk): customer page transfer order + cancel request in timeline by @fPolic in #10250
- feat: convert MikroORM entities to DML entities by @thetutlage in #10043
- feat: add ptBR (Brazilian Portuguese) in translations by @DanSilva41 in #10188
- feat: add Thai language support by @oDestroyeRo in #10249
- feat: French translation V2 by @triplecasquette in #10301
Bugs
- fix: Fix product module creation example by @sradevski in #10228
- fix: Inventory module schema by @olivermrbl in #10262
- fix(dashboard): Add Metadata form to variant page by @kasperkristensen in #10285
- fix(dashboard): Truncate long product organization tags by @kasperkristensen in #10261
- fix(core-flows): aggregate payment status by @carlos-r-l-rodrigues in #10278
- fix(dashboard): Align casing of fields in reset password event by @kasperkristensen in #10313
- fix(dashboard): adjust transfer SVG for theme by @fPolic in #10307
- fix(dashboard): Prevent product metadata form from throwing error by @kasperkristensen in #10312
- fix(utils): read dir recursive by @carlos-r-l-rodrigues in #10318
- fix(dashboard): Correct Spain provinces in country-states.ts by @anthid in #10264
Documentation
- docs: update injection zones for v2.0.5 by @shahednasser in #10225
- docs: add details on updating a cart's customer by @shahednasser in #10226
- docs: added section on medusa cloud by @shahednasser in #10265
- docs-util: fix references generator by @shahednasser in #10271
- docs-util: fix build errors by @shahednasser in #10275
- docs: fixes to Medusa Cloud sections by @shahednasser in #10270
- docs: changes for CLI tools by @shahednasser in #10284
- docs: fix link to payment session by @shahednasser in #10286
- docs: fix links in API reference workflows section by @shahednasser in #10269
- docs: revise scheduled jobs by @shahednasser in #10291
- docs: fix links in examples guide by @shahednasser in #10296
- docs: revise workflows docs by @shahednasser in #10294
- docs: fix link to medusa container by @shahednasser in #10298
- docs: revise admin customization pages by @shahednasser in #10297
- docs: clarify medusa_url in Stripe docs by @shahednasser in #10305
- docs: update list of events by @shahednasser in #10308
- docs: add resend integration guide by @shahednasser in #10268
- docs: fix database URL in railway guide by @shahednasser in #10311
- docs: fix updateProvider edit user's password example by @xqSimone in #10253
- docs: Update Redis connection string instructions for Railway by @qbitdoge in #10246
Chores
- chore: fix CI branch in test by @shahednasser in #10274
- chore(dashboard): Add missing keys to i18n translation files by @kasperkristensen #10260
New Contributors
- @DanSilva41 made their first contribution in #10188
- @xqSimone made their first contribution in #10253
- @qbitdoge made their first contribution in #10246
- @anthid made their first contribution in #10301
Full Changelog: v2.0.6...v2.0.7
v2.0.6
Highlights
Product image reordering
An issue with duplicated images on product create and update in v2.0.5 has been patched. For information about the feature, see the release notes for v2.0.5.
Bugs
- fix(product, dashboard): manual cleanup of uploaded images by @kasperkristensen in #10254
Full Changelog: v2.0.5...v2.0.6