Skip to content

Commit 7afda8a

Browse files
Merge pull request #597 from Shopify/jh/small-changes-fn
Propagating errors instead of panicking
2 parents 1c7c55e + 6df2e3c commit 7afda8a

File tree

2 files changed

+57
-59
lines changed

2 files changed

+57
-59
lines changed

discounts/rust/discounts/default/src/fetch.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use serde_json::json;
1+
use serde::Serialize;
22
use shopify_function::prelude::*;
33
use shopify_function::Result;
44

@@ -18,24 +18,30 @@ type DeliveryFetchResponseData = delivery_fetch::input::ResponseData;
1818
type CartHttpRequestHeader = cart_fetch::output::HttpRequestHeader;
1919
type DeliveryHttpRequestHeader = delivery_fetch::output::HttpRequestHeader;
2020

21+
#[derive(Serialize)]
22+
#[serde(rename_all = "camelCase")]
23+
struct RequestBody {
24+
entered_discount_codes: Vec<String>,
25+
}
26+
2127
#[shopify_function_target(
2228
target = "cart_fetch",
2329
query_path = "src/fetch.graphql",
2430
schema_path = "schema.graphql"
2531
)]
2632
fn cart_fetch(input: CartFetchResponseData) -> Result<FunctionCartFetchResult> {
27-
let body = json!({
28-
"enteredDiscountCodes": input.entered_discount_codes
29-
});
33+
let request_body = RequestBody {
34+
entered_discount_codes: input.entered_discount_codes,
35+
};
3036

3137
Ok(FunctionCartFetchResult {
3238
request: Some(CartHttpRequest {
33-
body: Some(body.to_string()),
39+
body: Some(serde_json::to_string(&request_body)?),
3440
headers: vec![CartHttpRequestHeader {
3541
name: "Accept".to_string(),
3642
value: "application/json; charset=utf-8".to_string(),
3743
}],
38-
json_body: Some(body.clone()),
44+
json_body: Some(serde_json::to_value(&request_body)?),
3945
method: CartHttpRequestMethod::POST,
4046
policy: CartHttpRequestPolicy {
4147
read_timeout_ms: 2000,
@@ -51,18 +57,18 @@ fn cart_fetch(input: CartFetchResponseData) -> Result<FunctionCartFetchResult> {
5157
schema_path = "schema.graphql"
5258
)]
5359
fn delivery_fetch(input: DeliveryFetchResponseData) -> Result<FunctionDeliveryFetchResult> {
54-
let body = json!({
55-
"enteredDiscountCodes": input.entered_discount_codes
56-
});
60+
let request_body = RequestBody {
61+
entered_discount_codes: input.entered_discount_codes,
62+
};
5763

5864
Ok(FunctionDeliveryFetchResult {
5965
request: Some(DeliveryHttpRequest {
60-
body: Some(body.to_string()),
66+
body: Some(serde_json::to_string(&request_body)?),
6167
headers: vec![DeliveryHttpRequestHeader {
6268
name: "Accept".to_string(),
6369
value: "application/json; charset=utf-8".to_string(),
6470
}],
65-
json_body: Some(body.clone()),
71+
json_body: Some(serde_json::to_value(&request_body)?),
6672
method: DeliveryHttpRequestMethod::POST,
6773
policy: DeliveryHttpRequestPolicy {
6874
read_timeout_ms: 2000,
@@ -75,6 +81,7 @@ fn delivery_fetch(input: DeliveryFetchResponseData) -> Result<FunctionDeliveryFe
7581
#[cfg(test)]
7682
mod tests {
7783
use super::*;
84+
use serde_json::json;
7885
use shopify_function::{run_function_with_input, Result};
7986

8087
fn get_fetch_input_json() -> serde_json::Value {

discounts/rust/discounts/default/src/run.rs

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -26,53 +26,46 @@ type CartResponseData = cart_run::input::ResponseData;
2626
type DeliveryResponseData = delivery_run::input::ResponseData;
2727

2828
impl CartResponseData {
29-
fn metafield(&self) -> Metafield {
30-
self.discount_node
29+
fn metafield(&self) -> Result<Metafield> {
30+
let metafield = self
31+
.discount_node
3132
.metafield
3233
.as_ref()
33-
.map(|metafield| serde_json::from_str(&metafield.value))
34-
.unwrap()
35-
.expect("Missing required metafield configuration")
34+
.ok_or("Missing metafield")?;
35+
serde_json::from_str(&metafield.value)
36+
.map_err(|_| "Metafield value cannot be parsed".into())
3637
}
37-
fn valid_discount_codes(&self) -> Vec<String> {
38-
self.fetch_result
39-
.as_ref()
40-
.unwrap()
41-
.body
42-
.as_ref()
43-
.map(|available_codes| serde_json::from_str(available_codes))
44-
.unwrap()
45-
.expect("Missing required metafield configuration")
38+
fn valid_discount_codes(&self) -> Result<Vec<String>> {
39+
let fetch_result = self.fetch_result.as_ref().ok_or("Missing fetch result")?;
40+
let body = fetch_result.body.as_ref().ok_or("Missing body")?;
41+
serde_json::from_str(body).map_err(|_| "Fetch result body cannot be parsed".into())
4642
}
4743
}
4844

4945
impl DeliveryResponseData {
50-
fn metafield(&self) -> Metafield {
51-
self.discount_node
46+
fn metafield(&self) -> Result<Metafield> {
47+
let metafield = self
48+
.discount_node
5249
.metafield
5350
.as_ref()
54-
.map(|metafield| serde_json::from_str(&metafield.value))
55-
.unwrap()
56-
.expect("Missing required metafield configuration")
51+
.ok_or("Missing metafield")?;
52+
serde_json::from_str(&metafield.value)
53+
.map_err(|_| "Metafield value cannot be parsed".into())
5754
}
5855

59-
fn valid_discount_codes(&self) -> Vec<String> {
60-
self.fetch_result
61-
.as_ref()
62-
.unwrap()
63-
.body
64-
.as_ref()
65-
.map(|available_codes| serde_json::from_str(available_codes))
66-
.unwrap()
67-
.expect("Missing required metafield configuration")
56+
fn valid_discount_codes(&self) -> Result<Vec<String>> {
57+
let fetch_result = self.fetch_result.as_ref().ok_or("Missing fetch result")?;
58+
let body = fetch_result.body.as_ref().ok_or("Missing body")?;
59+
serde_json::from_str(body).map_err(|_| "Fetch result body cannot be parsed".into())
6860
}
6961
}
7062

7163
#[derive(Deserialize)]
64+
#[serde(rename_all = "camelCase")]
7265
struct Metafield {
73-
cart_percent: Option<Decimal>,
74-
product_percent: Option<Decimal>,
75-
delivery_percent: Option<Decimal>,
66+
order_percentage: Option<Decimal>,
67+
product_percentage: Option<Decimal>,
68+
delivery_percentage: Option<Decimal>,
7669
}
7770

7871
#[shopify_function_target(
@@ -81,15 +74,14 @@ struct Metafield {
8174
schema_path = "schema.graphql"
8275
)]
8376
fn cart_run(input: CartResponseData) -> Result<FunctionCartRunResult> {
84-
let default = FunctionCartRunResult { operations: vec![] };
85-
let codes = input.valid_discount_codes();
77+
let codes = input.valid_discount_codes()?;
8678
let available_discount_code = codes.first();
8779

8880
if available_discount_code.is_none() {
89-
return Ok(default);
81+
return Ok(FunctionCartRunResult { operations: vec![] });
9082
}
9183

92-
let metafield = input.metafield();
84+
let metafield = input.metafield()?;
9385
let mut operations: Vec<CartOperation> = vec![];
9486
let available_discount_code = available_discount_code.unwrap();
9587

@@ -101,11 +93,11 @@ fn cart_run(input: CartResponseData) -> Result<FunctionCartRunResult> {
10193
},
10294
));
10395

104-
if metafield.cart_percent.is_some() {
96+
if metafield.order_percentage.is_some() {
10597
operations.push(create_order_discount(&metafield, available_discount_code));
10698
}
10799

108-
if metafield.product_percent.is_some() {
100+
if metafield.product_percentage.is_some() {
109101
let highest_priced_line = input
110102
.cart
111103
.lines
@@ -132,13 +124,12 @@ fn cart_run(input: CartResponseData) -> Result<FunctionCartRunResult> {
132124
schema_path = "schema.graphql"
133125
)]
134126
fn delivery_run(input: DeliveryResponseData) -> Result<FunctionDeliveryRunResult> {
135-
let default = FunctionDeliveryRunResult { operations: vec![] };
136-
let codes = input.valid_discount_codes();
127+
let codes = input.valid_discount_codes()?;
137128
let available_discount_code = codes.first();
138-
let metafield = input.metafield();
129+
let metafield = input.metafield()?;
139130

140-
if available_discount_code.is_none() || metafield.delivery_percent.is_none() {
141-
return Ok(default);
131+
if available_discount_code.is_none() || metafield.delivery_percentage.is_none() {
132+
return Ok(FunctionDeliveryRunResult { operations: vec![] });
142133
}
143134

144135
let mut operations: Vec<DeliveryOperation> = vec![];
@@ -183,7 +174,7 @@ fn create_order_discount(metafield: &Metafield, available_discount_code: &str) -
183174
}),
184175
message: None,
185176
value: OrderDiscountCandidateValue::Percentage(CartPercentage {
186-
value: metafield.cart_percent.unwrap(),
177+
value: metafield.order_percentage.unwrap(),
187178
}),
188179
conditions: None,
189180
}],
@@ -207,7 +198,7 @@ fn create_product_discount(
207198
}),
208199
message: None,
209200
value: ProductDiscountCandidateValue::Percentage(CartPercentage {
210-
value: metafield.product_percent.unwrap(),
201+
value: metafield.product_percentage.unwrap(),
211202
}),
212203
}],
213204
})
@@ -225,7 +216,7 @@ fn create_delivery_discount_candidate(
225216
},
226217
)],
227218
value: DeliveryDiscountCandidateValue::Percentage(DeliveryPercentage {
228-
value: metafield.delivery_percent.unwrap(),
219+
value: metafield.delivery_percentage.unwrap(),
229220
}),
230221
message: None,
231222
associated_discount_code: Some(DeliveryAssociatedDiscountCode {
@@ -271,9 +262,9 @@ mod tests {
271262
"discountNode": {
272263
"metafield": {
273264
"value": json!({
274-
"cart_percent": "10",
275-
"product_percent": "20",
276-
"delivery_percent": "30",
265+
"orderPercentage": "10",
266+
"productPercentage": "20",
267+
"deliveryPercentage": "30",
277268
}).to_string(),
278269
}
279270
},

0 commit comments

Comments
 (0)