medusa-export
v0.0.7
Published
A starter for Medusa plugins.
Maintainers
Readme
medusa-export
Medusa v2 admin export plugin that adds CSV export APIs and admin export buttons for core and extension pages.
Plugin Overview
medusa-export provides a generic admin export endpoint and UI integrations to download CSV files for Medusa entities.
Implemented behavior includes:
GET /admin/export/:model_nameCSV export endpoint.- Special inventory export mode (
inventory-item) with flattened location-level stock rows. - Generic remoteQuery-based export for arbitrary models.
- Empty/fallback CSV handling to avoid hard failures in many cases.
- Admin UI export buttons:
- Widget-based buttons on selected list pages.
- DOM-injected export button for selected extension pages.
It solves the need to quickly export operational/admin data from Medusa to spreadsheets.
Medusa Version
- Built for Medusa v2 (
@medusajs/framework,@medusajs/medusa2.12.4).
Installation & Setup
1) Install
npm install medusa-exportyarn add medusa-export2) Register plugin
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
plugins: [
{
resolve: "medusa-export",
},
],
})3) Build / run
npx medusa plugin:build
npx medusa develop4) Migrations
No custom models or migrations are implemented in this plugin; no plugin-specific migration is required.
Configuration (config.ts / plugin options)
No plugin options are read by the code.
| Option | Type | Required | Default | Description | |---|---|---|---|---| | None implemented | - | - | - | Plugin behavior is code-defined and route-driven; no runtime option parsing. |
Example registration:
{
resolve: "medusa-export"
}Environment Variables
No process.env.* variables are used in implemented plugin source files.
| Variable | Required | Purpose | Example | |---|---|---|---| | None | - | - | - |
REST APIs / Routes
1) GET /admin/export/:model_name
Exports CSV for the specified model.
- Auth requirement: Admin route context.
- Path params:
| Param | Type | Required | Description |
|---|---|---|---|
| model_name | string | Yes | Target model/entry point (for example product, order, customer, inventory-item). |
- Query params:
| Param | Type | Required | Description |
|---|---|---|---|
| limit | string | No | Pagination limit (parsed integer). |
| offset | string | No | Pagination offset (parsed integer). |
| fields | string | No | Comma-separated fields; defaults to *. |
| filter | string | No | JSON string for query filters. |
Special behavior: model_name=inventory-item
When model_name is inventory-item, the route:
- Uses
query.graphoninventory_item. - Resolves inventory levels via
Modules.INVENTORYlistInventoryLevels. - Resolves location names via
stock_location. - Returns flattened CSV columns:
id,title,location,instock.
Generic export behavior
For non-inventory-item models, route uses resolved remoteQuery with entryPoint and optional pagination/filter parameters.
Special mapping implemented:
contact-requestpath maps to remote query entry pointcontact_request.
Response
- Content type:
text/csv; charset=utf-8 - Attachment filename:
${model_name}_${YYYY-MM-DD}.csv - Includes UTF-8 BOM for Excel compatibility.
Error/fallback behavior
400ifmodel_namemissing orfilteris invalid JSON.- For certain extension models with no rows, returns
404JSON message. - In outer catch fallback, returns HTTP
200with empty CSV rather than500.
cURL examples
curl -X GET "http://localhost:9000/admin/export/product" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-o product.csvcurl -X GET "http://localhost:9000/admin/export/inventory-item?limit=500&offset=0" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-o inventory-item.csvcurl -G "http://localhost:9000/admin/export/order" \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
--data-urlencode "fields=id,status,email,created_at" \
--data-urlencode "filter={\"status\":\"pending\"}" \
-o order.csv2) GET /store/plugin
Health endpoint.
- Auth requirement: Public store route.
- Response: HTTP
200.
curl -X GET "http://localhost:9000/store/plugin"Services
No custom service classes are implemented.
The export route relies on container resources:
remoteQuery(resolved from scope)ContainerRegistrationKeys.QUERYgraph serviceModules.INVENTORYservice (listInventoryLevels)
Workflows & Steps (Medusa v2)
No custom workflows or steps are implemented.
Subscribers / Event Hooks
No subscribers/event hooks are implemented.
Admin UI / Widgets
This plugin implements admin extension behavior via widgets and DOM initialization scripts.
Widget: Inventory export button
- File:
src/admin/widgets/inventory-export-widget.tsx - Zone:
inventory_item.list.before - Placement behavior: Finds Create control on
/app/inventoryand injects export button beside it using portal + mutation observer. - Action: Calls
/admin/export/inventory-item, downloads returned CSV.
Widget: Dynamic export button
- File:
src/admin/widgets/dynamic-export-widget.tsx - Zones:
customer.list.before,order.list.before,promotion.list.before,location.list.before - Action: Resolves model from current URL mapping and calls
/admin/export/:model.
Extension-page DOM injection utility
- Files:
src/admin/init-extension-exports.tsx,src/admin/utils/extension-export-buttons.ts - Behavior: Mutation observer detects page content header and injects export buttons for specific extension paths:
/app/returns->return/app/contact-requests->contact-request/app/contact-email-subscriptions->contact-email-subscriptions
- Note: stock-monitoring export button is intentionally excluded in utility comments.
Export hub page
- File:
src/admin/pages/export-hub.tsx - Renders: standalone page with manual export buttons for several models.
- Status in codebase: present component, but no explicit
defineRouteConfigroute registration file in current plugin structure.
⚠️ Note:
src/admin/widgets/zones/export-zones.tsxcontains mappings for additional routes/models beyond widget zone registrations; these mappings are partially unused unless connected by surrounding extension code paths.
Models & Entities
No custom entities/models are defined.
Use Cases & Examples
Export core commerce records
- Use
/admin/export/orderor/admin/export/customerto download tabular operational data.
- Use
Export inventory by location for reconciliation
- Use
/admin/export/inventory-itemto get flattened rows withlocationandinstock.
- Use
Export filtered subsets
- Use
filterquery JSON andfieldsselection to reduce output scope.
- Use
One-click admin exports from list pages
- Use built-in widget buttons on customer/order/promotion/location and inventory pages.
Extension page export support
- Use injected export buttons on configured extension routes (returns/contact-request/contact-email-subscriptions).
Troubleshooting
Empty CSV output
- Cause: no matching rows or export fallback path.
- Fix: verify
model_name, remove overly restrictive filters, and retry withoutfields/filter.
404 for extension models
- Cause: route explicitly returns
404with message when no rows found for selected extension models. - Fix: ensure source plugin/module actually has data for that model.
Invalid filter JSON
- Cause: malformed
filterquery value. - Fix: send valid JSON string (URL-encoded when needed).
Export button not appearing in admin
- Cause: page DOM structure not matched by injection logic, or plugin bundle not loaded.
- Fix: rebuild plugin, restart admin, hard refresh browser, and verify route/path matches supported paths.
Inventory export missing location names
- Cause: location lookup query failure or missing location records.
- Fix: verify stock location data exists and query service is functioning.
