Repository: medusajs/medusa
File: packages/core/core-flows/src/cart/steps/validate-cart-shipping-options.ts (TypeScript)

Code before:
   * instead of querying the database.
   */
  shippingOptions?: { id: string }[]
}

export const validateCartShippingOptionsStepId =
  "validate-cart-shipping-options"
/**
 * This step validates shipping options to ensure they can be applied on a cart.
 * If not valid, the step throws an error.
 * 
 * @example
 * const data = validateCartShippingOptionsStep({
 *   // retrieve the details of the cart from another workflow
 *   // or in another step using the Cart Module's service
 *   cart,
 *   option_ids: ["so_123"],
 *   shippingOptionsContext: {}
 * })
 */
export const validateCartShippingOptionsStep = createStep(
  validateCartShippingOptionsStepId,
  async (data: ValidateCartShippingOptionsStepInput, { container }) => {
    const { option_ids: optionIds = [], cart, shippingOptionsContext, shippingOptions } = data

    if (!optionIds.length) {
      return new StepResponse(void 0)
    }

    let validShippingOptionIds: string[]

    if (shippingOptions) {
      // Use pre-fetched shipping options
      validShippingOptionIds = shippingOptions.map((o) => o.id)
    } else {
      // Legacy behavior: query the database
      if (!cart || !shippingOptionsContext) {
        throw new MedusaError(
          MedusaError.Types.INVALID_DATA,
          `cart and shippingOptionsContext are required when shippingOptions are not provided.`
        )
      }

      const fulfillmentModule = container.resolve<IFulfillmentModuleService>(
        Modules.FULFILLMENT
      )

      const validShippingOptions =
        await fulfillmentModule.listShippingOptionsForContext(
          {
            id: optionIds,

Review comment (suggestion):
question: shouldn't we check if `shippingOptions` is not present too? otherwise, I believe we return early in the case of only passing prefetched options

Code after:
   * instead of querying the database.
   */
  prefetched_shipping_options?: { id: string }[]
}

export const validateCartShippingOptionsStepId =
  "validate-cart-shipping-options"
/**
 * This step validates shipping options to ensure they can be applied on a cart.
 * If not valid, the step throws an error.
 * 
 * @example
 * const data = validateCartShippingOptionsStep({
 *   // retrieve the details of the cart from another workflow
 *   // or in another step using the Cart Module's service
 *   cart,
 *   option_ids: ["so_123"],
 *   shippingOptionsContext: {}
 * })
 */
export const validateCartShippingOptionsStep = createStep(
  validateCartShippingOptionsStepId,
  async (data: ValidateCartShippingOptionsStepInput, { container }) => {
    const { option_ids: optionIds = [], cart, shippingOptionsContext, prefetched_shipping_options: prefetchedShippingOptions } = data

    if (!optionIds.length) {
      return new StepResponse(void 0)
    }

    let validShippingOptionIds: string[]
    if (!prefetchedShippingOptions) {
      if (!cart || !shippingOptionsContext) {
        throw new MedusaError(
          MedusaError.Types.INVALID_DATA,
          `Cart and shippingOptionsContext need to be defined if prefetchedShippingOptions is not.`
        )
      }

      // Legacy behavior: query the database
      const fulfillmentModule = container.resolve<IFulfillmentModuleService>(
        Modules.FULFILLMENT
      )

      const validShippingOptions =
        await fulfillmentModule.listShippingOptionsForContext(
          {
            id: optionIds,
            context: shippingOptionsContext,
            address: {
              country_code: cart.shipping_address?.country_code,
              province_code: cart.shipping_address?.province,