JavaScript/TypeScript client for the Plugable File Management API.
npm install @plugable-io/jsWhen creating a bucket, you can choose a usage pattern that dictates how files are accessed and isolated:
- Public: Files are publicly readable by anyone (no auth token required). However, only authenticated users (your end-users) can upload files.
- Organization: Files are isolated by
org_id. Users can only access files belonging to their organization (as defined in their auth token). - Personal: Files are isolated by
owner_id. Users can only access their own files.
We work with your auth provider, to simplify the process of integration. Currently we support:
- Clerk
- Supabase
- Firebase Auth
Please setup provider on admin first.
If you would like to see any other providers supported, please let us know.
Initialize the client with your Bucket ID and a function to retrieve the user's authentication token.
import { BucketClient } from '@plugable-io/js';
const client = new BucketClient({
bucketId: 'YOUR_BUCKET_ID',
// Function that returns a Promise resolving to the auth token (e.g., from Clerk, Supabase, etc.). It should return a valid JWT token.
getToken: async () => {
// Example: return await auth.getToken();
return 'user-jwt-token';
}
});You can attach custom metadata to your files. This is useful for storing external IDs, tags, or other application-specific data. You can later search for files based on this metadata.
Limitations:
- Size: Maximum 5KB of JSON data.
- Structure: Must be a flat object (no nested objects).
- Arrays: Arrays are supported, but they cannot contain objects.
You can upload a file using the upload method. You can also pass metadata that you can use for search later, such as external IDs or tags.
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
try {
const uploadedFile = await client.upload(file, {
metadata: {
type: 'invoice',
order_id: 'ord_12345',
purchased: ['product_1', 'product_2']
},
onProgress: (percent) => {
console.log(`Upload progress: ${percent}%`);
},
onCompleted: (file) => {
console.log('Upload completed:', file);
},
onFailed: (error) => {
console.error('Upload failed:', error);
}
});
console.log('File uploaded:', uploadedFile);
} catch (error) {
console.error('Upload failed:', error);
}The results depend on your bucket's usage pattern:
- Public: Returns all files in the bucket.
- Organization: Returns files matching the user's
org_id. - Personal: Returns files matching the user's
owner_id.
// Example: Find all invoices for a specific order
const response = await client.list({
metadata: {
type: 'invoice',
purchased: ['product_1']
}
});
console.log('Files:', response.files);You can find a single file using find. This is a convenience method that searches for files and returns the first match. It's useful for finding files by metadata or other criteria.
const file = await client.find({
metadata: {
external_id: 'user_123_avatar'
}
});
if (file) {
console.log('Found file:', file);
} else {
console.log('File not found');
}const file = await client.get('file_id');
console.log('File details:', file);const updatedFile = await client.update('file_id', {
metadata: {
new_key: 'new_value'
}
});await client.delete('file_id');The client automatically leverages browser HTTP caching based on file checksums:
- File list responses are cached for 5 minutes in the browser
- Cache is validated using ETags based on file checksums
- If files haven't changed, the browser returns cached data instantly
- No manual cache management needed - it just works!
MIT