@digibuffer/file-manager
v1.0.3
Published
File management library for fetching, deleting, and managing files in R2/S3 with database operations and pagination support.
Maintainers
Readme
@digibuffer/file-manager
File management library for fetching, deleting, and managing files in R2/S3 with database operations and pagination support.
Features
- 📂 List files with pagination from R2/S3 or database
- 🗑️ Delete files with database sync callbacks
- 🔗 Generate download URLs with presigned URLs
- 📊 Pagination support with cursor-based navigation
- 🔄 Database integration with flexible callbacks
- 🎯 Type-safe with full TypeScript support
- ⚛️ React hooks for easy client-side integration
- 🚀 Next.js adapter for serverless functions
Installation
npm install @digibuffer/file-manager @digibuffer/upload-lib-server
# or
pnpm add @digibuffer/file-manager @digibuffer/upload-lib-serverQuick Start
Server Setup
import { cloudflareClient } from '@digibuffer/upload-lib-server/clients';
import { FileManager, createFileManagerRouter } from '@digibuffer/file-manager/server';
import { toRouteHandler } from '@digibuffer/file-manager/adapters/next';
// Create S3 client
const client = cloudflareClient({
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
accessKeyId: process.env.CLOUDFLARE_ACCESS_KEY_ID!,
secretAccessKey: process.env.CLOUDFLARE_SECRET_ACCESS_KEY!,
});
// Create file manager with database callbacks
const fileManager = new FileManager({
client,
bucketName: 'my-bucket',
database: {
onAfterDelete: async ({ key, success }) => {
if (success) {
await db.file.delete({ where: { key } });
}
},
getFiles: async ({ limit, cursor }) => {
const files = await db.file.findMany({
take: limit,
skip: cursor ? 1 : 0,
cursor: cursor ? { id: cursor } : undefined,
});
return {
items: files,
hasMore: files.length === limit,
nextCursor: files[files.length - 1]?.id,
};
},
},
});
// Create router
const router = createFileManagerRouter();
router.route('default', {
fileManager,
onAuthorize: async (request) => {
// Add your auth logic here
return true;
},
});
// Export Next.js handler
export const POST = toRouteHandler(router);Client Setup
import { FileManagerProvider } from '@digibuffer/file-manager/client';
function App() {
return (
<FileManagerProvider
config={{
endpoint: '/api/files',
headers: {
Authorization: `Bearer ${token}`,
},
}}
>
<FileList />
</FileManagerProvider>
);
}Using Hooks
import { useListFiles, useDeleteFile, useDownloadUrl } from '@digibuffer/file-manager/client';
function FileList() {
const { data, list, loadMore, hasMore, isLoading } = useListFiles();
const { deleteFile } = useDeleteFile();
const { download } = useDownloadUrl();
useEffect(() => {
list({ limit: 20 });
}, []);
return (
<div>
{data?.items.map((file) => (
<div key={file.key}>
<span>{file.key}</span>
<button onClick={() => download(file.key)}>Download</button>
<button onClick={() => deleteFile(file.key)}>Delete</button>
</div>
))}
{hasMore && <button onClick={() => loadMore()}>Load More</button>}
</div>
);
}API Reference
FileManager
Main server-side class for managing files.
const fileManager = new FileManager({
client: Client, // S3 client from upload-lib-server
bucketName: string,
database?: DatabaseCallbacks,
defaultLimit?: number, // Default: 50
maxLimit?: number, // Default: 1000
});Methods
list(options)- List files with paginationdelete(key)- Delete a single filedeleteBatch(keys)- Delete multiple filesgetDownloadUrl(key, options)- Generate presigned download URLexists(key)- Check if file existsgetMetadata(key)- Get file metadata
Database Callbacks
type DatabaseCallbacks = {
onAfterDelete?: (params) => Promise<void>;
onBeforeDelete?: (params) => Promise<boolean>;
onAfterBatchDelete?: (params) => Promise<void>;
getFileByKey?: (key) => Promise<File | null>;
getFiles?: (options) => Promise<PaginatedResponse<File>>;
updateFile?: (key, data) => Promise<File>;
};Client Hooks
useListFiles()
const {
data, // PaginatedResponse<File> | null
list, // (options) => Promise<PaginatedResponse>
loadMore, // () => Promise<PaginatedResponse>
hasMore, // boolean
isLoading,
isError,
error,
reset,
} = useListFiles();useDeleteFile()
const {
deleteFile, // (key) => Promise<DeleteResult>
deleteBatch, // (keys) => Promise<BatchDeleteResult>
isLoading,
isError,
error,
reset,
} = useDeleteFile();useDownloadUrl()
const {
getUrl, // (key, options) => Promise<string>
download, // (key, options) => Promise<string>
url,
isLoading,
isError,
error,
reset,
} = useDownloadUrl();License
MIT
