Releases: medusajs/medusa
v2.8.8: Improved error logging and overall robustness of core operations
Highlights
Carry over cart promotions to order
The cart-completion workflow has been updated to transfer promotions from carts to orders upon completion. This means you can now access promotions on the order like so:
const { data } = await query.graph({
entity: "order",
fields: ["id", "promotions.*"]
})
const order = data[0]
console.log(order.promotions)
// [{
// "id": "promo_1234",
// "code": "10OFF",
// "is_automatic": false,
// "is_tax_inclusive": false,
// "type": "standard",
// "status": "active",
// "campaign_id": null,
// "campaign": null,
// }]
Previously, promotions had to be accessed via the line item adjustments on the order.
Align accepted values in product import template
The CSV product import functionality has been updated to correctly handle unexpected columns. These columns are now ignored during import, ensuring a smoother process for creating and updating products.
Improved error logging
Client-side 4xx responses (such as 404s) are no longer logged as errors. These responses typically indicate expected conditions. Only 5xx responses, which indicate server-side issues, are now logged as errors. This reduces unnecessary noise in logs, making it easier to focus on actual server problems.
Expanded order methods in the JS SDK
Added archive and complete methods to the admin.order
module of the JS SDK. These methods provide support for the POST /admin/orders/{id}/archive
and POST /admin/orders/{id}/complete
endpoints, giving developers full access to the order lifecycle directly from the SDK.
The methods are used like so:
await sdk.admin.order.archive("order_123");
await sdk.admin.order.complete("order_123");
Bugs
- fix(link-modules,core-flows): Carry over cart promotions to order promotions by @riqwan in #12920
- fix(core-flows): updating tax lines when draft order shipping is removed by @fPolic in #12919
- fix(types): add attachments to CreateNotificationDTO type by @shahednasser in #12936
- fix(dashboard): combobox multiitem clear by @fPolic in #12939
- fix(core-flows): useQueryGraph util return type by @adrien2p in #12962
- chore(workflow-engine-*): Align event subscribers management by @adrien2p in #12976
- fix(orchestration): Prevent workf. cancellation to execute while rescheduling by @adrien2p in #12903
- fix: accepted values in import with template by @juanzgc in #12969
- fix(core-flows): properly delete variant inventory item by @fPolic in #12958
- chore(link-modules): keep promotion alias by @riqwan in #12928
- fix(wfe): should notify when finished + add state info by @adrien2p in #12982
- fix(wfe): add missing state in inmemory notify on run finished by @adrien2p in #12987
- fix(dashboard): allocation UI for orders with more than 20 reservation items by @fPolic in #12989
- fix(pricing): fix pricing query when max_quantity is null by @riqwan in #12981
- fix: fix script migrations order by @peterlgh7 in #13007
- fix(workflows-sdk): fix step name config used before default by @carlos-r-l-rodrigues in #12926
- fix(modules-sdk): Entity types by @olivermrbl in #13002
- fix(dashboard, product): product attributes update with a relation update by @fPolic in #13019
Documentation
- docs: add missing prop to kapa by @shahednasser in #12934
- chore(docs): fix generate OAS for gift card by @shahednasser in #12937
- chore(docs): Updated UI Reference (automated) by @github-actions[bot] in #12941
- docs: changes for new releases + fixes by @shahednasser in #12945
- chore(docs): Generated References (automated) by @github-actions[bot] in #12942
- docs: fix overlap between input and clear button in search by @shahednasser in #12949
- docs: updates to long-lived environment and billing docs by @shahednasser in #12948
- docs: fix example of updatePayment method by @shahednasser in #12947
- docs: added a note linking to create-medusa-app reference by @shahednasser in #12950
- docs: update next.js to 15.3.5 by @shahednasser in #12952
- docs: fix complete cart workflow in marketplace vendors recipe by @shahednasser in #12953
- docs: update customize stripe in next.js storefront guide by @shahednasser in #12963
- docs: add a troubleshooting section on creating a payment session with zero total by @shahednasser in #12974
- docs: use mappedBy property for all relationship types by @shahednasser in #12973
- docs: add examples to price rules and tiers by @shahednasser in #12700
- docs: improvements to the "Expose a Workflow Hook" documentation by @shahednasser in #12992
- docs: add a section on shipping options and requirement + improvements by @shahednasser in #12990
- chore: Fix freshness check script + update Linear SDK by @shahednasser in #12991
- docs: add inject dependencies section in module tests + improvements by @shahednasser in #12993
- docs: fix spacing between workflow steps and tooltip by @shahednasser in #12994
- docs: fix input type of some hooks in workflow reference by @shahednasser in #12995
- docs: add section on type aliases in admin + note for removing items from orders by @shahednasser in #12996
- docs: fix jest.config.js by @SteelRazor47 in #12999
- docs: improve alt of images by @shahednasser in #12998
- docs: freshness check for some guides by @shahednasser in #13000
- docs: remove non-existing sidebar items by @shahednasser in #13013
- docs: fix typos in learn and recipes by @mathieuh in #13017
- docs: add MCP server by @shahednasser in #13018
- docs: added pre-orders guide by @shahednasser in #12984
- docs: added personalized products guide by @shahednasser in #13012
- docs: added Docker local installation guide by @shahednasser in #13022
Chores
- chore(docs): Update version in documentation (automated) by @github-actions[bot] in #12935
- chore(docs): Generated DML JSON files (automated) by @github-actions[bot] in #12940
- chore(docs): Updated API Reference (automated) by @github-actions[bot] in #12943
- chore: fix tsdocs of updatePayment method by @shahednasser in #12946
- chore: upgrade to latest zod v3 by @riqwan in #12938
- chore(orchestration): improve transaction errors by @carlos-r-l-rodrigues in #12951
- chore: remove codegen action by @shahednasser in #12954
- chore: add to TSDocs note about removing item from order edit by @shahednasser in #12997
- chore(payment): use generate schema by @carlos-r-l-rodrigues in #13004
Other Changes
- chore(medusa): fix typo by @OnlyWick in #12907
- chore(docs): Update worker_mode description as environment by @DanSilva41 in #12894
- feat(i18n): update translation for Vietnamese by @NuxTijNhaX in #12931
- fix: only log server errors by @peterlgh7 in #12957
- feat: Added Malawi kwacha to currency list by @sevenreup in #12440
- docs: add data migration scripts section by @SteelRazor47 in #12975
- chore: Expose Awilix resolution errors by @trevster344 in #13008
- fix(js-sdk): add missing admin order archive and complete methods by @anteprimorac in #12944
New Contributors
- @OnlyWick made their first contribution in https://git...
v2.8.7: Improved `create-medusa-app` and corrected tax calculations
Highlights
New --version
flag for create-medusa-app
This release introduces a new flag, --version
to the create-medusa-app
command, allowing you to create Medusa projects with a specific version installed.
npx create-medusa-app ---version 2.8.5
Correct tax calculations for order item adjustments
This release introduces the is_tax_inclusive
flag on order line item adjustments to ensure tax calculations are correct for tax-inclusive promotions.
Features
- feat(create-medusa-app): Allow to create project with specific medusa version by @adrien2p in #12882
Bugs
- fix(core-flows): Locations levels check in draft order and order edit flows by @olivermrbl in #12881
- fix(index): merge filterable fields schema by @carlos-r-l-rodrigues in #12888
- fix(): Order constraint and receive return by @adrien2p in #12889
- fix(order, core-flows): Tax inclusive order line item adjustments by @olivermrbl in #12875
- fix(orchestration): Handle expected lifecycle errors by @adrien2p in #12886
- fix(dashboard): show TIP flag only for fixed promotions by @fPolic in #12897
- fix(medusa, core-flows): Update TIP on promotions by @olivermrbl in #12885
Documentation
- chore: Bump Kapa SDK by @olivermrbl in #12870
Other Changes
- fix(admin): prevent excessive polling in notifications by @jessy2027 in #12868
New Contributors
- @jessy2027 made their first contribution in #12868
Full Changelog: v2.8.6...v2.8.7
v2.8.6: Strengthened workflow engine and improved account holder management
Highlights
Strengthen the workflow engine
This release improves the workflow engine's data flow. When resuming workflows, we now compile workflow data (i.e. input and outputs of previous steps) from Redis and Postgres to ensure the most recent workflow execution and associated data are used.
Improve payment account holder flows
This release improves how payment account holders are managed when creating payment sessions in the createPaymentSessionWorkflow
. In this workflow, we create a new payment account holder for the customer on the cart if it doesn't already exist. When the workflow fails in a later step, the compensation flow is triggered, and we now ensure we are only deleting the account holder if it was created as part of the invoke, i.e. it didn't exist before running the workflow.
Bugs
- fix: do not apply prefix when getting file contents as buffer or stream by @thetutlage in #12831
- fix(core-flows,workflows-sdk): compensate account holders only when its created by @riqwan in #12825
- fix(): test utils events + workflow storage by @adrien2p in #12834
- fix: fix onScroll in Select.Content by @peterlgh7 in #12855
Documentation
- docs: documentation changes for next release by @shahednasser in #12773
- doc: Updated cloudflare R2 description by @scherddel in #12598
- docs: added first-purchase promotion guide by @shahednasser in #12828
- docs: update OAS for loyalty plugin by @shahednasser in #12836
- docs: remove usages of ts-ignore in examples by @shahednasser in #12839
- docs: fix step detection of useQueryGraphStep by @shahednasser in #12842
- docs: small typo fix by @shahednasser in #12843
- docs: documet withDeleted by @shahednasser in #12841
- docs: design fixes to toc and related elements by @shahednasser in #12747
- docs: added gift message guide by @shahednasser in #12833
- docs: sort events in reference alphabetically by @shahednasser in #12845
- docs-util: throw when schema parsing fails by @shahednasser in #12846
- docs: remove empty storefront guides by @shahednasser in #12844
- docs: add build with AI & LLMs doc by @shahednasser in #12848
- docs: document tax-inclusive promotions concept by @shahednasser in #12849
Chores
- chore: add version and deprecated tags to import routes and methods by @shahednasser in #12829
- chore: add missing types in TSDocs example by @shahednasser in #12835
- chore: improve description of findOrCreateCustomerStep by @shahednasser in #12840
Other Changes
New Contributors
- @scherddel made their first contribution in #12598
- @redeyecz made their first contribution in #12837
Full Changelog: v2.8.5...v2.8.6
v2.8.5: Tax-inclusive Promotions, Improved Product Imports, and Faster Application Startup
Highlights
Improved Product Imports
This release overhauls the bulk import process to make it more performant and include strict validations to catch formatting issues or typos during the pre-processing phase.
Import phases
A CSV file with products to import goes through the following two phases.
- Pre-processing: In the pre-processing phase, we validate the contents of the entire file, check for typos, unknown columns, invalid data types, or missing values, and report errors as soon as you upload the file.
- Importing: Products are imported in the background (as it could be time-consuming with large product catalogs). Since the validations have already been performed during the pre-processing phase, the chances of failure during the import phase are rare. However, certain database constraints around duplicate data might result in a failure.
Changes to import template
Earlier, the import template (downloaded from the admin dashboard) was out of sync with our documentation and supported many columns that were part of Medusa V1.
However, now the import template strictly allows the columns mentioned in the documentation, and an error will be raised if an unknown column is specified in the CSV file.
Performance improvements
The following changes have been made to the internals to improve the import performance and memory consumption.
- Use S3 direct uploads instead of self-importing and storing huge CSV files on a Medusa server. For this, you must configure the S3 file provider in production.
- Read the CSV contents as a stream of chunks and process/validate 1000 rows at a time. As a result, we never read or process the entire CSV file in memory. From our tests, this led to a memory drop from 4GB to 500MB when processing a file with 62000 rows.
Tax-inclusive Promotions
This release introduces an option to specify if fixed promotions take effect before or after taxes. Up until now, fixed promotions would always be applied before taxes, which could lead to unexpected total calculations in scenarios where pricing was otherwise tax-inclusive.
For example, consider a fixed promotion with a value of $10 applied to a tax-inclusive cart of $100 in a tax region with a 25% tax rate.
Before promotion is applied:
- Cart total (tax-inclusive) -> $100 ($80 ex. 25% VAT)
After promotion is applied:
- Cart total (tax-inclusive) -> $87.5 ($70 ex. 25% VAT)
As you can see, the cart is reduced by $12.5 even though the promotion value was $10. The calculation we used to perform to find the promotion adjustment was:
const adjustmentTotal = (cartWithoutTax - promotion.value) * (1 + tax_rate)
In our example, this would be:
const adjustmentTotal = (80 - 10) * (1.25) = 87.5
In this release, we updated this calculation to ensure the correct adjustment total. It looks as follows:
const adjustmentTotal = (cartWithoutTax - (promotion.value / 1 + tax_rate)) * (1 + tax_rate)
In our example, this would be:
const adjustmentTotal = (80 - 8) * (1.25) = 90
The tax-inclusivity option on a promotion is part of the promotion creation flow in the admin dashboard.
Improved application startup time
This release reduces application startup time by around ~75%. For example, on Medusa Cloud, the startup time for a relatively simple Medusa application has gone from 20 seconds to around 4 seconds. This improvement comes from parallelizing the bootstrapping of modules. Modules are strictly independent from each other, so this should have no side effects.
Querying deleted records
This release fixes issues with querying for deleted database records.
Up until now, filtering data by providing any value to the deleted_at
filter would be treated as if you wanted to fetch deleted records.
For example:
const { data } = await query.graph({
entity: "product",
filters: { deleted_at: { $eq: null } }
})
In this query request, we are asking for all non-deleted records; however, we mistakenly assumed that any deleted_at
filter would always be filtering for deleted records, so in this case, the result set would contain deleted records.
In this release, we remove the autodetection mechanism in favor of an explicit flag withDeleted
.
To query deleted records, you now need to pass the flag to the request:
const { data } = await query.graph({
entity: "product",
filters: { deleted_at: { "<some timestamp>" } }
withDeleted: true
})
Features
- feat: wire up direct uploads with local file provider by @thetutlage in #12643
- feat(promotion, dashboard, core-flows, cart, types, utils, medusa): tax inclusive promotions by @fPolic in #12412
- feat(dashboard,types): add credit lines + loyalty changes by @riqwan in #11885
- feat: Improve startup time by parallelizing module and link loading by @sradevski in #12731
- feat: Normalize payment method data and options when passed to Stripe by @sradevski in #12757
- fix(dashboard, types): loyalty UI changes by @fPolic in #12764
- feat(): Add support for jwt asymetric keys by @adrien2p in #12813
- feat: add cookie options by @riqwan in #12720
Bugs
- fix(workflow-sdk): Async/nested runAsStep propagation by @adrien2p in #12675
- fix: update product import template by @thetutlage in #12697
- fix(create-medusa-app): remove "Created admin user" message by @shahednasser in #12707
- fix(promotion, types): non discountable items check by @fPolic in #12644
- fix: remote query types by @thetutlage in #12712
- fix(core-flows): cart complete order address creation by @fPolic in #12493
- fix(utils): medusa internal service returned data should match typings by @adrien2p in #12715
- fix(utils): Typecasting non-text fields in FTS by @olivermrbl in #12729
- fix: Disable ensure database checks when establishing DB connection by @sradevski in #12734
- fix(create-medusa-app): ensure the same package manager is used consistently by @shahednasser in #12714
- fix(payment): add account holder methods to the manual provider by @fPolic in #12751
- fix(core, medusa-test-utils): Fix medusa test runner plugin modules loading by @adrien2p in #12753
- fix: Add missing partially funded event handler for Stripe by @sradevski in #12763
- fix: initiate request container before other express middleware by @thetutlage in #12761
- fix(dashboard): fix subtitle for tax inclusive fields in promotions by @shahednasser in #12776
- fix(workflow-engine-redis): Ensure PK is set without errors by @olivermrbl in #12775
- fix: add operators to RemoteQueryFilters by @peterlgh7 in #12735
- fix: Return and set the correct status when a session is created with… by @sradevski in #12769
- fix: Allow setting the status of a payment session when updating by @sradevski in #12809
- fix(workflow-engine-*): Cleanup expired executions and reduce redis storage usage by @adrien2p in #12795
- fix(medusa): Query Config update Order By filter by @juanzgc in #12781
- fix(payment): round currency precision by @carlos-r-l-rodrigues in #12803
- fix(dashboard): fix currency input locale formatting by @fPolic in #12812
- fix(utils): build query withDeleted remove auto detection by @adrien2p in #12788
- fix: Add missing migration for payment statuses by @sradevski in #12821
Documentation
- docs: add options to feedback component by @shahednasser in #12698
- docs: remove databaseSchema configuration by @shahednasser in #12699
- docs: fixes to references for draft orders and files by @shahednasser in #12693
- docs: ensure files are always sorted when generating llms-full.txt by @shahednasser in #12701
- docs: add missing export for CreateBundledProduct component by @Amar2Kk in #12704
- docs: added cloud documentation app by @shahednasser in #12711
- docs: added cloud introduction page by @shahednasser in #12716
- docs: added slack integration guide by @shahednasser in https://githu...
v2.8.4: Strengthening of cart-completion flows
Highlights
Eliminate race condition in cart-completion flow
This release strengthens the cart-completion flow by eliminating a potential race condition that, in rare cases, could result in an incorrectly refunded payment.
The race condition occurs when cart completion is triggered from two sources: 1) the regular HTTP request to POST /store/carts/:id/complete
, and 2) a webhook event from the payment provider signaling successful payment authorization.
To reduce the risk of a conflict, we have, up until now, delayed webhook processing by 5 seconds. However, this mitigation proved insufficient in some cases.
Now, whenever the completeCartWorkflow
is executed whether via the API route or the webhook handler, we now hold a lock on the cart ID for the duration of the workflow. This lock ensures that multiple completion attempts for the same cart are processed sequentially. Once a cart is successfully completed (typically on the first attempt), subsequent attempts will detect the completed cart and exit early, returning the associated order.
Features
- feat: run workflow hooks inside a when/then block by @thetutlage in #11963
- feat: introduce bulkDelete method for IFileProvider by @thetutlage in #12614
- feat(core-flows,js-sdk,medusa,types): draft order delete by @fPolic in #12172
- feat: implement stream based processing of the files by @thetutlage in #12574
Bugs
- fix: Correctly list files for all ids that are passed by @sradevski in #12575
- fix(framework): Fix compiler to create the dist after clean-up by @adrien2p in #12582
- fix: module import paths to contain unix slash by @thetutlage in #12592
- fix: expand method ALL for bodyparser config and additional validator by @thetutlage in #12612
- fix(dashboard): combobox initial item cache by @fPolic in #12522
- fix(core-flows): reservation management on order edit and draft order confirm by @fPolic in #12546
- fix(utils): move payment events to core flows events by @shahednasser in #12636
- fix(analytics): fix type of provider option by @shahednasser in #12642
- fix(core-flows): complete cart improvements by @carlos-r-l-rodrigues in #12646
Documentation
- docs: fix example in marketplace recipe by @shahednasser in #12595
- docs: add support for ignoring hooks by @shahednasser in #12599
- docs: document using env vars in plugins by @shahednasser in #12618
- docs: add setup details to contribution guidelines by @shahednasser in #12619
- docs: add missing equal sign for DATABASE_URL in env example by @Amar2Kk in #12620
- docs: phone authentication + otp guide by @shahednasser in #12544
- chore(types): fix example for createProductOptionValues in TSDocs and docs by @shahednasser in #12623
- chore(core-flows, types): change base64 comment fo files in TSDocs to binary by @shahednasser in #12627
- docs: redesign search by @shahednasser in #12628
- docs: fix loading in order reference pages by @shahednasser in #12629
- docs: added segment guide by @shahednasser in #12616
- docs: fix broken links utility + uncaught broken links by @shahednasser in #12637
- docs: redesign table of content by @shahednasser in #12647
- docs: fix log levels list by @shahednasser in #12648
- fix(docs): correct module reference in useQueryGraphStep tip by @Amar2Kk in #12654
- docs: add an example of injecting dependencies in module providers by @shahednasser in #12663
Chores
- chore(modules-sdk): Log full error when a loader fail to run by @adrien2p in #12584
- chore(core-flows): ignore hooks in complete cart workflow by @shahednasser in #12600
Other Changes
- update Chinese translation files by @leosin in #12611
- feat: add hebrew admin translation by @GuyPaikowsky in #12603
- feat(admin): Add Bahasa Indonesia language support by @Slackluky in #12657
New Contributors
- @Amar2Kk made their first contribution in #12620
- @GuyPaikowsky made their first contribution in #12603
- @Slackluky made their first contribution in #12657
Full Changelog: v2.8.3...v2.8.4
v2.8.3
Highlights
New Analytics module and Posthog provider
This release introduces a new Analytics module, allowing you to easily set up server-side tracking of events and users.
The module comes with two methods:
/**
* This method tracks an event in the analytics provider.
*
* @param {TrackAnalyticsEventDTO} data - The event's details.
* @returns {Promise<void>} Resolves when the event is tracked successfully.
*
* @example
* await analyticsModuleService.track({
* event: "order_placed",
* properties: {
* order_id: "order_123",
* customer_id: "customer_456",
* total: 100,
* }
* })
*/
track(data: TrackAnalyticsEventDTO): Promise<void>
/**
* This method identifies an actor or group in the analytics provider.
*
* @param {IdentifyAnalyticsEventDTO} data - The details of the actor or group.
* @returns {Promise<void>} Resolves when the actor or group is identified successfully.
*
* @example
* await analyticsModuleService.identify({
* actor_id: "123",
* properties: {
* name: "John Doe"
* }
* })
*/
identify(data: IdentifyAnalyticsEventDTO): Promise<void>
To configure the Analytics module, register it in the modules
of your medusa-config.ts
:
...
modules: [
...,
{
resolve: "@medusajs/medusa/analytics",
options: {
providers: [{ ... }],
},
},
],
...
The Analytics module does not do much as is. You need to configure a provider responsible for handling the tracking. This release comes with two moduNopeles, @medusajs/analytics-local
and @medusajs/analytics-posthog
. The former will log the events and can be used for local development. The latter is an official integration with Posthog.
The provider is installed like so:
...
modules: [
...,
{
resolve: "@medusajs/medusa/analytics",
options: {
providers: [
{
resolve: "@medusajs/analytics-posthog",
options: {
posthogEventsKey: "<your-api-key>",
posthogHost: "<your host>",
}
}
}],
},
],
...
Read more about the new module and providers in our documentation.
Features
- feat(index): Only run the synchronisation in worker/shared mode by @adrien2p in #12530
- chore(product, modules-sdk): Add missing index for select-in strategy + allow to pass top level strategy to force the behaviour by @adrien2p in #12508
- feat: Add an analytics module and local and posthog providers by @sradevski in #12505
- feat: process import from pre-processed chunks by @thetutlage in #12527
- feat: add presignedUrl method to upload sdk by @christiananese in #12569
Bugs
- fix: Skip migration if module is not installed by @sradevski in #12507
- test: remove snapshots usage by @thetutlage in #12516
- fix(utils): Missing zod deps by @adrien2p in #12518
- fix(dashboard): refund payment formatting by @fPolic in #12476
- fix(medusa): add estimate count to admin products by @carlos-r-l-rodrigues in #12467
- fix(index): Apply various fixes to the index engine by @carlos-r-l-rodrigues in #12501
- fix: Correctly import MedusaError in the analytics module by @sradevski in #12542
- fix(product): Deep update data retrieval bottleneck by @adrien2p in #12538
- fix: mark posthog-node as a peer dependency by @thetutlage in #12539
- fix(js-sdk): allow passing custom request body parameters in auth.register method by @shahednasser in #12545
- fix(core-flows): skip location check if inventory is not managed by @fPolic in #12540
- fix(core-flows, types): export steps and types related to credit lines by @shahednasser in #12567
- fix(product, utils): handle metadata key deletion on product update by @fPolic in #12478
Documentation
- docs: update recipe contents by @shahednasser in #12515
- docs: add vale rule for Next.js Starter Storefront by @shahednasser in #12517
- docs: change recipes on homepage by @shahednasser in #12520
- docs: fix timeout in order-related workflows reference by @shahednasser in #12533
- docs: added re-order guide by @shahednasser in #12363
- chore(docs): Update npm command by @kashifaris in #12547
- docs: show hooks in when condition in workflows reference by @shahednasser in #12552
- docs-util: extract feature flags in generated OAS by @shahednasser in #12554
- Fix: Incorrect Example File Name in Subscriber Section by @adityaerlangga in #12560
- docs: improve module isolation chapter by @shahednasser in #12565
- docs: show when condition in workflows reference by @shahednasser in #12566
Chores
- test(workflow-engine-redist): Update tests to ensure behaviour validation properly by @adrien2p in #12514
- chore(test-cli-with-database): Update cli tag from latest to preview by @adrien2p in #12529
- chore(index): return ids only by @carlos-r-l-rodrigues in #12543
- chore(core-flows): add tsdocs for hooks in complete cart by @shahednasser in #12555
- chore(types, utils): update TSDocs related to analytics module by @shahednasser in #12564
- chore(index): Few adjustments by @adrien2p in #12557
Other Changes
- Typo/index logs by @adrien2p in #12528
- fix: Fix garbled characters in zhCN.json translation file by @imhuso in #12537
New Contributors
- @imhuso made their first contribution in #12537
- @kashifaris made their first contribution in #12547
- @adityaerlangga made their first contribution in #12560
Full Changelog: v2.8.2...v2.8.3
v2.8.2
Highlights
Fixes regression related to updating weight, height, length, and width on products
Features
- feat: define validators and use normalize-products step by @thetutlage in #12473
Bugs
- fix(types): change update signature of IAuthProvider by @shahednasser in #12496
- fix: fix weight/length/height/width types in updates by @peterlgh7 in #12500
- fix(core-flows): fulfilment cancelation with shared inventory kit item by @fPolic in #12503
Documentation
- docs: add missing methods in guides and references by @shahednasser in #12495
- docs: improve payment-related guides by @shahednasser in #12502
- docs: update examples in sendgrid guide by @shahednasser in #12504
Chores
- chore(types, utils): TSDoc improvements for providers by @shahednasser in #12498
Full Changelog: v2.8.1...v2.8.2
v2.8.1
Highlights
Fixes a regression introduced in v2.8.0
In v2.8.0, we unintentionally introduced a regression that affected ordering products returned from the product module service. This broke workflows (e.g. updateProductsWorkflow
) that rely on consistent ordering for subsequent operations such as applying price updates. This release brings back the correct ordering behavior and resolves the issue.
We strongly recommend upgrading to v2.8.1 as soon as possible to avoid incorrect data.
Features
- feat: create CSV normalizer to normalize a CSV file by @thetutlage in #12396
Bugs
- fix(workflows-sdk): Miss match context usage within run as step by @adrien2p in #12449
- fix(index): query builder handle json array by @carlos-r-l-rodrigues in #12480
- fix: returned updates order in upsertWithReplace by @peterlgh7 in #12486
Documentation
- docs: tax provider updates for next release by @shahednasser in #12431
- docs: update read-only links by @shahednasser in #12468
- docs: fix client side error in references by @shahednasser in #12475
Chores
- chore(types,utils): add featureFlag and version tags by @shahednasser in #12464
- Chore/test runner improvements by @adrien2p in #12439
Full Changelog: v2.8.0...v2.8.1
v2.8.0: Fix regression with product updates
Highlights
Important: This release introduced a regression with product updates
We unintentionally introduced a regression that affected the ordering of products returned from the product module service. This broke workflows (e.g. updateProductsWorkflow) that rely on consistent ordering for subsequent operations such as applying price updates.
Upgrade to v2.8.1 as soon as possible to avoid any issues related to this change.
Cart-completion robustness
Warning
Breaking changes
This release introduces important changes to the completeCartWorkflow
aimed at improving robustness and making it easier to recover from failures.
Changes to idempotency
Until now, the workflow has had the following configuration:
{
name: completeCartWorkflowId
store: true,
idempotent: true,
retentionTime: THREE_DAYS,
}
Here's a brief description of what these properties do, excluding name
:
store
: Store the workflow execution. If no retention time is specified, the workflow is only stored for the duration of its executionidempotent
: Store the result of the first workflow execution and return it on subsequent runsretentionTime
: Store the result in the configured data store for "x" amount of time–here, three days
In this release, we change the idempotent
flag from true to false. Initially, the idea of having an idempotent cart-completion stemmed from wanting to ensure that multiple requests to complete the same cart would lead to the same outcome. This is, in of itself, still reasonable to ensure there is only ever one attempt to complete the same cart. However, in case of failures, the idempotent mechanism makes it challenging to recover, since a new cart with the same details is required to re-attempt the completion. This is because the result of the failing workflow is stored and returned on all subsequent runs, regardless of whether the cart is updated to satisfy the constraints for completion.
With idempotent
set to false, it will be possible to retry failed executions, making it simpler to bring the cart to a satisfying state and eventually create the order.
It is worth mentioning that concurrency continues to be appropriately managed by passing the cart ID as the transactionId
when running the workflow. The transaction ID ensures that only one workflow execution can run at a time.
Changes to the structure
The workflow has been slightly restructured to minimize the risk of payment sessions getting stuck in a state that is difficult to recover from. More specifically, the payment authorization step has been moved to the very end of the workflow, so that all first-party checks are performed before we authorize the payment.
To understand why this is important, we need to cover the compensateIfNeeded
step of the workflow briefly. This step compensates active payment sessions in the case of failure to avoid orphaned third-party payments and recreates the Medusa payment session so that new payment details can be attached.
For example, suppose the payment authorization is performed off-band (e.g., in a webhook), and the cart-completion workflow fails to execute. In that case, the step will void the third-party payment and bring the cart to a correct state, all while ensuring consistency between the two systems.
Moving the payment authorization step to the end of the workflow ensures that we only create an authorized payment if all other cart constraints are satisfied.
Changes to the webhook handler
The webhook handler ensures consistency between Medusa and the third-party payment provider. More specifically, it will handle the following scenarios:
- Payment authorization: when we receive a payment authorization event, we will attempt to authorize and create a payment in Medusa
- Payment capture: when we receive a payment capture event, we will attempt to capture the associated payment in Medusa
- Cart-completion: when we receive a payment authorization event, we will attempt to complete the cart
- Payment authorization and capture: when we receive a payment capture event and there is no existing payment in Medusa, we will attempt to authorize, create, and capture a payment in Medusa
We have only handled the first three scenarios until now. This release introduces functionality for the fourth, a more unusual scenario involving auto-captures in the third-party payment provider.
Line item generation
Warning
Breaking changes
This release changes the source of line item titles and subtitles. The title has changed from the variant title to the product title, and the subtitle has changed from the product title to the variant title.
Cross-module filters (experimental)
This release introduces experimental support for cross-module filters via a new module, @medusajs/index
.
Please remember that this module is experimental and in development, so please use it cautiously. It is subject to change as we finalize the design to enable cross-module filtering.
We will keep the description brief since the module is still in development. Here's what you need to know:
- Medusa's architecture is divided into a range of modules, each being isolated (at the data model level) from one another. By default, the modules share the same database, but the architecture is built to support external data sources, in case your module needs a different type of database, or you want to use a third-party service in place of Medusa's core module
- Consequently, queries to retrieve data are performed per module, and the data is aggregated in the end to create the result set
- Our new index module allows you to ingest data into a central, relational-like structure
- The structure enables efficient filtering over data coming from different data sources (provided it is ingested)
The index module can be enabled by installing the module:
yarn add @medusajs/index
Adding it to your Medusa config:
{
// ...rest of config
modules: [{ resolve: "@medusajs/index", options: {} }]
}
And finally, adding a feature flag to enable it:
// .env
MEDUSA_FF_INDEX_ENGINE=true
Then, apply the migrations to create the related tables:
npx medusa db:migrate
The next time you start your server, we will ingest data into the index engine.
In this first iteration, we only ingest the following core entities:
- Products
- Product Variants
- Prices
- Sales Channels
The data in the index is queried through a new API with semantics identical to the existing query graph:
const { data: products = [], metadata } = await query.index({
entity: "product",
fields: ["id", "name"],
});
In addition to ingesting a few select resources from the core, we have added support for ingesting data from custom modules through link definitions. For example, say you want to introduce a Brand on Products and filter your Products by it.
Assuming you have added a Brand module, you create a link as follows:
import { defineLink } from "@medusajs/framework/utils";
import ProductModule from "@medusajs/medusa/product";
import BrandModule from "../modules/brand";
export default defineLink(
{
linkable: ProductModule.linkable.product,
isList: true,
},
{
linkable: BrandModule.linkable.brand,
}
);
This link will associate the two data models and allow you to query them from both sides of the link.
Furthermore, to ingest the Brand into the index and make the data filterable, you need to add the new filterable
property to the link:
import { defineLink } from "@medusajs/framework/utils";
import ProductModule from "@medusajs/medusa/product";
import BrandModule from "../modules/brand";
export default defineLink(
{
linkable: ProductModule.linkable.product,
isList: true,
},
{
linkable: BrandModule.linkable.brand,
filterable: ["id", "name"]
}
);
The link above specifies that Brands should be ingested into the index and made filterable via the properties id
and title
.
As a result, you can now filter Products by Brands ID or title like so:
const { data: products = [], metadata } = await query.index({
entity: "product",
fields: ["id", "title", "brand.*"],
filters: {
brand: {
name: "Hermes"
}
},
});
An important trade-off in the index module is the need to avoid the performance cost of COUNT(*)
queries, which can be an incredibly high cost for very large data sets. Instead, we use Postgres’ internal query planner to compute an estimated count of the result set. For very small data sets, this estimate can be very inaccurate, but for larger ones it should provide a reasonable estimate. The trade-off allows us to achieve very fast response times making it ideal for user-facing search and browsing experiences. As noted earlier, the tool is still experimental, and we plan to continue iterating and improving it over time.
Custom Tax Providers
This release introduces full support for custom Tax Providers by making these key changes:
- Load custom Tax Providers in the Tax Module
- Manage (create, update) provider per Tax Region in the admin dashboard
- Migrate all Tax Regions to use a tax provider
The migration script will run the first time you start the server after upgrading. It will assign the default system provider to the Tax Region, if the region did not have a custom provider specified already.
Feat...
v2.7.1: Strengthened workflow engine, expanded data for fulfillments, and more robust event handling
Highlights
Expanded fulfillment data
This release extends fulfillment capabilities by exposing more core order data to fulfillment providers–that is, data passed upon creating fulfillments in Medusa.
The additional data included on orders passed to providers are:
display_id
region
customer_id
customer
sales_channel_id
sales_channel
items.variant.upc
items.variant.sku
items.variant.barcode
items.variant.hs_code
items.variant.origin_country
items.variant.product.origin_country
items.variant.product.hs_code
items.variant.product.mid_code
items.variant.product.material
items.tax_lines.rate
subtotal
discount_total
tax_total
item_total
shipping_total
total
created_at
Strengthened workflow engine
We have improved the core internals of our workflow engine, including fixing an issue with events grouping not working correctly for async workflows.
Read more in the PRs below:
Features
- feat(core-flows, js-sdk, medusa): draft order shipping removal by @fPolic in #12124
- feat: Add support for dynamoDB for storing sessions and some types cleanup by @thetutlage in #12140
- feat(orchestration): skip on permanent failure by @carlos-r-l-rodrigues in #12027
- feat: Add support for uploading a file directly to the file provider from the client by @sradevski in #12224
Bugs
- fix(dashboard): display null sku by @fPolic in #12155
- fix(types): fix type of application_method_type filter by @shahednasser in #12160
- fix(core-flows): draft order reservations by @fPolic in #12115
- fix(index): Default schema typings by @adrien2p in #12183
- fix(): Event group id propagation and event managements by @adrien2p in #12157
- fix(payment): properly delete refund by @fPolic in #12193
- fix: apply additional data validator using a global middleware by @thetutlage in #12194
- fix(dashboard): properly register settings custom routes by @fPolic in #12198
- fix(): Properly handle workflow as step now that events are fixed entirely by @adrien2p in #12196
- fix(core-flows): export registerOrderDeliveryStep by @shahednasser in #12221
- fix: expose beforeRefreshingPaymentCollection hook by @thetutlage in #12232
- fix(medusa): sales_channel_id middleware manipulation leading to lost of the sc by @adrien2p in #12234
- fix: steps to return undefined and still chain the config method by @thetutlage in #12255
- fix(core-flows, link-modules): return fulfillment creation by @fPolic in #12227
- fix: oas CLI to convert Windows paths to unix by @thetutlage in #12254
Documentation
- docs: changes for next release by @shahednasser in #12098
- docs: fix schema of product category by @shahednasser in #12145
- Update page.mdx by @Sai-Santhan-Dodda in #12141
- docs: fixed POST request in code snippet for quotation acceptance by @valerioXplo in #11983
- docs: more updates after 2.7.0 update by @shahednasser in #12156
- docs: generate OAS manually for 2.7.0 by @shahednasser in #12158
- docs: generate JS SDK reference with fixes by @shahednasser in #12161
- docs(resources): fix express checkout page for missing prop in CartContext Provider component by @relaxedrohan in #12188
- docs: changes to plugins page by @shahednasser in #12190
- docs: add loyalty points guide by @shahednasser in #12130
- docs: add a note to loyalty points guide by @shahednasser in #12201
- docs: hide colon when a note's title has a punctuation by @shahednasser in #12205
- docs: add framework page by @shahednasser in #12162
- docs: add framework to navbar by @shahednasser in #12206
- docs: capitalize use of Framework across docs by @shahednasser in #12207
- docs: update introduction and homepage following Framework changes by @shahednasser in #12211
- docs: rename Architectural Modules to Infrastructure Modules by @shahednasser in #12212
- docs: add new troubleshooting guides for Query and middlewares by @shahednasser in #12214
- docs: document conditional shipping option prices + expand on price rules by @shahednasser in #12217
- docs: fix links in submenu navigation by @shahednasser in #12220
- docs: expand on promotion rules by @shahednasser in #12218
- docs-util: fix examples in workflow reference that have multiple code by @shahednasser in #12223
- docs: fix step name in long-running workflow documentation by @Vallabh-Mahanta in #12215
- docs: updates to link to other modules docs by @shahednasser in #12225
- docs: add some redirects from v1 to v2 docs by @shahednasser in #12229
- dos: add docs on overriding allowed fields in routes by @shahednasser in #12233
- docs: add LLM dropdown menu to documentation pages by @shahednasser in #12235
- docs: fix redirect infrastructure modules by @shahednasser in #12238
- docs: improvements to admin, query, and read-only link docs by @shahednasser in #12239
- docs: fix index.html.md causing 404 by @shahednasser in #12241
- docs: fix revalidate cache guide by @shahednasser in #12243
- docs: Fix typo "documenation" in env vars page.mdx by @Ezequiel-Schejtman in #12247
- docs: fix messy layout bug by @shahednasser in #12248
- docs: Replace api_key_id with publishable_key_id by @Wcdaren in #12242
- docs: added a section on loader execution by @shahednasser in #12260
- docs: fix no lines code block example by @shahednasser in #12259
- docs: fix badges and titles not showing in code tabs by @shahednasser in #12261
Chores
- chore(utils): fix TSDoc example for payment provider by @ynzier in #12012
- chore: fixes to JS SDK TSDocs by @shahednasser in #12159
- chore(core-flows,types): fix links in TSDocs pointing to architectural modules by @shahednasser in #12213
- chore: fixes and updates to promotion and shipping option TSDocs by @shahednasser in #12222
- chore: Pass more data to fulfillment provider by @olivermrbl in #12186
- Chore/orchestration storage improvements by @adrien2p in #12178
- chore(types): small tsdoc change to file service by @shahednasser in #12240
Other Changes
- added dutch translation by @harmvdhorst in #12167
- added hungarian admin translation by @GergoVandor in #12176
- fix: Ensure shipment includes tracking numbers from fulfillment by @ionutgaina in #11775
- feat(cart): emit updated event in update line item workflow by @bqst in #12119
New Contributors
- @ynzier made their first contribution in #12012
- @valerioXplo made their first contribution in #11983
- @harmvdhorst made their first contribution in #12167
- @GergoVandor made their first contribution in #12176
- @relaxedrohan made their first contribution in #12188
- @ionutgaina made thei...