Files
TheGame/packages/web/pages/api/storage.ts
δυς 9e37df6207 Update MyMeta to ECMAScript Modules + Switch to DID:PKH (#1429)
* beginning ESM transition: Ceramic libraries, Next.js, & TypeScript configuration 🇭🇰

* updating Chakra, React, & Next image `import`s 👔

* upgrading `@types/react`, import extensions for Node, & b64 SVG to PNG ⛹🏿‍♀️

* fixing relative import names & upddating @types packages 📻

* removoing WYSIWYG editor, draft-js, & updating express ⛹🏿‍♀️

* updating OpenSea 🚲

* ¡@metafam/utils is building! 📰

* ¡Discord bot is building! 👘

* ¡backend is building! 🛩

* fixed everything but Ceramic DID update 🏍

* switching to DID:PKH 📦

* fixing "only one child allowed" error 🙇🏿‍♀️

* importing `React` as required by tsc's `isolatedModules` 🇲🇰

* disabling testing rather than taking the time to fix jest ⚜

* removing set `types` from `tsconfig` to fix compilation error 🥦

* printing tests disabled warning, hopefully 🙀

* setting file to be copied to the new resolver 👁️‍🗨️

* "paths-resolver" not "paths-resolve" 🦴

* switching back to relative paths rather than trying to fix `paths` 

* `yarn backend:dev` not working, testing GitHub build 🎺

* removing design system build & fixing some images ✊🏿

* fixed "expected function got string" error & trying to address undefined HTMLElement 🐡

* fixing @emotion/react tree shaking by making external 🏏

* including eslint config in Dockerfile 🌾

* fixing more images 🎯

* updating DIDs & switching back to an updated DID:3 ❇

* switching to w3s.link gateway & fixing early termination of storage endpoint 🔭

* switching back to ipfs.io gateway b/c w3s.link serves SVGs as application/xml which are CORB blocked 🥾

* fixing node config name in eslint ignore & shortening some paths 🧰

* fixing ts-node not handling project references 🥁
2022-11-14 11:26:41 -05:00

88 lines
2.4 KiB
TypeScript

import Busboy from 'busboy';
import { CONFIG } from 'config';
import * as fs from 'fs';
import { mkdtemp, rmdir, unlink } from 'fs/promises';
import type { NextApiRequest, NextApiResponse } from 'next';
import * as os from 'os';
import * as path from 'path';
import { Readable } from 'stream';
import { Web3Storage } from 'web3.storage';
export const handler: (
req: NextApiRequest,
res: NextApiResponse<Record<string, string>>,
) => Promise<void> = async (
req: NextApiRequest,
res: NextApiResponse<Record<string, string>>,
) => {
const upload = new Promise<Record<string, string>>((resolve, reject) => {
const storage = new Web3Storage({ token: CONFIG.web3StorageToken });
const busboy = Busboy({ headers: req.headers });
const files: { field: string; name: string }[] = [];
busboy.on(
'file',
async (fieldname: string, file: Readable, { filename }) => {
const field = path.basename(fieldname);
const name = path.join(
await mkdtemp(path.join(os.tmpdir(), `${field}-`)),
filename,
);
files.push({ field, name });
file.pipe(fs.createWriteStream(name));
},
);
busboy.on('finish', async () => {
try {
if (files.length === 0) {
throw new Error('No files uploaded.');
}
const tmpFiles = files.map(({ field, name }) => ({
name: `${field}/${path.basename(name)}`,
stream: () =>
fs.createReadStream(name) as unknown as ReadableStream<string>,
}));
const cid = await storage.put(tmpFiles);
await Promise.all(
files.map(async ({ name }) => {
await unlink(name);
await rmdir(path.dirname(name));
}),
);
const uploadedFiles = Object.fromEntries(
files.map(({ field, name }) => {
const filename = path.basename(name);
return [field, `${cid}/${field}/${filename}`];
}),
);
resolve(uploadedFiles);
} catch (err) {
reject((err as Error).message);
}
});
req.pipe(busboy);
});
try {
const uploaded = await upload;
res.status(201).json(uploaded);
} catch (err) {
console.error('error uploading to web3.storage', err);
res.status(500).json({ error: (err as Error).message });
}
};
export default handler;
export const config = {
api: {
bodyParser: false,
},
};