Shopify Function - jerry-ey/shopify-theme-boilerplate GitHub Wiki
Tutorial: Building Shopify Functions with Rust
Shopify Functions allow developers to write custom logic that integrates directly into Shopify's backend workflows. This tutorial demonstrates how to create a Shopify Function using Rust.
Prerequisites
-
Rust Installed:
- Install Rust from rust-lang.org.
- Ensure the
cargo
tool is available by runningcargo --version
.
-
Shopify CLI:
- Install the Shopify CLI from Shopify's CLI guide.
-
GraphQL Knowledge:
- Familiarity with GraphQL queries and schemas is beneficial.
Setting Up Your Project
-
Initialize a New Project:
cargo new shopify-function-example cd shopify-function-example
-
Add Dependencies: Update
Cargo.toml
to include Shopify-related dependencies.[dependencies] shopify_function = "0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" decimal = "0.20"
-
Install Shopify CLI Extensions:
shopify extension create --type=discount_function
Follow the prompts to configure the new function.
Writing the Function Logic
-
Define the Function: Create a new file
src/main.rs
with the following content:use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function_target(query_path = "src/run.graphql", schema_path = "schema.graphql")] fn run(input: input::ResponseData) -> Result<output::FunctionRunResult> { let no_discount = output::FunctionRunResult { discounts: vec![], discount_application_strategy: output::DiscountApplicationStrategy::FIRST, }; let targets = input.cart.lines .iter() .filter(|line| line.quantity >= 2) .map(|line| output::Target::CartLine(output::CartLineTarget { id: line.id.to_string(), quantity: None, })) .collect::<Vec<output::Target>>(); if targets.is_empty() { eprintln!("No cart lines qualify for volume discount."); return Ok(no_discount); } Ok(output::FunctionRunResult { discounts: vec![output::Discount { message: None, targets, value: output::Value::Percentage(output::Percentage { value: Decimal(10.0), }), }], discount_application_strategy: output::DiscountApplicationStrategy::FIRST, }) }
-
GraphQL Schema: Create a
schema.graphql
file to define the input/output structure for your function:type Query { cart: Cart! } type Cart { lines: [CartLine!]! } type CartLine { id: ID! quantity: Int! }
-
GraphQL Query: Create a
src/run.graphql
file to fetch the necessary data:query { cart { lines { id quantity } } }
Understanding the Code
-
Procedural Macro:
#[shopify_function_target(query_path = "src/run.graphql", schema_path = "schema.graphql")]
This macro:
- Links your function to Shopify’s backend.
- Ensures compliance with the provided GraphQL schema and query.
-
Filtering Logic:
let targets = input.cart.lines .iter() .filter(|line| line.quantity >= 2)
Filters cart lines where the quantity is 2 or more.
-
Applying Discounts:
Ok(output::FunctionRunResult { discounts: vec![output::Discount { value: output::Value::Percentage(output::Percentage { value: Decimal(10.0), }), }], })
Creates a 10% discount for eligible items.
Testing Your Function
-
Build the Project:
cargo build --release
-
Run Tests: Use the Shopify CLI to test the function:
shopify extension serve
-
Simulate Inputs: Use the Shopify GraphQL API to simulate various cart scenarios and verify the output.
Deploying the Function
-
Bundle the Function:
cargo build --release
Upload the
target/release
binary to Shopify. -
Use Shopify CLI:
shopify extension push
Deploy the function to your Shopify store.
Additional Resources
By following this guide, you’ve successfully built a Shopify Function in Rust that applies discounts based on cart line quantities. Feel free to extend this example to meet your specific business logic!