diff --git a/.gitignore b/.gitignore index 37d7e73..837f7f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules .env +.DS_Store diff --git a/docker-compose.yml b/docker-compose.yml index d25f7a1..5bdbb83 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,3 +22,14 @@ services: ports: - $SMTP_PORT:25 - $MAILDEV_PORT:80 + + minio: + image: minio/minio + ports: + - $MINIO_PORT:9000 + - $MINIO_CONSOLE_PORT:$MINIO_CONSOLE_PORT + entrypoint: bash -c 'mkdir -p /opt/minio/whip && minio server --console-address :$MINIO_CONSOLE_PORT /opt/minio' + environment: + MINIO_CONSOLE_PORT: $MINIO_CONSOLE_PORT + MINIO_ROOT_USER: $MINIO_ROOT_USER + MINIO_ROOT_PASSWORD: $MINIO_ROOT_PASSWORD diff --git a/example.env b/example.env index ea40215..1cdbe70 100644 --- a/example.env +++ b/example.env @@ -6,3 +6,7 @@ DB_PASS=wokeUpLikeThis DATABASE_URL="postgresql://whip:wokeUpLikeThis@localhost:5432/whip?schema=public" SMTP_PORT=25 MAILDEV_PORT=1080 +MINIO_PORT=9000 +MINIO_CONSOLE_PORT=9001 +MINIO_ROOT_USER=whip +MINIO_ROOT_PASSWORD=dontWasteNoTime diff --git a/packages/whip-storage/index.js b/packages/whip-storage/index.js index e69de29..6e8b559 100644 --- a/packages/whip-storage/index.js +++ b/packages/whip-storage/index.js @@ -0,0 +1,9 @@ +import { S3Client } from '@aws-sdk/client-s3' + +export default function storagePlugin (app, opts) { + app.storage = new S3Client(opts) + app.use(function storageMiddleware (req, res, next) { + req.storage = app.storage + next() + }) +} diff --git a/packages/whip-storage/package.json b/packages/whip-storage/package.json index 6560818..dbdee2b 100644 --- a/packages/whip-storage/package.json +++ b/packages/whip-storage/package.json @@ -2,6 +2,10 @@ "name": "@generates/whip-storage", "version": "0.0.0", "license": "UNLICENSED", + "type": "module", + "scripts": { + "example.app": "../../example.js ./tests/fixtures/app.js" + }, "dependencies": { "@aws-sdk/client-s3": "^3.45.0" } diff --git a/packages/whip-storage/tests/fixtures/app.js b/packages/whip-storage/tests/fixtures/app.js new file mode 100644 index 0000000..6a5a6f8 --- /dev/null +++ b/packages/whip-storage/tests/fixtures/app.js @@ -0,0 +1,38 @@ +import { promises as fs } from 'fs' +import { nanoid } from 'nanoid' +import { create } from '@generates/whip' +import { PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3' +import storage from '../../index.js' + +const Bucket = 'whip' +const fileUrl = new URL('josh-duncan-trunk-bay.jpg', import.meta.url) +const app = create() + +app.add({ + plugin: storage, + opts: { + region: 'us-east-1', + forcePathStyle: true, + endpoint: 'http://localhost:9000', + credentials: { accessKeyId: 'whip', secretAccessKey: 'dontWasteNoTime' } + } +}) + +let Key +app.get('/', async function download (req, res) { + if (Key) { + const out = await req.storage.send(new GetObjectCommand({ Bucket, Key })) + // TODO: + // req.logger.info('GetObjectCommand response', out) + res.set('Content-Type', 'image/jpeg').send(out.Body) + } else { + Key = nanoid() + const Body = await fs.readFile(fileUrl) + const command = new PutObjectCommand({ Bucket, Key, Body }) + const out = await req.storage.send(command) + req.logger.info('PutObjectCommand response', out) + res.send('File uploaded') + } +}) + +export default app diff --git a/packages/whip-storage/tests/fixtures/josh-duncan-trunk-bay.jpg b/packages/whip-storage/tests/fixtures/josh-duncan-trunk-bay.jpg new file mode 100644 index 0000000..25a5900 Binary files /dev/null and b/packages/whip-storage/tests/fixtures/josh-duncan-trunk-bay.jpg differ diff --git a/packages/whip-storage/tests/tests.js b/packages/whip-storage/tests/tests.js new file mode 100644 index 0000000..e680925 --- /dev/null +++ b/packages/whip-storage/tests/tests.js @@ -0,0 +1,5 @@ +import { test } from '@ianwalter/bff' + +test('', t => { + +}) diff --git a/packages/whip/lib/middleware/response.js b/packages/whip/lib/middleware/response.js index 37151db..9dc848a 100644 --- a/packages/whip/lib/middleware/response.js +++ b/packages/whip/lib/middleware/response.js @@ -15,6 +15,9 @@ export default function responseMiddleware (req, res, next) { if (typeof body === 'string') { res.writeHead(statusCode, req.state.headers) res.end(body) + } else if (typeof body?.pipe === 'function') { + res.writeHead(statusCode, req.state.headers) + body.pipe(res) } else { res .set('Content-Type', 'application/json')