From abaf10b31d1e9a60710da87cac5c9c869195660d Mon Sep 17 00:00:00 2001 From: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Date: Sat, 4 Jun 2022 16:37:21 +0800 Subject: [PATCH] feat(medusa-file-spaces): DigitalOcean fileservice streaming (#1585) * add file service interface initial * pr feedback * use abstract fileservice for file service plugins * update plugin loader for services * implement fileservices with abstractFileService and convert to ts * update fileservice interface * remove fileservice loading of old interface * re-add loading of old fileservice interface * re-rename digital ocean fileservice to javascript * revert s3 to js * revert minio to js * remove irrelevant method implementation * rename download stream method to reflect upload stream method * update fileservice * use isFileService in loaders * remove fields from js class * rename "generatePresignedDownloadUrl" to "getPresignedDownloadUrl" * make methods abstract in AbstractFileService * create download stream endpoint (#1583) * Feat/upload to storage (#1580) * add test generate endpoint to api * rename method to getUploadStream * cleanup generate example * upload file example * remove comment * make vars const * Feat/create presigned download url (#1582) * implement "generatePresignedDownloadUrl" * add get-download-url endpoint for testing * remove examples * update index ts * create generalized method for aws update in DO fileservice * update bucket configuration * update interface types * add typings to fileservice methods * update service loaders * update fileservice interface to extend transaction base service * create download stream endpoint (#1583) * Feat/upload to storage (#1580) * add test generate endpoint to api * rename method to getUploadStream * cleanup generate example * upload file example * remove comment * make vars const * Feat/create presigned download url (#1582) * implement "generatePresignedDownloadUrl" * add get-download-url endpoint for testing * remove examples * update index ts * create generalized method for aws update in DO fileservice * update bucket configuration * update interface types * update download method name * revert changes * add filekey and optional extension to the fileservice result * add key to the result of getUploadStream * rename key to filekey * rename key to filekey in getUploadStream result * rename key to filekey in getDownloadStream and getPresignedDownloadUrl * rename key to fileKey for getUploadedFileType Co-authored-by: olivermrbl --- .../src/services/digital-ocean.js | 90 +++++++++++++------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/packages/medusa-file-spaces/src/services/digital-ocean.js b/packages/medusa-file-spaces/src/services/digital-ocean.js index 2d26a63c35..bc73068148 100644 --- a/packages/medusa-file-spaces/src/services/digital-ocean.js +++ b/packages/medusa-file-spaces/src/services/digital-ocean.js @@ -1,8 +1,7 @@ -import fs from "fs" +import { AbstractFileService } from "@medusajs/medusa" import aws from "aws-sdk" +import fs from "fs" import { parse } from "path" -import { AbstractFileService, FileServiceUploadResult } from "@medusajs/medusa" -import { EntityManager } from "typeorm" import stream from "stream" class DigitalOceanService extends AbstractFileService { @@ -18,21 +17,12 @@ class DigitalOceanService extends AbstractFileService { } upload(file) { - aws.config.setPromisesDependency(null) - aws.config.update( - { - accessKeyId: this.accessKeyId_, - secretAccessKey: this.secretAccessKey_, - region: this.region_, - endpoint: this.endpoint_, - }, - true - ) + this.updateAwsConfig() const parsedFilename = parse(file.originalname) const fileKey = `${parsedFilename.name}-${Date.now()}${parsedFilename.ext}` const s3 = new aws.S3() - var params = { + const params = { ACL: "public-read", Bucket: this.bucket_, Body: fs.createReadStream(file.path), @@ -56,19 +46,10 @@ class DigitalOceanService extends AbstractFileService { } delete(file) { - aws.config.setPromisesDependency(null) - aws.config.update( - { - accessKeyId: this.accessKeyId_, - secretAccessKey: this.secretAccessKey_, - region: this.region_, - endpoint: this.endpoint_, - }, - true - ) + this.updateAwsConfig() const s3 = new aws.S3() - var params = { + const params = { Bucket: this.bucket_, Key: `${file}`, } @@ -85,15 +66,68 @@ class DigitalOceanService extends AbstractFileService { } async getUploadStreamDescriptor(fileData) { - throw new Error("Method not implemented.") + this.updateAwsConfig() + + const pass = new stream.PassThrough() + + const fileKey = `${fileData.name}-${Date.now()}.${fileData.ext}` + const params = { + ACL: fileData.acl ?? "private", + Bucket: this.bucket_, + Body: pass, + Key: fileKey, + } + + const s3 = new aws.S3() + return { + writeStream: pass, + promise: s3.upload(params).promise(), + url: `${this.spacesUrl_}/${fileKey}`, + fileKey, + } } async getDownloadStream(fileData) { - throw new Error("Method not implemented.") + this.updateAwsConfig() + + const s3 = new aws.S3() + + const params = { + Bucket: this.bucket_, + Key: `${fileData.fileKey}`, + } + + return s3.getObject(params).createReadStream() } async getPresignedDownloadUrl(fileData) { - throw new Error("Method not implemented.") + this.updateAwsConfig({ + signatureVersion: "v4", + }) + + const s3 = new aws.S3() + + const params = { + Bucket: this.bucket_, + Key: `${fileData.fileKey}`, + Expires: 60, // 60 seconds + } + + return await s3.getSignedUrlPromise("getObject", params) + } + + updateAwsConfig(additionalConfiguration = {}) { + aws.config.setPromisesDependency(null) + aws.config.update( + { + accessKeyId: this.accessKeyId_, + secretAccessKey: this.secretAccessKey_, + region: this.region_, + endpoint: this.endpoint_, + ...additionalConfiguration, + }, + true + ) } }