Releases: medusajs/medusa
v2.6.1
Highlights
Scheduled Jobs execution
Ensure Scheduled Jobs are only executed by server instances running in worker or shared mode. Our workflow engine powers scheduled jobs, and we create a workflow for every job. Scheduled Jobs (i.e. workflows) are not registered in servers that run in server mode. Consequently, if a server instance tries to pick up a Scheduled Job, it will fail, as it cannot find the underlying workflow. This change ensures that only worker and shared server instances execute Scheduled Jobs.
Features
Bugs
- fix(pricing): events by @carlos-r-l-rodrigues in #11742
- fix(workflow-engine-redis): Split the queues and respect worker mode for job executions by @adrien2p in #11740
- fix(core-flows): conditionally create, update or delete products when input is present by @riqwan in #11758
- Fix(framework): http cors middleware order and options by @adrien2p in #11765
- chore: pin swc to 1.5.7 by @thetutlage in #11759
- fix: Add created at and updated at dates to payment session by @sradevski in #11774
- fix(core-flows): fulfillment reservation check by @fPolic in #11735
- fix(dashboard): allow creating fulfillment for items without shipping profile by @fPolic in #11733
- fix(dashboard): display minute instead of month by @fPolic in #11731
- fix(medusa): Apply middleware to GET customers/:id/addresses/:address_id by @kasperkristensen in #11788
- fix(medusa): Use correct query config by @kasperkristensen in #11789
Documentation
- docs: changes for next release by @shahednasser in #11708
- docs-util: fix freshness check script by @shahednasser in #11737
- docs: fix tag for JS SDK draft order + other fixes by @shahednasser in #11747
- Update page.mdx by @MedusaNick in #11752
- docs: changes to main docs sidebar by @shahednasser in #11750
- docs: add sidebar sorting logic by @shahednasser in #11751
- docs-util: add exceptions for routes with custom auth middleware by @shahednasser in #11755
- docs: change link to cloud pricing by @shahednasser in #11753
- chore: remove ranges on medusa packages by @olivermrbl in #11738
- docs: support multiple sidebars in a project by @shahednasser in #11768
- docs: update UI docs to latest version by @shahednasser in #11770
- docs: fix duplicate footer in user guide by @shahednasser in #11785
Chores
- chore(product): Improve product normalization and fix http router with tracing by @adrien2p in #11724
- chore(js-sdk): fix tsdocs for properties and methods by @shahednasser in #11748
- chore(cart, core-flows): Improve tax lines algo management by @carlos-r-l-rodrigues in #11715
Full Changelog: v2.6.0...v2.6.1
v2.6.0
Highlights
Authentication improvements
This release enhances security around resetting passwords.
Updated token handling in password resets
Warning
Breaking changes: this change is not backward compatible due to security considerations
The token for updating provider identity is now accepted as a Bearer token in the authorization header instead of query parameters.
Before:
POST /auth/user/emailpass/update?token=ey...
After:
POST /auth/user/emailpass/update
// headers
{ authorization: "Bearer ey..." }
This enhances security around token management, for example, by preventing token exposure in logs.
More specifically, this will affect the reset password flow that relies on this endpoint.
Required action
- In your client (e.g. Next.js storefront), move the token from query params to the authorization header
Removed deprecated actorType
from reset password event
We have removed a long deprecated property, actorType
from the reset password event. Instead, use the actor_type
.
API Routes loader refactor
Important
While these changes sound dramatic, if you have used middleware and API Routes as intended, there will be no required actions nor breaking changes.
This release includes a refactor of our API Routes loading mechanism. The previous loader had long-standing issues that required hacky workarounds. To resolve these issues, weโve rebuilt the loader from scratch to ensure predictable behavior in how routes and middleware are registered within the application.
The root of the issues with the old implementation was mainly related to the following decisions:
-
Plugins, Medusa core, and the application used isolated router instances of Express. This means global middleware and error handlers are isolated, too. If you define an error handler in your app, it won't be able to handle errors from the core routes.
-
Middlewares defined inside the
src/api/middlewares.ts
file were always defined before the filesystem routes, and this led to unexpected behavior in many scenarios. For example, the middleware handler registered for routeadmin/payments/payment-providers
will also run when a request comes in for/admin/payments/:id
, even though there is a static route in place for the/admin/payments/payment-providers
URI. -
There was no clarity on the ordering in which routes and middleware were executed. With the new implementation, this has been fixed (more on ordering is discussed below).
-
Overriding an existing route defines multiple express handlers under the hood. It worked previously, because the route handlers never call
next
, hence the previous implementation was never executed. With the newer implementation, the route overrides from a Medusa application will be registered over the routes from the core or the plugins.
To resolve these issues, weโve rebuilt the loader from scratch to ensure predictable behavior in how routes and middleware are registered within the application. Additionally, the old API Routes loader unintentionally allowed overriding core API routes and middleware. While this behavior remains for now, it will be removed in a future release. Please prepare your application based on the behavior described in the following sections.
Global middleware
A global middleware is defined using the defineMiddlewares
function without specifying an HTTP method.
defineMiddlewares([
{
matcher: '/admin',
middleware: [
(req, res, next) => console.log("Hi from global middleware")
],
}
])
The order of registering global middleware is as follows:
- Global middleware from the core
- Global middleware from plugins (in the order plugins are registered)
- Global middleware from the app
Route middleware
A route middleware is also defined using the defineMiddlewares
method. However, they must always specify the HTTP method(s) they want to target.
defineMiddlewares([
{
matcher: '/admin/*',
methods: ["GET", "POST"],
middleware: [
(req, res, next) => console.log("Hi from route middleware")
],
}
])
The order of registering route middleware is as follows:
- Route middleware from the core
- Route middleware from plugins (in the order plugins are registered)
- Route middleware from the app
API Routes
An API Route is always attached to a method, decided by the exported const from the route file. API Routes are registered by scanning the filesystem.
Two types of API Routes are supported:
- Static segments:
/admin/products/route.ts
- Dynamic segments:
/admin/products/[id]/route.ts
Sorting routes and middleware
Before registering routes + middleware with Express, they are sorted as described below:
- Global middleware
- Route middleware
- API Routes
On top of this, each segment from the API Route matcher is sorted by its specificity:
- Wildcard segments, e.g.
/admin/products/*
- Regex segments, e.g.
/admin/(product-types|product-collections)
- Static segments, e.g.
/admin/products
- Dynamic segments, e.g.
/admin/products/:id
Important note about middleware
Middleware never overrides any existing middleware; they are added to the stack of existing middleware. For example, if you define a custom validation middleware on an existing route, then both the original and the custom validation middleware will run.
Performance improvements
This release contains general and, in some areas, significant performance improvements. Over the past weeks, we have focused on removing performance bottlenecks in Medusa. While many of the improvements impacted the entire application, the most significant ones are for cart operations.
Here's a summary of the changes and improvements:
Application-level changes
- Eliminated unnecessary module calls in cart workflows to ensure we don't create unused transactions and have redundant database communication
- Minimized redundant data fetching in cart workflows, ensuring that only the data that is needed for the operation is fetched
- Changed workflows to accept prefetched data instead of always fetching the data independently
- Introduced finer control over cart refresh logic to ensure we don't perform unnecessary cart refreshes
- Replaced the Redis
del
operation with the non-blocking deleteunlink
to reduce the load on Redis - Replaced inefficient soft and hard deletes by performing the operation in a single query instead of multiple
- (Dashboard) Minimized redundant data fetching for dashboard pages
Database-level changes
These changes are a result of thorough testing of our own infrastructure. Therefore, they should be deemed a recommendation rather than an absolute configuration. Additionally, it is important to highlight that these tests were run against a Neon Database with a PgBouncer setup. Without PgBouncer and Neon, the configuration would likely look different.
// medusa-config.ts
export default defineConfig({
projectConfig: {
// ...other options
databaseDriverOptions: {
pool: {
max: 8, // Fixed pool size of 8
idleTimeoutMillis: 30000, // Close idle connections after 30 seconds
connectionTimeoutMillis: 10000, // Fail on connection attempt after 10 seconds
createRetryIntervalMillis: 100 // Time between connection retries
},
},
...
},
}
Results
We have run two tests:
Test 1:
- Operation: Add to cart
- Database spec:
- 0.25 CPU
- 1 GB RAM
- Server spec:
- 1 CPU
- 2 GB RAM
- Load: 5 carts, operations for each cart run in parallel; for each cart, we add 100 items sequentially
p95: 1180ms -> 866ms
p50: 833ms -> 593ms
Test 2:
- Operation: Add to cart
- Database spec:
- 0.5 CPU
- 2 GB RAM
- Server spec:
- 1 CPU
- 2 GB RAM
- Load: 5 carts, operations for each cart run in parallel; for each cart, we add 100 items sequentially
p95: 1180ms -> 773ms
p50: 849 -> 537ms
Both tests show an approximate performance improvement of 30-35%.
Features
- feat: add middleware and routes sorter by @thetutlage in #11526
- feat(core-flows,types,cart): add credit lines to cart by @riqwan in #11419
- feat: add routes loader by @thetutlage in #11592
- feat: add middleware-file-loader by @thetutlage in #11638
- feat(utils): add error message when manager is not found in context by @riqwan in #11693
- feat: Replace existing router with the new implementation by @thetutlage in #11646
Bugs
- fix(types, medusa): remove fulfillment and payment status filters from validator + http types by @shahednasser in #11604
- fix(types): Allow providing either vite@5 or vite@6 for the peer dependency by @kasperkristensen in #11581
- fix(promotion): scope uniqueness index to non deleted promotions by @riqwan in #11624
- fix(core-flows): support 0 as a valid unit price for custom line items by @riqwan in #11631
- fix(core-flows): unsafe access to a variant property by @fPolic in #11588
- fix(medusa): deleting location level by @fPolic in #11630
- fix: Exclude the health endpoint from being logged by @sradevski in https://github.com/medusajs/med...
v2.5.1
Highlights
Support outlet routes, loader, and handle
This release introduces support for
- exporting a loader from a route file
- exporting a handle from a route file
Here's an example using the loader and handle:
// src/admin/routes/articles/[id]/page.tsx
import { Button, Container, Heading } from "@medusajs/ui";
import { Link, LoaderFunctionArgs, Outlet, UIMatch, useLoaderData } from "react-router-dom";
export async function loader({ params }: LoaderFunctionArgs) {
const { id } = params;
return {
id,
};
}
export const handle = {
breadcrumb: (match: UIMatch<{ id: string }>) => {
const { id } = match.params;
return `#${id}`;
},
};
const ProfilePage = () => {
const { id } = useLoaderData() as Awaited<ReturnType<typeof loader>>;
return (
<div>
<Container className="flex justify-between items-center">
<Heading>Article {id}</Heading>
<Button size="small" variant="secondary" asChild>
<Link to="edit">Edit</Link>
</Button>
</Container>
{/* This will be used for the next example of an Outlet route */}
<Outlet />
</div>
);
};
export default ProfilePage;
In the above example we are passing data to the route from a loader, and defining a breadcrumb using the handle.
See more in #11305.
Expand options for instrumentation via registerOtel
This release expands the available options in our registerOtel
function from our instrumentation tooling. More specifically, the function will allow all options from OpenTelemetry's NodeSDK, which will open up support for a broader range of instrumentation tools, including Sentry.
Here's an example of configuring Sentry:
import Sentry from '@sentry/node'
import otelApi from "@opentelemetry/api";
import { registerOtel } from "@medusajs/medusa"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc"
import { SentrySpanProcessor, SentryPropagator } from "@sentry/opentelemetry-node"
Sentry.init({
dsn: "<INSERT SENTRY DSN>",
tracesSampleRate: 1.0,
instrumenter: "otel",
});
otelApi.propagation.setGlobalPropagator(new SentryPropagator());
export function register() {
registerOtel({
serviceName: "medusa",
spanProcessor: new SentrySpanProcessor(),
traceExporter: new OTLPTraceExporter(),
instrument: {
http: true,
workflows: true,
query: true
},
})
}
See more in #11460.
Enrich and improve structural logging
This release improves structural logging by expanding the data with additional information, including request ID, request size, response size, request duration, and more.
Here's an example log line:
{"level":"http","client_ip":"10.18.85.250","request_id":"53123ef7-f8e9-4e85-8aea-3fecfc7d9ba0","http_version":"1.1","method":"POST","path":"/admin/products","status":200,"response_size":"10754","request_size":"1550","duration":1079.301,"referrer":"-","user_agent":"node","timestamp":"2025-02-24T08:36:17.748Z"}
See more in #11489.
Allow custom storage in JS-SDK
This release introduces support for a custom storage solution in the JS-SDK, instead of using the built-in memory
, session
, and local
. This allows you to pass a custom implementation of the storage interface to be responsible for token management.
See more in #11467.
What's Changed
Features
- feat: query.index by @carlos-r-l-rodrigues in #11348
- feat(dashboard,admin-vite-plugin): Add support for outlet routes, loader, and handle by @kasperkristensen in #11305
- feat: allow all NodeSDK options via registerOtel by @thetutlage in #11460
- feat(dashboard): Pickup option changes by @fPolic in #11306
- feat(): Backport metadata management by @adrien2p in #11469
- feat(ui,dashboard): Move InlineTip to UI package by @kasperkristensen in #11462
- feat: Add support for idempotency key in payments by @sradevski in #11494
- feat(framework): Improve production structured logging with more valuable information as well by @adrien2p in #11489
- feat(core-flows, dashboard, medusa, types): optional shipping profile by @fPolic in #11434
- feat: Add support to update account holder by @sradevski in #11499
- feat(medusa): Rollout index engine behind feature flag by @adrien2p in #11431
- feat(core-flows, types): add has missing inventory flag when listing shipping options by @fPolic in #11493
Bugs
- fix(dashboard): secret key display by @fPolic in #11365
- fix(utils): custom linkable keys by @carlos-r-l-rodrigues in #11400
- fix(admin-vite-plugin,admin-bundler,ui,icons,dashboard,framework,types): Update Vite dependencies by @kasperkristensen in #11414
- fix: Remove unnecessary swc production dependency by @sradevski in #11416
- fix(core-flows, types): reservation of shared inventory item by @fPolic in #11403
- fix(payment): update payment session data by @fPolic in #11410
- fix(medusa): Fix draft order validator, and endpoint by @kasperkristensen in #11398
- fix(design-system): singleton prompt by @fPolic in #11352
- fix: listVariantsList types by @thetutlage in #11441
- fix: relationships to accept ids by @thetutlage in #11399
- fix(medusa): Re throw error in instrumentation after reporting it by @adrien2p in #11464
- fix(medusa): Allow filtering by handle and title as arrays by @kasperkristensen in #11472
- fix(core-flows): Fix line item ids passed to deleteReservationsByLineItemsStep by @kasperkristensen in #11465
- fix(types): fix shipping profile type optional in create type / method by @shahednasser in #11453
- fix(dashboard): Fix size of buttons and use Link to navigate by @kasperkristensen in #11366
- fix: generate posix paths for migrations by @thetutlage in #11468
- fix(dashboard): Allow using the Enter key in product create Textarea by @kasperkristensen in #11488
- fix(dashboard): Properly delete metadata keys, and fix number parsing by @kasperkristensen in #11466
- fix(framework): add missing storefrontUrl from configuration type by @shahednasser in #11511
- fix(core-flows): add no_notification to fulfillment created event by @riqwan in #11507
- fix: allow setting DB_PORT and DATABASE_URL env variables by @thetutlage in #11519
- fix: typings for list payment method were incorrect by @sradevski in #11523
- fix(dashboard): Prevent overfetching data by @adrien2p in #11532
- fix(utils): Handle 0 correctly in build query by @olivermrbl in #11525
- fix(medusa,js-sdk,types): Add basic draft order operations to js-sdk by @kasperkristensen in #11514
- fix(): handle empty q filters - allow to query deleted records from graph API - staled_at fixes by @adrien2p in #11544
- fix(order): calculate taxes on order edit flows by @carlos-r-l-rodrigues in #11518
- fix(core-flows): Allow adding shipping methods through order edits by @kasperkristensen in #11504
- fix(js-sdk): Export Draft Order methods by @kasperkristensen in #11572
Documentation
- docs: update default for medusa start by @shahednasser in #11391
- docs: document payment changes + account holder by @shahednasser in #11242
- docs: add documentation for product <> shipping profile link by @shahednasser in #11397
- docs: general updates after 2.5.0 update by @shahednasser in #11402
- docs: added express checkout guide by @shahednasser in #10810
- docs: small fixes to workflow constraints chapter by @shahednasser in #11421
- docs: fix managing relationship for hasOne by @shahednasser in #11422
- docs: add section on validating module options by @shahednasser in #11427
- docs-util: fix inline code escape in generated references by @shahednasser i...
v2.5.0
Highlights
Revamped Payment Provider interface
Warning
Breaking changes
The payment provider interface, originally designed for Medusa V1, has now been redesigned for V2โa long overdue update. These changes deliver a more unified and intuitive API.
We apologise in advance for the inconvenience it might cause for your payment provider implementations.
The following are breaking changes:
Payment Provider interface
export interface IPaymentProvider {
...
- initiatePayment(
- data: CreatePaymentProviderSession
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse>
+ initiatePayment(data: InitiatePaymentInput): Promise<InitiatePaymentOutput>
- updatePayment(
- context: UpdatePaymentProviderSession
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse>
+ updatePayment(data: UpdatePaymentInput): Promise<UpdatePaymentOutput>
- deletePayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ deletePayment(data: DeletePaymentInput): Promise<DeletePaymentOutput>
- authorizePayment(
- paymentSessionData: Record<string, unknown>,
- context: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderAuthorizeResponse>
+ authorizePayment(data: AuthorizePaymentInput): Promise<AuthorizePaymentOutput>
- capturePayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ capturePayment(data: CapturePaymentInput): Promise<CapturePaymentOutput>
- refundPayment(
- paymentSessionData: Record<string, unknown>,
- refundAmount: BigNumberInput
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ refundPayment(data: RefundPaymentInput): Promise<RefundPaymentOutput>
- retrievePayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ retrievePayment(data: RetrievePaymentInput): Promise<RetrievePaymentOutput>
- cancelPayment(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentProviderError | PaymentProviderSessionResponse["data"]>
+ cancelPayment(data: CancelPaymentInput): Promise<CancelPaymentOutput>
+
+ createAccountHolder?(
+ data: CreateAccountHolderInput
+ ): Promise<CreateAccountHolderOutput>
+
+ deleteAccountHolder?(
+ data: DeleteAccountHolderInput
+ ): Promise<DeleteAccountHolderOutput>
- listPaymentMethods?(
- context: PaymentProviderContext
- ): Promise<PaymentMethodResponse[]>
+ listPaymentMethods?(
+ data: ListPaymentMethodsInput
+ ): Promise<ListPaymentMethodsOutput>
- savePaymentMethod?(
- input: SavePaymentMethod
- ): Promise<PaymentProviderError | SavePaymentMethodResponse>
+ savePaymentMethod?(
+ data: SavePaymentMethodInput
+ ): Promise<SavePaymentMethodOutput>
- getPaymentStatus(
- paymentSessionData: Record<string, unknown>
- ): Promise<PaymentSessionStatus>
+ getPaymentStatus(data: GetPaymentStatusInput): Promise<GetPaymentStatusOutput>
}
The input and return types of the updated interface can be found in this file.
Additionally, we've updated the interface to require payment providers to throw errors instead of returning them to the upstream payment module service.
Create Payment Sessions endpoint
In addition to the interface changes, we've also removed the context
field from the endpoint creating payment sessions:
`POST /store/payment-collections/:id/payment-sessions
This change addresses a security risk. The context
accepted by the payment module now only accept known fields, limiting the surface area of what can be passed through it.
Account Holders
Fortunately, the revamp did not only introduce breaking changes. This release also introduces support for Account Holders in payment providers. In Stripe, for example, we will create a customer for every signed up user on your platform so you can track payments more easily within Stripe. These methods are optional for payment providers.
You can find all the changes in this pull request.
Overriding Shipping Option for Fulfillments
Note
Schemas changes
This release improves fulfillment capabilities, allowing merchants to override the shipping option originally selected during order creation. For example, a different shipping option can now be specified directly in the dashboard when creating a fulfillment.
Key changes:
- Product <> Shipping Profile link
A link between Products and Shipping Profiles has been introduced, similar to the relationship in Medusa V1. Products now require a Shipping Profile upon creation. The create and update forms in the dashboard have been updated accordingly.
- Override Shipping Option on Fulfillments
The fulfillment creation endpoint now accept an optional shipping_option_id
. If passed, it will override the shipping option used when placing the order.
POST /admin/orders/:id/fulfillments
{ ..., shipping_option_id: "so_1234"}
This functionality is also available in the dashboard, allowing merchants to specify the override when creating a fulfillment.
- Data migration script
Since products now require a shipping profile, this release includes a data migration script. The script will assign all products to the default shipping profile, if it exists. The default shipping profile is determined by looking for a shipping profile with default
(case insensitive) in its name.
By default, data migration scripts run as part of the medusa db:migrate
command.
Alternatively, you can run the data migration separately from the regular database migrations. To do this, first run the migration command with an argument skipping scripts:
medusa db:migrate --skip-scripts
Then, run the command again without the argument:
medusa db:migrate
Type-hinting for custom module services
This release improves type-hinting for custom module services. The input types of autogenerated create and update methods will provide an approximate type inferred from the related data model. Please note, in this first iteration, all properties will be marked as optional in the type, even though they might be required at the DB-level. We intend to further improve this to bring the type even closer to what the database expects.
Clearing workflow_execution
s exceeding their retention time
Note
Schemas changes
This release introduces a recurring job within the workflow engine to clear stale workflow executions from the database. The job runs every hour and deletes workflow executions that have exceeded their configured retention time.
Retention time is set in the workflow execution options. However, to simplify this operation, weโve introduced a retention_time
column in the workflow_execution
table.
For existing workflow executions, the retention time will be automatically set if it was previously configured in the workflow execution options. The retention time is expected to be specified in seconds. If it was mistakenly configured in milliseconds, you may encounter a Postgres error when casting the retention time to an integer.
If you run into this issue, you can manually run the migration while specifying the correct retention time for your workflow executions.
Other noteworthy changes
Changes to medusa start
The medusa start
command is intended to be used for production envionments. Therefore, the NODE_ENV
now defaults to production
instead of development
.
New Divider component
The Divider
component has been added to the UI library.
Added Metadata forms
Metadata forms have been added for the Product Collection and Order pages.
Features
- feat(core-flows, dashboard, link-modules,medusa, types, utils): fulfillment shipping changes by @fPolic in #10902
- feat: Add tasks orchestrator by @thetutlage in #11161
- Feat/index sync data by @adrien2p in #11169
- feat: Revamp payment provider interface by @sradevski in #11015
- feat(medusa): add sku to variant query params by @riqwan in #11151
- feat(orchestration): hydrate resultset by @carlos-r-l-rodrigues in #11263
- feat: make AbstractModuleService create method type-safe by @thetutlage in #11216
- feat(core-flows): cart complete shipping validate by @fPolic in #10984
- feat: map container types for core services to interface by @thetutlage in #11295
- feat(index): full sync operations by @adrien2p in #11178
- feat(ui,dashboard): Migrate SC tables to DataTable by @kasperkristensen in #11106
- feat(ui,dashboard): Move Divider component to UI package by @kasperkristensen in #11357
Bugs
- fix(js-sdk,admin-bundler): Fix qs import by @kasperkristensen in #11172
- fix(dashboard): Matching product profile with shipping profile by @olivermrbl i...
v2.4.0
Highlights
Plugins
This release introduces Plugins. Plugins are customizations distributed as npm packages. A plugin can do everything a regular Medusa application can, including defining HTTP routes and workflows, registering subscribers, exporting custom modules, or defining links between modules.
Read our documentation on Plugins to learn more.
MikroORM V6 upgrade
This release marks the completion of the migration of all core modules to the Data Model API. As part of this effort, weโve upgraded our MikroORM dependency from V5 to V6, as V5 has entered maintenance mode. You can read more about the upgrade here.
While this upgrade introduced breaking changes, none of them will impact user projects directly. The only required action is upgrading the MikroORM dependencies in your project.
Required actions
Upgrade the following dependencies in your package.json
alongside your Medusa packages:
"dependencies": {
- "@mikro-orm/core": "5.9.7",
- "@mikro-orm/knex": "5.9.7",
- "@mikro-orm/migrations": "5.9.7",
- "@mikro-orm/postgresql": "5.9.7",
+ "@mikro-orm/core": "6.4.3",
+ "@mikro-orm/knex": "6.4.3",
+ "@mikro-orm/migrations": "6.4.3",
+ "@mikro-orm/postgresql": "6.4.3",
...
"devDependencies": {
- "@mikro-orm/cli": "5.9.7",
+ "@mikro-orm/cli": "6.4.3",
...
Update your lock-file by installing the dependencies:
npm install // use your preferred package manager
DataTable component
This release adds an opinionated DataTable component to @medusajs/ui
. The DataTable component is an opinionated implementation of our Table component and @tanstack/react-table
. It simplifies the setup of tables with advanced features such as pagination, sorting, filtering, row selection, and commands.
Read more about the DataTable and learn how to set it up in our documentation.
New translations added to Admin
This release adds Macedonian, Romanian, Chinese, Persian, Czech, Arabic, and Mongolian to supported languages in Medusa Admin.
Change in behavior of one-to-one relation
This release updates the generated SQL of the one-to-one relation in our Data Model API. Until now, defining a one-to-one relation would generate a unique constraint. Unique constraints do not account for soft-deleted rows, so new rows with the same foreign key as a previously deleted row cannot be inserted. With this release, one-to-one relations will generate a unique index instead to ensure that the uniqueness is only enforced on non-deleted rows.
Features
- feat(ui,dashboard): Add DataTable block by @kasperkristensen in #10024
- feat: Add translations for Macedonian by @sradevski in #11039
- feat: Add support for creating payment methods to payment module by @sradevski in #11063
- feat(dashboard): Refactor Users table to use the new DataTable block by @kasperkristensen in #11058
- feat(medusa,product,types): product type & tag store missing endpoints by @fPolic in #11057
Bugs
- fix(medusa): use correct request and response types for batch location levels route by @shahednasser in #11055
- fix(dashboard,js-sdk,types): Remove redundant body for markAsDelivered by @kasperkristensen in #10964
- fix(framework): migration scripts regexp by @adrien2p in #11072
- fix(create-medusa-app): fix database name from input not used in setup by @shahednasser in #11071
- fix(promotion): eval conditions for rules are made accurate by @riqwan in #10915
- fix(event): Subscriber ID miss usage by @adrien2p in #11047
- fix: Unique constraint should account for soft deleted records by @adrien2p in #11048
- fix(dashboard): Use date util to properly format date in order details view by @kasperkristensen in #11073
- fix(core-flows): change some types to interfaces by @shahednasser in #11061
- fix: Flaky behavior of Yalc by @thetutlage in #11084
- fix(admin-bundler): Fix Vite imports to prevent deprecation warnings by @kasperkristensen in #11086
- fix(dashboard): Persist variant_rank by @kasperkristensen in #11074
- fix(ui): Fix position of Checkbox indicator by @kasperkristensen in #11075
- fix(dashboard): Add global errorElement by @kasperkristensen in #10981
- fix: Medusa package version should use ~ instead of ^ by @adrien2p in #11077
- fix(fulfillment): migration so rules by @carlos-r-l-rodrigues in #11109
- fix(fulfillment): migration so rules by @carlos-r-l-rodrigues in #11113
- fix: switch from tsc watch to chokidar by @thetutlage in #11110
- fix(admin-bundler): Optimize tanstack/react-query by @kasperkristensen in #11112
- fix(dashboard): Format i18n schema with Prettier by @kasperkristensen in #11107
- fix(core-flows, dashboard): handling fulfillment rules by @fPolic in #11111
- fix(medusa,cli): Resources not correctly loaded when running the migration scripts by @adrien2p in #11108
Documentation
- docs: add search to workflows reference by @shahednasser in #11054
- docs: fixes for core workflows reference by @shahednasser in #11056
- docs: fix types with arguments not showing correct properties by @shahednasser in #11062
- chore(order): dml by @carlos-r-l-rodrigues in #10292
- docs: added note in API reference clarifying what schemas are by @shahednasser in #11116
- docs: update list of routes accepting additional data by @shahednasser in #11119
- docs: add a note about installing tanstack query as a dev dependency by @shahednasser in #11123
- docs-util: fix incorrect workflow extracted in OAS by @shahednasser in #11120
- docs: clarify condition / variable manipulation restriction for workflows and steps by @shahednasser in #11125
- typo by @devduttabain in #11128
- docs: document workflow retention by @shahednasser in #11138
- docs: add troubleshooting for cloudflare s3 by @shahednasser in #11143
- docs: fix sidebar items not showing if they have same title in API reference by @shahednasser in #11122
- docs: generate sidebar for main docs by @shahednasser in #11139
- docs: fix current sidebar not found by @shahednasser in #11155
Chores
- chore(ui): add tsdocs for DataTable components by @shahednasser in #11087
- chore(utils): patch unique index migration by @carlos-r-l-rodrigues in #11136
Other Changes
- docs: how to add new admin route under existing route by @eugenepro2 in #10652
- fix(dashboard): create sales channel toast type by @Avia-Code in #11019
- feat: Add translations for Mongolian by @sanchir2011 in #11085
- refactor(ui-preset): replace defaultTheme import by @pnodet in #11041
- add support to arabic by @gharbi-mohamed-dev in #11088
- Add Romanian translation by @python27tt in #10890
- feat: add translation for zh-CN by @leosin in #10757
- Add Persian (fa) translations for the admin dashboard by @behrouz-shafaati in #11091
- feat: add Czech language translation by @TomasKliner in #11127
- product categories hooks by @noubase in #11093
New Contributors
- @sanchir2011 made their first contribution in #11085
- @pnodet made their first contribution in #11041
- @python27tt made their first contribution in #10890
- @leosin made their first contribution in #10757
- @behrouz-shafaati made their first contribution in #11091
- @devduttabain made their firs...
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