feat: implement direct upload (#12328)

* feat: implement direct upload

* feat: add direct-upload endpoint

* refactor: implement feedback

* refactor: have a dedicated endpoint for direct uploads

* refactor: convert responses to snakecase

* refactor: rename method to createImport

* test: add tests for the presigned-urls endpoint
This commit is contained in:
Harminder Virk
2025-05-04 12:58:10 +02:00
committed by GitHub
parent ed55d17a36
commit 84f58f9058
22 changed files with 537 additions and 129 deletions
+177 -101
View File
@@ -17,16 +17,16 @@ export class Product {
/**
* This method creates a product import. The products are only imported after
* the import is confirmed using the {@link confirmImport} method.
*
* This method sends a request to the
*
* This method sends a request to the
* [Create Product Import](https://docs.medusajs.com/api/admin#products_postproductsimport)
* API route.
*
*
* @param body - The import's details.
* @param query - Query parameters to pass to the request.
* @param headers - Headers to pass in the request.
* @returns The import's details.
*
*
* @example
* sdk.admin.product.import({
* file // uploaded File instance
@@ -58,17 +58,93 @@ export class Product {
)
}
/**
* This method creates a product import. The products are only imported after
* the import is confirmed using the {@link confirmImport} method.
*
* This method sends a request to the
* [Create Product Import](https://docs.medusajs.com/api/admin#products_postproductsimport)
* API route.
*
* @param body - The import's details.
* @param query - Query parameters to pass to the request.
* @param headers - Headers to pass in the request.
* @returns The import's details.
*
* @example
* sdk.admin.product.createImport({
* file // uploaded File instance
* })
* .then(({ transaction_id }) => {
* console.log(transaction_id)
* })
*/
async createImport(
body: HttpTypes.AdminImportProductRequest,
query?: {},
headers?: ClientHeaders
) {
/**
* Get signed URL for file uploads
*/
const response =
await this.client.fetch<HttpTypes.AdminUploadPreSignedUrlResponse>(
"admin/uploads/presigned-urls",
{
method: "POST",
headers: headers,
body: {
originalname: body.file.name,
mime_type: body.file.type,
size: body.file.size,
} satisfies HttpTypes.AdminUploadPreSignedUrlRequest,
query,
}
)
/**
* Upload file using the signed URL. We cannot send cookies or any other
* special headers in this request, since external services like S3 will
* give a CORS error.
*/
await fetch(response.url, {
method: "PUT",
body: body.file,
})
/**
* Perform products import using the uploaded file name
*/
return await this.client.fetch<HttpTypes.AdminImportProductsResponse>(
"/admin/products/imports",
{
method: "POST",
headers: {
...headers,
},
body: {
file_key: response.filename,
originalname: response.originalname,
extension: response.extension,
size: response.size,
mime_type: response.mime_type,
} satisfies HttpTypes.AdminImportProductsRequest,
query,
}
)
}
/**
* This method confirms a product import created using the method {@link import}.
* It sends a request to the
* It sends a request to the
* [Confirm Product Import](https://docs.medusajs.com/api/admin#products_postproductsimporttransaction_idconfirm)
* API route.
*
*
* @param transactionId - The ID of the transaction of the created product import. This is returned
* by the API route used to create the product import.
* @param query - Query parameters to pass in the request.
* @param headers - Headers to pass in the request.
*
*
* @example
* sdk.admin.product.confirmImport("transaction_123")
* .then(() => {
@@ -93,23 +169,23 @@ export class Product {
/**
* This method starts a product export process to retrieve a CSV of exported products.
*
* You'll receive in the response the transaction ID of the workflow generating the CSV file.
* To check the status of the execution, send a `GET` request to
* `/admin/workflows-executions/export-products/:transaction-id`.
*
* Once the execution finishes successfully, a notification is created for the export.
* You can retrieve the notifications using the `/admin/notification` API route to
*
* You'll receive in the response the transaction ID of the workflow generating the CSV file.
* To check the status of the execution, send a `GET` request to
* `/admin/workflows-executions/export-products/:transaction-id`.
*
* Once the execution finishes successfully, a notification is created for the export.
* You can retrieve the notifications using the `/admin/notification` API route to
* retrieve the file's download URL.
*
*
* This method sends a request to the [Export Product](https://docs.medusajs.com/api/admin#products_postproductsexport)
* API route.
*
*
* @param body - The export's details.
* @param query - Filters to specify which products to export.
* @param headers - Headers to pass in the request.
* @param headers - Headers to pass in the request.
* @returns The export's details.
*
*
* @example
* sdk.admin.product.export({})
* .then(({ transaction_id }) => {
@@ -133,15 +209,15 @@ export class Product {
}
/**
* This method manages products to create, update, or delete them. It sends a request to the
* This method manages products to create, update, or delete them. It sends a request to the
* [Manage Products](https://docs.medusajs.com/api/admin#products_postproductsbatch)
* API route.
*
*
* @param body - The products to create, update, or delete.
* @param query - Configure the fields to retrieve in the products.
* @param headers - Headers to pass in the request
* @returns The batch operations details.
*
*
* @example
* sdk.admin.product.batch({
* create: [
@@ -189,15 +265,15 @@ export class Product {
}
/**
* This method creates a product. It sends a request to the
* This method creates a product. It sends a request to the
* [Create Product](https://docs.medusajs.com/api/admin#products_postproducts)
* API route.
*
*
* @param body - The product's details.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* sdk.admin.product.create({
* title: "Shirt",
@@ -240,13 +316,13 @@ export class Product {
* This method updates a product. It sends a request to the
* [Update Product](https://docs.medusajs.com/api/admin#products_postproductsid)
* API route.
*
*
* @param id - The product's ID.
* @param body - The data to update in the product.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* sdk.admin.product.update("prod_123", {
* title: "Shirt",
@@ -273,27 +349,27 @@ export class Product {
}
/**
* This method retrieves a paginated list of products. It sends a request to the
* This method retrieves a paginated list of products. It sends a request to the
* [List Products](https://docs.medusajs.com/api/admin#products_getproducts) API route.
*
*
* @param queryParams - Filters and pagination configurations.
* @param headers - Headers to pass in the request.
* @returns The paginated list of products.
*
*
* @example
* To retrieve the list of products:
*
*
* ```ts
* sdk.admin.product.list()
* .then(({ products, count, limit, offset }) => {
* console.log(products)
* })
* ```
*
*
* To configure the pagination, pass the `limit` and `offset` query parameters.
*
*
* For example, to retrieve only 10 items and skip 10 items:
*
*
* ```ts
* sdk.admin.product.list({
* limit: 10,
@@ -303,10 +379,10 @@ export class Product {
* console.log(products)
* })
* ```
*
*
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
* in each products:
*
*
* ```ts
* sdk.admin.product.list({
* fields: "id,*variants"
@@ -315,7 +391,7 @@ export class Product {
* console.log(products)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async list(
@@ -332,27 +408,27 @@ export class Product {
}
/**
* This method retrieves a product by its ID. It sends a request to the
* This method retrieves a product by its ID. It sends a request to the
* [Get Product](https://docs.medusajs.com/api/admin#products_getproductsid)
* API route.
*
*
* @param id - The product's ID.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* To retrieve a product by its ID:
*
*
* ```ts
* sdk.admin.product.retrieve("prod_123")
* .then(({ product }) => {
* console.log(product)
* })
* ```
*
*
* To specify the fields and relations to retrieve:
*
*
* ```ts
* sdk.admin.product.retrieve("prod_123", {
* fields: "id,*variants"
@@ -361,7 +437,7 @@ export class Product {
* console.log(product)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async retrieve(id: string, query?: SelectParams, headers?: ClientHeaders) {
@@ -378,11 +454,11 @@ export class Product {
* This method deletes a product. It sends a request to the
* [Delete Product](https://docs.medusajs.com/api/admin#products_deleteproductsid)
* API route.
*
*
* @param id - The product's ID.
* @param headers - Headers to pass in the request
* @returns The deletion's details.
*
*
* @example
* sdk.admin.product.delete("prod_123")
* .then(({ deleted }) => {
@@ -403,13 +479,13 @@ export class Product {
* This method manages the variants of a product. It sends a request to the
* [Manage Variants](https://docs.medusajs.com/api/admin#products_postproductsidvariantsbatch)
* API route.
*
*
* @param productId - The product's ID.
* @param body - The variants to create, update, or delete.
* @param query - Configure the fields to retrieve in the product variants.
* @param headers - Headers to pass in the request
* @returns The product variants' details.
*
*
* @example
* sdk.admin.product.batchVariants("prod_123", {
* create: [
@@ -454,13 +530,13 @@ export class Product {
* This method creates a variant for a product. It sends a request to the
* [Create Variant](https://docs.medusajs.com/api/admin#products_postproductsidvariants)
* API route.
*
*
* @param productId - The product's ID.
* @param body - The variant's details.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* sdk.admin.product.createVariant("prod_123", {
* title: "Blue Shirt",
@@ -499,17 +575,17 @@ export class Product {
* This method updates a variant of a product. It sends a request to the
* [Update Variant](https://docs.medusajs.com/api/admin#products_postproductsidvariantsvariant_id)
* API route.
*
*
* @param productId - The product's ID.
* @param id - The variant's ID.
* @param body - The data to update in the variant.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* sdk.admin.product.updateVariant(
* "prod_123",
* "prod_123",
* "variant_123",
* {
* title: "Blue Shirt",
@@ -538,28 +614,28 @@ export class Product {
}
/**
* This method retrieves a paginated list of products. It sends a request to the
* This method retrieves a paginated list of products. It sends a request to the
* [List Products](https://docs.medusajs.com/api/admin#products_getproductsidvariants) API route.
*
*
* @param productId - The ID of the product to retrieve its variants.
* @param query - Filters and pagination configurations.
* @param headers - Headers to pass in the request.
* @returns The paginated list of product variants.
*
*
* @example
* To retrieve the list of product variants:
*
*
* ```ts
* sdk.admin.product.listVariants("prod_123")
* .then(({ variants, count, limit, offset }) => {
* console.log(variants)
* })
* ```
*
*
* To configure the pagination, pass the `limit` and `offset` query parameters.
*
*
* For example, to retrieve only 10 items and skip 10 items:
*
*
* ```ts
* sdk.admin.product.listVariants("prod_123", {
* limit: 10,
@@ -569,10 +645,10 @@ export class Product {
* console.log(variants)
* })
* ```
*
*
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
* in each product variant:
*
*
* ```ts
* sdk.admin.product.listVariants("prod_123", {
* fields: "id,*product"
@@ -581,7 +657,7 @@ export class Product {
* console.log(variants)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async listVariants(
@@ -602,16 +678,16 @@ export class Product {
* This method retrieves a product's variant. It sends a request to the
* [Retrieve Variant](https://docs.medusajs.com/api/admin#products_getproductsidvariantsvariant_id)
* API route.
*
*
* @param productId - The product's ID.
* @param id - The variant's ID.
* @param query - Configure the fields to retrieve in the product variant.
* @param headers - Headers to pass in the request
* @returns The product variant's details.
*
*
* @example
* To retrieve a product variant by its ID:
*
*
* ```ts
* sdk.admin.product.retrieveVariant(
* "prod_123",
@@ -621,9 +697,9 @@ export class Product {
* console.log(variant)
* })
* ```
*
*
* To specify the fields and relations to retrieve:
*
*
* ```ts
* sdk.admin.product.retrieveVariant(
* "prod_123",
@@ -636,7 +712,7 @@ export class Product {
* console.log(variant)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async retrieveVariant(
@@ -658,12 +734,12 @@ export class Product {
* This method deletes a product's variant. It sends a request to the
* [Delete Variant](https://docs.medusajs.com/api/admin#products_deleteproductsidvariantsvariant_id)
* API route.
*
*
* @param productId - The product's ID.
* @param id - The ID of the variant.
* @param headers - Headers to pass in the request
* @returns The deletion's details.
*
*
* @example
* sdk.admin.product.deleteVariant("prod_123", "variant_123")
* .then(({ deleted }) => {
@@ -681,22 +757,22 @@ export class Product {
}
/**
* This method manages a product's variant's inventories to associate them with inventory items,
* This method manages a product's variant's inventories to associate them with inventory items,
* update their inventory items, or delete their association with inventory items.
*
* It sends a request to the
*
* It sends a request to the
* [Manage Variant Inventory](https://docs.medusajs.com/api/admin#products_postproductsidvariantsinventoryitemsbatch)
* API route.
*
*
* @param productId - The ID of the product that the variant belongs to.
* @param body - The inventory items to create, update, or delete.
* @param query - Pass query parameters in the request.
* @param headers - Headers to pass in the request
* @returns The details of the created, updated, or deleted inventory items.
*
*
* @example
* sdk.admin.product.batchVariantInventoryItems(
* "prod_123",
* "prod_123",
* {
* create: [
* {
@@ -745,16 +821,16 @@ export class Product {
* This method creates an option in a product. It sends a request to the
* [Create Option](https://docs.medusajs.com/api/admin#products_postproductsidoptions)
* API route.
*
*
* @param productId - The product's ID.
* @param body - The option's details.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* sdk.admin.product.createOption(
* "prod_123",
* "prod_123",
* {
* title: "Color",
* values: ["Green", "Blue"]
@@ -785,17 +861,17 @@ export class Product {
* This method updates a product's option. It sends a request to the
* [Update Option](https://docs.medusajs.com/api/admin#products_postproductsidoptionsoption_id)
* API route.
*
*
* @param productId - The product's ID.
* @param id - The ID of the option to update.
* @param body - The data to update in the option.
* @param query - Configure the fields to retrieve in the product.
* @param headers - Headers to pass in the request
* @returns The product's details.
*
*
* @example
* sdk.admin.product.updateOption(
* "prod_123",
* "prod_123",
* "prodopt_123",
* {
* title: "Color"
@@ -824,28 +900,28 @@ export class Product {
}
/**
* This method retrieves a paginated list of product options. It sends a request to the
* This method retrieves a paginated list of product options. It sends a request to the
* [List Options](https://docs.medusajs.com/api/admin#products_getproductsidoptions) API route.
*
*
* @param productId - The ID of the product to retrieve its options
* @param query - Filters and pagination configurations.
* @param headers - Headers to pass in the request.
* @returns The paginated list of product options.
*
*
* @example
* To retrieve the list of product options:
*
*
* ```ts
* sdk.admin.product.listOptions("prod_123")
* .then(({ product_options, count, limit, offset }) => {
* console.log(product_options)
* })
* ```
*
*
* To configure the pagination, pass the `limit` and `offset` query parameters.
*
*
* For example, to retrieve only 10 items and skip 10 items:
*
*
* ```ts
* sdk.admin.product.listOptions("prod_123", {
* limit: 10,
@@ -855,10 +931,10 @@ export class Product {
* console.log(product_options)
* })
* ```
*
*
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
* in each product options:
*
*
* ```ts
* sdk.admin.product.listOptions("prod_123", {
* fields: "id,title"
@@ -867,7 +943,7 @@ export class Product {
* console.log(product_options)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async listOptions(
@@ -888,16 +964,16 @@ export class Product {
* This method retrieves a product's option. It sends a request to the
* [Get Option](https://docs.medusajs.com/api/admin#products_getproductsidoptionsoption_id)
* API route.
*
*
* @param productId - The product's ID.
* @param id - The product option's ID.
* @param query - Configure the fields to retrieve in the product option.
* @param headers - Headers to pass in the request
* @returns The product option's details.
*
*
* @example
* To retrieve a product option by its ID:
*
*
* ```ts
* sdk.admin.product.retrieveOption(
* "prod_123",
@@ -907,9 +983,9 @@ export class Product {
* console.log(product_option)
* })
* ```
*
*
* To specify the fields and relations to retrieve:
*
*
* ```ts
* sdk.admin.product.retrieveOption(
* "prod_123",
@@ -922,7 +998,7 @@ export class Product {
* console.log(product_option)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async retrieveOption(
@@ -941,15 +1017,15 @@ export class Product {
}
/**
* This method deletes a product's option. It sends a request to the
* This method deletes a product's option. It sends a request to the
* [Delete Option](https://docs.medusajs.com/api/admin#products_deleteproductsidoptionsoption_id)
* API route.
*
*
* @param productId - The product's ID.
* @param id - The option's ID.
* @param headers - Headers to pass in the request
* @returns The deletion's details.
*
*
* @example
* sdk.admin.product.deleteOption("prod_123", "prodopt_123")
* .then(({ deleted }) => {