uploaders: allow deleting files by CID

This commit is contained in:
Alex Gleason 2023-09-08 15:01:30 -05:00
parent c40f10539d
commit 014b9f6d29
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
4 changed files with 66 additions and 28 deletions

View File

@ -20,7 +20,7 @@ const mediaController: AppController = async (c) => {
try {
const { file } = result.data;
const { cid } = await s3Uploader(file);
const { cid } = await s3Uploader.upload(file);
return c.json({
id: cid,

View File

@ -3,28 +3,48 @@ import { z } from '@/deps.ts';
import type { Uploader } from './types.ts';
const ipfsAddResultSchema = z.object({
/** Response schema for POST `/api/v0/add`. */
const ipfsAddResponseSchema = z.object({
Name: z.string(),
Hash: z.string(),
Size: z.string(),
});
const ipfsUploader: Uploader = async (file) => {
const url = new URL('/api/v0/add', Conf.ipfs.apiUrl);
/**
* IPFS uploader. It expects an IPFS node up and running.
* It will try to connect to `http://localhost:5001` by default,
* and upload the file using the REST API.
*/
const ipfsUploader: Uploader = {
async upload(file) {
const url = new URL('/api/v0/add', Conf.ipfs.apiUrl);
const formData = new FormData();
formData.append('file', file);
const formData = new FormData();
formData.append('file', file);
const response = await fetch(url, {
method: 'POST',
body: formData,
});
const response = await fetch(url, {
method: 'POST',
body: formData,
});
const { Hash } = ipfsAddResultSchema.parse(await response.json());
const { Hash } = ipfsAddResponseSchema.parse(await response.json());
return {
cid: Hash,
};
return {
cid: Hash,
};
},
async delete(cid) {
const url = new URL('/api/v0/pin/rm', Conf.ipfs.apiUrl);
const query = new URLSearchParams();
query.set('arg', cid);
url.search = query.toString();
await fetch(url, {
method: 'POST',
});
},
};
export { ipfsUploader };

View File

@ -5,19 +5,29 @@ import type { Uploader } from './types.ts';
const s3 = new S3Client({ ...Conf.s3 });
const s3Uploader: Uploader = async (file) => {
const cid = await IpfsHash.of(file.stream()) as string;
/**
* S3-compatible uploader for AWS, Wasabi, DigitalOcean Spaces, and more.
* Files are named by their IPFS CID and exposed at `/ipfs/<cid>`, letting it
* take advantage of IPFS features while not really using IPFS.
*/
const s3Uploader: Uploader = {
async upload(file) {
const cid = await IpfsHash.of(file.stream()) as string;
await s3.putObject(`ipfs/${cid}`, file.stream(), {
metadata: {
'Content-Type': file.type,
'x-amz-acl': 'public-read',
},
});
await s3.putObject(`ipfs/${cid}`, file.stream(), {
metadata: {
'Content-Type': file.type,
'x-amz-acl': 'public-read',
},
});
return {
cid,
};
return {
cid,
};
},
async delete(cid) {
await s3.deleteObject(`ipfs/${cid}`);
},
};
export { s3Uploader };

View File

@ -1,7 +1,15 @@
/** Modular uploader interface, to support uploading to different backends. */
interface Uploader {
/** Upload the file to the backend. */
upload(file: File): Promise<UploadResult>;
/** Delete the file from the backend. */
delete(cid: string): Promise<void>;
}
/** Return value from the uploader after uploading a file. */
interface UploadResult {
/** IPFS CID for the file. */
cid: string;
}
type Uploader = (file: File) => Promise<UploadResult>;
export type { Uploader, UploadResult };
export type { Uploader };