* feat(): Add product type and collection translation support
* Create sharp-poets-give.md
* feat(): Add product type and collection translation support
* feat(): Add product type and collection translation support
* options
* options
* shipping options/type
* return reason
* fix
* leave out shipping and return reason
* leave out shipping and return reason
* leave out shipping and return reason
## Summary
**What** — What changes are introduced in this PR?
Remove `default_locale` from Store <> Locale relation
**Why** — Why are these changes relevant or necessary?
*Please provide answer here*
**How** — How have these changes been implemented?
*Please provide answer here*
**Testing** — How have these changes been tested, or how can the reviewer test the feature?
*Please provide answer here*
---
## Examples
Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.
```ts
// Example usage
```
---
## Checklist
Please ensure the following before requesting a review:
- [ ] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [ ] The changes are covered by relevant **tests**
- [ ] I have verified the code works as intended locally
- [ ] I have linked the related issue(s) if applicable
---
## Additional Context
Add any additional context, related issues, or references that might help the reviewer understand this PR.
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
## Summary
**What** — What changes are introduced in this PR?
Export missing store locale link definition.
**Why** — Why are these changes relevant or necessary?
*Please provide answer here*
**How** — How have these changes been implemented?
*Please provide answer here*
**Testing** — How have these changes been tested, or how can the reviewer test the feature?
*Please provide answer here*
---
## Examples
Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.
```ts
// Example usage
```
---
## Checklist
Please ensure the following before requesting a review:
- [ ] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [ ] The changes are covered by relevant **tests**
- [ ] I have verified the code works as intended locally
- [ ] I have linked the related issue(s) if applicable
---
## Additional Context
Add any additional context, related issues, or references that might help the reviewer understand this PR.
* feat: order export
* Merge branch 'develop' of https://github.com/medusajs/medusa into feat/order-export
* normalize status
* rm util
* serialize totals
* test
* lock
* comments
* configurable order list
* fix(): Improve store currency readonly link
* fix(): Improve store currency readonly link
* fix(): Improve store currency readonly link
* Create wicked-rabbits-sparkle.md
* fix(): store supported locales read only link
* fix(): store supported locales read only link
* Create two-books-reply.md
* remove unnecessary links
* remove unnecessary links
* remove unnecessary links
* fix(): store supported locales read only link
* fix(): store supported locales read only link
* improve link
ref: https://github.com/medusajs/medusa/pull/14189
**Summary**
This PR extends the translation module to support automatic translation syncing for cart line items based on the cart's locale.
Key changes:
- Added locale field to the Cart model to store the cart's locale preference
- Created new workflow steps:
- getTranslatedLineItemsStep - Translates line items when adding to cart or creating a cart
- updateCartItemsTranslationsStep - Re-translates all cart items when the cart's locale changes
- Integrated translation logic into cart workflows:
- createCartWorkflow - Applies translations to initial line items
- addToCartWorkflow - Applies translations when adding new items
- updateCartWorkflow - Re-translates all items when locale_code is updated
- refreshCartItemsWorkflow - Maintains translations during cart refresh
- Added applyTranslationsToItems utility to map variant/product/type/collection translations to line item fields (title, subtitle, description, etc.)
* chore(): Accept an extra agument 'all-or-nothing' on the migrate command
* Create rich-camels-brush.md
* chore(): Accept an extra agument 'all-or-nothing' on the migrate command
* chore(): Accept an extra agument 'all-or-nothing' on the migrate command
* chore(): Accept an extra agument 'all-or-nothing' on the migrate command
* chore(): fix broken down migrations
* chore(): update changeset
* feat(): Translation first steps
* feat(): locale middleware
* feat(): readonly links
* feat(): feature flag
* feat(): modules sdk
* feat(): translation module re export
* start adding workflows
* update typings
* update typings
* test(): Add integration tests
* test(): centralize filters preparation
* test(): centralize filters preparation
* remove unnecessary importy
* fix workflows
* Define StoreLocale inside Store Module
* Link definition to extend Store with supported_locales
* store_locale migration
* Add supported_locales handling in Store Module
* Tests
* Accept supported_locales in Store endpoints
* Add locales to js-sdk
* Include locale list and default locale in Store Detail section
* Initialize local namespace in js-sdk
* Add locales route
* Make code primary key of locale table to facilitate upserts
* Add locales routes
* Show locale code as is
* Add list translations api route
* Batch endpoint
* Types
* New batchTranslationsWorkflow and various updates to existent ones
* Edit default locale UI
* WIP
* Apply translation agnostically
* middleware
* Apply translation agnostically
* fix Apply translation agnostically
* apply translations to product list
* Add feature flag
* fetch translations by batches of 250 max
* fix apply
* improve and test util
* apply to product list
* dont manage translations if no locale
* normalize locale
* potential todo
* Protect translations routes with feature flag
* Extract normalize locale util to core/utils
* Normalize locale on write
* Normalize locale for read
* Use feature flag to guard translations UI across the board
* Avoid throwing incorrectly when locale_code not present in partial updates
* move applyTranslations util
* remove old tests
* fix util tests
* fix(): product end points
* cleanup
* update lock
* remove unused var
* cleanup
* fix apply locale
* missing new dep for test utils
* Change entity_type, entity_id to reference, reference_id
* Remove comment
* Avoid registering translations route if ff not enabled
* Prevent registering express handler for disabled route via defineFileConfig
* Add tests
* Add changeset
* Update test
* fix integration tests, module and internals
* Add locale id plus fixed
* Allow to pass array of reference_id
* fix unit tests
* fix link loading
* fix store route
* fix sales channel test
* fix tests
---------
Co-authored-by: Nicolas Gorga <nicogorga11@gmail.com>
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
**What**
This PR introduces experimental Hot Module Replacement (HMR) for the Medusa backend, enabling developers to see code changes reflected immediately without restarting the server. This significantly improves the development experience by reducing iteration time.
### Key Features
- Hot reload support for:
- API Routes
- Workflows & Steps
- Scheduled Jobs
- Event Subscribers
- Modules
- IPC-based architecture: The dev server runs in a child process, communicating with the parent watcher via IPC. When HMR fails, the child process is killed and restarted, ensuring
clean resource cleanup.
- Recovery mechanism: Automatically recovers from broken module states without manual intervention.
- Graceful fallback: When HMR cannot handle a change (e.g., medusa-config.ts, .env), the server restarts completely.
### Architecture
```mermaid
flowchart TB
subgraph Parent["develop.ts (File Watcher)"]
W[Watch Files]
end
subgraph Child["start.ts (HTTP Server)"]
R[reloadResources]
R --> MR[ModuleReloader]
R --> WR[WorkflowReloader]
R --> RR[RouteReloader]
R --> SR[SubscriberReloader]
R --> JR[JobReloader]
end
W -->|"hmr-reload"| R
R -->|"hmr-result"| W
```
### How to enable it
Backend HMR is behind a feature flag. Enable it by setting:
```ts
// medusa-config.ts
module.exports = defineConfig({
featureFlags: {
backend_hmr: true
}
})
```
or
```bash
export MEDUSA_FF_BACKEND_HMR=true
```
or
```
// .env
MEDUSA_FF_BACKEND_HMR=true
```
Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
Summary
This PR adds BullMQ queue and worker configuration options to the workflow-engine-redis module, bringing feature parity with the event-bus-redis module. It also introduces per-queue
configuration options for fine-grained control over the three internal queues (main, job, and cleaner).
Key changes:
- Added per-queue BullMQ configuration options (mainQueueOptions, jobQueueOptions, cleanerQueueOptions and their worker counterparts) with shared defaults
- Unified Redis option naming across modules: deprecated url → redisUrl, options → redisOptions (with backward compatibility)
- Moved configuration resolution to the loader and registered options in the DI container
- Added comprehensive JSDoc documentation for all configuration options
- Added unit tests for option merging and queue/worker configuration
Configuration Example
```ts
// Simple configuration - same options for all queues
{
redisUrl: "redis://localhost:6379",
queueOptions: { defaultJobOptions: { removeOnComplete: 1000 } },
workerOptions: { concurrency: 10 }
}
```
```ts
// Advanced configuration - per-queue overrides
{
redisUrl: "redis://localhost:6379",
workerOptions: { concurrency: 10 }, // shared default
jobWorkerOptions: { concurrency: 5 }, // override for scheduled workflows
cleanerWorkerOptions: { concurrency: 1 } // override for cleanup (low priority)
}
```
> [!NOTE]
> Adds a configurable concurrency for link migrations (CLI/commands), forces concurrency=1 when pgstream is detected, and ignores duplicate link-table inserts.
>
> - **CLI**
> - Add `--concurrency` option to `db:migrate` and `db:sync-links`.
> - **Medusa commands**
> - `migrate` and `sync-links` accept `concurrency`; set `DB_MIGRATION_CONCURRENCY` and force `1` when `pgstream` schema exists via new `isPgstreamEnabled`.
> - **Link Modules (migrations)**
> - Execute plan actions with `executeWithConcurrency` using `DB_MIGRATION_CONCURRENCY`.
> - Make link-table tracking inserts idempotent with `ON CONFLICT DO NOTHING` (including bulk/upsert and per-create).
>
> <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 07432293c8fe8de30b07920fa47823b9081edacc. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
* fix(fulfillment): make relationship between SO and SO type M:1
* fix: test and types, remap type id to existing column
* Fix typo
* Fix typo
* chore: update changeset
* fix: typo
---------
Co-authored-by: Nicolas Gorga <62995075+NicolasGorga@users.noreply.github.com>
* feat: carry over promotions toggle on exchanges
* fix: inital flag value, return the flag on preview
* fix: validation of allocation type
* fix: revert client changes
* fix: invert condition
* feat: recompute adjustments when outbound item is updated
* fix: condition again
* fix: display more accurate inbound/outbound totals for exchanges
* fix: make exchanges specs green
* feat: more testing cases
* wip: pr feedback
* fix: use plural for the flag on Admin
* fix: schema test, route refactor
* feat: tooltip
* feat: refactor to use update workflow
* feat: display applied promotion per item on order details, show copy sku on hover
* feat: refactor edits and exchanges to have common flag toggle flow
* fix: delete empty file
* fix: exchange_id param query
* wip
* add wip
* wip
* reuse action
* finish first draft
* fix tests
* cleanup
* Only compute adjustments when necessary
* Create hot-carrots-look.md
* address comments
* minor tweaks
* fix pay col
* fix test
* wip
* Dwip
* wip
* fix: adjustment typo
* fix: import
* fix: workflow imports
* wip: update test
* feat: upsert versioned adjustments when previewing order
* fix: revert unique codes change
* fix: order spec test with versioning
* wip: save
* feat: make adjustments work for preview and confirm flow, wip base repo filtering of older version adjustments
* fix: missing populate where
* wip: populate where loading versioned adjustments
* fix: filter out older adjustment versions
* temp: comment adjustments in repo
* test: add adjustment if no version
* wip: configure populate where in order base repository
* fix: rm manual filtering
* fix: revert base repo changes
* fix: revert
* fix: use order item version instead of order version
* fix: rm only in test
* fix: update case spec
* fix: remove sceanrio, wip test with draft promotion
* feat: test correct adjustments when disabling promotion
* feat: complex test case
* feat: test consecutive order edits
* feat: 2 promotions test case with a fixed promo
* feat: migrate existing order line item adjustments to order items latest version
* feat: update dep after merge
* wip: load adjustments separatley
* feat: adjustments collections
* fix: spread result, handle related entity case
* fix: update lock
* feat: make sure version is loaded, refactor, handle related entity case
* fix: check fields
* feat: loading adjustments for list and count
* fix: correct items version field
* fix: rm empty array
* fix: wip order modules spec
* fix: order module specs
* feat: preinit items adjustments
* fix: rm only
* fix: rm only
* chore: cleanup
* fix: migration files
* fix: dont change formatting
* fix: core package build
* chore: more cleanup
* fix: item update util
* fix: duplicate import
* fix: refresh adjustments for exchanges (#13992)
* wip: exchange adjustments
* feat: test - receive items
* feat: finish test case
* fix: casing
* fix(draft-orders, core-flows, orders) refresh adjustments for draft orders (#14025)
* wip: draft orders adjustments refresh
* feat: rewrite to use REPLACE action + test
* fix: rm only
* feat: cleanup old REPLACE actions
* feat: cleanup adjustemnts when 0 promotions
* wip: canceling draft order
* fix: make version arg optional
* fix: restore promotion links
* feat: test reverting on cancelation
* fix: address comments in tests
* wip: fix summary on preview
* fix: get pending diff on preview summary from total
* fix: revert pending diff change
---------
Co-authored-by: fPolic <mainacc.polic@gmail.com>
Co-authored-by: Frane Polić <16856471+fPolic@users.noreply.github.com>
## Summary
**What** —
Add a providerData field to notifications
**Why** —
We need the ability to pass dynamic fields to specific providers. E.g. CC and BCC for emails
**How** —
Just adding the field to the model
**Testing** —
Added the field to existing tests
## Checklist
Please ensure the following before requesting a review:
- [x] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [x] The changes are covered by relevant **tests**
- [x] I have verified the code works as intended locally
- [ ] I have linked the related issue(s) if applicable
---
> [!NOTE]
> Adds `provider_data` to notifications (types, workflow input, DB model/migration) and forwards it in the Medusa Cloud Email provider, with tests updated accordingly.
>
> - **Data/Schema**:
> - Add `provider_data` (`jsonb`) to `notification` model and DB via migration `Migration20251121150408` and snapshot update.
> - **Types/DTOs**:
> - Add optional `provider_data` to `CreateNotificationDTO`, `NotificationDTO`, and `ProviderSendNotificationDTO`.
> - **Workflows**:
> - Extend `send-notifications` step input with `provider_data`.
> - **Providers**:
> - Medusa Cloud Email: include `provider_data` in outgoing request payload.
> - **Tests**:
> - Update integration tests to pass and assert `provider_data` propagation.
> - **Changeset**:
> - Patch bumps for `@medusajs/notification`, `@medusajs/core-flows`, `@medusajs/types`.
>
> <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6f114c75c974a145ef60213637d7c41bc605a0bf. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
## Summary
**What** — What changes are introduced in this PR?
This pull request adds support for OXXO payments to the Stripe payment provider module. The main changes include the addition of a new `OxxoProviderService`, updates to type definitions to support OXXO-specific options, and integration of the new service into the provider's exports and registration.
**Why** — Why are these changes relevant or necessary?
I was testing the MedusaJs server, I live in México and here oxxo as a Payment method is very used.
**How** — How have these changes been implemented?
* Introduced `OxxoProviderService` in `stripe-oxxo.ts`, which extends `StripeBase` and configures Stripe payment intents for OXXO, including expiration settings.
* Updated `StripeOptions` and `PaymentIntentOptions` types to include `oxxoExpiresDays` and OXXO-specific payment method options for intent configuration.
* Added `OXXO` to the `PaymentProviderKeys` enum for provider identification.
**Testing** — How have these changes been tested, or how can the reviewer test the feature?
You need to launch the medusa server, add Stripe OXXO as Payment Provider in your Store Region (OXXO only works in México and with mxn currency) and set payment_method_data type to oxxo.
Also you need to allow oxxo payment as payment method in stripe and configure your stripe webhook to your medusa server
---
## Examples
Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.
```ts
// Example usage using nextjs starter
const confirmParams: any = {
return_url: returnUrl,
}
if (isOxxo(providerId)) {
confirmParams.payment_method_data = {
type: "oxxo",
billing_details: {
name:
cart.billing_address?.first_name +
" " +
cart.billing_address?.last_name,
address: {
city: cart.billing_address?.city ?? undefined,
country: cart.billing_address?.country_code ?? undefined,
line1: cart.billing_address?.address_1 ?? undefined,
line2: cart.billing_address?.address_2 ?? undefined,
postal_code: cart.billing_address?.postal_code ?? undefined,
state: cart.billing_address?.province ?? undefined,
},
email: cart.email,
phone: cart.billing_address?.phone ?? undefined,
},
}
await stripe
.confirmPayment({
clientSecret,
confirmParams,
redirect: "if_required",
})
.then(({ error, paymentIntent }) => {
console.log({ error, paymentIntent })
const validateIntent = async (paymentIntent: any) => {
const link =
paymentIntent.next_action?.oxxo_display_details
?.hosted_voucher_url
if (link) {
setSubmitting(false)
setMessage(
"Se ha generado un cupón de pago de OXXO. Por favor, revisa la nueva pestaña abierta."
)
await onPaymentCompleted() // Here I call the function because I have custom logic for creating a pending order
}
}
if (error) {
const pi = error.payment_intent
if (
(pi && pi.status === "requires_capture") ||
(pi && pi.status === "succeeded")
) {
onPaymentCompleted()
}
if (pi && pi.status === "requires_action") {
validateIntent(pi)
return
}
setErrorMessage(error.message || null)
setSubmitting(false)
return
}
if (
(paymentIntent && paymentIntent.status === "requires_capture") ||
(paymentIntent && paymentIntent.status === "succeeded")
) {
return onPaymentCompleted()
}
if (paymentIntent && paymentIntent.status === "requires_action") {
validateIntent(paymentIntent) // This is the action that you normally get
}
})
}
}
// Configuration on the server (medusa-config.ts)
modules: [
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "@medusa/payment-stripe",
id: "stripe",
options: {
apiKey: process.env.STRIPE_API_KEY,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
capture: true,
oxxoExpiresDays: 7, // default to 3
},
},
],
},
},
],
// And not necessary buy you can extend even more creating a pending-orders module (for showing the vouchers created that costumer need to pay in the frontend, because if not the order only creates after the user have payed the voucher, for testing is 3 minutes), this is an example model:
import { model } from "@medusajs/framework/utils";
export const PendingOrder = model.define("pending_order", {
id: model.id().primaryKey(),
cart_id: model.text().unique(),
user_id: model.text(),
total: model.number(),
payment_type: model.text(),
voucher_url: model.text().nullable(),
payment_session_id: model.text(), // this are the ones that works to identify the payment
payment_collection_id: model.text(), // this are the ones that works to identify the payment
});
export default PendingOrder;
```
---
## Checklist
Please ensure the following before requesting a review:
- [x] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [x] The changes are covered by relevant **tests**
- [x] I have verified the code works as intended locally
- [x ] I have linked the related issue(s) if applicable
---
## Additional Context
#13804
---
> [!NOTE]
> Adds OXXO payment support to the Stripe provider with configurable expiration days and updates intent option handling and typings.
>
> - **Payment Providers**:
> - **New `OxxoProviderService`** (`services/stripe-oxxo.ts`): configures `payment_intent` for OXXO with `expires_after_days` (defaults to `3`, configurable via `options.oxxoExpiresDays`).
> - Registered in `src/index.ts` and exported from `services/index.ts`.
> - **Types**:
> - `StripeOptions` adds `oxxoExpiresDays`.
> - `PaymentIntentOptions` adds `payment_method_options.oxxo.expires_after_days`.
> - `PaymentProviderKeys` adds `OXXO`.
> - **Core**:
> - `core/stripe-base.ts`: `normalizePaymentIntentParameters` now falls back to `this.paymentIntentOptions.payment_method_options` when not provided in `extra`.
> - **Changeset**:
> - Patch release for `@medusajs/payment-stripe`.
>
> <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4d7fe0658b91e6948f011a73d77a6281c85cdd26. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup>
Co-authored-by: William Bouchard <46496014+willbouch@users.noreply.github.com>