medusa-customer-file-upload
v0.0.2
Published
A starter for Medusa plugins.
Downloads
175
Maintainers
Readme
medusa-customer-file-upload
Medusa v2 storefront plugin that adds authenticated customer file uploads using Medusa’s core file upload workflow.
Plugin Overview
medusa-customer-file-upload exposes a store route for customer-authenticated file uploads and validates incoming files (size and MIME type) before delegating upload execution to Medusa core uploadFilesWorkflow.
What problem it solves
Medusa provides admin upload routes by default, but storefront/customer-specific upload endpoints are often needed (for profile docs, customer-submitted assets, etc.). This plugin provides a dedicated store endpoint with customer auth enforcement and configurable validation.
Medusa version
Built for Medusa v2 (@medusajs/framework / @medusajs/medusa 2.12.4 in package.json).
Installation & Setup
Install
npm install medusa-customer-file-upload
# or
yarn add medusa-customer-file-uploadRegister plugin (medusa-config.ts)
import { defineConfig } from "@medusajs/framework"
export default defineConfig({
plugins: [
{
resolve: "medusa-customer-file-upload",
options: {},
},
],
})Migrations
No custom database models/migrations are present in this plugin source, so no plugin-specific migration step is required.
Configuration (config.ts / plugin options)
The plugin does not define plugin options in medusa-config.ts; it uses environment-backed runtime config from src/config.ts.
Runtime config shape
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
| maxFileSizeBytes | number | Optional | 5242880 (5MB) | Max allowed size for each uploaded file. |
| allowedMimeTypes | string[] | Optional | [] (allow all) | Allowed MIME types. If empty, no MIME filtering is applied. |
⚠️ Note: This config is derived from environment variables, not from plugin options in
medusa-config.ts.
Example config block (medusa-config.ts)
{
resolve: "medusa-customer-file-upload",
options: {}
}Environment Variables
Used in src/config.ts:
| Variable | Controls | Required | Example | Default behavior |
|---|---|---|---|---|
| MEDUSA_CUSTOMER_UPLOAD_MAX_FILE_SIZE_BYTES | Maximum bytes per uploaded file | Optional | 10485760 | Falls back to 5242880 if missing/invalid/non-positive |
| MEDUSA_CUSTOMER_UPLOAD_ALLOWED_MIME_TYPES | Comma-separated allowlist for MIME types | Optional | image/png,image/jpeg,application/pdf | Empty/missing means all MIME types allowed |
REST APIs / Routes
Route Summary
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /store/upload | Customer JWT/session (actor_type === "customer") | Upload one or more files after validation. |
| GET | /admin/plugin | Admin route namespace | Health-check style endpoint returning 200. |
POST /store/upload
- Auth requirement: customer actor only; otherwise
401. - Middleware:
multermemory storage (upload.array("files")) viasrc/api/middlewares.ts. - Request content-type:
multipart/form-data. - Form field:
files(array of file parts). - Validation:
- Rejects empty uploads (
No files were uploaded). - Rejects files above
maxFileSizeBytes. - Rejects non-allowed MIME types when allowlist is configured.
- Rejects empty uploads (
- Upload behavior: Calls
uploadFilesWorkflow(req.scope)with base64 content andaccess: "public". - Success response (
200):
{
"files": [
{
"id": "file_...",
"url": "https://..."
}
]
}GET /admin/plugin
- Auth requirement: admin route namespace.
- Behavior: returns HTTP status
200.
cURL examples
curl -X POST "http://localhost:9000/store/upload" \
-H "Authorization: Bearer <customer_token>" \
-F "files=@/path/to/image.png"curl -X POST "http://localhost:9000/store/upload" \
-H "Authorization: Bearer <customer_token>" \
-F "files=@/path/to/a.pdf" \
-F "files=@/path/to/b.jpg"Services
No custom service classes are defined in this plugin source.
Workflows & Steps (Medusa v2)
No custom workflows/steps are defined in this plugin source.
The plugin invokes Medusa core uploadFilesWorkflow from @medusajs/core-flows.
Subscribers / Event Hooks
No runtime subscribers/event hooks are implemented in this plugin source.
Admin UI / Widgets
No admin widgets/routes/extensions are implemented in this plugin source.
Models & Entities
No custom models/entities are implemented in this plugin source.
Uploads are delegated to Medusa file infrastructure through core workflow calls.
Use Cases & Examples
Customer profile document upload
- Scenario: allow logged-in customers to upload verification documents.
- Use:
POST /store/uploadwith customer auth.
Storefront media submission
- Scenario: customer uploads images for custom orders.
- Use: multipart
filesupload with optional MIME restrictions.
Controlled upload policy
- Scenario: enforce size and MIME constraints for security/compliance.
- Use:
MEDUSA_CUSTOMER_UPLOAD_MAX_FILE_SIZE_BYTESandMEDUSA_CUSTOMER_UPLOAD_ALLOWED_MIME_TYPES.
Reuse existing file provider stack
- Scenario: keep the same storage backend logic as Medusa admin uploads.
- Use: plugin route + core
uploadFilesWorkflow(storage resolved by app’s file module setup).
Troubleshooting
401 Unauthorized. Customer authentication required.
- Cause: no customer auth context or non-customer actor.
- Fix: call endpoint with authenticated customer session/token.
No files were uploaded
- Cause: missing
filesfield or empty multipart form. - Fix: send
multipart/form-datawith at least onefilespart.
File <name> exceeds maximum size
- Cause: file larger than configured limit.
- Fix: reduce file size or increase
MEDUSA_CUSTOMER_UPLOAD_MAX_FILE_SIZE_BYTES.
File type not allowed: <mime>
- Cause: MIME allowlist configured and file MIME not included.
- Fix: add MIME to
MEDUSA_CUSTOMER_UPLOAD_ALLOWED_MIME_TYPESor upload allowed type.
Upload succeeds but URL/storage behavior is unexpected
- Cause: storage backend behavior comes from Medusa file module/provider config, not plugin code.
- Fix: verify host app file module/provider configuration.
