From c4af44d582d5dca1bda9d590167896afe14247d8 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 7 Sep 2023 16:59:05 -0500 Subject: [PATCH] Move s3 to separate uploader module, add ipfs uploader --- src/controllers/api/media.ts | 25 ++++++++----------------- src/uploaders/ipfs.ts | 27 +++++++++++++++++++++++++++ src/uploaders/s3.ts | 23 +++++++++++++++++++++++ src/uploaders/types.ts | 7 +++++++ 4 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 src/uploaders/ipfs.ts create mode 100644 src/uploaders/s3.ts create mode 100644 src/uploaders/types.ts diff --git a/src/controllers/api/media.ts b/src/controllers/api/media.ts index db8299a..3df4f98 100644 --- a/src/controllers/api/media.ts +++ b/src/controllers/api/media.ts @@ -1,10 +1,8 @@ import { AppController } from '@/app.ts'; -import { Conf } from '@/config.ts'; -import { IpfsHash, S3Client, z } from '@/deps.ts'; +import { z } from '@/deps.ts'; import { fileSchema } from '@/schema.ts'; import { parseBody } from '@/utils/web.ts'; - -const s3 = new S3Client({ ...Conf.s3 }); +import { s3Uploader } from '@/uploaders/s3.ts'; const mediaBodySchema = z.object({ file: fileSchema.refine((file) => !!file.type), @@ -20,25 +18,18 @@ const mediaController: AppController = async (c) => { return c.json({ error: 'Bad request.', schema: result.error }, 422); } - const { file } = result.data; - const cid = await IpfsHash.of(file.stream()) as string; - try { - await s3.putObject(`ipfs/${cid}`, file.stream(), { - metadata: { - 'Content-Type': file.type, - 'x-amz-acl': 'public-read', - }, + const { file } = result.data; + const { cid } = await s3Uploader(file); + + return c.json({ + id: cid, + type: file.type, }); } catch (e) { console.error(e); return c.json({ error: 'Failed to upload file.' }, 500); } - - return c.json({ - id: cid, - type: file.type, - }); }; export { mediaController }; diff --git a/src/uploaders/ipfs.ts b/src/uploaders/ipfs.ts new file mode 100644 index 0000000..c391df9 --- /dev/null +++ b/src/uploaders/ipfs.ts @@ -0,0 +1,27 @@ +import { z } from '@/deps.ts'; + +import type { Uploader } from './types.ts'; + +const ipfsAddResultSchema = z.object({ + Name: z.string(), + Hash: z.string(), + Size: z.string(), +}); + +const ipfsUploader: Uploader = async (file) => { + const formData = new FormData(); + formData.append('file', file); + + const response = await fetch('http://localhost:5001/api/v0/add', { + method: 'POST', + body: formData, + }); + + const { Hash } = ipfsAddResultSchema.parse(await response.json()); + + return { + cid: Hash, + }; +}; + +export { ipfsUploader }; diff --git a/src/uploaders/s3.ts b/src/uploaders/s3.ts new file mode 100644 index 0000000..b96712e --- /dev/null +++ b/src/uploaders/s3.ts @@ -0,0 +1,23 @@ +import { Conf } from '@/config.ts'; +import { IpfsHash, S3Client } from '@/deps.ts'; + +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; + + await s3.putObject(`ipfs/${cid}`, file.stream(), { + metadata: { + 'Content-Type': file.type, + 'x-amz-acl': 'public-read', + }, + }); + + return { + cid, + }; +}; + +export { s3Uploader }; diff --git a/src/uploaders/types.ts b/src/uploaders/types.ts new file mode 100644 index 0000000..a60968f --- /dev/null +++ b/src/uploaders/types.ts @@ -0,0 +1,7 @@ +interface UploadResult { + cid: string; +} + +type Uploader = (file: File) => Promise; + +export type { Uploader, UploadResult };