Is anyone having a hard time working with the shopify_function crate version 1.0 and onwards?

Context

Since the API 2026-04 version, previous product, order and shipping discounts have to be migrated to the new Discount Function API.

The 0.x versions of the shopify_function crate had an easy to work with type generation: all fields were public structs and scalar types that implemented the Copy trait.

This meant that we could copy a list of cart lines for intermediate processing, or create instances of a type with struct literals to create tests for instance.

The following is a pseudocode example of on the tests we had for filters applied to the function’s input:

    #[test]
    fn test_x_filter_works() {
        let input_data: FunctionInput = FunctionInput {
            localization: (
                input::InputLocalization { 
                    market: input::InputLocalizationMarket {
                        handle: String::from("europe")
                    }
                }
            ),
            presentment_currency_rate: Decimal::from(1 as f64),
            cart: input::InputCart {
                buyer_identity: None,
                lines: vec![]
            },
            discount: input::InputDiscount {
                discount_classes: vec![
                    input::DiscountClass::PRODUCT
                ],
            }
        };

        let result = filters::cart_filters::apply_x_filter(
            &input_data,
            &BooleanOperator::from("eq"),
            0
        );
        assert_eq!(result, true);
    }

What changed?

From version 1.0 and onward, I could no longer use existing code and the development is a lot more frustrating:

  1. Fields are created as Rust Cell types and do not implement the Clone or Copy trait. This means that I have to fully re-implement the input struct type in order to pass and edit cart lines.
  2. Fields are private in the generated types. This means that there is no way to create instances using struct literals, so no way to create unitary tests that rely on generated types.

The problem

I can’t see how to avoid creating my own cart line struct and parse the complete input provided to the function. This adds a lot of maintenance, a lot of unnecessary code, and extra machine instructions in order to do something that was already possible.

The following is an example of what would be needed to be implemented in order to pass certain fields by value or cloning them. It was a lot of work, and I don’t see how this can be mantainable or efficient.

/**
 * Reimplementation of the schema-defined CartLine type, that implements the Clone trait.
 */
#[derive(Clone, Debug)]
pub struct CopyableCartLine {
    pub id: String,
    pub quantity: i32,
    pub cost: CartLineCost,
    pub merchandise: CartLineMerchandise,
    pub selling_plan_allocation: Option<CartLineSellingPlanAllocation>,
}


impl CopyableCartLine {
    pub fn from_cart_line(cart_line: &schema::cart_lines_discounts_generate_run::input::cart::Lines) -> CopyableCartLine {
        CopyableCartLine {
            id: cart_line.id().to_string().clone(),
            quantity: *cart_line.quantity(),
            cost: CartLineCost {
                amount_per_quantity: CartLineDecimalValue {
                    amount: cart_line.cost().amount_per_quantity().amount().clone()
                },
                total_amount: CartLineDecimalValue {
                    amount: cart_line.cost().total_amount().amount().clone()
                },
                compare_at_amount_per_quantity: match cart_line.cost().compare_at_amount_per_quantity() {
                    Some(compare_at_amount) => Some(CartLineDecimalValue {
                    amount: compare_at_amount.amount().clone()
                }),
                    None => None,
                },
            },
...

The biggest issue here is that I am forced to migrate existing and stable functions to the new API, but I cannot reuse the 90% of the tests (further more the code), so the migration involves a lot more work and less secure from introducing bugs.