Repository: medusajs/medusa
File: packages/core/core-flows/src/cart/steps/update-carts.ts (TypeScript)

Code before:

    const { selects, relations } = getSelectsAndRelationsFromObjectArray(data, {
      requiredFields: [
        "id",
        "region_id",
        "customer_id",
        "sales_channel_id",
        "email",
        "currency_code",
        "metadata",
        "completed_at",
      ],
    })
    const cartsBeforeUpdate = await cartModule.listCarts(
      { id: data.map((d) => d.id) },
      { select: selects, relations }
    )

	// Since service factory udpate method will correctly keep the reference to the addresses,
	// but won't update its fields, we do this separately
	const addressesInput = data.flatMap(cart => [cart.shipping_address, cart.billing_address])
		.filter(address => !!address)
	const addressesToUpdate = addressesInput.filter(address => "id" in address)
	const addressesBeforeUpdate = await cartModule.listAddresses(
		{ id: addressesToUpdate.map(address => address.id as string)}
	)
	if (addressesToUpdate.length) {
		await cartModule.updateAddresses(addressesToUpdate as unknown as UpdateAddressDTO[])
	}

    const updatedCart = await cartModule.updateCarts(data)

    return new StepResponse(updatedCart, {cartsBeforeUpdate, addressesBeforeUpdate})
  },
  async (dataToCompensate, { container }) => {
    if (!dataToCompensate) {
      return
    }

	const { cartsBeforeUpdate, addressesBeforeUpdate } = dataToCompensate

    const cartModule = container.resolve<ICartModuleService>(Modules.CART)

	const addressesToUpdate: UpdateAddressDTO[] = []
	for (const address of addressesBeforeUpdate) {
		addressesToUpdate.push({
			...address,
			metadata: address.metadata ?? undefined
		})
	}
	await cartModule.updateAddresses(addressesToUpdate)

Review comment (suggestion):
```suggestion
let addressesToUpdateIds: string[] = []
    const addressesToUpdate = addressesInput.filter(
      (address): address is UpdateAddressDTO => {
        if ("id" in address && !!address.id) {
          addressesToUpdateIds.push(address.id as string)
          return true
        }
        return false
      }
    )
    const addressesBeforeUpdate = await cartModule.listAddresses({
      id: addressesToUpdate.map((address) => address.id),
    })
```

Code after:

    const { selects, relations } = getSelectsAndRelationsFromObjectArray(data, {
      requiredFields: [
        "id",
        "region_id",
        "customer_id",
        "sales_channel_id",
        "email",
        "currency_code",
        "metadata",
        "completed_at",
      ],
    })
    const cartsBeforeUpdate = await cartModule.listCarts(
      { id: data.map((d) => d.id) },
      { select: selects, relations }
    )

    // Since service factory udpate method will correctly keep the reference to the addresses,
    // but won't update its fields, we do this separately
    const addressesInput = data
      .flatMap((cart) => [cart.shipping_address, cart.billing_address])
      .filter((address) => !!address)
    let addressesToUpdateIds: string[] = []
    const addressesToUpdate = addressesInput.filter(
      (address): address is UpdateAddressDTO => {
        if ("id" in address && !!address.id) {
          addressesToUpdateIds.push(address.id as string)
          return true
        }
        return false
      }
    )
    const addressesBeforeUpdate = await cartModule.listAddresses({
      id: addressesToUpdate.map((address) => address.id),
    })
    if (addressesToUpdate.length) {
      await cartModule.updateAddresses(addressesToUpdate)
    }

    const updatedCart = await cartModule.updateCarts(data)

    return new StepResponse(updatedCart, {
      cartsBeforeUpdate,
      addressesBeforeUpdate,
    })
  },
  async (dataToCompensate, { container }) => {
    if (!dataToCompensate) {
      return
    }