npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

medusa-customer-file-upload

v0.0.2

Published

A starter for Medusa plugins.

Downloads

175

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-upload

Register 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: multer memory storage (upload.array("files")) via src/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.
  • Upload behavior: Calls uploadFilesWorkflow(req.scope) with base64 content and access: "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

  1. Customer profile document upload

    • Scenario: allow logged-in customers to upload verification documents.
    • Use: POST /store/upload with customer auth.
  2. Storefront media submission

    • Scenario: customer uploads images for custom orders.
    • Use: multipart files upload with optional MIME restrictions.
  3. Controlled upload policy

    • Scenario: enforce size and MIME constraints for security/compliance.
    • Use: MEDUSA_CUSTOMER_UPLOAD_MAX_FILE_SIZE_BYTES and MEDUSA_CUSTOMER_UPLOAD_ALLOWED_MIME_TYPES.
  4. 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 files field or empty multipart form.
  • Fix: send multipart/form-data with at least one files part.

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_TYPES or 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.