Feat: Client admin uploads (#952)

* convert uploads to ts

* add custom headers to request

* uploads resource

* uploads routes updates

* index export

* add oas

* remove delete uploads endpoint

* add new package for form-data

* remove exports for delete upload endpoint

* remove dev package from medusa-js

* automatic package upgrade of medusa
This commit is contained in:
Philip Korsholm
2022-01-04 16:18:17 +01:00
committed by GitHub
parent ae839513b8
commit 5754534beb
10 changed files with 117 additions and 39 deletions

View File

@@ -17,6 +17,7 @@
"dependencies": {
"@medusajs/medusa": "^1.1.60",
"axios": "^0.24.0",
"form-data": "^4.0.0",
"retry-axios": "^2.6.0"
},
"repository": {

View File

@@ -102,12 +102,14 @@ class Client {
* @param {object} userHeaders user supplied headers
* @param {Types.RequestMethod} method request method
* @param {string} path request path
* @param {object} customHeaders user supplied headers
* @return {object}
*/
setHeaders(
userHeaders: RequestOptions,
method: RequestMethod,
path: string
path: string,
customHeaders: object = {}
): AxiosRequestHeaders {
let defaultHeaders: object = {
Accept: "application/json",
@@ -126,7 +128,12 @@ class Client {
defaultHeaders["Idempotency-Key"] = uuidv4()
}
return Object.assign({}, defaultHeaders, this.normalizeHeaders(userHeaders))
return Object.assign(
{},
defaultHeaders,
this.normalizeHeaders(userHeaders),
customHeaders
)
}
/**
@@ -170,13 +177,15 @@ class Client {
* @param {string} path request path
* @param {object} payload request payload
* @param {RequestOptions} options axios configuration
* @param {object} customHeaders custom request headers
* @return {object}
*/
async request(
method: RequestMethod,
path: string,
payload: object = {},
options: RequestOptions = {}
options: RequestOptions = {},
customHeaders: object = {}
): Promise<any> {
const reqOpts = {
method,
@@ -184,7 +193,7 @@ class Client {
url: path,
data: payload,
json: true,
headers: this.setHeaders(options, method, path),
headers: this.setHeaders(options, method, path, customHeaders),
}
// e.g. data = { cart: { ... } }, response = { status, headers, ... }

View File

@@ -19,6 +19,7 @@ import AdminStoresResource from "./store"
import AdminShippingOptionsResource from "./shipping-options"
import AdminRegionsResource from "./regions"
import AdminNotificationsResource from "./notifications"
import AdminUploadsResource from "./uploads"
class Admin extends BaseResource {
public auth = new AdminAuthResource(this.client)
@@ -41,6 +42,7 @@ class Admin extends BaseResource {
public shippingOptions = new AdminShippingOptionsResource(this.client)
public regions = new AdminRegionsResource(this.client)
public notifications = new AdminNotificationsResource(this.client)
public uploads = new AdminUploadsResource(this.client)
}
export default Admin

View File

@@ -0,0 +1,21 @@
import { AdminUploadRes, IAdminPostUploadsFile } from "@medusajs/medusa"
import { ResponsePromise } from "../../typings"
import BaseResource from "../base"
import FormData from "form-data"
class AdminUploadsResource extends BaseResource {
private headers = {
"Content-Type": "multipart/form-data",
}
create(file: IAdminPostUploadsFile): ResponsePromise<AdminUploadRes> {
const path = `/admin/uploads`
const payload = new FormData()
payload.append("files", file)
return this.client.request("POST", path, payload, {}, this.headers)
}
}
export default AdminUploadsResource

View File

@@ -33,7 +33,7 @@ export * from "./routes/admin/orders"
export * from "./routes/admin/variants"
export * from "./routes/admin/return-reasons"
export * from "./routes/admin/swaps"
export * from "./routes/admin/store"
export * from "./routes/admin/uploads"
export * from "./routes/admin/returns"
export * from "./routes/admin/shipping-options"
export * from "./routes/admin/regions"

View File

@@ -1,21 +0,0 @@
import fs from "fs"
export default async (req, res) => {
try {
const fileService = req.scope.resolve("fileService")
const result = await Promise.all(
req.files.map(async (f) => {
return fileService.upload(f).then((result) => {
fs.unlinkSync(f.path)
return result
})
})
)
res.status(200).json({ uploads: result })
} catch (err) {
console.log(err)
throw err
}
}

View File

@@ -0,0 +1,43 @@
import fs from "fs"
/**
* @oas [post] /
* operationId: "PostUploads"
* summary: "Uploads an array of files"
* description: "Uploads an array of files to the specific fileservice that is installed in medusa."
* x-authenticated: true
* tags:
* - Uploads
* responses:
* 200:
* description: OK
* content:
* application/json:
* schema:
* properties:
* uploads
*/
export default async (req, res) => {
try {
const fileService = req.scope.resolve("fileService")
const result = await Promise.all(
req.files.map(async (f) => {
return fileService.upload(f).then((result) => {
fs.unlinkSync(f.path)
return result
})
})
)
res.status(200).json({ uploads: result })
} catch (err) {
console.log(err)
throw err
}
}
export class IAdminPostUploadsFile {
originalName: string
path: string
}

View File

@@ -1,12 +0,0 @@
export default async (req, res) => {
try {
const fileService = req.scope.resolve("fileService")
await fileService.delete(req.body.file)
res.status(200).send("Deleted image")
} catch (err) {
console.log(err)
throw err
}
}

View File

@@ -0,0 +1,24 @@
/**
* [delete] /uploads
* operationId: "AdminDeleteUpload"
* summary: "Removes an uploaded file"
* description: "Removes an uploaded file using the installed fileservice"
* x-authenticated: true
* tags:
* - Uploads
* responses:
* 200:
* description: OK
*/
export default async (req, res) => {
try {
const fileService = req.scope.resolve("fileService")
await fileService.delete(req.body.file)
res.status(200).send({ id: "", object: "file", deleted: true })
} catch (err) {
console.log(err)
throw err
}
}

View File

@@ -1,5 +1,6 @@
import { Router } from "express"
import multer from "multer"
import { DeleteResponse } from "../../../../types/common"
import middlewares from "../../../middlewares"
@@ -15,7 +16,17 @@ export default (app) => {
middlewares.wrap(require("./create-upload").default)
)
route.post("/delete", middlewares.wrap(require("./delete-upload").default))
// removed on purpose
// route.post("/delete", middlewares.wrap(require("./delete-upload").default))
return app
}
export type AdminUploadRes = {
uploads: any[]
}
export type AdminDeleteUploadRes = DeleteResponse
export * from "./create-upload"
// export * from "./delete-upload"