graphql-upload

Express/Koa middleware and an Upload scalar for GraphQL multipart file uploads

Library
npm
v18.0.0
1,443 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
78 /100 Good
Development Activity 72
Maintenance 84
Community 56
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
65 /100 Good
Architecture 68
Code Quality 74
Innovation 60
Learning Curve 58

graphql-upload is the server-side counterpart to clients like apollo-upload-client: it provides Express and Koa middleware that intercepts incoming GraphQL multipart requests (per the community graphql-multipart-request-spec), parses the multipart form to separate the GraphQL operations JSON from the uploaded file streams, and reassembles them into a single operations object where file variables become Upload scalar promises resolving to readable-stream-backed file objects.

It also exports the GraphQLUpload scalar type itself, so a schema can declare Upload as an input type and resolvers receive fully-formed file objects (filename, mimetype, encoding, and a createReadStream() method) instead of raw multipart parts, regardless of which Node.js GraphQL server framework or client sent the request.

What You Get

  • graphqlUploadExpress — Express middleware that detects and parses multipart GraphQL requests before they reach the GraphQL handler
  • graphqlUploadKoa — the equivalent middleware for Koa applications
  • GraphQLUpload — a ready-to-use GraphQL scalar type for declaring Upload fields/arguments in a schema
  • processRequest — the underlying framework-agnostic request-processing function, usable directly for custom server integrations
  • Upload — the class instances resolvers receive, exposing filename/mimetype/encoding plus a createReadStream() method for streaming file contents to storage

Common Use Cases

  • Accepting file uploads (avatars, documents, media) through a mutation on an Express- or Koa-based GraphQL server
  • Streaming uploaded files directly to cloud storage (S3, GCS) via createReadStream() without buffering the whole file in memory
  • Interoperating with any client implementing the graphql-multipart-request-spec, including apollo-upload-client
  • Integrating GraphQL file uploads into a custom or less common Node.js server setup via the lower-level processRequest function

Under The Hood

Architecture - processRequest.mjs (roughly 400+ lines) is the core: it uses the busboy streaming multipart parser to read the incoming request, extracts the operations JSON part and the map part (which links file field names to JSON-pointer paths inside operations), then walks the map to substitute each referenced path with a Upload instance whose internal promise resolves once the corresponding file part streams in — giving resolvers a value they can await (or access via GraphQLUpload’s parseValue) even though the underlying bytes may still be arriving. graphqlUploadExpress.mjs and graphqlUploadKoa.mjs are thin adapters that call processRequest with the right request/response objects for each framework’s middleware signature, only engaging when the request’s content-type is multipart. Tech Stack - Pure ESM (.mjs, no CJS build), with busboy as the sole non-peer runtime dependency for streaming multipart parsing, and graphql, @types/express, @types/koa as (optional) peer dependencies so the package doesn’t force a specific server framework or pin a GraphQL version. Code Quality - Every module has an adjacent .test.mjs file, with processRequest.test.mjs alone exceeding 1,500 lines covering malformed multipart bodies, oversized files/field counts, aborted uploads, and both Express and Koa integration paths; // @ts-check JSDoc annotations provide type-checking without a separate TypeScript build. API Design - The layered design — a low-level processRequest plus framework-specific graphqlUploadExpress/graphqlUploadKoa wrappers — lets most consumers just drop in one middleware call, while server authors using an unsupported framework can still integrate via the documented lower-level function; the tradeoff is that Upload values are promises-in-disguise (resolved via a hidden .promise) which resolvers must await or otherwise handle correctly, a subtlety documented in the README but easy to miss on first use.

Used by 5 apps in this directory

TypeScript
82%
Other

AFFiNE

Collaboration · Note Taking · Productivity

73,040

Write, draw, and plan in one infinite canvas — the open-source alternative to Notion and Miro that keeps your data yours.

View details
91
Repo Health
87
Technical
67
Dependency
Built with
TypeScript 82%
Rust 11%
Updated 6 days ago
TypeScript
96%
Other

Amplication

AI Code Assistants · Automation · Developer Tools

16,015

Create production-ready backend services with your organization's standards baked in — generating NestJS, Prisma, and GraphQL code that you own and control.

View details
58
Repo Health
84
Technical
60
Dependency
Built with
TypeScript 96%
Updated 3 months ago
TypeScript
99%
MIT

KeystoneJS

CMS · Developer Tools

9,982

The superpowered headless CMS for developers built with GraphQL and React

View details
92
Repo Health
81
Technical
64
Dependency
Built with
TypeScript 99%
Updated 5 days ago
JavaScript
98%
Apache 2.0

Parse Server

Databases · Developer Tools

21,405

Self-hosted Backend-as-a-Service for Node.js with REST, GraphQL, real-time Live Query, cloud code, and pluggable adapters for any infrastructure.

View details
98
Repo Health
81
Technical
77
Dependency
Built with
JavaScript 98%
Updated 6 days ago
TypeScript
82%
Other

twenty

CRM

57,585

The open-source CRM you build, ship, and version like the rest of your stack — with customizable objects, AI agents, and a TypeScript SDK.

View details
92
Repo Health
82
Technical
64
Dependency
Built with
TypeScript 82%
MDX 15%
Updated 5 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers