@hyperse/apollo-upload-client
v1.0.1
Published
A terminating Apollo Link for Apollo Client that handles GraphQL file uploads using multipart requests.
Readme
@hyperse/apollo-upload-client
A terminating Apollo Link for Apollo Client that handles GraphQL file uploads using multipart requests. When GraphQL variables contain files (FileList, File, or Blob instances), it sends a multipart/form-data request. Otherwise, it falls back to standard GraphQL POST/GET requests based on the configuration and operation type.
Features
- 🚀 Seamless Integration: Drop-in replacement for Apollo Client's HttpLink
- 📁 File Upload Support: Handles File, Blob, and FileList instances automatically
- 🔄 Smart Request Handling: Automatically switches between multipart and regular GraphQL requests
- 🎯 TypeScript Support: Full TypeScript support with comprehensive type definitions
- 🌐 Universal Compatibility: Works in browsers, React Native, and Node.js environments
- ⚡ Performance Optimized: Efficient file extraction and request handling
Installation
npm install @hyperse/apollo-upload-client
# or
yarn add @hyperse/apollo-upload-client
# or
pnpm add @hyperse/apollo-upload-clientQuick Start
Basic Setup
import { ApolloClient, InMemoryCache, ApolloLink } from '@apollo/client';
import { UploadHttpLink } from '@hyperse/apollo-upload-client';
const client = new ApolloClient({
cache: new InMemoryCache(),
link: ApolloLink.from([
new UploadHttpLink({
uri: '/graphql',
}),
]),
});With Multiple Links
import { ApolloClient, InMemoryCache, ApolloLink } from '@apollo/client';
import { UploadHttpLink } from '@hyperse/apollo-upload-client';
const client = new ApolloClient({
cache: new InMemoryCache(),
link: ApolloLink.from([
new ClientAwarenessLink(),
// Add other links here (e.g., error handling, authentication)
new UploadHttpLink({
uri: '/graphql',
}),
]),
});Usage
File Upload Mutation
import { gql, useMutation } from '@apollo/client';
const UPLOAD_FILE = gql`
mutation UploadFile($file: Upload!, $description: String) {
uploadFile(file: $file, description: $description) {
id
filename
url
}
}
`;
function FileUploadComponent() {
const [uploadFile, { loading, error, data }] = useMutation(UPLOAD_FILE);
const handleFileChange = (event) => {
const file = event.target.files[0];
if (file) {
uploadFile({
variables: {
file: file,
description: 'My uploaded file'
}
});
}
};
return (
<div>
<input type="file" onChange={handleFileChange} />
{loading && <p>Uploading...</p>}
{error && <p>Error: {error.message}</p>}
{data && <p>File uploaded: {data.uploadFile.filename}</p>}
</div>
);
}Multiple File Upload
const UPLOAD_MULTIPLE_FILES = gql`
mutation UploadMultipleFiles($files: [Upload!]!) {
uploadMultipleFiles(files: $files) {
id
filename
url
}
}
`;
function MultipleFileUploadComponent() {
const [uploadFiles, { loading }] = useMutation(UPLOAD_MULTIPLE_FILES);
const handleFilesChange = (event) => {
const files = Array.from(event.target.files);
if (files.length > 0) {
uploadFiles({
variables: {
files: files
}
});
}
};
return (
<input type="file" multiple onChange={handleFilesChange} />
);
}API Reference
UploadHttpLink
The main class that handles file uploads in GraphQL requests.
Constructor Options
interface UploadHttpLinkOptions<T extends ExtractableFile> {
// HTTP Link options
uri?: string;
fetch?: WindowOrWorkerGlobalScope['fetch'];
headers?: Record<string, string>;
credentials?: RequestCredentials;
// Upload-specific options
FormData?: typeof FormData;
isExtractableFile?: ExtractableFileMatcher<T>;
formDataAppendFile?: FormDataFileAppender<T>;
}Options
uri(string, default:/graphql): The GraphQL endpoint URIfetch(function): Custom fetch implementationheaders(object): Additional HTTP headerscredentials(string): Request credentials policyFormData(class): Custom FormData implementationisExtractableFile(function): Custom file detection logicformDataAppendFile(function): Custom file appending logic
ExtractableFile
type ExtractableFile = File | Blob;Supported file types that can be automatically detected and uploaded.
extractFiles
Utility function to extract files from objects and create upload-ready data.
import {
extractFiles,
isExtractableFile,
} from '@hyperse/apollo-upload-client/extractFiles';
const { clone, files } = extractFiles(
{ file: myFile, data: { nested: { file: anotherFile } } },
isExtractableFile
);How It Works
- Request Analysis: The link analyzes GraphQL operation variables for file objects
- Smart Routing:
- If files are detected: Creates a multipart/form-data request
- If no files: Falls back to regular GraphQL HTTP request
- File Extraction: Extracts files and their object paths from variables
- Request Construction: Builds the multipart request according to the GraphQL multipart request specification
- Response Handling: Processes the response and forwards it to Apollo Client
License
MIT License - see LICENSE file for details.
Support
Related Projects
- Apollo Client - GraphQL client for React
- GraphQL Multipart Request Spec - File upload specification
Made with ❤️ by the Hyperse team
