Skip to content

Commit f8e6ba0

Browse files
ginmrttjoyal
authored andcommitted
Update Validation function templates
1 parent efb3697 commit f8e6ba0

16 files changed

+480
-181
lines changed

checkout/javascript/cart-checkout-validation/default/schema.graphql

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ Scale the Functions resource limits based on the field's length.
1313
"""
1414
directive @scaleLimits(rate: Float!) on FIELD_DEFINITION
1515

16+
"""
17+
Requires that exactly one field must be supplied and that field must not be `null`.
18+
"""
19+
directive @oneOf on INPUT_OBJECT
20+
1621
"""
1722
A custom property. Attributes are used to store additional information about a Shopify resource, such as
1823
products, customers, or orders. Attributes are stored as key-value pairs.
@@ -363,6 +368,27 @@ type CartLineCost {
363368
totalAmount: MoneyV2!
364369
}
365370

371+
"""
372+
The fetch target result. Your Function must return this data structure when generating the request.
373+
"""
374+
input CartValidationsGenerateFetchResult {
375+
"""
376+
The attributes associated with an HTTP request.
377+
"""
378+
request: HttpRequest
379+
}
380+
381+
"""
382+
The output of the Function run target. The object contains the validation errors
383+
that display to customers and prevent them from proceeding through checkout.
384+
"""
385+
input CartValidationsGenerateRunResult {
386+
"""
387+
The ordered list of operations to apply.
388+
"""
389+
operations: [Operation!]!
390+
}
391+
366392
"""
367393
Whether the product is in the specified collection.
368394
@@ -3030,9 +3056,9 @@ type HttpResponse {
30303056
headers: [HttpResponseHeader!]! @deprecated(reason: "Use `header` instead.")
30313057

30323058
"""
3033-
The HTTP response body parsed as JSON.
3034-
If the body is valid JSON, it will be parsed and returned as a JSON object.
3035-
If parsing fails, then raw body is returned as a string.
3059+
The HTTP response body parsed as JSON.
3060+
If the body is valid JSON, it will be parsed and returned as a JSON object.
3061+
If parsing fails, then raw body is returned as a string.
30363062
Use this field when you expect the response to be JSON, or when you're dealing
30373063
with mixed response types, meaning both JSON and non-JSON.
30383064
Using this field reduces function instruction consumption and ensures that the data is formatted in logs.
@@ -3099,7 +3125,7 @@ type Input {
30993125
your fetch target, and that is passed as input to the run target. For more
31003126
information, refer to [network access for Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/network-access).
31013127
"""
3102-
fetchResult: HttpResponse @restrictTarget(only: ["purchase.validation.run"])
3128+
fetchResult: HttpResponse @restrictTarget(only: ["purchase.validation.run", "cart.validations.generate.run"])
31033129

31043130
"""
31053131
The regional and language settings that determine how the Function
@@ -3973,7 +3999,7 @@ type Localization {
39733999
"""
39744000
The market of the active localized experience.
39754001
"""
3976-
market: Market!
4002+
market: Market! @deprecated(reason: "This `market` field will be removed in a future version of the API.")
39774003
}
39784004

39794005
"""
@@ -4241,7 +4267,7 @@ type MailingAddress {
42414267
"""
42424268
The market of the address.
42434269
"""
4244-
market: Market
4270+
market: Market @deprecated(reason: "This `market` field will be removed in a future version of the API.")
42454271

42464272
"""
42474273
The full name of the customer, based on firstName and lastName.
@@ -4400,6 +4426,26 @@ type MoneyV2 {
44004426
The root mutation for the API.
44014427
"""
44024428
type MutationRoot {
4429+
"""
4430+
Handles the Function result for the cart.validations.generate.fetch target.
4431+
"""
4432+
cartValidationsGenerateFetch(
4433+
"""
4434+
The result of the Function.
4435+
"""
4436+
result: CartValidationsGenerateFetchResult!
4437+
): Void!
4438+
4439+
"""
4440+
Handles the Function result for the cart.validations.generate.run target.
4441+
"""
4442+
cartValidationsGenerateRun(
4443+
"""
4444+
The result of the Function.
4445+
"""
4446+
result: CartValidationsGenerateRunResult!
4447+
): Void!
4448+
44034449
"""
44044450
Handles the Function result for the purchase.validation.fetch target.
44054451
"""
@@ -4431,6 +4477,16 @@ type MutationRoot {
44314477
): Void!
44324478
}
44334479

4480+
"""
4481+
An operation to apply.
4482+
"""
4483+
input Operation @oneOf {
4484+
"""
4485+
Add a performed validation.
4486+
"""
4487+
validationAdd: ValidationAddOperation
4488+
}
4489+
44344490
"""
44354491
The goods and services that merchants offer to customers. Products can include details such as
44364492
title, vendor, and custom data stored in [metafields](https://shopify.dev/docs/apps/build/custom-data).
@@ -4820,6 +4876,32 @@ type Validation implements HasMetafields {
48204876
): Metafield
48214877
}
48224878

4879+
"""
4880+
Add a performed validation.
4881+
"""
4882+
input ValidationAddOperation {
4883+
"""
4884+
Errors.
4885+
"""
4886+
errors: [ValidationError!]!
4887+
}
4888+
4889+
"""
4890+
A Function error for a path.
4891+
"""
4892+
input ValidationError {
4893+
"""
4894+
Returns a message describing the error.
4895+
"""
4896+
message: String!
4897+
4898+
"""
4899+
Specifies the path/target for use by the UI. See [Supported checkout field targets](https://shopify.dev/docs/api/functions/reference/cart-checkout-validation/graphql#supported-checkout-field-targets)
4900+
for a list of supported targets.
4901+
"""
4902+
target: String!
4903+
}
4904+
48234905
"""
48244906
A void type that can be used to return a null value from a mutation.
48254907
"""
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
api_version = "2025-01"
1+
api_version = "2025-07"
22

33
[[extensions]]
44
name = "t:name"
@@ -8,11 +8,10 @@ type = "function"
88
description = "t:description"
99

1010
[[extensions.targeting]]
11-
target = "purchase.validation.run"
12-
input_query = "src/run.graphql"
13-
export = "run"
11+
target = "cart.validations.generate.run"
12+
input_query = "src/cart_validations_generate_run.graphql"
13+
export = "cart-validations-generate-run"
1414

1515
[extensions.build]
1616
command = ""
1717
path = "dist/function.wasm"
18-

checkout/javascript/cart-checkout-validation/default/src/run.graphql.liquid renamed to checkout/javascript/cart-checkout-validation/default/src/cart_validations_generate_run.graphql.liquid

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
query RunInput {
1+
query CartValidationsGenerateRunInput {
22
cart {
33
lines {
44
quantity
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{%- if flavor contains "vanilla-js" -%}
2+
// @ts-check
3+
4+
/**
5+
* @typedef {import("../generated/api").CartValidationsGenerateRunInput} CartValidationsGenerateRunInput
6+
* @typedef {import("../generated/api").CartValidationsGenerateRunResult} CartValidationsGenerateRunResult
7+
*/
8+
9+
/**
10+
* @param {CartValidationsGenerateRunInput} input
11+
* @returns {CartValidationsGenerateRunResult}
12+
*/
13+
export function cartValidationsGenerateRun(input) {
14+
const errors = input.cart.lines
15+
.filter(({ quantity }) => quantity > 1)
16+
.map(() => ({
17+
message: "Not possible to order more than one of each",
18+
target: "$.cart"
19+
}));
20+
21+
const operations = [
22+
{
23+
validationAdd: {
24+
errors
25+
},
26+
},
27+
];
28+
29+
return { operations };
30+
};
31+
{%- elsif flavor contains "typescript" -%}
32+
import type {
33+
CartValidationsGenerateRunInput,
34+
CartValidationsGenerateRunResult,
35+
ValidationError,
36+
} from "../generated/api";
37+
38+
export function cartValidationsGenerateRun(input: CartValidationsGenerateRunInput): CartValidationsGenerateRunResult {
39+
const errors: ValidationError[] = input.cart.lines
40+
.filter(({ quantity }) => quantity > 1)
41+
.map(() => ({
42+
message: "Not possible to order more than one of each",
43+
target: "$.cart"
44+
}));
45+
46+
const operations = [
47+
{
48+
validationAdd: {
49+
errors
50+
},
51+
},
52+
];
53+
54+
return { operations };
55+
};
56+
{%- endif -%}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
{%- if flavor contains "vanilla-js" -%}
2+
import { describe, it, expect } from 'vitest';
3+
import { cartValidationsGenerateRun } from './cart_validations_generate_run';
4+
5+
/**
6+
* @typedef {import("../generated/api").CartValidationsGenerateRunResult} CartValidationsGenerateRunResult
7+
*/
8+
9+
describe('cart checkout validation function', () => {
10+
it('returns an error when quantity exceeds one', () => {
11+
const result = cartValidationsGenerateRun({
12+
cart: {
13+
lines: [
14+
{
15+
quantity: 3
16+
}
17+
]
18+
}
19+
});
20+
const expected = /** @type {CartValidationsGenerateRunResult} */ ({
21+
operations: [
22+
{
23+
validationAdd: {
24+
errors: [
25+
{
26+
message: "Not possible to order more than one of each",
27+
target: "$.cart"
28+
}
29+
]
30+
}
31+
}
32+
]
33+
});
34+
35+
expect(result).toEqual(expected);
36+
});
37+
38+
it('returns no errors when quantity is one', () => {
39+
const result = cartValidationsGenerateRun({
40+
cart: {
41+
lines: [
42+
{
43+
quantity: 1
44+
}
45+
]
46+
}
47+
});
48+
const expected = /** @type {CartValidationsGenerateRunResult} */ ({
49+
operations: [
50+
{
51+
validationAdd: {
52+
errors: []
53+
}
54+
}
55+
]
56+
});
57+
58+
expect(result).toEqual(expected);
59+
});
60+
});
61+
62+
{%- elsif flavor contains "typescript" -%}
63+
import { describe, it, expect } from 'vitest';
64+
import { cartValidationsGenerateRun } from './cart_validations_generate_run';
65+
import { CartValidationsGenerateRunResult } from "../generated/api";
66+
67+
describe('cart checkout validation function', () => {
68+
it('returns an error when quantity exceeds one', () => {
69+
const result = cartValidationsGenerateRun({
70+
cart: {
71+
lines: [
72+
{
73+
quantity: 3
74+
}
75+
]
76+
}
77+
});
78+
const expected: CartValidationsGenerateRunResult = {
79+
operations: [
80+
{
81+
validationAdd: {
82+
errors: [
83+
{
84+
message: "Not possible to order more than one of each",
85+
target: "$.cart"
86+
}
87+
]
88+
}
89+
}
90+
]
91+
};
92+
93+
expect(result).toEqual(expected);
94+
});
95+
96+
it('returns no errors when quantity is one', () => {
97+
const result = cartValidationsGenerateRun({
98+
cart: {
99+
lines: [
100+
{
101+
quantity: 1
102+
}
103+
]
104+
}
105+
});
106+
const expected: CartValidationsGenerateRunResult = {
107+
operations: [
108+
{
109+
validationAdd: {
110+
errors: []
111+
}
112+
}
113+
]
114+
};
115+
116+
expect(result).toEqual(expected);
117+
});
118+
});
119+
{%- endif -%}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './run';
1+
export * from './cart_validations_generate_run';

0 commit comments

Comments
 (0)