Skip to content

Commit ba0d4dd

Browse files
authored
Merge pull request #40 from Shopify/shopify-function-target
Add `shopify_function_target` macro
2 parents b7f3417 + b731209 commit ba0d4dd

File tree

22 files changed

+686
-19
lines changed

22 files changed

+686
-19
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
target
2-
shopify_function/.output.graphql
2+
shopify_function/*.output.graphql

Cargo.lock

Lines changed: 28 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
[workspace]
22
members = [
33
"example",
4+
"example_with_targets",
45
"shopify_function",
5-
"shopify_function_macro"
6+
"shopify_function_macro",
67
]
78

89
[profile.release]

example/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55
license = "MIT"
66

77
[dependencies]
8-
shopify_function = { path = "../shopify_function", version = "0.2.5" }
8+
shopify_function = { path = "../shopify_function", version = "0.3.0" }
99
serde = { version = "1.0.13", features = ["derive"] }
1010
serde_json = "1.0"
1111
graphql_client = "0.13.0"

example/metadata.json

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mutation Output($result: FunctionTargetAResult!) {
2+
targetA(result: $result)
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mutation Output($result: FunctionTargetBResult!) {
2+
targetB(result: $result)
3+
}

example_with_targets/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "example_with_targets"
3+
version = "1.0.0"
4+
edition = "2021"
5+
license = "MIT"
6+
7+
[dependencies]
8+
shopify_function = { path = "../shopify_function", version = "0.3.0" }
9+
serde = { version = "1.0.13", features = ["derive"] }
10+
serde_json = "1.0"
11+
graphql_client = "0.13.0"

example_with_targets/README.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Shopify Rust function example with targets
2+
3+
This is an example of how to use the [Shopify Function Rust crate][crate] with the `shopify_function_target` macro to write a Shopify Function with multiple API targets.
4+
5+
## Example API
6+
7+
Target | Handle (`snake_case`) | GraphQL mutation
8+
-- | -- | --
9+
`example.target-a` | `target_a` | `targetA(result: FunctionTargetAResult!)`
10+
`example.target-b` | `target_b` | `targetB(result: FunctionTargetBResult!)`
11+
12+
### `schema.graphql`
13+
14+
```graphql
15+
"""
16+
The input object for the function.
17+
"""
18+
type Input {
19+
id: ID!
20+
num: Int
21+
name: String
22+
targetAResult: Int @restrictTarget(only: ["example.target-b"])
23+
}
24+
25+
"""
26+
The root mutation for the API.
27+
"""
28+
type MutationRoot {
29+
"""
30+
The function for API target A.
31+
"""
32+
targetA(
33+
"""
34+
The result of calling the function for API target A.
35+
"""
36+
result: FunctionTargetAResult!
37+
): Void!
38+
39+
"""
40+
The function for API target B.
41+
"""
42+
targetB(
43+
"""
44+
The result of calling the function for API target B.
45+
"""
46+
result: FunctionTargetBResult!
47+
): Void!
48+
}
49+
50+
"""
51+
The result of API target A.
52+
"""
53+
input FunctionTargetAResult {
54+
status: Int
55+
}
56+
57+
"""
58+
The result of API target B.
59+
"""
60+
input FunctionTargetBResult {
61+
name: String
62+
}
63+
```
64+
65+
## `shopify.function.extension.toml`
66+
67+
```toml
68+
[[targeting]]
69+
target = "example.target-a"
70+
input_query = "a.graphql"
71+
72+
[[targeting]]
73+
target = "example.target-b"
74+
input_query = "b.graphql"
75+
export = "function_b"
76+
```
77+
78+
- `target`: the API-specific handle for the target implemented by the Wasm function
79+
- `input_query`: the path to the target-specific input query file
80+
- `export` (optional): the name of the function to export to Wasm
81+
- default: the target handle as `snake_case`
82+
83+
## `shopify_function_target` usage
84+
85+
### Arguments
86+
87+
- `query_path`: the path to the input query file for the target
88+
- `schema_path`: the path to the API schema file for the target
89+
- `target` (optional): the API-specific handle for the target if the function name does not match the target handle as `snake_case`
90+
- `module_name` (optional): the name of the generated module
91+
- default: the target handle as `snake_case`
92+
93+
### `src/lib.rs`
94+
95+
```rust
96+
#[shopify_function_target(
97+
// Implicit target = "example.target-a"
98+
// Implicit generated module name = "target_a"
99+
query_path = "a.graphql",
100+
schema_path = "schema.graphql"
101+
)]
102+
fn target_a(
103+
_input: target_a::input::ResponseData,
104+
) -> Result<target_a::output::FunctionTargetAResult> {
105+
Ok(target_a::output::FunctionTargetAResult { status: Some(200) })
106+
}
107+
108+
#[shopify_function_target(
109+
// Explicit target if function name does not match target handle
110+
target = "example.target-b",
111+
// Override generated module name
112+
module_name = "mod_b",
113+
query_path = "b.graphql",
114+
schema_path = "schema.graphql"
115+
)]
116+
fn function_b(input: mod_b::input::ResponseData) -> Result<mod_b::output::FunctionTargetBResult> {
117+
Ok(mod_b::output::FunctionTargetBResult {
118+
name: Some(format!("new name: \"{}\"", input.id)),
119+
})
120+
}
121+
```
122+
123+
### Generated code
124+
125+
The `shopify_function_target` macro uses `generate_types` and `shopify_function` to generate a module (optionally using `module_name`) containing:
126+
127+
- `input`
128+
- `ResponseData` for the target-specific input query
129+
- `output`
130+
- a target-specific result type, e.g. `FunctionTargetAResult`
131+
- `export`: The function exported to the Wasm module using the Rust function name, which must match the export specified for the target in `shopify.function.extension.toml`
132+
133+
The generated types can be viewed using the instructions in the `shopify_function` crate `README`.
134+
135+
#### `*.output.graphql`
136+
137+
Each target will have an `.output.graphql` file prefixed with the target handle as `snake_case`. This file is used to generate the target-specific `output` types, and can be added to `.gitignore`.
138+
139+
Target handle (`snake_case`) | Output file | GraphQL mutation
140+
-- | -- | --
141+
`target_a` | `.target_a.output.graphql` | `mutation Output($result: FunctionTargetAResult!) { targetA(result: $result) }`
142+
`target_b` | `.target_a.output.graphql` | `mutation Output($result: FunctionTargetBResult!) { targetB(result: $result) }`
143+
144+
If the Rust function name does not match the target handle as `snake_case`, the `target` argument must be provided to `shopify_function_target` to generate the `output` types.
145+
146+
[crate]: https://crates.io/crates/shopify-function

example_with_targets/a.graphql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
query Input {
2+
id
3+
num
4+
name
5+
}

0 commit comments

Comments
 (0)