@medusajs/utils
Version:
Medusa utilities functions shared by Medusa core and Modules
412 lines • 16.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractFulfillmentProviderService = void 0;
/**
* ### constructor
*
* The constructor allows you to access resources from the [module's container](https://docs.medusajs.com/learn/fundamentals/modules/container)
* using the first parameter, and the module's options using the second parameter.
*
* :::note
*
* A module's options are passed when you register it in the Medusa application.
*
* :::
*
* If you're creating a client or establishing a connection with a third-party service, do it in the constructor.
*
* #### Example
*
* ```ts title="src/modules/my-fulfillment/service.ts"
* import { AbstractFulfillmentProviderService } from "@medusajs/framework/utils"
* import { Logger } from "@medusajs/framework/types"
*
* type InjectedDependencies = {
* logger: Logger
* }
*
* type Options = {
* apiKey: string
* }
*
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // other properties...
* protected logger_: Logger
* protected options_: Options
* // assuming you're initializing a client
* protected client
*
* constructor(
* { logger }: InjectedDependencies,
* options: Options
* ) {
* super()
*
* this.logger_ = logger
* this.options_ = options
*
* // TODO initialize your client
* }
* }
*
* export default MyFulfillmentProviderService
* ```
*/
class AbstractFulfillmentProviderService {
/**
* @ignore
*/
static isFulfillmentService(obj) {
return obj?.constructor?._isFulfillmentService;
}
/**
* @ignore
*/
getIdentifier() {
return this.constructor.identifier;
}
/**
* This method retrieves a list of fulfillment options that this provider supports. Admin users will then choose from these options when
* they're creating a shipping option. The chosen fulfillment option's object is then stored within the created shipping option's `data` property.
* The `data` property is useful to store data relevant for the third-party provider to later process the fulfillment.
*
* This method is useful if your third-party provider allows you to retrieve support options, carriers, or services from an API. You can then
* retrieve those and return then in the method, allowing the admin user to choose from the services provided by the third-party provider.
*
* @returns The list of fulfillment options. Each object in the array should have an `id` property unique to an item, and a `name` property
* that's used to display the option in the admin.
*
* @example
* // other imports...
* import { FulfillmentOption } from "@medusajs/framework/types"
*
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async getFulfillmentOptions(): Promise<FulfillmentOption[]> {
* // assuming you have a client
* const services = await this.client.getServices()
*
* return services.map((service) => ({
* id: service.service_id,
* name: service.name,
* service_code: service.code,
* // can add other relevant data for the provider to later process the shipping option.
* }))
* }
* }
*/
async getFulfillmentOptions() {
throw Error("getFulfillmentOptions must be overridden by the child class");
}
/**
* This method validates the `data` property of a shipping method and returns it. The returned data
* is stored in the shipping method's `data` property.
*
* Your fulfillment provider can use the `data` property to store additional information useful for
* handling the fulfillment later. For example, you may store an ID from the third-party fulfillment
* system.
*
* @param optionData - The `data` property of the shipping option.
* @param data - The `data` property of the shipping method.
* @param context - Context details, such as context of the cart or customer.
* @returns the data to store in the `data` property of the shipping method.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async validateFulfillmentData(
* optionData: any,
* data: any,
* context: any
* ): Promise<any> {
* // assuming your client retrieves an ID from the
* // third-party service
* const externalId = await this.client.getId()
*
* return {
* ...data,
* externalId
* }
* }
* }
*/
async validateFulfillmentData(optionData, data, context) {
throw Error("validateFulfillmentData must be overridden by the child class");
}
/**
* This method validates the `data` property of a shipping option when it's created.
*
* The `data` property can hold useful information that's later added to the `data` attribute
* of shipping methods created from this option.
*
* @param data - The data to validate.
* @return Whether the data is valid.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async validateOption(data: any): Promise<boolean> {
* return data.external_id !== undefined
* }
* }
*/
async validateOption(data) {
throw Error("validateOption must be overridden by the child class");
}
/**
* This method validates whether a shippin option's price can be calculated during checkout. It's executed when the admin user creates a shipping
* option of type `calculated`. If this method returns `false`, an error is thrown as the shipping option's price can't be calculated.
*
* You can perform the checking using the third-party provider if applicable. The `data` parameter will hold the shipping option's `data` property, which
* includes the data of a fulfillment option returned by {@link getFulfillmentOptions}.
*
* @param data - The `data` property of the shipping option.
* @returns Whether the price can be calculated for the shipping option.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async canCalculate(data: CreateShippingOptionDTO): Promise<boolean> {
* // assuming you have a client
* return await this.client.hasRates(data.id)
* }
* }
*/
async canCalculate(data) {
throw Error("canCalculate must be overridden by the child class");
}
/**
* This method calculates the price of a shipping method when it's created or its cart is refreshed.
*
* In this method, you can send a request to your third-party provider to retrieve the prices. The first
* parameters holds the `data` property of the shipping method's shipping option, which has fulfillment
* object data returned by {@link getFulfillmentOptions}.
*
* The second parameter holds the `data` property of the shipping method, which has data returned by {@link validateFulfillmentData}.
* It can also hold custom data passed from the frontend during checkout.
*
* So, using both of these data, assuming you're storing in them data related to the third-party service,
* you can retrieve the calculated price of the shipping method.
*
* @param optionData - The `data` property of a shipping option.
* @param data - The shipping method's `data` property with custom data passed from the frontend.
* @param context - The context details, such as the cart details.
* @returns The calculated price's details.
*
* @example
* import { CalculateShippingOptionPriceDTO } from "@medusajs/framework/types"
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async calculatePrice(
* optionData: CalculateShippingOptionPriceDTO["optionData"],
* data: CalculateShippingOptionPriceDTO["data"],
* context: CalculateShippingOptionPriceDTO["context"]
* ): Promise<CalculatedShippingOptionPrice> {
* // assuming the client can calculate the price using
* // the third-party service
* const price = await this.client.calculate(data)
* return {
* calculated_amount: price,
* // Update this boolean value based on your logic
* is_calculated_price_tax_inclusive: true,
* }
* }
* }
*/
async calculatePrice(optionData, data, context) {
throw Error("calculatePrice must be overridden by the child class");
}
/**
* This method is used when a fulfillment is created. If the method returns in the object a
* `data` property, it's stored in the fulfillment's `data` property.
*
* The `data` property is useful when handling the fulfillment later,
* as you can access information useful for your integration, such as the ID in the
* third-party provider.
*
* You can also use this method to perform an action with the third-party fulfillment service
* since a fulfillment is created, such as purchase a label.
*
* @param data - The `data` property of the shipping method this fulfillment is created for.
* @param items - The items in the fulfillment.
* @param order - The order this fulfillment is created for.
* @param fulfillment - The fulfillment's details.
* @returns An object whose `data` property is stored in the fulfillment's `data` property.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async createFulfillment(
* data: Record<string, unknown>,
* items: Partial<Omit<FulfillmentItemDTO, "fulfillment">>[],
* order: Partial<FulfillmentOrderDTO> | undefined,
* fulfillment: Partial<Omit<FulfillmentDTO, "provider_id" | "data" | "items">>
* ): Promise<CreateFulfillmentResult> {
* // assuming the client creates a fulfillment
* // in the third-party service
* const externalData = await this.client.create(
* fulfillment,
* items
* )
*
* return {
* data: {
* ...(fulfillment.data as object || {}),
* ...externalData
* }
* }
* }
* }
*/
async createFulfillment(data, items, order, fulfillment) {
throw Error("createFulfillment must be overridden by the child class");
}
/**
* This method is used when a fulfillment is canceled. Use it to perform operations
* with the third-party fulfillment service.
*
* @param data - The fulfillment's `data` property.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async cancelFulfillment(data: Record<string, unknown>): Promise<any> {
* // assuming the client cancels a fulfillment
* // in the third-party service
* const { external_id } = data as {
* external_id: string
* }
* await this.client.cancel(external_id)
* }
* }
*/
async cancelFulfillment(data) {
throw Error("cancelFulfillment must be overridden by the child class");
}
/**
* This method retrieves the documents of a fulfillment.
*
* @param data - The `data` property of the fulfillment.
* @returns The fulfillment's documents.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async getFulfillmentDocuments(data: any): Promise<never[]> {
* // assuming the client retrieves documents
* // from a third-party service
* return await this.client.documents(data)
* }
* }
*/
async getFulfillmentDocuments(data) {
return [];
}
/**
* This method is used when a fulfillment is created for a return. If the method returns in the object a
* `data` property, it's stored in the fulfillment's `data` property.
*
* The `data` property is useful when handling the fulfillment later,
* as you can access information useful for your integration. For example, you
* can store an ID for the fulfillment in the third-party service.
*
* Use this method to perform actions necessary in the third-party fulfillment service, such as
* purchasing a label for the return fulfillment.
*
* @param fulfillment - The fulfillment's details.
* @returns An object containing `data` which is stored in the fulfillment's `data` property and `labels` array which is used to create FulfillmentLabels.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async createReturnFulfillment(fulfillment: Record<string, unknown>): Promise<CreateFulfillmentResult> {
* // assuming the client creates a fulfillment for a return
* // in the third-party service
* const externalData = await this.client.createReturn(
* fulfillment
* )
*
* return {
* data: {
* ...(fulfillment.data as object || {}),
* ...externalData
* }
* }
* }
* }
*/
async createReturnFulfillment(fulfillment) {
throw Error("createReturn must be overridden by the child class");
}
/**
* This method retrieves documents for a return's fulfillment.
*
* @param data - The `data` property of the fulfillment.
* @returns The fulfillment's documents.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async getReturnDocuments(data: any): Promise<never[]> {
* // assuming the client retrieves documents
* // from a third-party service
* return await this.client.documents(data)
* }
* }
*/
async getReturnDocuments(data) {
return [];
}
/**
* This method retrieves the documents for a shipment.
*
* @param data - The `data` property of the shipmnet.
* @returns The shipment's documents.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async getShipmentDocuments(data: any): Promise<never[]> {
* // assuming the client retrieves documents
* // from a third-party service
* return await this.client.documents(data)
* }
* }
*
*/
async getShipmentDocuments(data) {
return [];
}
/**
* This method retrieves the documents of a fulfillment of a certain type.
*
* @param fulfillmentData - The `data` property of the fulfillment.
* @param documentType - The document's type. For example, `invoice`.
* @returns The fulfillment's documents.
*
* @example
* class MyFulfillmentProviderService extends AbstractFulfillmentProviderService {
* // ...
* async retrieveDocuments(
* fulfillmentData: any,
* documentType: any
* ): Promise<void> {
* // assuming the client retrieves documents
* // from a third-party service
* return await this.client.documents(
* fulfillmentData,
* documentType
* )
* }
* }
*/
async retrieveDocuments(fulfillmentData, documentType) {
throw Error("retrieveDocuments must be overridden by the child class");
}
}
exports.AbstractFulfillmentProviderService = AbstractFulfillmentProviderService;
/**
* @ignore
*/
AbstractFulfillmentProviderService._isFulfillmentService = true;
//# sourceMappingURL=provider.js.map
;