diff --git a/discounts/javascript/discount/default/package.json.liquid b/discounts/javascript/discount/default/package.json.liquid new file mode 100644 index 00000000..b4a20dad --- /dev/null +++ b/discounts/javascript/discount/default/package.json.liquid @@ -0,0 +1,30 @@ +{ + "name": "{{handle}}", + "version": "0.0.1", + "license": "UNLICENSED", + "scripts": { + "shopify": "npm exec -- shopify", + "typegen": "npm exec -- shopify app function typegen", + "build": "npm exec -- shopify app function build", + "preview": "npm exec -- shopify app function run", + "test": "vitest" + }, + "codegen": { + "schema": "schema.graphql", + "documents": "src/*.graphql", + "generates": { + "./generated/api.ts": { + "plugins": [ + "typescript", + "typescript-operations" + ] + } + }, + "config": { + "omitOperationSuffix": true + } + }, + "devDependencies": { + "vitest": "^0.29.8" + } +} diff --git a/discounts/javascript/discount/default/schema.graphql b/discounts/javascript/discount/default/schema.graphql new file mode 100644 index 00000000..2c2f866b --- /dev/null +++ b/discounts/javascript/discount/default/schema.graphql @@ -0,0 +1,5172 @@ +schema { + query: Input + mutation: MutationRoot +} + +""" +Only allow the field to be queried when targeting one of the specified targets. +""" +directive @restrictTarget(only: [String!]!) on FIELD_DEFINITION + +""" +Scale the Functions resource limits based on the field's length. +""" +directive @scaleLimits(rate: Float!) on FIELD_DEFINITION + +""" +Requires that exactly one field must be supplied and that field must not be `null`. +""" +directive @oneOf on INPUT_OBJECT + +""" +A discount code that is associated with a discount candidate. +""" +input AssociatedDiscountCode { + """ + The discount code. + """ + code: String! +} + +""" +Represents a generic custom attribute, such as whether an order is a customer's first. +""" +type Attribute { + """ + The key or name of the attribute. For example, `"customersFirstOrder"`. + """ + key: String! + + """ + The value of the attribute. For example, `"true"`. + """ + value: String +} + +""" +Represents information about the buyer that is interacting with the cart. +""" +type BuyerIdentity { + """ + The customer associated with the cart. + """ + customer: Customer + + """ + The email address of the buyer that's interacting with the cart. + """ + email: String + + """ + Whether the buyer authenticated with a customer account. + """ + isAuthenticated: Boolean! + + """ + The phone number of the buyer that's interacting with the cart. + """ + phone: String + + """ + The purchasing company associated with the cart. + """ + purchasingCompany: PurchasingCompany +} + +""" +A cart represents the merchandise that a buyer intends to purchase, and the cost associated with the cart. +""" +type Cart { + """ + The attributes associated with the cart. Attributes are represented as key-value pairs. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + Information about the buyer that is interacting with the cart. + """ + buyerIdentity: BuyerIdentity + + """ + The costs that the buyer will pay at checkout. + """ + cost: CartCost! + + """ + A list of lines containing information about the items that can be delivered. + """ + deliverableLines: [DeliverableCartLine!]! + + """ + The delivery groups available for the cart based on the buyer's shipping address. + """ + deliveryGroups: [CartDeliveryGroup!]! + + """ + A list of lines containing information about the items the customer intends to purchase. + """ + lines: [CartLine!]! @scaleLimits(rate: 0.005) + + """ + The localized fields available for the cart. + """ + localizedFields( + """ + The keys of the localized fields to retrieve. + """ + keys: [LocalizedFieldKey!]! = [] + ): [LocalizedField!]! +} + +""" +The cost that the buyer will pay at checkout. +""" +type CartCost { + """ + The amount, before taxes and discounts, for the customer to pay. + """ + subtotalAmount: MoneyV2! + + """ + The total amount for the customer to pay. + """ + totalAmount: MoneyV2! + + """ + The duty amount for the customer to pay at checkout. + """ + totalDutyAmount: MoneyV2 + + """ + The tax amount for the customer to pay at checkout. + """ + totalTaxAmount: MoneyV2 +} + +""" +Information about the options available for one or more line items to be delivered to a specific address. +""" +type CartDeliveryGroup { + """ + A list of cart lines for the delivery group. + """ + cartLines: [CartLine!]! @scaleLimits(rate: 0.005) + + """ + The destination address for the delivery group. + """ + deliveryAddress: MailingAddress + + """ + The delivery options available for the delivery group. + """ + deliveryOptions: [CartDeliveryOption!]! + + """ + Unique identifier for the delivery group. + """ + id: ID! + + """ + Information about the delivery option the buyer has selected. + """ + selectedDeliveryOption: CartDeliveryOption +} + +""" +Information about a delivery option. +""" +type CartDeliveryOption { + """ + The code of the delivery option. + """ + code: String + + """ + The cost for the delivery option. + """ + cost: MoneyV2! + + """ + The method for the delivery option. + """ + deliveryMethodType: DeliveryMethod! + + """ + The description of the delivery option. + """ + description: String + + """ + The unique identifier of the delivery option. + """ + handle: Handle! + + """ + The title of the delivery option. + """ + title: String +} + +""" +Represents information about the merchandise in the cart. +""" +type CartLine { + """ + Retrieve a cart line attribute by key. + + Cart line attributes are also known as line item properties in Liquid. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + The cost of the merchandise line that the buyer will pay at checkout. + """ + cost: CartLineCost! + + """ + The ID of the cart line. + """ + id: ID! + + """ + The merchandise that the buyer intends to purchase. + """ + merchandise: Merchandise! + + """ + The quantity of the merchandise that the customer intends to purchase. + """ + quantity: Int! + + """ + The selling plan associated with the cart line and the effect that each + selling plan has on variants when they're purchased. + """ + sellingPlanAllocation: SellingPlanAllocation +} + +""" +The cost of the merchandise line that the buyer will pay at checkout. +""" +type CartLineCost { + """ + The amount of the merchandise line. + """ + amountPerQuantity: MoneyV2! + + """ + The compare at amount of the merchandise line. This value varies depending on + the buyer's identity, and is null when the value is hidden to buyers. + """ + compareAtAmountPerQuantity: MoneyV2 + + """ + The cost of the merchandise line before line-level discounts. + """ + subtotalAmount: MoneyV2! + + """ + The total cost of the merchandise line. + """ + totalAmount: MoneyV2! +} + +""" +The condition for checking the minimum quantity of products across a group of cart lines. +""" +input CartLineMinimumQuantity { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum quantity purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum quantity of a product. + """ + minimumQuantity: Int! +} + +""" +The condition for checking the minimum subtotal of products across a group of cart lines. +""" +input CartLineMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum subtotal purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum subtotal amount of the product. + """ + minimumAmount: Decimal! +} + +""" +A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. +""" +input CartLineTarget { + """ + The ID of the targeted cart line. + """ + id: ID! + + """ + The number of line items that are being discounted. + The default value is `null`, which represents the quantity of the matching line items. + + The value is validated against: > 0. + """ + quantity: Int +} + +""" +The operations that can be performed to apply discounts to the cart. +""" +input CartOperation @oneOf { + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes + + """ + A group of order discounts that share a selection strategy. + """ + addOrderDiscounts: OrderDiscounts + + """ + A group of product discounts that share a selection strategy. + """ + addProductDiscounts: ProductDiscounts +} + +""" +Represents whether the product is a member of the given collection. +""" +type CollectionMembership { + """ + The ID of the collection. + """ + collectionId: ID! + + """ + Whether the product is a member of the collection. + """ + isMember: Boolean! +} + +""" +Represents information about a company which is also a customer of the shop. +""" +type Company implements HasMetafields { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was created in Shopify. + """ + createdAt: DateTime! + + """ + A unique externally-supplied ID for the company. + """ + externalId: String + + """ + The ID of the company. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the company. + """ + name: String! + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was last modified. + """ + updatedAt: DateTime! +} + +""" +A company's main point of contact. +""" +type CompanyContact { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company contact was created in Shopify. + """ + createdAt: DateTime! + + """ + The ID of the company. + """ + id: ID! + + """ + The company contact's locale (language). + """ + locale: String + + """ + The company contact's job title. + """ + title: String + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company contact was last modified. + """ + updatedAt: DateTime! +} + +""" +A company's location. +""" +type CompanyLocation implements HasMetafields { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company location was created in Shopify. + """ + createdAt: DateTime! + + """ + A unique externally-supplied ID for the company. + """ + externalId: String + + """ + The ID of the company. + """ + id: ID! + + """ + The preferred locale of the company location. + """ + locale: String + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the company location. + """ + name: String! + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company location was last modified. + """ + updatedAt: DateTime! +} + +""" +The condition to apply the discount candidate. +""" +input Condition @oneOf { + """ + The condition for checking the minimum quantity of products across a group of cart lines. + """ + cartLineMinimumQuantity: CartLineMinimumQuantity + + """ + The condition for checking the minimum subtotal of products across a group of cart lines. + """ + cartLineMinimumSubtotal: CartLineMinimumSubtotal + + """ + The condition for checking the minimum subtotal amount of the order. + """ + orderMinimumSubtotal: OrderMinimumSubtotal +} + +""" +A country. +""" +type Country { + """ + The ISO code of the country. + """ + isoCode: CountryCode! +} + +""" +The code designating a country/region, which generally follows ISO 3166-1 alpha-2 guidelines. +If a territory doesn't have a country code value in the `CountryCode` enum, then it might be considered a subdivision +of another country. For example, the territories associated with Spain are represented by the country code `ES`, +and the territories associated with the United States of America are represented by the country code `US`. +""" +enum CountryCode { + """ + Ascension Island. + """ + AC + + """ + Andorra. + """ + AD + + """ + United Arab Emirates. + """ + AE + + """ + Afghanistan. + """ + AF + + """ + Antigua & Barbuda. + """ + AG + + """ + Anguilla. + """ + AI + + """ + Albania. + """ + AL + + """ + Armenia. + """ + AM + + """ + Netherlands Antilles. + """ + AN + + """ + Angola. + """ + AO + + """ + Argentina. + """ + AR + + """ + Austria. + """ + AT + + """ + Australia. + """ + AU + + """ + Aruba. + """ + AW + + """ + Åland Islands. + """ + AX + + """ + Azerbaijan. + """ + AZ + + """ + Bosnia & Herzegovina. + """ + BA + + """ + Barbados. + """ + BB + + """ + Bangladesh. + """ + BD + + """ + Belgium. + """ + BE + + """ + Burkina Faso. + """ + BF + + """ + Bulgaria. + """ + BG + + """ + Bahrain. + """ + BH + + """ + Burundi. + """ + BI + + """ + Benin. + """ + BJ + + """ + St. Barthélemy. + """ + BL + + """ + Bermuda. + """ + BM + + """ + Brunei. + """ + BN + + """ + Bolivia. + """ + BO + + """ + Caribbean Netherlands. + """ + BQ + + """ + Brazil. + """ + BR + + """ + Bahamas. + """ + BS + + """ + Bhutan. + """ + BT + + """ + Bouvet Island. + """ + BV + + """ + Botswana. + """ + BW + + """ + Belarus. + """ + BY + + """ + Belize. + """ + BZ + + """ + Canada. + """ + CA + + """ + Cocos (Keeling) Islands. + """ + CC + + """ + Congo - Kinshasa. + """ + CD + + """ + Central African Republic. + """ + CF + + """ + Congo - Brazzaville. + """ + CG + + """ + Switzerland. + """ + CH + + """ + Côte d’Ivoire. + """ + CI + + """ + Cook Islands. + """ + CK + + """ + Chile. + """ + CL + + """ + Cameroon. + """ + CM + + """ + China. + """ + CN + + """ + Colombia. + """ + CO + + """ + Costa Rica. + """ + CR + + """ + Cuba. + """ + CU + + """ + Cape Verde. + """ + CV + + """ + Curaçao. + """ + CW + + """ + Christmas Island. + """ + CX + + """ + Cyprus. + """ + CY + + """ + Czechia. + """ + CZ + + """ + Germany. + """ + DE + + """ + Djibouti. + """ + DJ + + """ + Denmark. + """ + DK + + """ + Dominica. + """ + DM + + """ + Dominican Republic. + """ + DO + + """ + Algeria. + """ + DZ + + """ + Ecuador. + """ + EC + + """ + Estonia. + """ + EE + + """ + Egypt. + """ + EG + + """ + Western Sahara. + """ + EH + + """ + Eritrea. + """ + ER + + """ + Spain. + """ + ES + + """ + Ethiopia. + """ + ET + + """ + Finland. + """ + FI + + """ + Fiji. + """ + FJ + + """ + Falkland Islands. + """ + FK + + """ + Faroe Islands. + """ + FO + + """ + France. + """ + FR + + """ + Gabon. + """ + GA + + """ + United Kingdom. + """ + GB + + """ + Grenada. + """ + GD + + """ + Georgia. + """ + GE + + """ + French Guiana. + """ + GF + + """ + Guernsey. + """ + GG + + """ + Ghana. + """ + GH + + """ + Gibraltar. + """ + GI + + """ + Greenland. + """ + GL + + """ + Gambia. + """ + GM + + """ + Guinea. + """ + GN + + """ + Guadeloupe. + """ + GP + + """ + Equatorial Guinea. + """ + GQ + + """ + Greece. + """ + GR + + """ + South Georgia & South Sandwich Islands. + """ + GS + + """ + Guatemala. + """ + GT + + """ + Guinea-Bissau. + """ + GW + + """ + Guyana. + """ + GY + + """ + Hong Kong SAR. + """ + HK + + """ + Heard & McDonald Islands. + """ + HM + + """ + Honduras. + """ + HN + + """ + Croatia. + """ + HR + + """ + Haiti. + """ + HT + + """ + Hungary. + """ + HU + + """ + Indonesia. + """ + ID + + """ + Ireland. + """ + IE + + """ + Israel. + """ + IL + + """ + Isle of Man. + """ + IM + + """ + India. + """ + IN + + """ + British Indian Ocean Territory. + """ + IO + + """ + Iraq. + """ + IQ + + """ + Iran. + """ + IR + + """ + Iceland. + """ + IS + + """ + Italy. + """ + IT + + """ + Jersey. + """ + JE + + """ + Jamaica. + """ + JM + + """ + Jordan. + """ + JO + + """ + Japan. + """ + JP + + """ + Kenya. + """ + KE + + """ + Kyrgyzstan. + """ + KG + + """ + Cambodia. + """ + KH + + """ + Kiribati. + """ + KI + + """ + Comoros. + """ + KM + + """ + St. Kitts & Nevis. + """ + KN + + """ + North Korea. + """ + KP + + """ + South Korea. + """ + KR + + """ + Kuwait. + """ + KW + + """ + Cayman Islands. + """ + KY + + """ + Kazakhstan. + """ + KZ + + """ + Laos. + """ + LA + + """ + Lebanon. + """ + LB + + """ + St. Lucia. + """ + LC + + """ + Liechtenstein. + """ + LI + + """ + Sri Lanka. + """ + LK + + """ + Liberia. + """ + LR + + """ + Lesotho. + """ + LS + + """ + Lithuania. + """ + LT + + """ + Luxembourg. + """ + LU + + """ + Latvia. + """ + LV + + """ + Libya. + """ + LY + + """ + Morocco. + """ + MA + + """ + Monaco. + """ + MC + + """ + Moldova. + """ + MD + + """ + Montenegro. + """ + ME + + """ + St. Martin. + """ + MF + + """ + Madagascar. + """ + MG + + """ + North Macedonia. + """ + MK + + """ + Mali. + """ + ML + + """ + Myanmar (Burma). + """ + MM + + """ + Mongolia. + """ + MN + + """ + Macao SAR. + """ + MO + + """ + Martinique. + """ + MQ + + """ + Mauritania. + """ + MR + + """ + Montserrat. + """ + MS + + """ + Malta. + """ + MT + + """ + Mauritius. + """ + MU + + """ + Maldives. + """ + MV + + """ + Malawi. + """ + MW + + """ + Mexico. + """ + MX + + """ + Malaysia. + """ + MY + + """ + Mozambique. + """ + MZ + + """ + Namibia. + """ + NA + + """ + New Caledonia. + """ + NC + + """ + Niger. + """ + NE + + """ + Norfolk Island. + """ + NF + + """ + Nigeria. + """ + NG + + """ + Nicaragua. + """ + NI + + """ + Netherlands. + """ + NL + + """ + Norway. + """ + NO + + """ + Nepal. + """ + NP + + """ + Nauru. + """ + NR + + """ + Niue. + """ + NU + + """ + New Zealand. + """ + NZ + + """ + Oman. + """ + OM + + """ + Panama. + """ + PA + + """ + Peru. + """ + PE + + """ + French Polynesia. + """ + PF + + """ + Papua New Guinea. + """ + PG + + """ + Philippines. + """ + PH + + """ + Pakistan. + """ + PK + + """ + Poland. + """ + PL + + """ + St. Pierre & Miquelon. + """ + PM + + """ + Pitcairn Islands. + """ + PN + + """ + Palestinian Territories. + """ + PS + + """ + Portugal. + """ + PT + + """ + Paraguay. + """ + PY + + """ + Qatar. + """ + QA + + """ + Réunion. + """ + RE + + """ + Romania. + """ + RO + + """ + Serbia. + """ + RS + + """ + Russia. + """ + RU + + """ + Rwanda. + """ + RW + + """ + Saudi Arabia. + """ + SA + + """ + Solomon Islands. + """ + SB + + """ + Seychelles. + """ + SC + + """ + Sudan. + """ + SD + + """ + Sweden. + """ + SE + + """ + Singapore. + """ + SG + + """ + St. Helena. + """ + SH + + """ + Slovenia. + """ + SI + + """ + Svalbard & Jan Mayen. + """ + SJ + + """ + Slovakia. + """ + SK + + """ + Sierra Leone. + """ + SL + + """ + San Marino. + """ + SM + + """ + Senegal. + """ + SN + + """ + Somalia. + """ + SO + + """ + Suriname. + """ + SR + + """ + South Sudan. + """ + SS + + """ + São Tomé & Príncipe. + """ + ST + + """ + El Salvador. + """ + SV + + """ + Sint Maarten. + """ + SX + + """ + Syria. + """ + SY + + """ + Eswatini. + """ + SZ + + """ + Tristan da Cunha. + """ + TA + + """ + Turks & Caicos Islands. + """ + TC + + """ + Chad. + """ + TD + + """ + French Southern Territories. + """ + TF + + """ + Togo. + """ + TG + + """ + Thailand. + """ + TH + + """ + Tajikistan. + """ + TJ + + """ + Tokelau. + """ + TK + + """ + Timor-Leste. + """ + TL + + """ + Turkmenistan. + """ + TM + + """ + Tunisia. + """ + TN + + """ + Tonga. + """ + TO + + """ + Türkiye. + """ + TR + + """ + Trinidad & Tobago. + """ + TT + + """ + Tuvalu. + """ + TV + + """ + Taiwan. + """ + TW + + """ + Tanzania. + """ + TZ + + """ + Ukraine. + """ + UA + + """ + Uganda. + """ + UG + + """ + U.S. Outlying Islands. + """ + UM + + """ + United States. + """ + US + + """ + Uruguay. + """ + UY + + """ + Uzbekistan. + """ + UZ + + """ + Vatican City. + """ + VA + + """ + St. Vincent & Grenadines. + """ + VC + + """ + Venezuela. + """ + VE + + """ + British Virgin Islands. + """ + VG + + """ + Vietnam. + """ + VN + + """ + Vanuatu. + """ + VU + + """ + Wallis & Futuna. + """ + WF + + """ + Samoa. + """ + WS + + """ + Kosovo. + """ + XK + + """ + Yemen. + """ + YE + + """ + Mayotte. + """ + YT + + """ + South Africa. + """ + ZA + + """ + Zambia. + """ + ZM + + """ + Zimbabwe. + """ + ZW + + """ + Unknown Region. + """ + ZZ +} + +""" +The three-letter currency codes that represent the world currencies used in +stores. These include standard ISO 4217 codes, legacy codes, +and non-standard codes. +""" +enum CurrencyCode { + """ + United Arab Emirates Dirham (AED). + """ + AED + + """ + Afghan Afghani (AFN). + """ + AFN + + """ + Albanian Lek (ALL). + """ + ALL + + """ + Armenian Dram (AMD). + """ + AMD + + """ + Netherlands Antillean Guilder. + """ + ANG + + """ + Angolan Kwanza (AOA). + """ + AOA + + """ + Argentine Pesos (ARS). + """ + ARS + + """ + Australian Dollars (AUD). + """ + AUD + + """ + Aruban Florin (AWG). + """ + AWG + + """ + Azerbaijani Manat (AZN). + """ + AZN + + """ + Bosnia and Herzegovina Convertible Mark (BAM). + """ + BAM + + """ + Barbadian Dollar (BBD). + """ + BBD + + """ + Bangladesh Taka (BDT). + """ + BDT + + """ + Bulgarian Lev (BGN). + """ + BGN + + """ + Bahraini Dinar (BHD). + """ + BHD + + """ + Burundian Franc (BIF). + """ + BIF + + """ + Bermudian Dollar (BMD). + """ + BMD + + """ + Brunei Dollar (BND). + """ + BND + + """ + Bolivian Boliviano (BOB). + """ + BOB + + """ + Brazilian Real (BRL). + """ + BRL + + """ + Bahamian Dollar (BSD). + """ + BSD + + """ + Bhutanese Ngultrum (BTN). + """ + BTN + + """ + Botswana Pula (BWP). + """ + BWP + + """ + Belarusian Ruble (BYN). + """ + BYN + + """ + Belarusian Ruble (BYR). + """ + BYR @deprecated(reason: "`BYR` is deprecated. Use `BYN` available from version `2021-01` onwards instead.") + + """ + Belize Dollar (BZD). + """ + BZD + + """ + Canadian Dollars (CAD). + """ + CAD + + """ + Congolese franc (CDF). + """ + CDF + + """ + Swiss Francs (CHF). + """ + CHF + + """ + Chilean Peso (CLP). + """ + CLP + + """ + Chinese Yuan Renminbi (CNY). + """ + CNY + + """ + Colombian Peso (COP). + """ + COP + + """ + Costa Rican Colones (CRC). + """ + CRC + + """ + Cape Verdean escudo (CVE). + """ + CVE + + """ + Czech Koruny (CZK). + """ + CZK + + """ + Djiboutian Franc (DJF). + """ + DJF + + """ + Danish Kroner (DKK). + """ + DKK + + """ + Dominican Peso (DOP). + """ + DOP + + """ + Algerian Dinar (DZD). + """ + DZD + + """ + Egyptian Pound (EGP). + """ + EGP + + """ + Eritrean Nakfa (ERN). + """ + ERN + + """ + Ethiopian Birr (ETB). + """ + ETB + + """ + Euro (EUR). + """ + EUR + + """ + Fijian Dollars (FJD). + """ + FJD + + """ + Falkland Islands Pounds (FKP). + """ + FKP + + """ + United Kingdom Pounds (GBP). + """ + GBP + + """ + Georgian Lari (GEL). + """ + GEL + + """ + Ghanaian Cedi (GHS). + """ + GHS + + """ + Gibraltar Pounds (GIP). + """ + GIP + + """ + Gambian Dalasi (GMD). + """ + GMD + + """ + Guinean Franc (GNF). + """ + GNF + + """ + Guatemalan Quetzal (GTQ). + """ + GTQ + + """ + Guyanese Dollar (GYD). + """ + GYD + + """ + Hong Kong Dollars (HKD). + """ + HKD + + """ + Honduran Lempira (HNL). + """ + HNL + + """ + Croatian Kuna (HRK). + """ + HRK + + """ + Haitian Gourde (HTG). + """ + HTG + + """ + Hungarian Forint (HUF). + """ + HUF + + """ + Indonesian Rupiah (IDR). + """ + IDR + + """ + Israeli New Shekel (NIS). + """ + ILS + + """ + Indian Rupees (INR). + """ + INR + + """ + Iraqi Dinar (IQD). + """ + IQD + + """ + Iranian Rial (IRR). + """ + IRR + + """ + Icelandic Kronur (ISK). + """ + ISK + + """ + Jersey Pound. + """ + JEP + + """ + Jamaican Dollars (JMD). + """ + JMD + + """ + Jordanian Dinar (JOD). + """ + JOD + + """ + Japanese Yen (JPY). + """ + JPY + + """ + Kenyan Shilling (KES). + """ + KES + + """ + Kyrgyzstani Som (KGS). + """ + KGS + + """ + Cambodian Riel. + """ + KHR + + """ + Kiribati Dollar (KID). + """ + KID + + """ + Comorian Franc (KMF). + """ + KMF + + """ + South Korean Won (KRW). + """ + KRW + + """ + Kuwaiti Dinar (KWD). + """ + KWD + + """ + Cayman Dollars (KYD). + """ + KYD + + """ + Kazakhstani Tenge (KZT). + """ + KZT + + """ + Laotian Kip (LAK). + """ + LAK + + """ + Lebanese Pounds (LBP). + """ + LBP + + """ + Sri Lankan Rupees (LKR). + """ + LKR + + """ + Liberian Dollar (LRD). + """ + LRD + + """ + Lesotho Loti (LSL). + """ + LSL + + """ + Lithuanian Litai (LTL). + """ + LTL + + """ + Latvian Lati (LVL). + """ + LVL + + """ + Libyan Dinar (LYD). + """ + LYD + + """ + Moroccan Dirham. + """ + MAD + + """ + Moldovan Leu (MDL). + """ + MDL + + """ + Malagasy Ariary (MGA). + """ + MGA + + """ + Macedonia Denar (MKD). + """ + MKD + + """ + Burmese Kyat (MMK). + """ + MMK + + """ + Mongolian Tugrik. + """ + MNT + + """ + Macanese Pataca (MOP). + """ + MOP + + """ + Mauritanian Ouguiya (MRU). + """ + MRU + + """ + Mauritian Rupee (MUR). + """ + MUR + + """ + Maldivian Rufiyaa (MVR). + """ + MVR + + """ + Malawian Kwacha (MWK). + """ + MWK + + """ + Mexican Pesos (MXN). + """ + MXN + + """ + Malaysian Ringgits (MYR). + """ + MYR + + """ + Mozambican Metical. + """ + MZN + + """ + Namibian Dollar. + """ + NAD + + """ + Nigerian Naira (NGN). + """ + NGN + + """ + Nicaraguan Córdoba (NIO). + """ + NIO + + """ + Norwegian Kroner (NOK). + """ + NOK + + """ + Nepalese Rupee (NPR). + """ + NPR + + """ + New Zealand Dollars (NZD). + """ + NZD + + """ + Omani Rial (OMR). + """ + OMR + + """ + Panamian Balboa (PAB). + """ + PAB + + """ + Peruvian Nuevo Sol (PEN). + """ + PEN + + """ + Papua New Guinean Kina (PGK). + """ + PGK + + """ + Philippine Peso (PHP). + """ + PHP + + """ + Pakistani Rupee (PKR). + """ + PKR + + """ + Polish Zlotych (PLN). + """ + PLN + + """ + Paraguayan Guarani (PYG). + """ + PYG + + """ + Qatari Rial (QAR). + """ + QAR + + """ + Romanian Lei (RON). + """ + RON + + """ + Serbian dinar (RSD). + """ + RSD + + """ + Russian Rubles (RUB). + """ + RUB + + """ + Rwandan Franc (RWF). + """ + RWF + + """ + Saudi Riyal (SAR). + """ + SAR + + """ + Solomon Islands Dollar (SBD). + """ + SBD + + """ + Seychellois Rupee (SCR). + """ + SCR + + """ + Sudanese Pound (SDG). + """ + SDG + + """ + Swedish Kronor (SEK). + """ + SEK + + """ + Singapore Dollars (SGD). + """ + SGD + + """ + Saint Helena Pounds (SHP). + """ + SHP + + """ + Sierra Leonean Leone (SLL). + """ + SLL + + """ + Somali Shilling (SOS). + """ + SOS + + """ + Surinamese Dollar (SRD). + """ + SRD + + """ + South Sudanese Pound (SSP). + """ + SSP + + """ + Sao Tome And Principe Dobra (STD). + """ + STD @deprecated(reason: "`STD` is deprecated. Use `STN` available from version `2022-07` onwards instead.") + + """ + Sao Tome And Principe Dobra (STN). + """ + STN + + """ + Syrian Pound (SYP). + """ + SYP + + """ + Swazi Lilangeni (SZL). + """ + SZL + + """ + Thai baht (THB). + """ + THB + + """ + Tajikistani Somoni (TJS). + """ + TJS + + """ + Turkmenistani Manat (TMT). + """ + TMT + + """ + Tunisian Dinar (TND). + """ + TND + + """ + Tongan Pa'anga (TOP). + """ + TOP + + """ + Turkish Lira (TRY). + """ + TRY + + """ + Trinidad and Tobago Dollars (TTD). + """ + TTD + + """ + Taiwan Dollars (TWD). + """ + TWD + + """ + Tanzanian Shilling (TZS). + """ + TZS + + """ + Ukrainian Hryvnia (UAH). + """ + UAH + + """ + Ugandan Shilling (UGX). + """ + UGX + + """ + United States Dollars (USD). + """ + USD + + """ + Uruguayan Pesos (UYU). + """ + UYU + + """ + Uzbekistan som (UZS). + """ + UZS + + """ + Venezuelan Bolivares (VED). + """ + VED + + """ + Venezuelan Bolivares (VEF). + """ + VEF @deprecated(reason: "`VEF` is deprecated. Use `VES` available from version `2020-10` onwards instead.") + + """ + Venezuelan Bolivares Soberanos (VES). + """ + VES + + """ + Vietnamese đồng (VND). + """ + VND + + """ + Vanuatu Vatu (VUV). + """ + VUV + + """ + Samoan Tala (WST). + """ + WST + + """ + Central African CFA Franc (XAF). + """ + XAF + + """ + East Caribbean Dollar (XCD). + """ + XCD + + """ + West African CFA franc (XOF). + """ + XOF + + """ + CFP Franc (XPF). + """ + XPF + + """ + Unrecognized currency. + """ + XXX + + """ + Yemeni Rial (YER). + """ + YER + + """ + South African Rand (ZAR). + """ + ZAR + + """ + Zambian Kwacha (ZMW). + """ + ZMW +} + +""" +A custom product. +""" +type CustomProduct { + """ + Whether the merchandise is a gift card. + """ + isGiftCard: Boolean! + + """ + Whether the merchandise requires shipping. + """ + requiresShipping: Boolean! + + """ + The localized title of the product in the customer’s locale. + """ + title: String! + + """ + The weight of the product variant in the unit system specified with `weight_unit`. + """ + weight: Float + + """ + Unit of measurement for weight. + """ + weightUnit: WeightUnit! +} + +""" +Represents a customer with the shop. +""" +type Customer implements HasMetafields { + """ + The total amount of money spent by the customer. Converted from the shop's + currency to the currency of the cart using a market rate. + """ + amountSpent: MoneyV2! + + """ + The customer’s name, email or phone number. + """ + displayName: String! + + """ + The customer’s email address. + """ + email: String + + """ + The customer's first name. + """ + firstName: String + + """ + Whether the customer has any of the given tags. + """ + hasAnyTag( + """ + The tags to search for. + """ + tags: [String!]! = [] + ): Boolean! + + """ + Whether the customer has the given tags. + """ + hasTags( + """ + The tags to check. + """ + tags: [String!]! = [] + ): [HasTagResponse!]! + + """ + A unique identifier for the customer. + """ + id: ID! + + """ + The customer's last name. + """ + lastName: String + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The number of orders made by the customer. + """ + numberOfOrders: Int! +} + +""" +Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date string. +For example, September 7, 2019 is represented as `"2019-07-16"`. +""" +scalar Date + +""" +Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date and time string. +For example, 3:50 pm on September 7, 2019 in the time zone of UTC (Coordinated Universal Time) is +represented as `"2019-09-07T15:50:00Z`". +""" +scalar DateTime + +""" +A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that +includes the date and time but not the timezone which is determined from context. + +For example, "2018-01-01T00:00:00". +""" +scalar DateTimeWithoutTimezone + +""" +A signed decimal number, which supports arbitrary precision and is serialized as a string. + +Example values: `"29.99"`, `"29.999"`. +""" +scalar Decimal + +""" +Represents information about the merchandise in the cart. +""" +type DeliverableCartLine { + """ + Retrieve a cart line attribute by key. + + Cart line attributes are also known as line item properties in Liquid. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + The ID of the cart line. + """ + id: ID! + + """ + The merchandise that the buyer intends to purchase. + """ + merchandise: Merchandise! + + """ + The quantity of the merchandise that the customer intends to purchase. + """ + quantity: Int! +} + +""" +The delivery discount candidate to be applied. +""" +input DeliveryDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The discount message. + """ + message: String + + """ + The targets of the delivery discount candidate. + """ + targets: [DeliveryDiscountCandidateTarget!]! + + """ + The value of the delivery discount candidate. + """ + value: DeliveryDiscountCandidateValue! +} + +""" +The target of the delivery discount candidate. +""" +input DeliveryDiscountCandidateTarget @oneOf { + """ + The target delivery group. + """ + deliveryGroup: DeliveryGroupTarget + + """ + The target delivery option. + """ + deliveryOption: DeliveryOptionTarget +} + +""" +The delivery discount candidate value. +""" +input DeliveryDiscountCandidateValue @oneOf { + """ + A fixed amount value. + """ + fixedAmount: FixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of delivery discount candidates. +""" +enum DeliveryDiscountSelectionStrategy { + """ + Apply all delivery discount candidates with conditions that are satisfied. This does not override + discount combination or stacking rules. + """ + ALL +} + +""" +A group of delivery discounts that share a selection strategy. +""" +input DeliveryDiscounts { + """ + The list of delivery discount candidates to be applied. + """ + candidates: [DeliveryDiscountCandidate!]! + + """ + The strategy that's applied to the list of discounts. + """ + selectionStrategy: DeliveryDiscountSelectionStrategy! +} + +""" +The target delivery group. +""" +input DeliveryGroupTarget { + """ + The ID of the target delivery group. + """ + id: ID! +} + +""" +List of different delivery method types. +""" +enum DeliveryMethod { + """ + Local Delivery. + """ + LOCAL + + """ + None. + """ + NONE + + """ + Shipping to a Pickup Point. + """ + PICKUP_POINT + + """ + Local Pickup. + """ + PICK_UP + + """ + Retail. + """ + RETAIL + + """ + Shipping. + """ + SHIPPING +} + +""" +The operations that can be performed to apply discounts to the delivery lines. +""" +input DeliveryOperation @oneOf { + """ + A group of delivery discounts that share a selection strategy. + """ + addDeliveryDiscounts: DeliveryDiscounts + + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes +} + +""" +The target delivery option. +""" +input DeliveryOptionTarget { + """ + The handle of the target delivery option. + """ + handle: Handle! +} + +""" +The discount that invoked the Function. +""" +type Discount implements HasMetafields { + """ + The discount classes supported by the discount node. + """ + discountClasses: [DiscountClass!]! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +The [discount class](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) +that's used to control how discounts can be combined. +""" +enum DiscountClass { + """ + The discount is combined with an + [order discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + ORDER + + """ + The discount is combined with a + [product discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + PRODUCT + + """ + The discount is combined with a + [shipping discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + SHIPPING +} + +""" +A fixed amount value. +""" +input FixedAmount { + """ + The fixed amount value of the discount, in the currency of the cart. + + The amount must be greater than or equal to 0. + """ + amount: Decimal! +} + +""" +The cart.fetch target result. Refer to [network access] +(https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. +""" +input FunctionCartFetchResult { + """ + The http request. + """ + request: HttpRequest +} + +""" +The cart.run target result. +""" +input FunctionCartRunResult { + """ + The list of operations to apply discounts to the cart. + """ + operations: [CartOperation!]! +} + +""" +The delivery.fetch target result. Refer to +[network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. +""" +input FunctionDeliveryFetchResult { + """ + The http request. + """ + request: HttpRequest +} + +""" +The delivery.run target result. +""" +input FunctionDeliveryRunResult { + """ + The list of operations to apply discounts to the delivery lines. + """ + operations: [DeliveryOperation!]! +} + +""" +Represents a gate configuration. +""" +type GateConfiguration implements HasMetafields { + """ + An optional string identifier. + """ + appId: String + + """ + A non-unique string used to group gate configurations. + """ + handle: Handle + + """ + The ID of the gate configuration. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +Represents a connection from a subject to a gate configuration. +""" +type GateSubject { + """ + The bound gate configuration. + """ + configuration( + """ + The appId of the gate configurations to search for. + """ + appId: String @deprecated(reason: "Use GateSubject.handle to filter gates instead.") + ): GateConfiguration! + + """ + The ID of the gate subject. + """ + id: ID! +} + +""" +A function-scoped handle to a refer a resource. +The Handle type appears in a JSON response as a String, but it is not intended to be human-readable. +Example value: `"10079785100"` +""" +scalar Handle + +""" +Gate subjects associated to the specified resource. +""" +interface HasGates { + """ + Returns active gate subjects bound to the resource. + """ + gates( + """ + The handle of the gate configurations to search for. + """ + handle: Handle + ): [GateSubject!]! +} + +""" +Represents information about the metafields associated to the specified resource. +""" +interface HasMetafields { + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +Represents whether the current object has the given tag. +""" +type HasTagResponse { + """ + Whether the current object has the tag. + """ + hasTag: Boolean! + + """ + The tag. + """ + tag: String! +} + +""" +The attributes associated with an HTTP request. +""" +input HttpRequest { + """ + The HTTP request body as a plain string. + Use this field when the body isn't in JSON format. + """ + body: String + + """ + The HTTP headers. + """ + headers: [HttpRequestHeader!]! + + """ + The HTTP request body as a JSON object. + Use this field when the body's in JSON format, to reduce function instruction consumption + and to ensure the body's formatted in logs. + Don't use this field together with the `body` field. If both are provided, then the `body` field + will take precedence. + If this field is specified and no `Content-Type` header is included, then the header will + automatically be set to `application/json`. + """ + jsonBody: JSON + + """ + The HTTP method. + """ + method: HttpRequestMethod! + + """ + Policy attached to the HTTP request. + """ + policy: HttpRequestPolicy! + + """ + The HTTP url (eg.: https://example.com). The scheme needs to be HTTPS. + """ + url: URL! +} + +""" +The attributes associated with an HTTP request header. +""" +input HttpRequestHeader { + """ + Header name. + """ + name: String! + + """ + Header value. + """ + value: String! +} + +""" +The HTTP request available methods. +""" +enum HttpRequestMethod { + """ + Http GET. + """ + GET + + """ + Http POST. + """ + POST +} + +""" +The attributes associated with an HTTP request policy. +""" +input HttpRequestPolicy { + """ + Read timeout in milliseconds. + """ + readTimeoutMs: Int! +} + +""" +The attributes associated with an HTTP response. +""" +type HttpResponse { + """ + The HTTP response body as a plain string. + Use this field when the body is not in JSON format. + """ + body: String + + """ + An HTTP header. + """ + header( + """ + A case-insensitive header name. + """ + name: String! + ): HttpResponseHeader + + """ + The HTTP headers. + """ + headers: [HttpResponseHeader!]! @deprecated(reason: "Use `header` instead.") + + """ + The HTTP response body parsed as JSON. + If the body is valid JSON, it will be parsed and returned as a JSON object. + If parsing fails, then raw body is returned as a string. + Use this field when you expect the response to be JSON, or when you're dealing + with mixed response types, meaning both JSON and non-JSON. + Using this field reduces function instruction consumption and ensures that the data is formatted in logs. + To prevent increasing the function target input size unnecessarily, avoid querying + both `body` and `jsonBody` simultaneously. + """ + jsonBody: JSON + + """ + The HTTP status code. + """ + status: Int! +} + +""" +The attributes associated with an HTTP response header. +""" +type HttpResponseHeader { + """ + Header name. + """ + name: String! + + """ + Header value. + """ + value: String! +} + +""" +Represents a unique identifier, often used to refetch an object. +The ID type appears in a JSON response as a String, but it is not intended to be human-readable. + +Example value: `"gid://shopify/Product/10079785100"` +""" +scalar ID + +""" +The input object for the Function. +""" +type Input { + """ + The cart. + """ + cart: Cart! + + """ + The discount node executing the Function. + """ + discount: Discount! + + """ + Discount codes entered by the buyer as an array of strings, excluding gift cards. + Codes are not validated in any way other than gift card filtering. + """ + enteredDiscountCodes: [String!]! @restrictTarget(only: ["cart.lines.discounts.generate.fetch", "cart.delivery-options.discounts.generate.fetch"]) + + """ + The result of the fetch target. Refer to [network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) + for Shopify Functions. + """ + fetchResult: HttpResponse @restrictTarget(only: ["cart.lines.discounts.generate.run", "cart.delivery-options.discounts.generate.run"]) + + """ + The localization of the Function execution context. + """ + localization: Localization! + + """ + The conversion rate between the shop's currency and the currency of the cart. + """ + presentmentCurrencyRate: Decimal! + + """ + Information about the shop. + """ + shop: Shop! + + """ + The discount code entered by the buyer that caused the Function to run. + This input is only available in the cart.lines.discounts.generate.run + and cart.delivery-options.discounts.generate.run extension targets. + """ + triggeringDiscountCode: String @restrictTarget(only: ["cart.lines.discounts.generate.run", "cart.delivery-options.discounts.generate.run"]) +} + +""" +A [JSON](https://www.json.org/json-en.html) object. + +Example value: +`{ + "product": { + "id": "gid://shopify/Product/1346443542550", + "title": "White T-shirt", + "options": [{ + "name": "Size", + "values": ["M", "L"] + }] + } +}` +""" +scalar JSON + +""" +A language. +""" +type Language { + """ + The ISO code. + """ + isoCode: LanguageCode! +} + +""" +Language codes supported by Shopify. +""" +enum LanguageCode { + """ + Afrikaans. + """ + AF + + """ + Akan. + """ + AK + + """ + Amharic. + """ + AM + + """ + Arabic. + """ + AR + + """ + Assamese. + """ + AS + + """ + Azerbaijani. + """ + AZ + + """ + Belarusian. + """ + BE + + """ + Bulgarian. + """ + BG + + """ + Bambara. + """ + BM + + """ + Bangla. + """ + BN + + """ + Tibetan. + """ + BO + + """ + Breton. + """ + BR + + """ + Bosnian. + """ + BS + + """ + Catalan. + """ + CA + + """ + Chechen. + """ + CE + + """ + Central Kurdish. + """ + CKB + + """ + Czech. + """ + CS + + """ + Church Slavic. + """ + CU + + """ + Welsh. + """ + CY + + """ + Danish. + """ + DA + + """ + German. + """ + DE + + """ + Dzongkha. + """ + DZ + + """ + Ewe. + """ + EE + + """ + Greek. + """ + EL + + """ + English. + """ + EN + + """ + Esperanto. + """ + EO + + """ + Spanish. + """ + ES + + """ + Estonian. + """ + ET + + """ + Basque. + """ + EU + + """ + Persian. + """ + FA + + """ + Fulah. + """ + FF + + """ + Finnish. + """ + FI + + """ + Filipino. + """ + FIL + + """ + Faroese. + """ + FO + + """ + French. + """ + FR + + """ + Western Frisian. + """ + FY + + """ + Irish. + """ + GA + + """ + Scottish Gaelic. + """ + GD + + """ + Galician. + """ + GL + + """ + Gujarati. + """ + GU + + """ + Manx. + """ + GV + + """ + Hausa. + """ + HA + + """ + Hebrew. + """ + HE + + """ + Hindi. + """ + HI + + """ + Croatian. + """ + HR + + """ + Hungarian. + """ + HU + + """ + Armenian. + """ + HY + + """ + Interlingua. + """ + IA + + """ + Indonesian. + """ + ID + + """ + Igbo. + """ + IG + + """ + Sichuan Yi. + """ + II + + """ + Icelandic. + """ + IS + + """ + Italian. + """ + IT + + """ + Japanese. + """ + JA + + """ + Javanese. + """ + JV + + """ + Georgian. + """ + KA + + """ + Kikuyu. + """ + KI + + """ + Kazakh. + """ + KK + + """ + Kalaallisut. + """ + KL + + """ + Khmer. + """ + KM + + """ + Kannada. + """ + KN + + """ + Korean. + """ + KO + + """ + Kashmiri. + """ + KS + + """ + Kurdish. + """ + KU + + """ + Cornish. + """ + KW + + """ + Kyrgyz. + """ + KY + + """ + Luxembourgish. + """ + LB + + """ + Ganda. + """ + LG + + """ + Lingala. + """ + LN + + """ + Lao. + """ + LO + + """ + Lithuanian. + """ + LT + + """ + Luba-Katanga. + """ + LU + + """ + Latvian. + """ + LV + + """ + Malagasy. + """ + MG + + """ + Māori. + """ + MI + + """ + Macedonian. + """ + MK + + """ + Malayalam. + """ + ML + + """ + Mongolian. + """ + MN + + """ + Marathi. + """ + MR + + """ + Malay. + """ + MS + + """ + Maltese. + """ + MT + + """ + Burmese. + """ + MY + + """ + Norwegian (Bokmål). + """ + NB + + """ + North Ndebele. + """ + ND + + """ + Nepali. + """ + NE + + """ + Dutch. + """ + NL + + """ + Norwegian Nynorsk. + """ + NN + + """ + Norwegian. + """ + NO + + """ + Oromo. + """ + OM + + """ + Odia. + """ + OR + + """ + Ossetic. + """ + OS + + """ + Punjabi. + """ + PA + + """ + Polish. + """ + PL + + """ + Pashto. + """ + PS + + """ + Portuguese. + """ + PT + + """ + Portuguese (Brazil). + """ + PT_BR + + """ + Portuguese (Portugal). + """ + PT_PT + + """ + Quechua. + """ + QU + + """ + Romansh. + """ + RM + + """ + Rundi. + """ + RN + + """ + Romanian. + """ + RO + + """ + Russian. + """ + RU + + """ + Kinyarwanda. + """ + RW + + """ + Sanskrit. + """ + SA + + """ + Sardinian. + """ + SC + + """ + Sindhi. + """ + SD + + """ + Northern Sami. + """ + SE + + """ + Sango. + """ + SG + + """ + Sinhala. + """ + SI + + """ + Slovak. + """ + SK + + """ + Slovenian. + """ + SL + + """ + Shona. + """ + SN + + """ + Somali. + """ + SO + + """ + Albanian. + """ + SQ + + """ + Serbian. + """ + SR + + """ + Sundanese. + """ + SU + + """ + Swedish. + """ + SV + + """ + Swahili. + """ + SW + + """ + Tamil. + """ + TA + + """ + Telugu. + """ + TE + + """ + Tajik. + """ + TG + + """ + Thai. + """ + TH + + """ + Tigrinya. + """ + TI + + """ + Turkmen. + """ + TK + + """ + Tongan. + """ + TO + + """ + Turkish. + """ + TR + + """ + Tatar. + """ + TT + + """ + Uyghur. + """ + UG + + """ + Ukrainian. + """ + UK + + """ + Urdu. + """ + UR + + """ + Uzbek. + """ + UZ + + """ + Vietnamese. + """ + VI + + """ + Volapük. + """ + VO + + """ + Wolof. + """ + WO + + """ + Xhosa. + """ + XH + + """ + Yiddish. + """ + YI + + """ + Yoruba. + """ + YO + + """ + Chinese. + """ + ZH + + """ + Chinese (Simplified). + """ + ZH_CN + + """ + Chinese (Traditional). + """ + ZH_TW + + """ + Zulu. + """ + ZU +} + +""" +Represents limited information about the current time relative to the parent object. +""" +type LocalTime { + """ + The current date relative to the parent object. + """ + date: Date! + + """ + Returns true if the current date and time is at or past the given date and time, and false otherwise. + """ + dateTimeAfter( + """ + The date and time to compare against, assumed to be in the timezone of the parent object. + """ + dateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current date and time is before the given date and time, and false otherwise. + """ + dateTimeBefore( + """ + The date and time to compare against, assumed to be in the timezone of the parent timezone. + """ + dateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current date and time is between the two given date and times, and false otherwise. + """ + dateTimeBetween( + """ + The upper bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + endDateTime: DateTimeWithoutTimezone! + + """ + The lower bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + startDateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is at or past the given time, and false otherwise. + """ + timeAfter( + """ + The time to compare against, assumed to be in the timezone of the parent timezone. + """ + time: TimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is at or past the given time, and false otherwise. + """ + timeBefore( + """ + The time to compare against, assumed to be in the timezone of the parent timezone. + """ + time: TimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is between the two given times, and false otherwise. + """ + timeBetween( + """ + The upper bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + endTime: TimeWithoutTimezone! + + """ + The lower bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + startTime: TimeWithoutTimezone! + ): Boolean! +} + +""" +Information about the localized experiences configured for the shop. +""" +type Localization { + """ + The country of the active localized experience. + """ + country: Country! + + """ + The language of the active localized experience. + """ + language: Language! + + """ + The market of the active localized experience. + """ + market: Market! @deprecated(reason: "This `market` field will be removed in a future version of the API.") +} + +""" +Represents the value captured by a localized field. Localized fields are +additional fields required by certain countries on international orders. For +example, some countries require additional fields for customs information or tax +identification numbers. +""" +type LocalizedField { + """ + The key of the localized field. + """ + key: LocalizedFieldKey! + + """ + The title of the localized field. + """ + title: String! + + """ + The value of the localized field. + """ + value: String +} + +""" +Unique key identifying localized fields. +""" +enum LocalizedFieldKey { + """ + Localized field key 'shipping_credential_br' for country Brazil. + """ + SHIPPING_CREDENTIAL_BR + + """ + Localized field key 'shipping_credential_cl' for country Chile. + """ + SHIPPING_CREDENTIAL_CL + + """ + Localized field key 'shipping_credential_cn' for country China. + """ + SHIPPING_CREDENTIAL_CN + + """ + Localized field key 'shipping_credential_co' for country Colombia. + """ + SHIPPING_CREDENTIAL_CO + + """ + Localized field key 'shipping_credential_cr' for country Costa Rica. + """ + SHIPPING_CREDENTIAL_CR + + """ + Localized field key 'shipping_credential_ec' for country Ecuador. + """ + SHIPPING_CREDENTIAL_EC + + """ + Localized field key 'shipping_credential_es' for country Spain. + """ + SHIPPING_CREDENTIAL_ES + + """ + Localized field key 'shipping_credential_gt' for country Guatemala. + """ + SHIPPING_CREDENTIAL_GT + + """ + Localized field key 'shipping_credential_id' for country Indonesia. + """ + SHIPPING_CREDENTIAL_ID + + """ + Localized field key 'shipping_credential_kr' for country South Korea. + """ + SHIPPING_CREDENTIAL_KR + + """ + Localized field key 'shipping_credential_mx' for country Mexico. + """ + SHIPPING_CREDENTIAL_MX + + """ + Localized field key 'shipping_credential_my' for country Malaysia. + """ + SHIPPING_CREDENTIAL_MY + + """ + Localized field key 'shipping_credential_pe' for country Peru. + """ + SHIPPING_CREDENTIAL_PE + + """ + Localized field key 'shipping_credential_pt' for country Portugal. + """ + SHIPPING_CREDENTIAL_PT + + """ + Localized field key 'shipping_credential_py' for country Paraguay. + """ + SHIPPING_CREDENTIAL_PY + + """ + Localized field key 'shipping_credential_tr' for country Turkey. + """ + SHIPPING_CREDENTIAL_TR + + """ + Localized field key 'shipping_credential_tw' for country Taiwan. + """ + SHIPPING_CREDENTIAL_TW + + """ + Localized field key 'shipping_credential_type_co' for country Colombia. + """ + SHIPPING_CREDENTIAL_TYPE_CO + + """ + Localized field key 'tax_credential_br' for country Brazil. + """ + TAX_CREDENTIAL_BR + + """ + Localized field key 'tax_credential_cl' for country Chile. + """ + TAX_CREDENTIAL_CL + + """ + Localized field key 'tax_credential_co' for country Colombia. + """ + TAX_CREDENTIAL_CO + + """ + Localized field key 'tax_credential_cr' for country Costa Rica. + """ + TAX_CREDENTIAL_CR + + """ + Localized field key 'tax_credential_ec' for country Ecuador. + """ + TAX_CREDENTIAL_EC + + """ + Localized field key 'tax_credential_es' for country Spain. + """ + TAX_CREDENTIAL_ES + + """ + Localized field key 'tax_credential_gt' for country Guatemala. + """ + TAX_CREDENTIAL_GT + + """ + Localized field key 'tax_credential_id' for country Indonesia. + """ + TAX_CREDENTIAL_ID + + """ + Localized field key 'tax_credential_it' for country Italy. + """ + TAX_CREDENTIAL_IT + + """ + Localized field key 'tax_credential_mx' for country Mexico. + """ + TAX_CREDENTIAL_MX + + """ + Localized field key 'tax_credential_my' for country Malaysia. + """ + TAX_CREDENTIAL_MY + + """ + Localized field key 'tax_credential_pe' for country Peru. + """ + TAX_CREDENTIAL_PE + + """ + Localized field key 'tax_credential_pt' for country Portugal. + """ + TAX_CREDENTIAL_PT + + """ + Localized field key 'tax_credential_py' for country Paraguay. + """ + TAX_CREDENTIAL_PY + + """ + Localized field key 'tax_credential_tr' for country Turkey. + """ + TAX_CREDENTIAL_TR + + """ + Localized field key 'tax_credential_type_co' for country Colombia. + """ + TAX_CREDENTIAL_TYPE_CO + + """ + Localized field key 'tax_credential_type_mx' for country Mexico. + """ + TAX_CREDENTIAL_TYPE_MX + + """ + Localized field key 'tax_credential_use_mx' for country Mexico. + """ + TAX_CREDENTIAL_USE_MX + + """ + Localized field key 'tax_email_it' for country Italy. + """ + TAX_EMAIL_IT +} + +""" +Represents a mailing address. +""" +type MailingAddress { + """ + The first line of the address. Typically the street address or PO Box number. + """ + address1: String + + """ + The second line of the address. Typically the number of the apartment, suite, or unit. + """ + address2: String + + """ + The name of the city, district, village, or town. + """ + city: String + + """ + The name of the customer's company or organization. + """ + company: String + + """ + The two-letter code for the country of the address. For example, US. + """ + countryCode: CountryCode + + """ + The first name of the customer. + """ + firstName: String + + """ + The last name of the customer. + """ + lastName: String + + """ + The approximate latitude of the address. + """ + latitude: Float + + """ + The approximate longitude of the address. + """ + longitude: Float + + """ + The market of the address. + """ + market: Market @deprecated(reason: "This `market` field will be removed in a future version of the API.") + + """ + The full name of the customer, based on firstName and lastName. + """ + name: String + + """ + A unique phone number for the customer. Formatted using E.164 standard. For example, +16135551111. + """ + phone: String + + """ + The alphanumeric code for the region. For example, ON. + """ + provinceCode: String + + """ + The zip or postal code of the address. + """ + zip: String +} + +""" +A market is a group of one or more regions that you want to target for international sales. +By creating a market, you can configure a distinct, localized shopping experience for +customers from a specific area of the world. For example, you can +[change currency](https://shopify.dev/api/admin-graphql/current/mutations/marketCurrencySettingsUpdate), +[configure international pricing](https://shopify.dev/api/examples/product-price-lists), +or [add market-specific domains or subfolders](https://shopify.dev/api/admin-graphql/current/objects/MarketWebPresence). +""" +type Market implements HasMetafields { + """ + A human-readable unique string for the market automatically generated from its title. + """ + handle: Handle! + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + A geographic region which comprises a market. + """ + regions: [MarketRegion!]! +} + +""" +Represents a region. +""" +interface MarketRegion { + """ + The name of the region in the language of the current localization. + """ + name: String +} + +""" +A country which comprises a market. +""" +type MarketRegionCountry implements MarketRegion { + """ + The two-letter code for the country. + """ + code: CountryCode! + + """ + The country name in the language of the current localization. + """ + name: String! +} + +""" +The merchandise to be purchased at checkout. +""" +union Merchandise = CustomProduct | ProductVariant + +""" +[Metafields](https://shopify.dev/apps/metafields) +enable you to attach additional information to a +Shopify resource, such as a [Product](https://shopify.dev/api/admin-graphql/latest/objects/product) +or a [Collection](https://shopify.dev/api/admin-graphql/latest/objects/collection). +For more information about the Shopify resources that you can attach metafields to, refer to +[HasMetafields](https://shopify.dev/api/admin/graphql/reference/common-objects/HasMetafields). +""" +type Metafield { + """ + The data stored in the metafield in JSON format. + """ + jsonValue: JSON! + + """ + The type of data that the metafield stores in the `value` field. + Refer to the list of [supported types](https://shopify.dev/apps/metafields/types). + """ + type: String! + + """ + The data stored in the metafield. Always stored as a string, regardless of the metafield's type. + """ + value: String! +} + +""" +A monetary value with currency. +""" +type MoneyV2 { + """ + Decimal money amount. + """ + amount: Decimal! + + """ + Currency of the money. + """ + currencyCode: CurrencyCode! +} + +""" +The root mutation for the API. +""" +type MutationRoot { + """ + Handles the Function result for the cart.delivery-options.discounts.generate.fetch target. + """ + cartDeliveryOptionsDiscountsGenerateFetch( + """ + The result of the Function. + """ + result: FunctionDeliveryFetchResult! + ): Void! + + """ + Handles the Function result for the cart.delivery-options.discounts.generate.run target. + """ + cartDeliveryOptionsDiscountsGenerateRun( + """ + The result of the Function. + """ + result: FunctionDeliveryRunResult! + ): Void! + + """ + Handles the Function result for the cart.lines.discounts.generate.fetch target. + """ + cartLinesDiscountsGenerateFetch( + """ + The result of the Function. + """ + result: FunctionCartFetchResult! + ): Void! + + """ + Handles the Function result for the cart.lines.discounts.generate.run target. + """ + cartLinesDiscountsGenerateRun( + """ + The result of the Function. + """ + result: FunctionCartRunResult! + ): Void! +} + +""" +The order discount candidate to be applied. +""" +input OrderDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The conditions that must be satisfied to apply the order discount candidate. + """ + conditions: [Condition!] + + """ + The discount message. + """ + message: String + + """ + The targets of the order discount candidate. + """ + targets: [OrderDiscountCandidateTarget!]! + + """ + The value of the order discount candidate. + """ + value: OrderDiscountCandidateValue! +} + +""" +A target of a order discount candidate. +""" +input OrderDiscountCandidateTarget @oneOf { + """ + If used, the discount targets the entire order subtotal after product discounts are applied. + """ + orderSubtotal: OrderSubtotalTarget +} + +""" +The order discount candidate value. +""" +input OrderDiscountCandidateValue @oneOf { + """ + A fixed amount value. + """ + fixedAmount: FixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of order discount candidates. +""" +enum OrderDiscountSelectionStrategy { + """ + Only apply the first order discount candidate with conditions that are satisfied. + """ + FIRST + + """ + Only apply the order discount candidate that offers the maximum reduction. + """ + MAXIMUM +} + +""" +A group of order discounts that share a selection strategy. +""" +input OrderDiscounts { + """ + The list of order discount candidates to be applied. + """ + candidates: [OrderDiscountCandidate!]! + + """ + The strategy that's applied to the list of discounts. + """ + selectionStrategy: OrderDiscountSelectionStrategy! +} + +""" +The condition for checking the minimum subtotal amount of the order. +""" +input OrderMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's excluded to calculate the minimum subtotal amount of the order. + """ + excludedCartLineIds: [ID!]! + + """ + The minimum subtotal amount of the order. + """ + minimumAmount: Decimal! +} + +""" +If used, the discount targets the entire order subtotal after product discounts are applied. +""" +input OrderSubtotalTarget { + """ + The list of excluded cart line IDs. These cart lines are excluded from the order + subtotal calculation when calculating the maximum value of the discount. + """ + excludedCartLineIds: [ID!]! +} + +""" +A percentage value. +""" +input Percentage { + """ + The percentage value. + + The value is validated against: >= 0 and <= 100. + """ + value: Decimal! +} + +""" +Represents a product. +""" +type Product implements HasGates & HasMetafields { + """ + Returns active gate subjects bound to the resource. + """ + gates( + """ + The handle of the gate configurations to search for. + """ + handle: Handle + ): [GateSubject!]! + + """ + A unique human-friendly string of the product's title. + """ + handle: Handle! + + """ + Whether the product has any of the given tags. + """ + hasAnyTag( + """ + The tags to check. + """ + tags: [String!]! = [] + ): Boolean! + + """ + Whether the product has the given tags. + """ + hasTags( + """ + The tags to check. + """ + tags: [String!]! = [] + ): [HasTagResponse!]! + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Whether the product is in any of the given collections. + """ + inAnyCollection( + """ + The IDs of the collections to check. + """ + ids: [ID!]! = [] + ): Boolean! + + """ + Whether the product is in the given collections. + """ + inCollections( + """ + The IDs of the collections to check. + """ + ids: [ID!]! = [] + ): [CollectionMembership!]! + + """ + Whether the product is a gift card. + """ + isGiftCard: Boolean! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The product type specified by the merchant. + """ + productType: String + + """ + The localized title of the product in the customer’s locale. + """ + title: String! + + """ + The name of the product's vendor. + """ + vendor: String +} + +""" +The product discount candidate to be applied. +""" +input ProductDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The discount message. + """ + message: String + + """ + The targets of the product discount candidate. + """ + targets: [ProductDiscountCandidateTarget!]! + + """ + The value of the product discount candidate. + """ + value: ProductDiscountCandidateValue! +} + +""" +A product discount candidate fixed amount value. +""" +input ProductDiscountCandidateFixedAmount { + """ + The fixed amount value of the product discount candidate, in the currency of the cart. + + The amount must be greater than or equal to 0. + """ + amount: Decimal! + + """ + Whether to apply the value to each entitled item. + + The default value is `false`, which causes the value to be applied once across the entitled items. + When the value is `true`, the value will be applied to each of the entitled items. + """ + appliesToEachItem: Boolean = false +} + +""" +A target of a product discount candidate, which determines which cart line(s) the discount will affect. + +Multiple targets with the same type and ID are the same as a single target of that type and ID with their +quantities added together, or `null` if any of those targets have a quantity of `null`. + +See the [Discounts API reference](https://shopify.dev/docs/api/functions/reference/product-discounts/graphql#functionrunresult) for examples. +""" +input ProductDiscountCandidateTarget @oneOf { + """ + A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. + """ + cartLine: CartLineTarget +} + +""" +The value of the product discount candidate. +""" +input ProductDiscountCandidateValue @oneOf { + """ + A product discount candidate fixed amount value. + """ + fixedAmount: ProductDiscountCandidateFixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of product discount candidates. +""" +enum ProductDiscountSelectionStrategy { + """ + Apply all product discount candidates with conditions that are satisfied. This + does not override discount combination or stacking rules. + """ + ALL + + """ + Only apply the first product discount candidate with conditions that are satisfied. + """ + FIRST + + """ + Only apply the product discount candidate that offers the maximum reduction. + """ + MAXIMUM +} + +""" +A group of product discounts that share a selection strategy. +""" +input ProductDiscounts { + """ + The list of product discount candidates to be applied. + """ + candidates: [ProductDiscountCandidate!]! + + """ + The strategy that's applied to the list of product discount candidates. + """ + selectionStrategy: ProductDiscountSelectionStrategy! +} + +""" +Represents a product variant. +""" +type ProductVariant implements HasMetafields { + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The product that this variant belongs to. + """ + product: Product! + + """ + Whether the merchandise requires shipping. + """ + requiresShipping: Boolean! + + """ + An identifier for the product variant in the shop. Required in order to connect to a fulfillment service. + """ + sku: String + + """ + The localized title of the product variant in the customer’s locale. + """ + title: String + + """ + The weight of the product variant in the unit system specified with `weight_unit`. + """ + weight: Float + + """ + Unit of measurement for weight. + """ + weightUnit: WeightUnit! +} + +""" +Represents information about the buyer that is interacting with the cart. +""" +type PurchasingCompany { + """ + The company associated to the order or draft order. + """ + company: Company! + + """ + The company contact associated to the order or draft order. + """ + contact: CompanyContact + + """ + The company location associated to the order or draft order. + """ + location: CompanyLocation! +} + +""" +Represents how products and variants can be sold and purchased. +""" +type SellingPlan implements HasMetafields { + """ + The description of the selling plan. + """ + description: String + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. + """ + name: String! + + """ + Whether purchasing the selling plan will result in multiple deliveries. + """ + recurringDeliveries: Boolean! +} + +""" +Represents an association between a variant and a selling plan. Selling plan +allocations describe the options offered for each variant, and the price of the +variant when purchased with a selling plan. +""" +type SellingPlanAllocation { + """ + A list of price adjustments, with a maximum of two. When there are two, the + first price adjustment goes into effect at the time of purchase, while the + second one starts after a certain number of orders. A price adjustment + represents how a selling plan affects pricing when a variant is purchased with + a selling plan. Prices display in the customer's currency if the shop is + configured for it. + """ + priceAdjustments: [SellingPlanAllocationPriceAdjustment!]! + + """ + A representation of how products and variants can be sold and purchased. For + example, an individual selling plan could be '6 weeks of prepaid granola, + delivered weekly'. + """ + sellingPlan: SellingPlan! +} + +""" +The resulting prices for variants when they're purchased with a specific selling plan. +""" +type SellingPlanAllocationPriceAdjustment { + """ + The effective price for a single delivery. For example, for a prepaid + subscription plan that includes 6 deliveries at the price of $48.00, the per + delivery price is $8.00. + """ + perDeliveryPrice: MoneyV2! + + """ + The price of the variant when it's purchased with a selling plan For example, + for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, + where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. + """ + price: MoneyV2! +} + +""" +Information about the shop. +""" +type Shop implements HasMetafields { + """ + Information about the current time relative to the shop's timezone setting. + """ + localTime: LocalTime! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that +includes the time but not the date or timezone which is determined from context. +For example, "05:43:21". +""" +scalar TimeWithoutTimezone + +""" +Represents an [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and +[RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987)-compliant URI string. + +For example, `"https://example.myshopify.com"` is a valid URL. It includes a scheme (`https`) and a host +(`example.myshopify.com`). +""" +scalar URL + +""" +A discount code that corresponds to a valid external discount. +This can only be used by Functions with network access. +""" +input ValidDiscountCode { + """ + The discount code. + """ + code: String! +} + +""" +A list of valid discount codes that correspond to external discounts. This can +only be used by Functions with network access. +""" +input ValidDiscountCodes { + """ + The list of valid discount codes. + """ + codes: [ValidDiscountCode!]! +} + +""" +A void type that can be used to return a null value from a mutation. +""" +scalar Void + +""" +Units of measurement for weight. +""" +enum WeightUnit { + """ + Metric system unit of mass. + """ + GRAMS + + """ + 1 kilogram equals 1000 grams. + """ + KILOGRAMS + + """ + Imperial system unit of mass. + """ + OUNCES + + """ + 1 pound equals 16 ounces. + """ + POUNDS +} diff --git a/discounts/javascript/discount/default/shopify.extension.toml.liquid b/discounts/javascript/discount/default/shopify.extension.toml.liquid new file mode 100644 index 00000000..a5b77025 --- /dev/null +++ b/discounts/javascript/discount/default/shopify.extension.toml.liquid @@ -0,0 +1,22 @@ +api_version = "2025-04" + +[[extensions]] +name = "t:name" +handle = "{{handle}}" +type = "function" +{% if uid %}uid = "{{ uid }}"{% endif %} +description = "t:description" + + [[extensions.targeting]] + target = "cart.lines.discounts.generate.run" + input_query = "src/generate_cart_run.graphql" + export = "generate-cart-run" + + [[extensions.targeting]] + target = "cart.delivery-options.discounts.generate.run" + input_query = "src/generate_delivery_run.graphql" + export = "generate-delivery-run" + + [extensions.build] + command = "" + path = "dist/function.wasm" diff --git a/discounts/javascript/discount/default/src/discount.test.liquid b/discounts/javascript/discount/default/src/discount.test.liquid new file mode 100644 index 00000000..52f2c49e --- /dev/null +++ b/discounts/javascript/discount/default/src/discount.test.liquid @@ -0,0 +1,113 @@ +import { describe, it, expect } from "vitest"; + +import { generateCartRun } from "./generate_cart_run"; +import { generateDeliveryRun } from "./generate_delivery_run"; +import { + OrderDiscountSelectionStrategy, + ProductDiscountSelectionStrategy, + DeliveryDiscountSelectionStrategy, +} from "../generated/api"; + +describe("discount", () => { + it("cart.lines.discounts.generate.run returns a product and order discount", () => { + const input = { + cart: { + lines: [ + { + id: "gid://shopify/CartLine/0", + cost: { + subtotalAmount: 100, + }, + }, + ], + }, + }; + + const result = generateCartRun(input); + + expect(result.operations.length).toBe(2); + expect(result.operations[0]).toMatchObject({ + addOrderDiscounts: { + candidates: [ + { + message: "10% OFF ORDER", + targets: [ + { + orderSubtotal: { + excludedCartLineIds: [], + }, + }, + ], + value: { + percentage: { + value: 10, + }, + }, + }, + ], + selectionStrategy: OrderDiscountSelectionStrategy.First, + }, + }); + + expect(result.operations[1]).toMatchObject({ + addProductDiscounts: { + candidates: [ + { + message: "20% OFF PRODUCT", + targets: [ + { + cartLine: { + id: "gid://shopify/CartLine/0", + }, + }, + ], + value: { + percentage: { + value: 20, + }, + }, + }, + ], + selectionStrategy: ProductDiscountSelectionStrategy.First, + }, + }); + }); + + it("cart.delivery-options.generate.run returns a delivery discount", () => { + const input = { + cart: { + deliveryGroups: [ + { + id: "gid://shopify/DeliveryGroup/0", + }, + ], + }, + }; + + const result = generateDeliveryRun(input); + + expect(result.operations.length).toBe(1); + expect(result.operations[0]).toMatchObject({ + addDeliveryDiscounts: { + candidates: [ + { + message: "FREE DELIVERY", + targets: [ + { + deliveryGroup: { + id: "gid://shopify/DeliveryGroup/0", + }, + }, + ], + value: { + percentage: { + value: 100, + }, + }, + }, + ], + selectionStrategy: DeliveryDiscountSelectionStrategy.All, + }, + }); + }); +}); diff --git a/discounts/javascript/discount/default/src/generate_cart_run.graphql.liquid b/discounts/javascript/discount/default/src/generate_cart_run.graphql.liquid new file mode 100644 index 00000000..148989d0 --- /dev/null +++ b/discounts/javascript/discount/default/src/generate_cart_run.graphql.liquid @@ -0,0 +1,12 @@ +query CartInput { + cart { + lines { + id + cost { + subtotalAmount { + amount + } + } + } + } +} diff --git a/discounts/javascript/discount/default/src/generate_cart_run.liquid b/discounts/javascript/discount/default/src/generate_cart_run.liquid new file mode 100644 index 00000000..7fbe2043 --- /dev/null +++ b/discounts/javascript/discount/default/src/generate_cart_run.liquid @@ -0,0 +1,147 @@ +{%- if flavor contains "vanilla-js" -%} +// @ts-check + +import { + OrderDiscountSelectionStrategy, + ProductDiscountSelectionStrategy, +} from '../generated/api'; + +/** + * @typedef {import("../generated/api").CartInput} CartInput + * @typedef {import("../generated/api").FunctionCartRunResult} FunctionCartRunResult + */ + +/** + * generateCartRun + * @param {CartInput} input - The CartInput + * @returns {FunctionCartRunResult} - The function result with discounts. + */ +export function generateCartRun(input) { + if (!input.cart.lines.length) { + throw new Error('No cart lines found'); + } + const maxCartLine = input.cart.lines.reduce((maxLine, line) => { + if (line.cost.subtotalAmount > maxLine.cost.subtotalAmount) { + return line; + } + return maxLine; + }, input.cart.lines[0]); + return { + operations: [ + { + addOrderDiscounts: { + candidates: [ + { + message: '10% OFF ORDER', + targets: [ + { + orderSubtotal: { + excludedCartLineIds: [], + }, + }, + ], + value: { + percentage: { + value: 10, + }, + }, + }, + ], + selectionStrategy: OrderDiscountSelectionStrategy.First, + }, + }, + { + addProductDiscounts: { + candidates: [ + { + message: '20% OFF PRODUCT', + targets: [ + { + cartLine: { + id: maxCartLine.id, + }, + }, + ], + value: { + percentage: { + value: 20, + }, + }, + }, + ], + selectionStrategy: ProductDiscountSelectionStrategy.First, + }, + }, + ], + }; +} +{%- elsif flavor contains "typescript" -%} +import { + OrderDiscountSelectionStrategy, + ProductDiscountSelectionStrategy, + CartInput, + FunctionCartRunResult, +} from '../generated/api'; + +export function generateCartRun(input: CartInput): FunctionCartRunResult { + if (!input.cart.lines.length) { + throw new Error('No cart lines found'); + } + + const maxCartLine = input.cart.lines.reduce((maxLine, line) => { + if (line.cost.subtotalAmount > maxLine.cost.subtotalAmount) { + return line; + } + return maxLine; + }, input.cart.lines[0]); + + return { + operations: [ + { + addOrderDiscounts: { + candidates: [ + { + message: '10% OFF ORDER', + targets: [ + { + orderSubtotal: { + excludedCartLineIds: [], + }, + }, + ], + value: { + percentage: { + value: 10, + }, + }, + }, + ], + selectionStrategy: OrderDiscountSelectionStrategy.First, + }, + }, + { + addProductDiscounts: { + candidates: [ + { + message: '20% OFF PRODUCT', + targets: [ + { + cartLine: { + id: maxCartLine.id, + }, + }, + ], + value: { + percentage: { + value: 20, + }, + }, + }, + ], + selectionStrategy: ProductDiscountSelectionStrategy.First, + }, + }, + ], + }; +} +{%- endif -%} diff --git a/discounts/javascript/discount/default/src/generate_delivery_run.graphql.liquid b/discounts/javascript/discount/default/src/generate_delivery_run.graphql.liquid new file mode 100644 index 00000000..ff7c2878 --- /dev/null +++ b/discounts/javascript/discount/default/src/generate_delivery_run.graphql.liquid @@ -0,0 +1,7 @@ +query DeliveryInput { + cart { + deliveryGroups { + id + } + } +} diff --git a/discounts/javascript/discount/default/src/generate_delivery_run.liquid b/discounts/javascript/discount/default/src/generate_delivery_run.liquid new file mode 100644 index 00000000..45a034a9 --- /dev/null +++ b/discounts/javascript/discount/default/src/generate_delivery_run.liquid @@ -0,0 +1,89 @@ +{%- if flavor contains "vanilla-js" -%} +// @ts-check + +import { DeliveryDiscountSelectionStrategy} from '../generated/api'; + +/** + * @typedef {import("../generated/api").DeliveryInput} RunInput + * @typedef {import("../generated/api").FunctionDeliveryRunResult} FunctionDeliveryRunResult + */ +/** + * generateDeliveryRun + * @param {RunInput} input - The DeliveryInput + * @returns {FunctionDeliveryRunResult} - The function result with discounts. + */ +export function generateDeliveryRun(input) { + const firstDeliveryGroup = input.cart.deliveryGroups[0]; + if (!firstDeliveryGroup) { + throw new Error('No delivery groups found'); + } + return { + operations: [ + { + addDeliveryDiscounts: { + candidates: [ + { + message: 'FREE DELIVERY', + targets: [ + { + deliveryGroup: { + id: firstDeliveryGroup.id, + }, + }, + ], + value: { + percentage: { + value: 100, + }, + }, + }, + ], + selectionStrategy: DeliveryDiscountSelectionStrategy.All, + }, + }, + ], + }; +} +{%- elsif flavor contains "typescript" -%} +import { + DeliveryDiscountSelectionStrategy, + DeliveryInput, + FunctionDeliveryRunResult, +} from '../generated/api'; + +export function generateDeliveryRun( + input: DeliveryInput, +): FunctionDeliveryRunResult { + const firstDeliveryGroup = input.cart.deliveryGroups[0]; + if (!firstDeliveryGroup) { + throw new Error('No delivery groups found'); + } + + return { + operations: [ + { + addDeliveryDiscounts: { + candidates: [ + { + message: 'FREE DELIVERY', + targets: [ + { + deliveryGroup: { + id: firstDeliveryGroup.id, + }, + }, + ], + value: { + percentage: { + value: 100, + }, + }, + }, + ], + selectionStrategy: DeliveryDiscountSelectionStrategy.All, + }, + }, + ], + }; +} +{%- endif -%} diff --git a/discounts/javascript/discount/default/src/index.liquid b/discounts/javascript/discount/default/src/index.liquid new file mode 100644 index 00000000..84ba5c03 --- /dev/null +++ b/discounts/javascript/discount/default/src/index.liquid @@ -0,0 +1,2 @@ +export * from './generate_cart_run'; +export * from './generate_delivery_run'; diff --git a/discounts/javascript/discount/default/vite.config.js b/discounts/javascript/discount/default/vite.config.js new file mode 100644 index 00000000..210c90d4 --- /dev/null +++ b/discounts/javascript/discount/default/vite.config.js @@ -0,0 +1 @@ +// Prevents inheritance from parent Remix project diff --git a/discounts/javascript/network/default/.gitignore b/discounts/javascript/network/default/.gitignore new file mode 100644 index 00000000..aa0926aa --- /dev/null +++ b/discounts/javascript/network/default/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +.env +*.log diff --git a/discounts/javascript/network/default/package.json.liquid b/discounts/javascript/network/default/package.json.liquid new file mode 100644 index 00000000..956d682f --- /dev/null +++ b/discounts/javascript/network/default/package.json.liquid @@ -0,0 +1,31 @@ +{ + "name": "{{handle}}", + "version": "0.0.1", + "license": "UNLICENSED", + "scripts": { + "shopify": "npm exec -- shopify", + "typegen": "npm exec -- shopify app function typegen", + "build": "npm exec -- shopify app function build", + "preview": "npm exec -- shopify app function run", + "test": "vitest" + }, + "codegen": { + "schema": "schema.graphql", + "documents": "src/*.graphql", + "generates": { + "./generated/api.ts": { + "plugins": [ + "typescript", + "typescript-operations" + ] + } + }, + "config": { + "omitOperationSuffix": true + } + }, + "devDependencies": { + "vitest": "^0.29.8" + } + } + \ No newline at end of file diff --git a/discounts/javascript/network/default/schema.graphql b/discounts/javascript/network/default/schema.graphql new file mode 100644 index 00000000..2c2f866b --- /dev/null +++ b/discounts/javascript/network/default/schema.graphql @@ -0,0 +1,5172 @@ +schema { + query: Input + mutation: MutationRoot +} + +""" +Only allow the field to be queried when targeting one of the specified targets. +""" +directive @restrictTarget(only: [String!]!) on FIELD_DEFINITION + +""" +Scale the Functions resource limits based on the field's length. +""" +directive @scaleLimits(rate: Float!) on FIELD_DEFINITION + +""" +Requires that exactly one field must be supplied and that field must not be `null`. +""" +directive @oneOf on INPUT_OBJECT + +""" +A discount code that is associated with a discount candidate. +""" +input AssociatedDiscountCode { + """ + The discount code. + """ + code: String! +} + +""" +Represents a generic custom attribute, such as whether an order is a customer's first. +""" +type Attribute { + """ + The key or name of the attribute. For example, `"customersFirstOrder"`. + """ + key: String! + + """ + The value of the attribute. For example, `"true"`. + """ + value: String +} + +""" +Represents information about the buyer that is interacting with the cart. +""" +type BuyerIdentity { + """ + The customer associated with the cart. + """ + customer: Customer + + """ + The email address of the buyer that's interacting with the cart. + """ + email: String + + """ + Whether the buyer authenticated with a customer account. + """ + isAuthenticated: Boolean! + + """ + The phone number of the buyer that's interacting with the cart. + """ + phone: String + + """ + The purchasing company associated with the cart. + """ + purchasingCompany: PurchasingCompany +} + +""" +A cart represents the merchandise that a buyer intends to purchase, and the cost associated with the cart. +""" +type Cart { + """ + The attributes associated with the cart. Attributes are represented as key-value pairs. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + Information about the buyer that is interacting with the cart. + """ + buyerIdentity: BuyerIdentity + + """ + The costs that the buyer will pay at checkout. + """ + cost: CartCost! + + """ + A list of lines containing information about the items that can be delivered. + """ + deliverableLines: [DeliverableCartLine!]! + + """ + The delivery groups available for the cart based on the buyer's shipping address. + """ + deliveryGroups: [CartDeliveryGroup!]! + + """ + A list of lines containing information about the items the customer intends to purchase. + """ + lines: [CartLine!]! @scaleLimits(rate: 0.005) + + """ + The localized fields available for the cart. + """ + localizedFields( + """ + The keys of the localized fields to retrieve. + """ + keys: [LocalizedFieldKey!]! = [] + ): [LocalizedField!]! +} + +""" +The cost that the buyer will pay at checkout. +""" +type CartCost { + """ + The amount, before taxes and discounts, for the customer to pay. + """ + subtotalAmount: MoneyV2! + + """ + The total amount for the customer to pay. + """ + totalAmount: MoneyV2! + + """ + The duty amount for the customer to pay at checkout. + """ + totalDutyAmount: MoneyV2 + + """ + The tax amount for the customer to pay at checkout. + """ + totalTaxAmount: MoneyV2 +} + +""" +Information about the options available for one or more line items to be delivered to a specific address. +""" +type CartDeliveryGroup { + """ + A list of cart lines for the delivery group. + """ + cartLines: [CartLine!]! @scaleLimits(rate: 0.005) + + """ + The destination address for the delivery group. + """ + deliveryAddress: MailingAddress + + """ + The delivery options available for the delivery group. + """ + deliveryOptions: [CartDeliveryOption!]! + + """ + Unique identifier for the delivery group. + """ + id: ID! + + """ + Information about the delivery option the buyer has selected. + """ + selectedDeliveryOption: CartDeliveryOption +} + +""" +Information about a delivery option. +""" +type CartDeliveryOption { + """ + The code of the delivery option. + """ + code: String + + """ + The cost for the delivery option. + """ + cost: MoneyV2! + + """ + The method for the delivery option. + """ + deliveryMethodType: DeliveryMethod! + + """ + The description of the delivery option. + """ + description: String + + """ + The unique identifier of the delivery option. + """ + handle: Handle! + + """ + The title of the delivery option. + """ + title: String +} + +""" +Represents information about the merchandise in the cart. +""" +type CartLine { + """ + Retrieve a cart line attribute by key. + + Cart line attributes are also known as line item properties in Liquid. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + The cost of the merchandise line that the buyer will pay at checkout. + """ + cost: CartLineCost! + + """ + The ID of the cart line. + """ + id: ID! + + """ + The merchandise that the buyer intends to purchase. + """ + merchandise: Merchandise! + + """ + The quantity of the merchandise that the customer intends to purchase. + """ + quantity: Int! + + """ + The selling plan associated with the cart line and the effect that each + selling plan has on variants when they're purchased. + """ + sellingPlanAllocation: SellingPlanAllocation +} + +""" +The cost of the merchandise line that the buyer will pay at checkout. +""" +type CartLineCost { + """ + The amount of the merchandise line. + """ + amountPerQuantity: MoneyV2! + + """ + The compare at amount of the merchandise line. This value varies depending on + the buyer's identity, and is null when the value is hidden to buyers. + """ + compareAtAmountPerQuantity: MoneyV2 + + """ + The cost of the merchandise line before line-level discounts. + """ + subtotalAmount: MoneyV2! + + """ + The total cost of the merchandise line. + """ + totalAmount: MoneyV2! +} + +""" +The condition for checking the minimum quantity of products across a group of cart lines. +""" +input CartLineMinimumQuantity { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum quantity purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum quantity of a product. + """ + minimumQuantity: Int! +} + +""" +The condition for checking the minimum subtotal of products across a group of cart lines. +""" +input CartLineMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum subtotal purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum subtotal amount of the product. + """ + minimumAmount: Decimal! +} + +""" +A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. +""" +input CartLineTarget { + """ + The ID of the targeted cart line. + """ + id: ID! + + """ + The number of line items that are being discounted. + The default value is `null`, which represents the quantity of the matching line items. + + The value is validated against: > 0. + """ + quantity: Int +} + +""" +The operations that can be performed to apply discounts to the cart. +""" +input CartOperation @oneOf { + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes + + """ + A group of order discounts that share a selection strategy. + """ + addOrderDiscounts: OrderDiscounts + + """ + A group of product discounts that share a selection strategy. + """ + addProductDiscounts: ProductDiscounts +} + +""" +Represents whether the product is a member of the given collection. +""" +type CollectionMembership { + """ + The ID of the collection. + """ + collectionId: ID! + + """ + Whether the product is a member of the collection. + """ + isMember: Boolean! +} + +""" +Represents information about a company which is also a customer of the shop. +""" +type Company implements HasMetafields { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was created in Shopify. + """ + createdAt: DateTime! + + """ + A unique externally-supplied ID for the company. + """ + externalId: String + + """ + The ID of the company. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the company. + """ + name: String! + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was last modified. + """ + updatedAt: DateTime! +} + +""" +A company's main point of contact. +""" +type CompanyContact { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company contact was created in Shopify. + """ + createdAt: DateTime! + + """ + The ID of the company. + """ + id: ID! + + """ + The company contact's locale (language). + """ + locale: String + + """ + The company contact's job title. + """ + title: String + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company contact was last modified. + """ + updatedAt: DateTime! +} + +""" +A company's location. +""" +type CompanyLocation implements HasMetafields { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company location was created in Shopify. + """ + createdAt: DateTime! + + """ + A unique externally-supplied ID for the company. + """ + externalId: String + + """ + The ID of the company. + """ + id: ID! + + """ + The preferred locale of the company location. + """ + locale: String + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the company location. + """ + name: String! + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company location was last modified. + """ + updatedAt: DateTime! +} + +""" +The condition to apply the discount candidate. +""" +input Condition @oneOf { + """ + The condition for checking the minimum quantity of products across a group of cart lines. + """ + cartLineMinimumQuantity: CartLineMinimumQuantity + + """ + The condition for checking the minimum subtotal of products across a group of cart lines. + """ + cartLineMinimumSubtotal: CartLineMinimumSubtotal + + """ + The condition for checking the minimum subtotal amount of the order. + """ + orderMinimumSubtotal: OrderMinimumSubtotal +} + +""" +A country. +""" +type Country { + """ + The ISO code of the country. + """ + isoCode: CountryCode! +} + +""" +The code designating a country/region, which generally follows ISO 3166-1 alpha-2 guidelines. +If a territory doesn't have a country code value in the `CountryCode` enum, then it might be considered a subdivision +of another country. For example, the territories associated with Spain are represented by the country code `ES`, +and the territories associated with the United States of America are represented by the country code `US`. +""" +enum CountryCode { + """ + Ascension Island. + """ + AC + + """ + Andorra. + """ + AD + + """ + United Arab Emirates. + """ + AE + + """ + Afghanistan. + """ + AF + + """ + Antigua & Barbuda. + """ + AG + + """ + Anguilla. + """ + AI + + """ + Albania. + """ + AL + + """ + Armenia. + """ + AM + + """ + Netherlands Antilles. + """ + AN + + """ + Angola. + """ + AO + + """ + Argentina. + """ + AR + + """ + Austria. + """ + AT + + """ + Australia. + """ + AU + + """ + Aruba. + """ + AW + + """ + Åland Islands. + """ + AX + + """ + Azerbaijan. + """ + AZ + + """ + Bosnia & Herzegovina. + """ + BA + + """ + Barbados. + """ + BB + + """ + Bangladesh. + """ + BD + + """ + Belgium. + """ + BE + + """ + Burkina Faso. + """ + BF + + """ + Bulgaria. + """ + BG + + """ + Bahrain. + """ + BH + + """ + Burundi. + """ + BI + + """ + Benin. + """ + BJ + + """ + St. Barthélemy. + """ + BL + + """ + Bermuda. + """ + BM + + """ + Brunei. + """ + BN + + """ + Bolivia. + """ + BO + + """ + Caribbean Netherlands. + """ + BQ + + """ + Brazil. + """ + BR + + """ + Bahamas. + """ + BS + + """ + Bhutan. + """ + BT + + """ + Bouvet Island. + """ + BV + + """ + Botswana. + """ + BW + + """ + Belarus. + """ + BY + + """ + Belize. + """ + BZ + + """ + Canada. + """ + CA + + """ + Cocos (Keeling) Islands. + """ + CC + + """ + Congo - Kinshasa. + """ + CD + + """ + Central African Republic. + """ + CF + + """ + Congo - Brazzaville. + """ + CG + + """ + Switzerland. + """ + CH + + """ + Côte d’Ivoire. + """ + CI + + """ + Cook Islands. + """ + CK + + """ + Chile. + """ + CL + + """ + Cameroon. + """ + CM + + """ + China. + """ + CN + + """ + Colombia. + """ + CO + + """ + Costa Rica. + """ + CR + + """ + Cuba. + """ + CU + + """ + Cape Verde. + """ + CV + + """ + Curaçao. + """ + CW + + """ + Christmas Island. + """ + CX + + """ + Cyprus. + """ + CY + + """ + Czechia. + """ + CZ + + """ + Germany. + """ + DE + + """ + Djibouti. + """ + DJ + + """ + Denmark. + """ + DK + + """ + Dominica. + """ + DM + + """ + Dominican Republic. + """ + DO + + """ + Algeria. + """ + DZ + + """ + Ecuador. + """ + EC + + """ + Estonia. + """ + EE + + """ + Egypt. + """ + EG + + """ + Western Sahara. + """ + EH + + """ + Eritrea. + """ + ER + + """ + Spain. + """ + ES + + """ + Ethiopia. + """ + ET + + """ + Finland. + """ + FI + + """ + Fiji. + """ + FJ + + """ + Falkland Islands. + """ + FK + + """ + Faroe Islands. + """ + FO + + """ + France. + """ + FR + + """ + Gabon. + """ + GA + + """ + United Kingdom. + """ + GB + + """ + Grenada. + """ + GD + + """ + Georgia. + """ + GE + + """ + French Guiana. + """ + GF + + """ + Guernsey. + """ + GG + + """ + Ghana. + """ + GH + + """ + Gibraltar. + """ + GI + + """ + Greenland. + """ + GL + + """ + Gambia. + """ + GM + + """ + Guinea. + """ + GN + + """ + Guadeloupe. + """ + GP + + """ + Equatorial Guinea. + """ + GQ + + """ + Greece. + """ + GR + + """ + South Georgia & South Sandwich Islands. + """ + GS + + """ + Guatemala. + """ + GT + + """ + Guinea-Bissau. + """ + GW + + """ + Guyana. + """ + GY + + """ + Hong Kong SAR. + """ + HK + + """ + Heard & McDonald Islands. + """ + HM + + """ + Honduras. + """ + HN + + """ + Croatia. + """ + HR + + """ + Haiti. + """ + HT + + """ + Hungary. + """ + HU + + """ + Indonesia. + """ + ID + + """ + Ireland. + """ + IE + + """ + Israel. + """ + IL + + """ + Isle of Man. + """ + IM + + """ + India. + """ + IN + + """ + British Indian Ocean Territory. + """ + IO + + """ + Iraq. + """ + IQ + + """ + Iran. + """ + IR + + """ + Iceland. + """ + IS + + """ + Italy. + """ + IT + + """ + Jersey. + """ + JE + + """ + Jamaica. + """ + JM + + """ + Jordan. + """ + JO + + """ + Japan. + """ + JP + + """ + Kenya. + """ + KE + + """ + Kyrgyzstan. + """ + KG + + """ + Cambodia. + """ + KH + + """ + Kiribati. + """ + KI + + """ + Comoros. + """ + KM + + """ + St. Kitts & Nevis. + """ + KN + + """ + North Korea. + """ + KP + + """ + South Korea. + """ + KR + + """ + Kuwait. + """ + KW + + """ + Cayman Islands. + """ + KY + + """ + Kazakhstan. + """ + KZ + + """ + Laos. + """ + LA + + """ + Lebanon. + """ + LB + + """ + St. Lucia. + """ + LC + + """ + Liechtenstein. + """ + LI + + """ + Sri Lanka. + """ + LK + + """ + Liberia. + """ + LR + + """ + Lesotho. + """ + LS + + """ + Lithuania. + """ + LT + + """ + Luxembourg. + """ + LU + + """ + Latvia. + """ + LV + + """ + Libya. + """ + LY + + """ + Morocco. + """ + MA + + """ + Monaco. + """ + MC + + """ + Moldova. + """ + MD + + """ + Montenegro. + """ + ME + + """ + St. Martin. + """ + MF + + """ + Madagascar. + """ + MG + + """ + North Macedonia. + """ + MK + + """ + Mali. + """ + ML + + """ + Myanmar (Burma). + """ + MM + + """ + Mongolia. + """ + MN + + """ + Macao SAR. + """ + MO + + """ + Martinique. + """ + MQ + + """ + Mauritania. + """ + MR + + """ + Montserrat. + """ + MS + + """ + Malta. + """ + MT + + """ + Mauritius. + """ + MU + + """ + Maldives. + """ + MV + + """ + Malawi. + """ + MW + + """ + Mexico. + """ + MX + + """ + Malaysia. + """ + MY + + """ + Mozambique. + """ + MZ + + """ + Namibia. + """ + NA + + """ + New Caledonia. + """ + NC + + """ + Niger. + """ + NE + + """ + Norfolk Island. + """ + NF + + """ + Nigeria. + """ + NG + + """ + Nicaragua. + """ + NI + + """ + Netherlands. + """ + NL + + """ + Norway. + """ + NO + + """ + Nepal. + """ + NP + + """ + Nauru. + """ + NR + + """ + Niue. + """ + NU + + """ + New Zealand. + """ + NZ + + """ + Oman. + """ + OM + + """ + Panama. + """ + PA + + """ + Peru. + """ + PE + + """ + French Polynesia. + """ + PF + + """ + Papua New Guinea. + """ + PG + + """ + Philippines. + """ + PH + + """ + Pakistan. + """ + PK + + """ + Poland. + """ + PL + + """ + St. Pierre & Miquelon. + """ + PM + + """ + Pitcairn Islands. + """ + PN + + """ + Palestinian Territories. + """ + PS + + """ + Portugal. + """ + PT + + """ + Paraguay. + """ + PY + + """ + Qatar. + """ + QA + + """ + Réunion. + """ + RE + + """ + Romania. + """ + RO + + """ + Serbia. + """ + RS + + """ + Russia. + """ + RU + + """ + Rwanda. + """ + RW + + """ + Saudi Arabia. + """ + SA + + """ + Solomon Islands. + """ + SB + + """ + Seychelles. + """ + SC + + """ + Sudan. + """ + SD + + """ + Sweden. + """ + SE + + """ + Singapore. + """ + SG + + """ + St. Helena. + """ + SH + + """ + Slovenia. + """ + SI + + """ + Svalbard & Jan Mayen. + """ + SJ + + """ + Slovakia. + """ + SK + + """ + Sierra Leone. + """ + SL + + """ + San Marino. + """ + SM + + """ + Senegal. + """ + SN + + """ + Somalia. + """ + SO + + """ + Suriname. + """ + SR + + """ + South Sudan. + """ + SS + + """ + São Tomé & Príncipe. + """ + ST + + """ + El Salvador. + """ + SV + + """ + Sint Maarten. + """ + SX + + """ + Syria. + """ + SY + + """ + Eswatini. + """ + SZ + + """ + Tristan da Cunha. + """ + TA + + """ + Turks & Caicos Islands. + """ + TC + + """ + Chad. + """ + TD + + """ + French Southern Territories. + """ + TF + + """ + Togo. + """ + TG + + """ + Thailand. + """ + TH + + """ + Tajikistan. + """ + TJ + + """ + Tokelau. + """ + TK + + """ + Timor-Leste. + """ + TL + + """ + Turkmenistan. + """ + TM + + """ + Tunisia. + """ + TN + + """ + Tonga. + """ + TO + + """ + Türkiye. + """ + TR + + """ + Trinidad & Tobago. + """ + TT + + """ + Tuvalu. + """ + TV + + """ + Taiwan. + """ + TW + + """ + Tanzania. + """ + TZ + + """ + Ukraine. + """ + UA + + """ + Uganda. + """ + UG + + """ + U.S. Outlying Islands. + """ + UM + + """ + United States. + """ + US + + """ + Uruguay. + """ + UY + + """ + Uzbekistan. + """ + UZ + + """ + Vatican City. + """ + VA + + """ + St. Vincent & Grenadines. + """ + VC + + """ + Venezuela. + """ + VE + + """ + British Virgin Islands. + """ + VG + + """ + Vietnam. + """ + VN + + """ + Vanuatu. + """ + VU + + """ + Wallis & Futuna. + """ + WF + + """ + Samoa. + """ + WS + + """ + Kosovo. + """ + XK + + """ + Yemen. + """ + YE + + """ + Mayotte. + """ + YT + + """ + South Africa. + """ + ZA + + """ + Zambia. + """ + ZM + + """ + Zimbabwe. + """ + ZW + + """ + Unknown Region. + """ + ZZ +} + +""" +The three-letter currency codes that represent the world currencies used in +stores. These include standard ISO 4217 codes, legacy codes, +and non-standard codes. +""" +enum CurrencyCode { + """ + United Arab Emirates Dirham (AED). + """ + AED + + """ + Afghan Afghani (AFN). + """ + AFN + + """ + Albanian Lek (ALL). + """ + ALL + + """ + Armenian Dram (AMD). + """ + AMD + + """ + Netherlands Antillean Guilder. + """ + ANG + + """ + Angolan Kwanza (AOA). + """ + AOA + + """ + Argentine Pesos (ARS). + """ + ARS + + """ + Australian Dollars (AUD). + """ + AUD + + """ + Aruban Florin (AWG). + """ + AWG + + """ + Azerbaijani Manat (AZN). + """ + AZN + + """ + Bosnia and Herzegovina Convertible Mark (BAM). + """ + BAM + + """ + Barbadian Dollar (BBD). + """ + BBD + + """ + Bangladesh Taka (BDT). + """ + BDT + + """ + Bulgarian Lev (BGN). + """ + BGN + + """ + Bahraini Dinar (BHD). + """ + BHD + + """ + Burundian Franc (BIF). + """ + BIF + + """ + Bermudian Dollar (BMD). + """ + BMD + + """ + Brunei Dollar (BND). + """ + BND + + """ + Bolivian Boliviano (BOB). + """ + BOB + + """ + Brazilian Real (BRL). + """ + BRL + + """ + Bahamian Dollar (BSD). + """ + BSD + + """ + Bhutanese Ngultrum (BTN). + """ + BTN + + """ + Botswana Pula (BWP). + """ + BWP + + """ + Belarusian Ruble (BYN). + """ + BYN + + """ + Belarusian Ruble (BYR). + """ + BYR @deprecated(reason: "`BYR` is deprecated. Use `BYN` available from version `2021-01` onwards instead.") + + """ + Belize Dollar (BZD). + """ + BZD + + """ + Canadian Dollars (CAD). + """ + CAD + + """ + Congolese franc (CDF). + """ + CDF + + """ + Swiss Francs (CHF). + """ + CHF + + """ + Chilean Peso (CLP). + """ + CLP + + """ + Chinese Yuan Renminbi (CNY). + """ + CNY + + """ + Colombian Peso (COP). + """ + COP + + """ + Costa Rican Colones (CRC). + """ + CRC + + """ + Cape Verdean escudo (CVE). + """ + CVE + + """ + Czech Koruny (CZK). + """ + CZK + + """ + Djiboutian Franc (DJF). + """ + DJF + + """ + Danish Kroner (DKK). + """ + DKK + + """ + Dominican Peso (DOP). + """ + DOP + + """ + Algerian Dinar (DZD). + """ + DZD + + """ + Egyptian Pound (EGP). + """ + EGP + + """ + Eritrean Nakfa (ERN). + """ + ERN + + """ + Ethiopian Birr (ETB). + """ + ETB + + """ + Euro (EUR). + """ + EUR + + """ + Fijian Dollars (FJD). + """ + FJD + + """ + Falkland Islands Pounds (FKP). + """ + FKP + + """ + United Kingdom Pounds (GBP). + """ + GBP + + """ + Georgian Lari (GEL). + """ + GEL + + """ + Ghanaian Cedi (GHS). + """ + GHS + + """ + Gibraltar Pounds (GIP). + """ + GIP + + """ + Gambian Dalasi (GMD). + """ + GMD + + """ + Guinean Franc (GNF). + """ + GNF + + """ + Guatemalan Quetzal (GTQ). + """ + GTQ + + """ + Guyanese Dollar (GYD). + """ + GYD + + """ + Hong Kong Dollars (HKD). + """ + HKD + + """ + Honduran Lempira (HNL). + """ + HNL + + """ + Croatian Kuna (HRK). + """ + HRK + + """ + Haitian Gourde (HTG). + """ + HTG + + """ + Hungarian Forint (HUF). + """ + HUF + + """ + Indonesian Rupiah (IDR). + """ + IDR + + """ + Israeli New Shekel (NIS). + """ + ILS + + """ + Indian Rupees (INR). + """ + INR + + """ + Iraqi Dinar (IQD). + """ + IQD + + """ + Iranian Rial (IRR). + """ + IRR + + """ + Icelandic Kronur (ISK). + """ + ISK + + """ + Jersey Pound. + """ + JEP + + """ + Jamaican Dollars (JMD). + """ + JMD + + """ + Jordanian Dinar (JOD). + """ + JOD + + """ + Japanese Yen (JPY). + """ + JPY + + """ + Kenyan Shilling (KES). + """ + KES + + """ + Kyrgyzstani Som (KGS). + """ + KGS + + """ + Cambodian Riel. + """ + KHR + + """ + Kiribati Dollar (KID). + """ + KID + + """ + Comorian Franc (KMF). + """ + KMF + + """ + South Korean Won (KRW). + """ + KRW + + """ + Kuwaiti Dinar (KWD). + """ + KWD + + """ + Cayman Dollars (KYD). + """ + KYD + + """ + Kazakhstani Tenge (KZT). + """ + KZT + + """ + Laotian Kip (LAK). + """ + LAK + + """ + Lebanese Pounds (LBP). + """ + LBP + + """ + Sri Lankan Rupees (LKR). + """ + LKR + + """ + Liberian Dollar (LRD). + """ + LRD + + """ + Lesotho Loti (LSL). + """ + LSL + + """ + Lithuanian Litai (LTL). + """ + LTL + + """ + Latvian Lati (LVL). + """ + LVL + + """ + Libyan Dinar (LYD). + """ + LYD + + """ + Moroccan Dirham. + """ + MAD + + """ + Moldovan Leu (MDL). + """ + MDL + + """ + Malagasy Ariary (MGA). + """ + MGA + + """ + Macedonia Denar (MKD). + """ + MKD + + """ + Burmese Kyat (MMK). + """ + MMK + + """ + Mongolian Tugrik. + """ + MNT + + """ + Macanese Pataca (MOP). + """ + MOP + + """ + Mauritanian Ouguiya (MRU). + """ + MRU + + """ + Mauritian Rupee (MUR). + """ + MUR + + """ + Maldivian Rufiyaa (MVR). + """ + MVR + + """ + Malawian Kwacha (MWK). + """ + MWK + + """ + Mexican Pesos (MXN). + """ + MXN + + """ + Malaysian Ringgits (MYR). + """ + MYR + + """ + Mozambican Metical. + """ + MZN + + """ + Namibian Dollar. + """ + NAD + + """ + Nigerian Naira (NGN). + """ + NGN + + """ + Nicaraguan Córdoba (NIO). + """ + NIO + + """ + Norwegian Kroner (NOK). + """ + NOK + + """ + Nepalese Rupee (NPR). + """ + NPR + + """ + New Zealand Dollars (NZD). + """ + NZD + + """ + Omani Rial (OMR). + """ + OMR + + """ + Panamian Balboa (PAB). + """ + PAB + + """ + Peruvian Nuevo Sol (PEN). + """ + PEN + + """ + Papua New Guinean Kina (PGK). + """ + PGK + + """ + Philippine Peso (PHP). + """ + PHP + + """ + Pakistani Rupee (PKR). + """ + PKR + + """ + Polish Zlotych (PLN). + """ + PLN + + """ + Paraguayan Guarani (PYG). + """ + PYG + + """ + Qatari Rial (QAR). + """ + QAR + + """ + Romanian Lei (RON). + """ + RON + + """ + Serbian dinar (RSD). + """ + RSD + + """ + Russian Rubles (RUB). + """ + RUB + + """ + Rwandan Franc (RWF). + """ + RWF + + """ + Saudi Riyal (SAR). + """ + SAR + + """ + Solomon Islands Dollar (SBD). + """ + SBD + + """ + Seychellois Rupee (SCR). + """ + SCR + + """ + Sudanese Pound (SDG). + """ + SDG + + """ + Swedish Kronor (SEK). + """ + SEK + + """ + Singapore Dollars (SGD). + """ + SGD + + """ + Saint Helena Pounds (SHP). + """ + SHP + + """ + Sierra Leonean Leone (SLL). + """ + SLL + + """ + Somali Shilling (SOS). + """ + SOS + + """ + Surinamese Dollar (SRD). + """ + SRD + + """ + South Sudanese Pound (SSP). + """ + SSP + + """ + Sao Tome And Principe Dobra (STD). + """ + STD @deprecated(reason: "`STD` is deprecated. Use `STN` available from version `2022-07` onwards instead.") + + """ + Sao Tome And Principe Dobra (STN). + """ + STN + + """ + Syrian Pound (SYP). + """ + SYP + + """ + Swazi Lilangeni (SZL). + """ + SZL + + """ + Thai baht (THB). + """ + THB + + """ + Tajikistani Somoni (TJS). + """ + TJS + + """ + Turkmenistani Manat (TMT). + """ + TMT + + """ + Tunisian Dinar (TND). + """ + TND + + """ + Tongan Pa'anga (TOP). + """ + TOP + + """ + Turkish Lira (TRY). + """ + TRY + + """ + Trinidad and Tobago Dollars (TTD). + """ + TTD + + """ + Taiwan Dollars (TWD). + """ + TWD + + """ + Tanzanian Shilling (TZS). + """ + TZS + + """ + Ukrainian Hryvnia (UAH). + """ + UAH + + """ + Ugandan Shilling (UGX). + """ + UGX + + """ + United States Dollars (USD). + """ + USD + + """ + Uruguayan Pesos (UYU). + """ + UYU + + """ + Uzbekistan som (UZS). + """ + UZS + + """ + Venezuelan Bolivares (VED). + """ + VED + + """ + Venezuelan Bolivares (VEF). + """ + VEF @deprecated(reason: "`VEF` is deprecated. Use `VES` available from version `2020-10` onwards instead.") + + """ + Venezuelan Bolivares Soberanos (VES). + """ + VES + + """ + Vietnamese đồng (VND). + """ + VND + + """ + Vanuatu Vatu (VUV). + """ + VUV + + """ + Samoan Tala (WST). + """ + WST + + """ + Central African CFA Franc (XAF). + """ + XAF + + """ + East Caribbean Dollar (XCD). + """ + XCD + + """ + West African CFA franc (XOF). + """ + XOF + + """ + CFP Franc (XPF). + """ + XPF + + """ + Unrecognized currency. + """ + XXX + + """ + Yemeni Rial (YER). + """ + YER + + """ + South African Rand (ZAR). + """ + ZAR + + """ + Zambian Kwacha (ZMW). + """ + ZMW +} + +""" +A custom product. +""" +type CustomProduct { + """ + Whether the merchandise is a gift card. + """ + isGiftCard: Boolean! + + """ + Whether the merchandise requires shipping. + """ + requiresShipping: Boolean! + + """ + The localized title of the product in the customer’s locale. + """ + title: String! + + """ + The weight of the product variant in the unit system specified with `weight_unit`. + """ + weight: Float + + """ + Unit of measurement for weight. + """ + weightUnit: WeightUnit! +} + +""" +Represents a customer with the shop. +""" +type Customer implements HasMetafields { + """ + The total amount of money spent by the customer. Converted from the shop's + currency to the currency of the cart using a market rate. + """ + amountSpent: MoneyV2! + + """ + The customer’s name, email or phone number. + """ + displayName: String! + + """ + The customer’s email address. + """ + email: String + + """ + The customer's first name. + """ + firstName: String + + """ + Whether the customer has any of the given tags. + """ + hasAnyTag( + """ + The tags to search for. + """ + tags: [String!]! = [] + ): Boolean! + + """ + Whether the customer has the given tags. + """ + hasTags( + """ + The tags to check. + """ + tags: [String!]! = [] + ): [HasTagResponse!]! + + """ + A unique identifier for the customer. + """ + id: ID! + + """ + The customer's last name. + """ + lastName: String + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The number of orders made by the customer. + """ + numberOfOrders: Int! +} + +""" +Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date string. +For example, September 7, 2019 is represented as `"2019-07-16"`. +""" +scalar Date + +""" +Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date and time string. +For example, 3:50 pm on September 7, 2019 in the time zone of UTC (Coordinated Universal Time) is +represented as `"2019-09-07T15:50:00Z`". +""" +scalar DateTime + +""" +A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that +includes the date and time but not the timezone which is determined from context. + +For example, "2018-01-01T00:00:00". +""" +scalar DateTimeWithoutTimezone + +""" +A signed decimal number, which supports arbitrary precision and is serialized as a string. + +Example values: `"29.99"`, `"29.999"`. +""" +scalar Decimal + +""" +Represents information about the merchandise in the cart. +""" +type DeliverableCartLine { + """ + Retrieve a cart line attribute by key. + + Cart line attributes are also known as line item properties in Liquid. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + The ID of the cart line. + """ + id: ID! + + """ + The merchandise that the buyer intends to purchase. + """ + merchandise: Merchandise! + + """ + The quantity of the merchandise that the customer intends to purchase. + """ + quantity: Int! +} + +""" +The delivery discount candidate to be applied. +""" +input DeliveryDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The discount message. + """ + message: String + + """ + The targets of the delivery discount candidate. + """ + targets: [DeliveryDiscountCandidateTarget!]! + + """ + The value of the delivery discount candidate. + """ + value: DeliveryDiscountCandidateValue! +} + +""" +The target of the delivery discount candidate. +""" +input DeliveryDiscountCandidateTarget @oneOf { + """ + The target delivery group. + """ + deliveryGroup: DeliveryGroupTarget + + """ + The target delivery option. + """ + deliveryOption: DeliveryOptionTarget +} + +""" +The delivery discount candidate value. +""" +input DeliveryDiscountCandidateValue @oneOf { + """ + A fixed amount value. + """ + fixedAmount: FixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of delivery discount candidates. +""" +enum DeliveryDiscountSelectionStrategy { + """ + Apply all delivery discount candidates with conditions that are satisfied. This does not override + discount combination or stacking rules. + """ + ALL +} + +""" +A group of delivery discounts that share a selection strategy. +""" +input DeliveryDiscounts { + """ + The list of delivery discount candidates to be applied. + """ + candidates: [DeliveryDiscountCandidate!]! + + """ + The strategy that's applied to the list of discounts. + """ + selectionStrategy: DeliveryDiscountSelectionStrategy! +} + +""" +The target delivery group. +""" +input DeliveryGroupTarget { + """ + The ID of the target delivery group. + """ + id: ID! +} + +""" +List of different delivery method types. +""" +enum DeliveryMethod { + """ + Local Delivery. + """ + LOCAL + + """ + None. + """ + NONE + + """ + Shipping to a Pickup Point. + """ + PICKUP_POINT + + """ + Local Pickup. + """ + PICK_UP + + """ + Retail. + """ + RETAIL + + """ + Shipping. + """ + SHIPPING +} + +""" +The operations that can be performed to apply discounts to the delivery lines. +""" +input DeliveryOperation @oneOf { + """ + A group of delivery discounts that share a selection strategy. + """ + addDeliveryDiscounts: DeliveryDiscounts + + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes +} + +""" +The target delivery option. +""" +input DeliveryOptionTarget { + """ + The handle of the target delivery option. + """ + handle: Handle! +} + +""" +The discount that invoked the Function. +""" +type Discount implements HasMetafields { + """ + The discount classes supported by the discount node. + """ + discountClasses: [DiscountClass!]! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +The [discount class](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) +that's used to control how discounts can be combined. +""" +enum DiscountClass { + """ + The discount is combined with an + [order discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + ORDER + + """ + The discount is combined with a + [product discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + PRODUCT + + """ + The discount is combined with a + [shipping discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + SHIPPING +} + +""" +A fixed amount value. +""" +input FixedAmount { + """ + The fixed amount value of the discount, in the currency of the cart. + + The amount must be greater than or equal to 0. + """ + amount: Decimal! +} + +""" +The cart.fetch target result. Refer to [network access] +(https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. +""" +input FunctionCartFetchResult { + """ + The http request. + """ + request: HttpRequest +} + +""" +The cart.run target result. +""" +input FunctionCartRunResult { + """ + The list of operations to apply discounts to the cart. + """ + operations: [CartOperation!]! +} + +""" +The delivery.fetch target result. Refer to +[network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. +""" +input FunctionDeliveryFetchResult { + """ + The http request. + """ + request: HttpRequest +} + +""" +The delivery.run target result. +""" +input FunctionDeliveryRunResult { + """ + The list of operations to apply discounts to the delivery lines. + """ + operations: [DeliveryOperation!]! +} + +""" +Represents a gate configuration. +""" +type GateConfiguration implements HasMetafields { + """ + An optional string identifier. + """ + appId: String + + """ + A non-unique string used to group gate configurations. + """ + handle: Handle + + """ + The ID of the gate configuration. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +Represents a connection from a subject to a gate configuration. +""" +type GateSubject { + """ + The bound gate configuration. + """ + configuration( + """ + The appId of the gate configurations to search for. + """ + appId: String @deprecated(reason: "Use GateSubject.handle to filter gates instead.") + ): GateConfiguration! + + """ + The ID of the gate subject. + """ + id: ID! +} + +""" +A function-scoped handle to a refer a resource. +The Handle type appears in a JSON response as a String, but it is not intended to be human-readable. +Example value: `"10079785100"` +""" +scalar Handle + +""" +Gate subjects associated to the specified resource. +""" +interface HasGates { + """ + Returns active gate subjects bound to the resource. + """ + gates( + """ + The handle of the gate configurations to search for. + """ + handle: Handle + ): [GateSubject!]! +} + +""" +Represents information about the metafields associated to the specified resource. +""" +interface HasMetafields { + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +Represents whether the current object has the given tag. +""" +type HasTagResponse { + """ + Whether the current object has the tag. + """ + hasTag: Boolean! + + """ + The tag. + """ + tag: String! +} + +""" +The attributes associated with an HTTP request. +""" +input HttpRequest { + """ + The HTTP request body as a plain string. + Use this field when the body isn't in JSON format. + """ + body: String + + """ + The HTTP headers. + """ + headers: [HttpRequestHeader!]! + + """ + The HTTP request body as a JSON object. + Use this field when the body's in JSON format, to reduce function instruction consumption + and to ensure the body's formatted in logs. + Don't use this field together with the `body` field. If both are provided, then the `body` field + will take precedence. + If this field is specified and no `Content-Type` header is included, then the header will + automatically be set to `application/json`. + """ + jsonBody: JSON + + """ + The HTTP method. + """ + method: HttpRequestMethod! + + """ + Policy attached to the HTTP request. + """ + policy: HttpRequestPolicy! + + """ + The HTTP url (eg.: https://example.com). The scheme needs to be HTTPS. + """ + url: URL! +} + +""" +The attributes associated with an HTTP request header. +""" +input HttpRequestHeader { + """ + Header name. + """ + name: String! + + """ + Header value. + """ + value: String! +} + +""" +The HTTP request available methods. +""" +enum HttpRequestMethod { + """ + Http GET. + """ + GET + + """ + Http POST. + """ + POST +} + +""" +The attributes associated with an HTTP request policy. +""" +input HttpRequestPolicy { + """ + Read timeout in milliseconds. + """ + readTimeoutMs: Int! +} + +""" +The attributes associated with an HTTP response. +""" +type HttpResponse { + """ + The HTTP response body as a plain string. + Use this field when the body is not in JSON format. + """ + body: String + + """ + An HTTP header. + """ + header( + """ + A case-insensitive header name. + """ + name: String! + ): HttpResponseHeader + + """ + The HTTP headers. + """ + headers: [HttpResponseHeader!]! @deprecated(reason: "Use `header` instead.") + + """ + The HTTP response body parsed as JSON. + If the body is valid JSON, it will be parsed and returned as a JSON object. + If parsing fails, then raw body is returned as a string. + Use this field when you expect the response to be JSON, or when you're dealing + with mixed response types, meaning both JSON and non-JSON. + Using this field reduces function instruction consumption and ensures that the data is formatted in logs. + To prevent increasing the function target input size unnecessarily, avoid querying + both `body` and `jsonBody` simultaneously. + """ + jsonBody: JSON + + """ + The HTTP status code. + """ + status: Int! +} + +""" +The attributes associated with an HTTP response header. +""" +type HttpResponseHeader { + """ + Header name. + """ + name: String! + + """ + Header value. + """ + value: String! +} + +""" +Represents a unique identifier, often used to refetch an object. +The ID type appears in a JSON response as a String, but it is not intended to be human-readable. + +Example value: `"gid://shopify/Product/10079785100"` +""" +scalar ID + +""" +The input object for the Function. +""" +type Input { + """ + The cart. + """ + cart: Cart! + + """ + The discount node executing the Function. + """ + discount: Discount! + + """ + Discount codes entered by the buyer as an array of strings, excluding gift cards. + Codes are not validated in any way other than gift card filtering. + """ + enteredDiscountCodes: [String!]! @restrictTarget(only: ["cart.lines.discounts.generate.fetch", "cart.delivery-options.discounts.generate.fetch"]) + + """ + The result of the fetch target. Refer to [network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) + for Shopify Functions. + """ + fetchResult: HttpResponse @restrictTarget(only: ["cart.lines.discounts.generate.run", "cart.delivery-options.discounts.generate.run"]) + + """ + The localization of the Function execution context. + """ + localization: Localization! + + """ + The conversion rate between the shop's currency and the currency of the cart. + """ + presentmentCurrencyRate: Decimal! + + """ + Information about the shop. + """ + shop: Shop! + + """ + The discount code entered by the buyer that caused the Function to run. + This input is only available in the cart.lines.discounts.generate.run + and cart.delivery-options.discounts.generate.run extension targets. + """ + triggeringDiscountCode: String @restrictTarget(only: ["cart.lines.discounts.generate.run", "cart.delivery-options.discounts.generate.run"]) +} + +""" +A [JSON](https://www.json.org/json-en.html) object. + +Example value: +`{ + "product": { + "id": "gid://shopify/Product/1346443542550", + "title": "White T-shirt", + "options": [{ + "name": "Size", + "values": ["M", "L"] + }] + } +}` +""" +scalar JSON + +""" +A language. +""" +type Language { + """ + The ISO code. + """ + isoCode: LanguageCode! +} + +""" +Language codes supported by Shopify. +""" +enum LanguageCode { + """ + Afrikaans. + """ + AF + + """ + Akan. + """ + AK + + """ + Amharic. + """ + AM + + """ + Arabic. + """ + AR + + """ + Assamese. + """ + AS + + """ + Azerbaijani. + """ + AZ + + """ + Belarusian. + """ + BE + + """ + Bulgarian. + """ + BG + + """ + Bambara. + """ + BM + + """ + Bangla. + """ + BN + + """ + Tibetan. + """ + BO + + """ + Breton. + """ + BR + + """ + Bosnian. + """ + BS + + """ + Catalan. + """ + CA + + """ + Chechen. + """ + CE + + """ + Central Kurdish. + """ + CKB + + """ + Czech. + """ + CS + + """ + Church Slavic. + """ + CU + + """ + Welsh. + """ + CY + + """ + Danish. + """ + DA + + """ + German. + """ + DE + + """ + Dzongkha. + """ + DZ + + """ + Ewe. + """ + EE + + """ + Greek. + """ + EL + + """ + English. + """ + EN + + """ + Esperanto. + """ + EO + + """ + Spanish. + """ + ES + + """ + Estonian. + """ + ET + + """ + Basque. + """ + EU + + """ + Persian. + """ + FA + + """ + Fulah. + """ + FF + + """ + Finnish. + """ + FI + + """ + Filipino. + """ + FIL + + """ + Faroese. + """ + FO + + """ + French. + """ + FR + + """ + Western Frisian. + """ + FY + + """ + Irish. + """ + GA + + """ + Scottish Gaelic. + """ + GD + + """ + Galician. + """ + GL + + """ + Gujarati. + """ + GU + + """ + Manx. + """ + GV + + """ + Hausa. + """ + HA + + """ + Hebrew. + """ + HE + + """ + Hindi. + """ + HI + + """ + Croatian. + """ + HR + + """ + Hungarian. + """ + HU + + """ + Armenian. + """ + HY + + """ + Interlingua. + """ + IA + + """ + Indonesian. + """ + ID + + """ + Igbo. + """ + IG + + """ + Sichuan Yi. + """ + II + + """ + Icelandic. + """ + IS + + """ + Italian. + """ + IT + + """ + Japanese. + """ + JA + + """ + Javanese. + """ + JV + + """ + Georgian. + """ + KA + + """ + Kikuyu. + """ + KI + + """ + Kazakh. + """ + KK + + """ + Kalaallisut. + """ + KL + + """ + Khmer. + """ + KM + + """ + Kannada. + """ + KN + + """ + Korean. + """ + KO + + """ + Kashmiri. + """ + KS + + """ + Kurdish. + """ + KU + + """ + Cornish. + """ + KW + + """ + Kyrgyz. + """ + KY + + """ + Luxembourgish. + """ + LB + + """ + Ganda. + """ + LG + + """ + Lingala. + """ + LN + + """ + Lao. + """ + LO + + """ + Lithuanian. + """ + LT + + """ + Luba-Katanga. + """ + LU + + """ + Latvian. + """ + LV + + """ + Malagasy. + """ + MG + + """ + Māori. + """ + MI + + """ + Macedonian. + """ + MK + + """ + Malayalam. + """ + ML + + """ + Mongolian. + """ + MN + + """ + Marathi. + """ + MR + + """ + Malay. + """ + MS + + """ + Maltese. + """ + MT + + """ + Burmese. + """ + MY + + """ + Norwegian (Bokmål). + """ + NB + + """ + North Ndebele. + """ + ND + + """ + Nepali. + """ + NE + + """ + Dutch. + """ + NL + + """ + Norwegian Nynorsk. + """ + NN + + """ + Norwegian. + """ + NO + + """ + Oromo. + """ + OM + + """ + Odia. + """ + OR + + """ + Ossetic. + """ + OS + + """ + Punjabi. + """ + PA + + """ + Polish. + """ + PL + + """ + Pashto. + """ + PS + + """ + Portuguese. + """ + PT + + """ + Portuguese (Brazil). + """ + PT_BR + + """ + Portuguese (Portugal). + """ + PT_PT + + """ + Quechua. + """ + QU + + """ + Romansh. + """ + RM + + """ + Rundi. + """ + RN + + """ + Romanian. + """ + RO + + """ + Russian. + """ + RU + + """ + Kinyarwanda. + """ + RW + + """ + Sanskrit. + """ + SA + + """ + Sardinian. + """ + SC + + """ + Sindhi. + """ + SD + + """ + Northern Sami. + """ + SE + + """ + Sango. + """ + SG + + """ + Sinhala. + """ + SI + + """ + Slovak. + """ + SK + + """ + Slovenian. + """ + SL + + """ + Shona. + """ + SN + + """ + Somali. + """ + SO + + """ + Albanian. + """ + SQ + + """ + Serbian. + """ + SR + + """ + Sundanese. + """ + SU + + """ + Swedish. + """ + SV + + """ + Swahili. + """ + SW + + """ + Tamil. + """ + TA + + """ + Telugu. + """ + TE + + """ + Tajik. + """ + TG + + """ + Thai. + """ + TH + + """ + Tigrinya. + """ + TI + + """ + Turkmen. + """ + TK + + """ + Tongan. + """ + TO + + """ + Turkish. + """ + TR + + """ + Tatar. + """ + TT + + """ + Uyghur. + """ + UG + + """ + Ukrainian. + """ + UK + + """ + Urdu. + """ + UR + + """ + Uzbek. + """ + UZ + + """ + Vietnamese. + """ + VI + + """ + Volapük. + """ + VO + + """ + Wolof. + """ + WO + + """ + Xhosa. + """ + XH + + """ + Yiddish. + """ + YI + + """ + Yoruba. + """ + YO + + """ + Chinese. + """ + ZH + + """ + Chinese (Simplified). + """ + ZH_CN + + """ + Chinese (Traditional). + """ + ZH_TW + + """ + Zulu. + """ + ZU +} + +""" +Represents limited information about the current time relative to the parent object. +""" +type LocalTime { + """ + The current date relative to the parent object. + """ + date: Date! + + """ + Returns true if the current date and time is at or past the given date and time, and false otherwise. + """ + dateTimeAfter( + """ + The date and time to compare against, assumed to be in the timezone of the parent object. + """ + dateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current date and time is before the given date and time, and false otherwise. + """ + dateTimeBefore( + """ + The date and time to compare against, assumed to be in the timezone of the parent timezone. + """ + dateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current date and time is between the two given date and times, and false otherwise. + """ + dateTimeBetween( + """ + The upper bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + endDateTime: DateTimeWithoutTimezone! + + """ + The lower bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + startDateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is at or past the given time, and false otherwise. + """ + timeAfter( + """ + The time to compare against, assumed to be in the timezone of the parent timezone. + """ + time: TimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is at or past the given time, and false otherwise. + """ + timeBefore( + """ + The time to compare against, assumed to be in the timezone of the parent timezone. + """ + time: TimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is between the two given times, and false otherwise. + """ + timeBetween( + """ + The upper bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + endTime: TimeWithoutTimezone! + + """ + The lower bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + startTime: TimeWithoutTimezone! + ): Boolean! +} + +""" +Information about the localized experiences configured for the shop. +""" +type Localization { + """ + The country of the active localized experience. + """ + country: Country! + + """ + The language of the active localized experience. + """ + language: Language! + + """ + The market of the active localized experience. + """ + market: Market! @deprecated(reason: "This `market` field will be removed in a future version of the API.") +} + +""" +Represents the value captured by a localized field. Localized fields are +additional fields required by certain countries on international orders. For +example, some countries require additional fields for customs information or tax +identification numbers. +""" +type LocalizedField { + """ + The key of the localized field. + """ + key: LocalizedFieldKey! + + """ + The title of the localized field. + """ + title: String! + + """ + The value of the localized field. + """ + value: String +} + +""" +Unique key identifying localized fields. +""" +enum LocalizedFieldKey { + """ + Localized field key 'shipping_credential_br' for country Brazil. + """ + SHIPPING_CREDENTIAL_BR + + """ + Localized field key 'shipping_credential_cl' for country Chile. + """ + SHIPPING_CREDENTIAL_CL + + """ + Localized field key 'shipping_credential_cn' for country China. + """ + SHIPPING_CREDENTIAL_CN + + """ + Localized field key 'shipping_credential_co' for country Colombia. + """ + SHIPPING_CREDENTIAL_CO + + """ + Localized field key 'shipping_credential_cr' for country Costa Rica. + """ + SHIPPING_CREDENTIAL_CR + + """ + Localized field key 'shipping_credential_ec' for country Ecuador. + """ + SHIPPING_CREDENTIAL_EC + + """ + Localized field key 'shipping_credential_es' for country Spain. + """ + SHIPPING_CREDENTIAL_ES + + """ + Localized field key 'shipping_credential_gt' for country Guatemala. + """ + SHIPPING_CREDENTIAL_GT + + """ + Localized field key 'shipping_credential_id' for country Indonesia. + """ + SHIPPING_CREDENTIAL_ID + + """ + Localized field key 'shipping_credential_kr' for country South Korea. + """ + SHIPPING_CREDENTIAL_KR + + """ + Localized field key 'shipping_credential_mx' for country Mexico. + """ + SHIPPING_CREDENTIAL_MX + + """ + Localized field key 'shipping_credential_my' for country Malaysia. + """ + SHIPPING_CREDENTIAL_MY + + """ + Localized field key 'shipping_credential_pe' for country Peru. + """ + SHIPPING_CREDENTIAL_PE + + """ + Localized field key 'shipping_credential_pt' for country Portugal. + """ + SHIPPING_CREDENTIAL_PT + + """ + Localized field key 'shipping_credential_py' for country Paraguay. + """ + SHIPPING_CREDENTIAL_PY + + """ + Localized field key 'shipping_credential_tr' for country Turkey. + """ + SHIPPING_CREDENTIAL_TR + + """ + Localized field key 'shipping_credential_tw' for country Taiwan. + """ + SHIPPING_CREDENTIAL_TW + + """ + Localized field key 'shipping_credential_type_co' for country Colombia. + """ + SHIPPING_CREDENTIAL_TYPE_CO + + """ + Localized field key 'tax_credential_br' for country Brazil. + """ + TAX_CREDENTIAL_BR + + """ + Localized field key 'tax_credential_cl' for country Chile. + """ + TAX_CREDENTIAL_CL + + """ + Localized field key 'tax_credential_co' for country Colombia. + """ + TAX_CREDENTIAL_CO + + """ + Localized field key 'tax_credential_cr' for country Costa Rica. + """ + TAX_CREDENTIAL_CR + + """ + Localized field key 'tax_credential_ec' for country Ecuador. + """ + TAX_CREDENTIAL_EC + + """ + Localized field key 'tax_credential_es' for country Spain. + """ + TAX_CREDENTIAL_ES + + """ + Localized field key 'tax_credential_gt' for country Guatemala. + """ + TAX_CREDENTIAL_GT + + """ + Localized field key 'tax_credential_id' for country Indonesia. + """ + TAX_CREDENTIAL_ID + + """ + Localized field key 'tax_credential_it' for country Italy. + """ + TAX_CREDENTIAL_IT + + """ + Localized field key 'tax_credential_mx' for country Mexico. + """ + TAX_CREDENTIAL_MX + + """ + Localized field key 'tax_credential_my' for country Malaysia. + """ + TAX_CREDENTIAL_MY + + """ + Localized field key 'tax_credential_pe' for country Peru. + """ + TAX_CREDENTIAL_PE + + """ + Localized field key 'tax_credential_pt' for country Portugal. + """ + TAX_CREDENTIAL_PT + + """ + Localized field key 'tax_credential_py' for country Paraguay. + """ + TAX_CREDENTIAL_PY + + """ + Localized field key 'tax_credential_tr' for country Turkey. + """ + TAX_CREDENTIAL_TR + + """ + Localized field key 'tax_credential_type_co' for country Colombia. + """ + TAX_CREDENTIAL_TYPE_CO + + """ + Localized field key 'tax_credential_type_mx' for country Mexico. + """ + TAX_CREDENTIAL_TYPE_MX + + """ + Localized field key 'tax_credential_use_mx' for country Mexico. + """ + TAX_CREDENTIAL_USE_MX + + """ + Localized field key 'tax_email_it' for country Italy. + """ + TAX_EMAIL_IT +} + +""" +Represents a mailing address. +""" +type MailingAddress { + """ + The first line of the address. Typically the street address or PO Box number. + """ + address1: String + + """ + The second line of the address. Typically the number of the apartment, suite, or unit. + """ + address2: String + + """ + The name of the city, district, village, or town. + """ + city: String + + """ + The name of the customer's company or organization. + """ + company: String + + """ + The two-letter code for the country of the address. For example, US. + """ + countryCode: CountryCode + + """ + The first name of the customer. + """ + firstName: String + + """ + The last name of the customer. + """ + lastName: String + + """ + The approximate latitude of the address. + """ + latitude: Float + + """ + The approximate longitude of the address. + """ + longitude: Float + + """ + The market of the address. + """ + market: Market @deprecated(reason: "This `market` field will be removed in a future version of the API.") + + """ + The full name of the customer, based on firstName and lastName. + """ + name: String + + """ + A unique phone number for the customer. Formatted using E.164 standard. For example, +16135551111. + """ + phone: String + + """ + The alphanumeric code for the region. For example, ON. + """ + provinceCode: String + + """ + The zip or postal code of the address. + """ + zip: String +} + +""" +A market is a group of one or more regions that you want to target for international sales. +By creating a market, you can configure a distinct, localized shopping experience for +customers from a specific area of the world. For example, you can +[change currency](https://shopify.dev/api/admin-graphql/current/mutations/marketCurrencySettingsUpdate), +[configure international pricing](https://shopify.dev/api/examples/product-price-lists), +or [add market-specific domains or subfolders](https://shopify.dev/api/admin-graphql/current/objects/MarketWebPresence). +""" +type Market implements HasMetafields { + """ + A human-readable unique string for the market automatically generated from its title. + """ + handle: Handle! + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + A geographic region which comprises a market. + """ + regions: [MarketRegion!]! +} + +""" +Represents a region. +""" +interface MarketRegion { + """ + The name of the region in the language of the current localization. + """ + name: String +} + +""" +A country which comprises a market. +""" +type MarketRegionCountry implements MarketRegion { + """ + The two-letter code for the country. + """ + code: CountryCode! + + """ + The country name in the language of the current localization. + """ + name: String! +} + +""" +The merchandise to be purchased at checkout. +""" +union Merchandise = CustomProduct | ProductVariant + +""" +[Metafields](https://shopify.dev/apps/metafields) +enable you to attach additional information to a +Shopify resource, such as a [Product](https://shopify.dev/api/admin-graphql/latest/objects/product) +or a [Collection](https://shopify.dev/api/admin-graphql/latest/objects/collection). +For more information about the Shopify resources that you can attach metafields to, refer to +[HasMetafields](https://shopify.dev/api/admin/graphql/reference/common-objects/HasMetafields). +""" +type Metafield { + """ + The data stored in the metafield in JSON format. + """ + jsonValue: JSON! + + """ + The type of data that the metafield stores in the `value` field. + Refer to the list of [supported types](https://shopify.dev/apps/metafields/types). + """ + type: String! + + """ + The data stored in the metafield. Always stored as a string, regardless of the metafield's type. + """ + value: String! +} + +""" +A monetary value with currency. +""" +type MoneyV2 { + """ + Decimal money amount. + """ + amount: Decimal! + + """ + Currency of the money. + """ + currencyCode: CurrencyCode! +} + +""" +The root mutation for the API. +""" +type MutationRoot { + """ + Handles the Function result for the cart.delivery-options.discounts.generate.fetch target. + """ + cartDeliveryOptionsDiscountsGenerateFetch( + """ + The result of the Function. + """ + result: FunctionDeliveryFetchResult! + ): Void! + + """ + Handles the Function result for the cart.delivery-options.discounts.generate.run target. + """ + cartDeliveryOptionsDiscountsGenerateRun( + """ + The result of the Function. + """ + result: FunctionDeliveryRunResult! + ): Void! + + """ + Handles the Function result for the cart.lines.discounts.generate.fetch target. + """ + cartLinesDiscountsGenerateFetch( + """ + The result of the Function. + """ + result: FunctionCartFetchResult! + ): Void! + + """ + Handles the Function result for the cart.lines.discounts.generate.run target. + """ + cartLinesDiscountsGenerateRun( + """ + The result of the Function. + """ + result: FunctionCartRunResult! + ): Void! +} + +""" +The order discount candidate to be applied. +""" +input OrderDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The conditions that must be satisfied to apply the order discount candidate. + """ + conditions: [Condition!] + + """ + The discount message. + """ + message: String + + """ + The targets of the order discount candidate. + """ + targets: [OrderDiscountCandidateTarget!]! + + """ + The value of the order discount candidate. + """ + value: OrderDiscountCandidateValue! +} + +""" +A target of a order discount candidate. +""" +input OrderDiscountCandidateTarget @oneOf { + """ + If used, the discount targets the entire order subtotal after product discounts are applied. + """ + orderSubtotal: OrderSubtotalTarget +} + +""" +The order discount candidate value. +""" +input OrderDiscountCandidateValue @oneOf { + """ + A fixed amount value. + """ + fixedAmount: FixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of order discount candidates. +""" +enum OrderDiscountSelectionStrategy { + """ + Only apply the first order discount candidate with conditions that are satisfied. + """ + FIRST + + """ + Only apply the order discount candidate that offers the maximum reduction. + """ + MAXIMUM +} + +""" +A group of order discounts that share a selection strategy. +""" +input OrderDiscounts { + """ + The list of order discount candidates to be applied. + """ + candidates: [OrderDiscountCandidate!]! + + """ + The strategy that's applied to the list of discounts. + """ + selectionStrategy: OrderDiscountSelectionStrategy! +} + +""" +The condition for checking the minimum subtotal amount of the order. +""" +input OrderMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's excluded to calculate the minimum subtotal amount of the order. + """ + excludedCartLineIds: [ID!]! + + """ + The minimum subtotal amount of the order. + """ + minimumAmount: Decimal! +} + +""" +If used, the discount targets the entire order subtotal after product discounts are applied. +""" +input OrderSubtotalTarget { + """ + The list of excluded cart line IDs. These cart lines are excluded from the order + subtotal calculation when calculating the maximum value of the discount. + """ + excludedCartLineIds: [ID!]! +} + +""" +A percentage value. +""" +input Percentage { + """ + The percentage value. + + The value is validated against: >= 0 and <= 100. + """ + value: Decimal! +} + +""" +Represents a product. +""" +type Product implements HasGates & HasMetafields { + """ + Returns active gate subjects bound to the resource. + """ + gates( + """ + The handle of the gate configurations to search for. + """ + handle: Handle + ): [GateSubject!]! + + """ + A unique human-friendly string of the product's title. + """ + handle: Handle! + + """ + Whether the product has any of the given tags. + """ + hasAnyTag( + """ + The tags to check. + """ + tags: [String!]! = [] + ): Boolean! + + """ + Whether the product has the given tags. + """ + hasTags( + """ + The tags to check. + """ + tags: [String!]! = [] + ): [HasTagResponse!]! + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Whether the product is in any of the given collections. + """ + inAnyCollection( + """ + The IDs of the collections to check. + """ + ids: [ID!]! = [] + ): Boolean! + + """ + Whether the product is in the given collections. + """ + inCollections( + """ + The IDs of the collections to check. + """ + ids: [ID!]! = [] + ): [CollectionMembership!]! + + """ + Whether the product is a gift card. + """ + isGiftCard: Boolean! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The product type specified by the merchant. + """ + productType: String + + """ + The localized title of the product in the customer’s locale. + """ + title: String! + + """ + The name of the product's vendor. + """ + vendor: String +} + +""" +The product discount candidate to be applied. +""" +input ProductDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The discount message. + """ + message: String + + """ + The targets of the product discount candidate. + """ + targets: [ProductDiscountCandidateTarget!]! + + """ + The value of the product discount candidate. + """ + value: ProductDiscountCandidateValue! +} + +""" +A product discount candidate fixed amount value. +""" +input ProductDiscountCandidateFixedAmount { + """ + The fixed amount value of the product discount candidate, in the currency of the cart. + + The amount must be greater than or equal to 0. + """ + amount: Decimal! + + """ + Whether to apply the value to each entitled item. + + The default value is `false`, which causes the value to be applied once across the entitled items. + When the value is `true`, the value will be applied to each of the entitled items. + """ + appliesToEachItem: Boolean = false +} + +""" +A target of a product discount candidate, which determines which cart line(s) the discount will affect. + +Multiple targets with the same type and ID are the same as a single target of that type and ID with their +quantities added together, or `null` if any of those targets have a quantity of `null`. + +See the [Discounts API reference](https://shopify.dev/docs/api/functions/reference/product-discounts/graphql#functionrunresult) for examples. +""" +input ProductDiscountCandidateTarget @oneOf { + """ + A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. + """ + cartLine: CartLineTarget +} + +""" +The value of the product discount candidate. +""" +input ProductDiscountCandidateValue @oneOf { + """ + A product discount candidate fixed amount value. + """ + fixedAmount: ProductDiscountCandidateFixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of product discount candidates. +""" +enum ProductDiscountSelectionStrategy { + """ + Apply all product discount candidates with conditions that are satisfied. This + does not override discount combination or stacking rules. + """ + ALL + + """ + Only apply the first product discount candidate with conditions that are satisfied. + """ + FIRST + + """ + Only apply the product discount candidate that offers the maximum reduction. + """ + MAXIMUM +} + +""" +A group of product discounts that share a selection strategy. +""" +input ProductDiscounts { + """ + The list of product discount candidates to be applied. + """ + candidates: [ProductDiscountCandidate!]! + + """ + The strategy that's applied to the list of product discount candidates. + """ + selectionStrategy: ProductDiscountSelectionStrategy! +} + +""" +Represents a product variant. +""" +type ProductVariant implements HasMetafields { + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The product that this variant belongs to. + """ + product: Product! + + """ + Whether the merchandise requires shipping. + """ + requiresShipping: Boolean! + + """ + An identifier for the product variant in the shop. Required in order to connect to a fulfillment service. + """ + sku: String + + """ + The localized title of the product variant in the customer’s locale. + """ + title: String + + """ + The weight of the product variant in the unit system specified with `weight_unit`. + """ + weight: Float + + """ + Unit of measurement for weight. + """ + weightUnit: WeightUnit! +} + +""" +Represents information about the buyer that is interacting with the cart. +""" +type PurchasingCompany { + """ + The company associated to the order or draft order. + """ + company: Company! + + """ + The company contact associated to the order or draft order. + """ + contact: CompanyContact + + """ + The company location associated to the order or draft order. + """ + location: CompanyLocation! +} + +""" +Represents how products and variants can be sold and purchased. +""" +type SellingPlan implements HasMetafields { + """ + The description of the selling plan. + """ + description: String + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. + """ + name: String! + + """ + Whether purchasing the selling plan will result in multiple deliveries. + """ + recurringDeliveries: Boolean! +} + +""" +Represents an association between a variant and a selling plan. Selling plan +allocations describe the options offered for each variant, and the price of the +variant when purchased with a selling plan. +""" +type SellingPlanAllocation { + """ + A list of price adjustments, with a maximum of two. When there are two, the + first price adjustment goes into effect at the time of purchase, while the + second one starts after a certain number of orders. A price adjustment + represents how a selling plan affects pricing when a variant is purchased with + a selling plan. Prices display in the customer's currency if the shop is + configured for it. + """ + priceAdjustments: [SellingPlanAllocationPriceAdjustment!]! + + """ + A representation of how products and variants can be sold and purchased. For + example, an individual selling plan could be '6 weeks of prepaid granola, + delivered weekly'. + """ + sellingPlan: SellingPlan! +} + +""" +The resulting prices for variants when they're purchased with a specific selling plan. +""" +type SellingPlanAllocationPriceAdjustment { + """ + The effective price for a single delivery. For example, for a prepaid + subscription plan that includes 6 deliveries at the price of $48.00, the per + delivery price is $8.00. + """ + perDeliveryPrice: MoneyV2! + + """ + The price of the variant when it's purchased with a selling plan For example, + for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, + where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. + """ + price: MoneyV2! +} + +""" +Information about the shop. +""" +type Shop implements HasMetafields { + """ + Information about the current time relative to the shop's timezone setting. + """ + localTime: LocalTime! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that +includes the time but not the date or timezone which is determined from context. +For example, "05:43:21". +""" +scalar TimeWithoutTimezone + +""" +Represents an [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and +[RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987)-compliant URI string. + +For example, `"https://example.myshopify.com"` is a valid URL. It includes a scheme (`https`) and a host +(`example.myshopify.com`). +""" +scalar URL + +""" +A discount code that corresponds to a valid external discount. +This can only be used by Functions with network access. +""" +input ValidDiscountCode { + """ + The discount code. + """ + code: String! +} + +""" +A list of valid discount codes that correspond to external discounts. This can +only be used by Functions with network access. +""" +input ValidDiscountCodes { + """ + The list of valid discount codes. + """ + codes: [ValidDiscountCode!]! +} + +""" +A void type that can be used to return a null value from a mutation. +""" +scalar Void + +""" +Units of measurement for weight. +""" +enum WeightUnit { + """ + Metric system unit of mass. + """ + GRAMS + + """ + 1 kilogram equals 1000 grams. + """ + KILOGRAMS + + """ + Imperial system unit of mass. + """ + OUNCES + + """ + 1 pound equals 16 ounces. + """ + POUNDS +} diff --git a/discounts/javascript/network/default/shopify.extension.toml.liquid b/discounts/javascript/network/default/shopify.extension.toml.liquid new file mode 100644 index 00000000..afd78e93 --- /dev/null +++ b/discounts/javascript/network/default/shopify.extension.toml.liquid @@ -0,0 +1,32 @@ +api_version = "2025-04" + +[[extensions]] +name = "t:name" +handle = "{{handle}}" +type = "function" +{% if uid %}uid = "{{ uid }}"{% endif %} +description = "t:description" + + [[extensions.targeting]] + target = "cart.lines.discounts.generate.run" + input_query = "src/generate_cart_run.graphql" + export = "generate-cart-run" + + [[extensions.targeting]] + target = "cart.delivery-options.discounts.generate.run" + input_query = "src/generate_delivery_run.graphql" + export = "generate-delivery-run" + + [[extensions.targeting]] + target = "cart.lines.discounts.generate.fetch" + input_query = "src/generate_cart_fetch.graphql" + export = "generate-cart-fetch" + + [[extensions.targeting]] + target = "cart.delivery-options.discounts.generate.fetch" + input_query = "src/generate_delivery_fetch.graphql" + export = "generate-delivery-fetch" + + [extensions.build] + command = "" + path = "dist/function.wasm" diff --git a/discounts/javascript/network/default/src/generate_cart_fetch.graphql.liquid b/discounts/javascript/network/default/src/generate_cart_fetch.graphql.liquid new file mode 100644 index 00000000..e44ae593 --- /dev/null +++ b/discounts/javascript/network/default/src/generate_cart_fetch.graphql.liquid @@ -0,0 +1,3 @@ +query InputCartFetch { + enteredDiscountCodes +} diff --git a/discounts/javascript/network/default/src/generate_cart_fetch.liquid b/discounts/javascript/network/default/src/generate_cart_fetch.liquid new file mode 100644 index 00000000..498ae4a7 --- /dev/null +++ b/discounts/javascript/network/default/src/generate_cart_fetch.liquid @@ -0,0 +1,65 @@ +{%- if flavor contains "vanilla-js" -%} +// @ts-check + +import {HttpRequestMethod} from '../generated/api'; + +/** + * @typedef {import("../generated/api").InputCartFetch} InputCartFetch + * @typedef {import("../generated/api").FunctionCartFetchResult} FunctionCartFetchResult + */ +/** + * Generates a network request to fetch cart discount information + * @param {InputCartFetch} input - The cart fetch input data + * @returns {FunctionCartFetchResult} - The function result with network request configuration + */ +export function generateCartFetch(input) { + const { enteredDiscountCodes } = input; + const jsonBody = { enteredDiscountCodes }; + const request = { + headers: [ + { + name: 'accept', + value: 'application/json', + }, + ], + method: HttpRequestMethod.Post, + policy: { + readTimeoutMs: 2000, + }, + url: '', + body: JSON.stringify(jsonBody), + jsonBody, + }; + return { request }; +} +{%- elsif flavor contains "typescript" -%} +import { + HttpRequestMethod, + InputCartFetch, + FunctionCartFetchResult, +} from '../generated/api'; + +export function generateCartFetch( + input: InputCartFetch, +): FunctionCartFetchResult { + const {enteredDiscountCodes} = input; + const jsonBody = {enteredDiscountCodes}; + const request = { + headers: [ + { + name: 'accept', + value: 'application/json', + }, + ], + method: HttpRequestMethod.Post, + policy: { + readTimeoutMs: 2000, + }, + url: '', + body: JSON.stringify(jsonBody), + jsonBody, + }; + + return {request}; +} +{%- endif -%} diff --git a/discounts/javascript/network/default/src/generate_cart_run.graphql.liquid b/discounts/javascript/network/default/src/generate_cart_run.graphql.liquid new file mode 100644 index 00000000..2ba17002 --- /dev/null +++ b/discounts/javascript/network/default/src/generate_cart_run.graphql.liquid @@ -0,0 +1,6 @@ +query InputCartRun { + fetchResult { + body + } +} + diff --git a/discounts/javascript/network/default/src/generate_cart_run.liquid b/discounts/javascript/network/default/src/generate_cart_run.liquid new file mode 100644 index 00000000..04c3ba8d --- /dev/null +++ b/discounts/javascript/network/default/src/generate_cart_run.liquid @@ -0,0 +1,37 @@ +{%- if flavor contains "vanilla-js" -%} +// @ts-check +/** + * @typedef {import("../generated/api").InputCartRun} InputCartRun + * @typedef {import("../generated/api").FunctionCartRunResult} FunctionCartRunResult + */ +/** + * Processes the fetched cart discount data and generates operations + * @param {InputCartRun} input - The cart run input data including fetch results + * @returns {FunctionCartRunResult} - The function result with discount operations + */ +export function generateCartRun(input) { + const { fetchResult } = input; + const body = fetchResult?.body; + if (!body) { + throw new Error('Missing response body'); + } + // Parse the response body and extract the operations + const { operations } = JSON.parse(body); + return { operations }; +} +{%- elsif flavor contains "typescript" -%} +import {InputCartRun, FunctionCartRunResult} from '../generated/api'; + +export function generateCartRun(input: InputCartRun): FunctionCartRunResult { + const {fetchResult} = input; + const body = fetchResult?.body; + + if (!body) { + throw new Error('Missing response body'); + } + + // Parse the response body and extract the operations + const {operations} = JSON.parse(body); + return {operations}; +} +{%- endif -%} diff --git a/discounts/javascript/network/default/src/generate_delivery_fetch.graphql.liquid b/discounts/javascript/network/default/src/generate_delivery_fetch.graphql.liquid new file mode 100644 index 00000000..005de91b --- /dev/null +++ b/discounts/javascript/network/default/src/generate_delivery_fetch.graphql.liquid @@ -0,0 +1,3 @@ +query InputDeliveryFetch { + enteredDiscountCodes +} diff --git a/discounts/javascript/network/default/src/generate_delivery_fetch.liquid b/discounts/javascript/network/default/src/generate_delivery_fetch.liquid new file mode 100644 index 00000000..c959a69c --- /dev/null +++ b/discounts/javascript/network/default/src/generate_delivery_fetch.liquid @@ -0,0 +1,64 @@ +{%- if flavor contains "vanilla-js" -%} +// @ts-check +import {HttpRequestMethod} from '../generated/api'; + +/** + * @typedef {import("../generated/api").InputDeliveryFetch} InputDeliveryFetch + * @typedef {import("../generated/api").FunctionDeliveryFetchResult} FunctionDeliveryFetchResult + */ +/** + * Generates a network request to fetch delivery discount information + * @param {InputDeliveryFetch} input - The delivery fetch input data + * @returns {FunctionDeliveryFetchResult} - The function result with network request configuration + */ +export function generateDeliveryFetch(input) { + const { enteredDiscountCodes } = input; + const jsonBody = { enteredDiscountCodes }; + const request = { + headers: [ + { + name: 'accept', + value: 'application/json', + }, + ], + method: HttpRequestMethod.Post, + policy: { + readTimeoutMs: 2000, + }, + url: '', + body: JSON.stringify(jsonBody), + jsonBody, + }; + return { request }; +} +{%- elsif flavor contains "typescript" -%} +import { + HttpRequestMethod, + InputDeliveryFetch, + FunctionDeliveryFetchResult, +} from '../generated/api'; +export function generateDeliveryFetch( + input: InputDeliveryFetch, +): FunctionDeliveryFetchResult { + const {enteredDiscountCodes} = input; + const jsonBody = {enteredDiscountCodes}; + + const request = { + headers: [ + { + name: 'accept', + value: 'application/json', + }, + ], + method: HttpRequestMethod.Post, + policy: { + readTimeoutMs: 2000, + }, + url: '', + body: JSON.stringify(jsonBody), + jsonBody, + }; + + return {request}; +} +{%- endif -%} diff --git a/discounts/javascript/network/default/src/generate_delivery_run.graphql.liquid b/discounts/javascript/network/default/src/generate_delivery_run.graphql.liquid new file mode 100644 index 00000000..73503a1b --- /dev/null +++ b/discounts/javascript/network/default/src/generate_delivery_run.graphql.liquid @@ -0,0 +1,11 @@ +query InputDeliveryRun { + fetchResult { + body + status + } + cart { + deliveryGroups { + id + } + } +} diff --git a/discounts/javascript/network/default/src/generate_delivery_run.liquid b/discounts/javascript/network/default/src/generate_delivery_run.liquid new file mode 100644 index 00000000..48ec221c --- /dev/null +++ b/discounts/javascript/network/default/src/generate_delivery_run.liquid @@ -0,0 +1,39 @@ +{%- if flavor contains "vanilla-js" -%} +// @ts-check +/** + * @typedef {import("../generated/api").InputDeliveryRun} InputDeliveryRun + * @typedef {import("../generated/api").FunctionDeliveryRunResult} FunctionDeliveryRunResult + */ +/** + * Processes the fetched delivery discount data and generates operations + * @param {InputDeliveryRun} input - The delivery run input data including fetch results + * @returns {FunctionDeliveryRunResult} - The function result with discount operations + */ +export function generateDeliveryRun(input) { + const { fetchResult } = input; + const body = fetchResult?.body; + if (!body) { + throw new Error('Missing response body'); + } + // Parse the response body and extract the operations + const { operations } = JSON.parse(body); + return { operations }; +} +{%- elsif flavor contains "typescript" -%} +import {InputDeliveryRun, FunctionDeliveryRunResult} from '../generated/api'; + +export function generateDeliveryRun( + input: InputDeliveryRun, +): FunctionDeliveryRunResult { + const {fetchResult} = input; + const body = fetchResult?.body; + + if (!body) { + throw new Error('Missing response body'); + } + + // Parse the response body and extract the operations + const {operations} = JSON.parse(body); + return {operations}; +} +{%- endif -%} diff --git a/discounts/javascript/network/default/src/generate_discount_default.test.liquid b/discounts/javascript/network/default/src/generate_discount_default.test.liquid new file mode 100644 index 00000000..eda1cf66 --- /dev/null +++ b/discounts/javascript/network/default/src/generate_discount_default.test.liquid @@ -0,0 +1,8 @@ +import { describe, it, expect } from 'vitest'; + + +describe('generate_discount_default', () => { + it('passes the test', () => { + expect(true).toBe(true); + }); +}); \ No newline at end of file diff --git a/discounts/javascript/network/default/src/index.liquid b/discounts/javascript/network/default/src/index.liquid new file mode 100644 index 00000000..1e8b90b3 --- /dev/null +++ b/discounts/javascript/network/default/src/index.liquid @@ -0,0 +1,4 @@ +export * from './generate_cart_run'; +export * from './generate_delivery_run'; +export * from './generate_cart_fetch'; +export * from './generate_delivery_fetch'; diff --git a/discounts/javascript/network/default/src/network.test.liquid b/discounts/javascript/network/default/src/network.test.liquid new file mode 100644 index 00000000..2110e7d6 --- /dev/null +++ b/discounts/javascript/network/default/src/network.test.liquid @@ -0,0 +1,167 @@ +import { describe, it, expect } from "vitest"; + +import { generateCartFetch } from "./generate_cart_fetch"; +import { generateDeliveryFetch } from "./generate_delivery_fetch"; +import { generateCartRun } from "./generate_cart_run"; +import { + HttpRequestMethod, + OrderDiscountSelectionStrategy, + ProductDiscountSelectionStrategy, + DeliveryDiscountSelectionStrategy, +} from "../generated/api"; + +describe("discount", () => { + it("cart.lines.discounts.generate.fetch returns a fetch request", () => { + const input = { + enteredDiscountCodes: ["10% OFF ORDER", "20% OFF PRODUCT"], + }; + + const result = generateCartFetch(input); + + expect(result.request).toMatchObject({ + headers: [ + { + name: "accept", + value: "application/json", + }, + ], + method: HttpRequestMethod.Post, + policy: { + readTimeoutMs: 2000, + }, + url: "", + body: JSON.stringify(input), + jsonBody: input, + }); + }); + + it("cart.delivery-options.discounts.generate.fetch returns a fetch request", () => { + const input = { + enteredDiscountCodes: ["FREE_DELIVERY"], + }; + + const result = generateDeliveryFetch(input); + + expect(result.request).toMatchObject({ + headers: [ + { + name: "accept", + value: "application/json", + }, + ], + method: HttpRequestMethod.Post, + policy: { + readTimeoutMs: 2000, + }, + url: "", + body: JSON.stringify(input), + jsonBody: input, + }); + }); + + it("cart.lines.discounts.generate.run returns a list of operations", () => { + const operations = [ + { + addDiscountCodeValidations: { + codes: ["10% OFF ORDER", "20% OFF PRODUCT"], + }, + }, + { + addOrderDiscounts: { + candidates: [ + { + message: "10% OFF ORDER", + targets: [ + { + orderSubtotal: { + excludedCartLineIds: [], + }, + }, + ], + value: { + percentage: { + value: 10, + }, + }, + }, + ], + selectionStrategy: OrderDiscountSelectionStrategy.First, + }, + }, + { + addProductDiscounts: { + candidates: [ + { + message: "20% OFF PRODUCT", + targets: [ + { + cartLine: { + id: "gid://shopify/CartLine/0", + }, + }, + ], + value: { + percentage: { + value: 20, + }, + }, + }, + ], + selectionStrategy: ProductDiscountSelectionStrategy.First, + }, + }, + ]; + + const input = { + fetchResult: { + body: JSON.stringify({ operations }), + }, + }; + + const result = generateCartRun(input); + + expect(result.operations).toMatchObject(operations); + }); + + it("cart.delivery-options.discounts.generate.run returns a list of operations", () => { + const operations = [ + { + addDiscountCodeValidations: { + codes: ["FREE_DELIVERY"], + }, + }, + { + addDeliveryDiscounts: { + candidates: [ + { + message: "FREE DELIVERY", + targets: [ + { + deliveryGroup: { + id: "gid://shopify/DeliveryGroup/0", + }, + }, + ], + value: { + percentage: { + value: 100, + }, + }, + }, + ], + selectionStrategy: DeliveryDiscountSelectionStrategy.All, + }, + }, + ]; + + const input = { + fetchResult: { + body: JSON.stringify({ operations }), + }, + }; + + const result = generateCartRun(input); + + expect(result.operations).toMatchObject(operations); + }); +}); diff --git a/discounts/javascript/network/default/vite.config.js b/discounts/javascript/network/default/vite.config.js new file mode 100644 index 00000000..210c90d4 --- /dev/null +++ b/discounts/javascript/network/default/vite.config.js @@ -0,0 +1 @@ +// Prevents inheritance from parent Remix project diff --git a/discounts/rust/discounts/default/.gitignore b/discounts/rust/discount/default/.gitignore similarity index 100% rename from discounts/rust/discounts/default/.gitignore rename to discounts/rust/discount/default/.gitignore diff --git a/discounts/rust/discounts/default/Cargo.toml.liquid b/discounts/rust/discount/default/Cargo.toml.liquid similarity index 72% rename from discounts/rust/discounts/default/Cargo.toml.liquid rename to discounts/rust/discount/default/Cargo.toml.liquid index 4d4850fe..72bdfcd7 100644 --- a/discounts/rust/discounts/default/Cargo.toml.liquid +++ b/discounts/rust/discount/default/Cargo.toml.liquid @@ -4,12 +4,15 @@ version = "1.0.0" edition = "2021" [dependencies] -serde = { version = "1.0.13", features = ["derive"] } serde_json = "1.0" shopify_function = "0.8.1" graphql_client = "0.14.0" + [dependencies.serde] + version = "1.0.13" + features = [ "derive" ] + [profile.release] lto = true -opt-level = 'z' +opt-level = "z" strip = true diff --git a/discounts/rust/discounts/default/README.md b/discounts/rust/discount/default/README.md similarity index 100% rename from discounts/rust/discounts/default/README.md rename to discounts/rust/discount/default/README.md diff --git a/discounts/rust/discounts/default/locales/en.default.json.liquid b/discounts/rust/discount/default/locales/en.default.json.liquid similarity index 100% rename from discounts/rust/discounts/default/locales/en.default.json.liquid rename to discounts/rust/discount/default/locales/en.default.json.liquid diff --git a/discounts/rust/discount/default/schema.graphql b/discounts/rust/discount/default/schema.graphql new file mode 100644 index 00000000..2c2f866b --- /dev/null +++ b/discounts/rust/discount/default/schema.graphql @@ -0,0 +1,5172 @@ +schema { + query: Input + mutation: MutationRoot +} + +""" +Only allow the field to be queried when targeting one of the specified targets. +""" +directive @restrictTarget(only: [String!]!) on FIELD_DEFINITION + +""" +Scale the Functions resource limits based on the field's length. +""" +directive @scaleLimits(rate: Float!) on FIELD_DEFINITION + +""" +Requires that exactly one field must be supplied and that field must not be `null`. +""" +directive @oneOf on INPUT_OBJECT + +""" +A discount code that is associated with a discount candidate. +""" +input AssociatedDiscountCode { + """ + The discount code. + """ + code: String! +} + +""" +Represents a generic custom attribute, such as whether an order is a customer's first. +""" +type Attribute { + """ + The key or name of the attribute. For example, `"customersFirstOrder"`. + """ + key: String! + + """ + The value of the attribute. For example, `"true"`. + """ + value: String +} + +""" +Represents information about the buyer that is interacting with the cart. +""" +type BuyerIdentity { + """ + The customer associated with the cart. + """ + customer: Customer + + """ + The email address of the buyer that's interacting with the cart. + """ + email: String + + """ + Whether the buyer authenticated with a customer account. + """ + isAuthenticated: Boolean! + + """ + The phone number of the buyer that's interacting with the cart. + """ + phone: String + + """ + The purchasing company associated with the cart. + """ + purchasingCompany: PurchasingCompany +} + +""" +A cart represents the merchandise that a buyer intends to purchase, and the cost associated with the cart. +""" +type Cart { + """ + The attributes associated with the cart. Attributes are represented as key-value pairs. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + Information about the buyer that is interacting with the cart. + """ + buyerIdentity: BuyerIdentity + + """ + The costs that the buyer will pay at checkout. + """ + cost: CartCost! + + """ + A list of lines containing information about the items that can be delivered. + """ + deliverableLines: [DeliverableCartLine!]! + + """ + The delivery groups available for the cart based on the buyer's shipping address. + """ + deliveryGroups: [CartDeliveryGroup!]! + + """ + A list of lines containing information about the items the customer intends to purchase. + """ + lines: [CartLine!]! @scaleLimits(rate: 0.005) + + """ + The localized fields available for the cart. + """ + localizedFields( + """ + The keys of the localized fields to retrieve. + """ + keys: [LocalizedFieldKey!]! = [] + ): [LocalizedField!]! +} + +""" +The cost that the buyer will pay at checkout. +""" +type CartCost { + """ + The amount, before taxes and discounts, for the customer to pay. + """ + subtotalAmount: MoneyV2! + + """ + The total amount for the customer to pay. + """ + totalAmount: MoneyV2! + + """ + The duty amount for the customer to pay at checkout. + """ + totalDutyAmount: MoneyV2 + + """ + The tax amount for the customer to pay at checkout. + """ + totalTaxAmount: MoneyV2 +} + +""" +Information about the options available for one or more line items to be delivered to a specific address. +""" +type CartDeliveryGroup { + """ + A list of cart lines for the delivery group. + """ + cartLines: [CartLine!]! @scaleLimits(rate: 0.005) + + """ + The destination address for the delivery group. + """ + deliveryAddress: MailingAddress + + """ + The delivery options available for the delivery group. + """ + deliveryOptions: [CartDeliveryOption!]! + + """ + Unique identifier for the delivery group. + """ + id: ID! + + """ + Information about the delivery option the buyer has selected. + """ + selectedDeliveryOption: CartDeliveryOption +} + +""" +Information about a delivery option. +""" +type CartDeliveryOption { + """ + The code of the delivery option. + """ + code: String + + """ + The cost for the delivery option. + """ + cost: MoneyV2! + + """ + The method for the delivery option. + """ + deliveryMethodType: DeliveryMethod! + + """ + The description of the delivery option. + """ + description: String + + """ + The unique identifier of the delivery option. + """ + handle: Handle! + + """ + The title of the delivery option. + """ + title: String +} + +""" +Represents information about the merchandise in the cart. +""" +type CartLine { + """ + Retrieve a cart line attribute by key. + + Cart line attributes are also known as line item properties in Liquid. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + The cost of the merchandise line that the buyer will pay at checkout. + """ + cost: CartLineCost! + + """ + The ID of the cart line. + """ + id: ID! + + """ + The merchandise that the buyer intends to purchase. + """ + merchandise: Merchandise! + + """ + The quantity of the merchandise that the customer intends to purchase. + """ + quantity: Int! + + """ + The selling plan associated with the cart line and the effect that each + selling plan has on variants when they're purchased. + """ + sellingPlanAllocation: SellingPlanAllocation +} + +""" +The cost of the merchandise line that the buyer will pay at checkout. +""" +type CartLineCost { + """ + The amount of the merchandise line. + """ + amountPerQuantity: MoneyV2! + + """ + The compare at amount of the merchandise line. This value varies depending on + the buyer's identity, and is null when the value is hidden to buyers. + """ + compareAtAmountPerQuantity: MoneyV2 + + """ + The cost of the merchandise line before line-level discounts. + """ + subtotalAmount: MoneyV2! + + """ + The total cost of the merchandise line. + """ + totalAmount: MoneyV2! +} + +""" +The condition for checking the minimum quantity of products across a group of cart lines. +""" +input CartLineMinimumQuantity { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum quantity purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum quantity of a product. + """ + minimumQuantity: Int! +} + +""" +The condition for checking the minimum subtotal of products across a group of cart lines. +""" +input CartLineMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum subtotal purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum subtotal amount of the product. + """ + minimumAmount: Decimal! +} + +""" +A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. +""" +input CartLineTarget { + """ + The ID of the targeted cart line. + """ + id: ID! + + """ + The number of line items that are being discounted. + The default value is `null`, which represents the quantity of the matching line items. + + The value is validated against: > 0. + """ + quantity: Int +} + +""" +The operations that can be performed to apply discounts to the cart. +""" +input CartOperation @oneOf { + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes + + """ + A group of order discounts that share a selection strategy. + """ + addOrderDiscounts: OrderDiscounts + + """ + A group of product discounts that share a selection strategy. + """ + addProductDiscounts: ProductDiscounts +} + +""" +Represents whether the product is a member of the given collection. +""" +type CollectionMembership { + """ + The ID of the collection. + """ + collectionId: ID! + + """ + Whether the product is a member of the collection. + """ + isMember: Boolean! +} + +""" +Represents information about a company which is also a customer of the shop. +""" +type Company implements HasMetafields { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was created in Shopify. + """ + createdAt: DateTime! + + """ + A unique externally-supplied ID for the company. + """ + externalId: String + + """ + The ID of the company. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the company. + """ + name: String! + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was last modified. + """ + updatedAt: DateTime! +} + +""" +A company's main point of contact. +""" +type CompanyContact { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company contact was created in Shopify. + """ + createdAt: DateTime! + + """ + The ID of the company. + """ + id: ID! + + """ + The company contact's locale (language). + """ + locale: String + + """ + The company contact's job title. + """ + title: String + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company contact was last modified. + """ + updatedAt: DateTime! +} + +""" +A company's location. +""" +type CompanyLocation implements HasMetafields { + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company location was created in Shopify. + """ + createdAt: DateTime! + + """ + A unique externally-supplied ID for the company. + """ + externalId: String + + """ + The ID of the company. + """ + id: ID! + + """ + The preferred locale of the company location. + """ + locale: String + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the company location. + """ + name: String! + + """ + The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) + at which the company location was last modified. + """ + updatedAt: DateTime! +} + +""" +The condition to apply the discount candidate. +""" +input Condition @oneOf { + """ + The condition for checking the minimum quantity of products across a group of cart lines. + """ + cartLineMinimumQuantity: CartLineMinimumQuantity + + """ + The condition for checking the minimum subtotal of products across a group of cart lines. + """ + cartLineMinimumSubtotal: CartLineMinimumSubtotal + + """ + The condition for checking the minimum subtotal amount of the order. + """ + orderMinimumSubtotal: OrderMinimumSubtotal +} + +""" +A country. +""" +type Country { + """ + The ISO code of the country. + """ + isoCode: CountryCode! +} + +""" +The code designating a country/region, which generally follows ISO 3166-1 alpha-2 guidelines. +If a territory doesn't have a country code value in the `CountryCode` enum, then it might be considered a subdivision +of another country. For example, the territories associated with Spain are represented by the country code `ES`, +and the territories associated with the United States of America are represented by the country code `US`. +""" +enum CountryCode { + """ + Ascension Island. + """ + AC + + """ + Andorra. + """ + AD + + """ + United Arab Emirates. + """ + AE + + """ + Afghanistan. + """ + AF + + """ + Antigua & Barbuda. + """ + AG + + """ + Anguilla. + """ + AI + + """ + Albania. + """ + AL + + """ + Armenia. + """ + AM + + """ + Netherlands Antilles. + """ + AN + + """ + Angola. + """ + AO + + """ + Argentina. + """ + AR + + """ + Austria. + """ + AT + + """ + Australia. + """ + AU + + """ + Aruba. + """ + AW + + """ + Åland Islands. + """ + AX + + """ + Azerbaijan. + """ + AZ + + """ + Bosnia & Herzegovina. + """ + BA + + """ + Barbados. + """ + BB + + """ + Bangladesh. + """ + BD + + """ + Belgium. + """ + BE + + """ + Burkina Faso. + """ + BF + + """ + Bulgaria. + """ + BG + + """ + Bahrain. + """ + BH + + """ + Burundi. + """ + BI + + """ + Benin. + """ + BJ + + """ + St. Barthélemy. + """ + BL + + """ + Bermuda. + """ + BM + + """ + Brunei. + """ + BN + + """ + Bolivia. + """ + BO + + """ + Caribbean Netherlands. + """ + BQ + + """ + Brazil. + """ + BR + + """ + Bahamas. + """ + BS + + """ + Bhutan. + """ + BT + + """ + Bouvet Island. + """ + BV + + """ + Botswana. + """ + BW + + """ + Belarus. + """ + BY + + """ + Belize. + """ + BZ + + """ + Canada. + """ + CA + + """ + Cocos (Keeling) Islands. + """ + CC + + """ + Congo - Kinshasa. + """ + CD + + """ + Central African Republic. + """ + CF + + """ + Congo - Brazzaville. + """ + CG + + """ + Switzerland. + """ + CH + + """ + Côte d’Ivoire. + """ + CI + + """ + Cook Islands. + """ + CK + + """ + Chile. + """ + CL + + """ + Cameroon. + """ + CM + + """ + China. + """ + CN + + """ + Colombia. + """ + CO + + """ + Costa Rica. + """ + CR + + """ + Cuba. + """ + CU + + """ + Cape Verde. + """ + CV + + """ + Curaçao. + """ + CW + + """ + Christmas Island. + """ + CX + + """ + Cyprus. + """ + CY + + """ + Czechia. + """ + CZ + + """ + Germany. + """ + DE + + """ + Djibouti. + """ + DJ + + """ + Denmark. + """ + DK + + """ + Dominica. + """ + DM + + """ + Dominican Republic. + """ + DO + + """ + Algeria. + """ + DZ + + """ + Ecuador. + """ + EC + + """ + Estonia. + """ + EE + + """ + Egypt. + """ + EG + + """ + Western Sahara. + """ + EH + + """ + Eritrea. + """ + ER + + """ + Spain. + """ + ES + + """ + Ethiopia. + """ + ET + + """ + Finland. + """ + FI + + """ + Fiji. + """ + FJ + + """ + Falkland Islands. + """ + FK + + """ + Faroe Islands. + """ + FO + + """ + France. + """ + FR + + """ + Gabon. + """ + GA + + """ + United Kingdom. + """ + GB + + """ + Grenada. + """ + GD + + """ + Georgia. + """ + GE + + """ + French Guiana. + """ + GF + + """ + Guernsey. + """ + GG + + """ + Ghana. + """ + GH + + """ + Gibraltar. + """ + GI + + """ + Greenland. + """ + GL + + """ + Gambia. + """ + GM + + """ + Guinea. + """ + GN + + """ + Guadeloupe. + """ + GP + + """ + Equatorial Guinea. + """ + GQ + + """ + Greece. + """ + GR + + """ + South Georgia & South Sandwich Islands. + """ + GS + + """ + Guatemala. + """ + GT + + """ + Guinea-Bissau. + """ + GW + + """ + Guyana. + """ + GY + + """ + Hong Kong SAR. + """ + HK + + """ + Heard & McDonald Islands. + """ + HM + + """ + Honduras. + """ + HN + + """ + Croatia. + """ + HR + + """ + Haiti. + """ + HT + + """ + Hungary. + """ + HU + + """ + Indonesia. + """ + ID + + """ + Ireland. + """ + IE + + """ + Israel. + """ + IL + + """ + Isle of Man. + """ + IM + + """ + India. + """ + IN + + """ + British Indian Ocean Territory. + """ + IO + + """ + Iraq. + """ + IQ + + """ + Iran. + """ + IR + + """ + Iceland. + """ + IS + + """ + Italy. + """ + IT + + """ + Jersey. + """ + JE + + """ + Jamaica. + """ + JM + + """ + Jordan. + """ + JO + + """ + Japan. + """ + JP + + """ + Kenya. + """ + KE + + """ + Kyrgyzstan. + """ + KG + + """ + Cambodia. + """ + KH + + """ + Kiribati. + """ + KI + + """ + Comoros. + """ + KM + + """ + St. Kitts & Nevis. + """ + KN + + """ + North Korea. + """ + KP + + """ + South Korea. + """ + KR + + """ + Kuwait. + """ + KW + + """ + Cayman Islands. + """ + KY + + """ + Kazakhstan. + """ + KZ + + """ + Laos. + """ + LA + + """ + Lebanon. + """ + LB + + """ + St. Lucia. + """ + LC + + """ + Liechtenstein. + """ + LI + + """ + Sri Lanka. + """ + LK + + """ + Liberia. + """ + LR + + """ + Lesotho. + """ + LS + + """ + Lithuania. + """ + LT + + """ + Luxembourg. + """ + LU + + """ + Latvia. + """ + LV + + """ + Libya. + """ + LY + + """ + Morocco. + """ + MA + + """ + Monaco. + """ + MC + + """ + Moldova. + """ + MD + + """ + Montenegro. + """ + ME + + """ + St. Martin. + """ + MF + + """ + Madagascar. + """ + MG + + """ + North Macedonia. + """ + MK + + """ + Mali. + """ + ML + + """ + Myanmar (Burma). + """ + MM + + """ + Mongolia. + """ + MN + + """ + Macao SAR. + """ + MO + + """ + Martinique. + """ + MQ + + """ + Mauritania. + """ + MR + + """ + Montserrat. + """ + MS + + """ + Malta. + """ + MT + + """ + Mauritius. + """ + MU + + """ + Maldives. + """ + MV + + """ + Malawi. + """ + MW + + """ + Mexico. + """ + MX + + """ + Malaysia. + """ + MY + + """ + Mozambique. + """ + MZ + + """ + Namibia. + """ + NA + + """ + New Caledonia. + """ + NC + + """ + Niger. + """ + NE + + """ + Norfolk Island. + """ + NF + + """ + Nigeria. + """ + NG + + """ + Nicaragua. + """ + NI + + """ + Netherlands. + """ + NL + + """ + Norway. + """ + NO + + """ + Nepal. + """ + NP + + """ + Nauru. + """ + NR + + """ + Niue. + """ + NU + + """ + New Zealand. + """ + NZ + + """ + Oman. + """ + OM + + """ + Panama. + """ + PA + + """ + Peru. + """ + PE + + """ + French Polynesia. + """ + PF + + """ + Papua New Guinea. + """ + PG + + """ + Philippines. + """ + PH + + """ + Pakistan. + """ + PK + + """ + Poland. + """ + PL + + """ + St. Pierre & Miquelon. + """ + PM + + """ + Pitcairn Islands. + """ + PN + + """ + Palestinian Territories. + """ + PS + + """ + Portugal. + """ + PT + + """ + Paraguay. + """ + PY + + """ + Qatar. + """ + QA + + """ + Réunion. + """ + RE + + """ + Romania. + """ + RO + + """ + Serbia. + """ + RS + + """ + Russia. + """ + RU + + """ + Rwanda. + """ + RW + + """ + Saudi Arabia. + """ + SA + + """ + Solomon Islands. + """ + SB + + """ + Seychelles. + """ + SC + + """ + Sudan. + """ + SD + + """ + Sweden. + """ + SE + + """ + Singapore. + """ + SG + + """ + St. Helena. + """ + SH + + """ + Slovenia. + """ + SI + + """ + Svalbard & Jan Mayen. + """ + SJ + + """ + Slovakia. + """ + SK + + """ + Sierra Leone. + """ + SL + + """ + San Marino. + """ + SM + + """ + Senegal. + """ + SN + + """ + Somalia. + """ + SO + + """ + Suriname. + """ + SR + + """ + South Sudan. + """ + SS + + """ + São Tomé & Príncipe. + """ + ST + + """ + El Salvador. + """ + SV + + """ + Sint Maarten. + """ + SX + + """ + Syria. + """ + SY + + """ + Eswatini. + """ + SZ + + """ + Tristan da Cunha. + """ + TA + + """ + Turks & Caicos Islands. + """ + TC + + """ + Chad. + """ + TD + + """ + French Southern Territories. + """ + TF + + """ + Togo. + """ + TG + + """ + Thailand. + """ + TH + + """ + Tajikistan. + """ + TJ + + """ + Tokelau. + """ + TK + + """ + Timor-Leste. + """ + TL + + """ + Turkmenistan. + """ + TM + + """ + Tunisia. + """ + TN + + """ + Tonga. + """ + TO + + """ + Türkiye. + """ + TR + + """ + Trinidad & Tobago. + """ + TT + + """ + Tuvalu. + """ + TV + + """ + Taiwan. + """ + TW + + """ + Tanzania. + """ + TZ + + """ + Ukraine. + """ + UA + + """ + Uganda. + """ + UG + + """ + U.S. Outlying Islands. + """ + UM + + """ + United States. + """ + US + + """ + Uruguay. + """ + UY + + """ + Uzbekistan. + """ + UZ + + """ + Vatican City. + """ + VA + + """ + St. Vincent & Grenadines. + """ + VC + + """ + Venezuela. + """ + VE + + """ + British Virgin Islands. + """ + VG + + """ + Vietnam. + """ + VN + + """ + Vanuatu. + """ + VU + + """ + Wallis & Futuna. + """ + WF + + """ + Samoa. + """ + WS + + """ + Kosovo. + """ + XK + + """ + Yemen. + """ + YE + + """ + Mayotte. + """ + YT + + """ + South Africa. + """ + ZA + + """ + Zambia. + """ + ZM + + """ + Zimbabwe. + """ + ZW + + """ + Unknown Region. + """ + ZZ +} + +""" +The three-letter currency codes that represent the world currencies used in +stores. These include standard ISO 4217 codes, legacy codes, +and non-standard codes. +""" +enum CurrencyCode { + """ + United Arab Emirates Dirham (AED). + """ + AED + + """ + Afghan Afghani (AFN). + """ + AFN + + """ + Albanian Lek (ALL). + """ + ALL + + """ + Armenian Dram (AMD). + """ + AMD + + """ + Netherlands Antillean Guilder. + """ + ANG + + """ + Angolan Kwanza (AOA). + """ + AOA + + """ + Argentine Pesos (ARS). + """ + ARS + + """ + Australian Dollars (AUD). + """ + AUD + + """ + Aruban Florin (AWG). + """ + AWG + + """ + Azerbaijani Manat (AZN). + """ + AZN + + """ + Bosnia and Herzegovina Convertible Mark (BAM). + """ + BAM + + """ + Barbadian Dollar (BBD). + """ + BBD + + """ + Bangladesh Taka (BDT). + """ + BDT + + """ + Bulgarian Lev (BGN). + """ + BGN + + """ + Bahraini Dinar (BHD). + """ + BHD + + """ + Burundian Franc (BIF). + """ + BIF + + """ + Bermudian Dollar (BMD). + """ + BMD + + """ + Brunei Dollar (BND). + """ + BND + + """ + Bolivian Boliviano (BOB). + """ + BOB + + """ + Brazilian Real (BRL). + """ + BRL + + """ + Bahamian Dollar (BSD). + """ + BSD + + """ + Bhutanese Ngultrum (BTN). + """ + BTN + + """ + Botswana Pula (BWP). + """ + BWP + + """ + Belarusian Ruble (BYN). + """ + BYN + + """ + Belarusian Ruble (BYR). + """ + BYR @deprecated(reason: "`BYR` is deprecated. Use `BYN` available from version `2021-01` onwards instead.") + + """ + Belize Dollar (BZD). + """ + BZD + + """ + Canadian Dollars (CAD). + """ + CAD + + """ + Congolese franc (CDF). + """ + CDF + + """ + Swiss Francs (CHF). + """ + CHF + + """ + Chilean Peso (CLP). + """ + CLP + + """ + Chinese Yuan Renminbi (CNY). + """ + CNY + + """ + Colombian Peso (COP). + """ + COP + + """ + Costa Rican Colones (CRC). + """ + CRC + + """ + Cape Verdean escudo (CVE). + """ + CVE + + """ + Czech Koruny (CZK). + """ + CZK + + """ + Djiboutian Franc (DJF). + """ + DJF + + """ + Danish Kroner (DKK). + """ + DKK + + """ + Dominican Peso (DOP). + """ + DOP + + """ + Algerian Dinar (DZD). + """ + DZD + + """ + Egyptian Pound (EGP). + """ + EGP + + """ + Eritrean Nakfa (ERN). + """ + ERN + + """ + Ethiopian Birr (ETB). + """ + ETB + + """ + Euro (EUR). + """ + EUR + + """ + Fijian Dollars (FJD). + """ + FJD + + """ + Falkland Islands Pounds (FKP). + """ + FKP + + """ + United Kingdom Pounds (GBP). + """ + GBP + + """ + Georgian Lari (GEL). + """ + GEL + + """ + Ghanaian Cedi (GHS). + """ + GHS + + """ + Gibraltar Pounds (GIP). + """ + GIP + + """ + Gambian Dalasi (GMD). + """ + GMD + + """ + Guinean Franc (GNF). + """ + GNF + + """ + Guatemalan Quetzal (GTQ). + """ + GTQ + + """ + Guyanese Dollar (GYD). + """ + GYD + + """ + Hong Kong Dollars (HKD). + """ + HKD + + """ + Honduran Lempira (HNL). + """ + HNL + + """ + Croatian Kuna (HRK). + """ + HRK + + """ + Haitian Gourde (HTG). + """ + HTG + + """ + Hungarian Forint (HUF). + """ + HUF + + """ + Indonesian Rupiah (IDR). + """ + IDR + + """ + Israeli New Shekel (NIS). + """ + ILS + + """ + Indian Rupees (INR). + """ + INR + + """ + Iraqi Dinar (IQD). + """ + IQD + + """ + Iranian Rial (IRR). + """ + IRR + + """ + Icelandic Kronur (ISK). + """ + ISK + + """ + Jersey Pound. + """ + JEP + + """ + Jamaican Dollars (JMD). + """ + JMD + + """ + Jordanian Dinar (JOD). + """ + JOD + + """ + Japanese Yen (JPY). + """ + JPY + + """ + Kenyan Shilling (KES). + """ + KES + + """ + Kyrgyzstani Som (KGS). + """ + KGS + + """ + Cambodian Riel. + """ + KHR + + """ + Kiribati Dollar (KID). + """ + KID + + """ + Comorian Franc (KMF). + """ + KMF + + """ + South Korean Won (KRW). + """ + KRW + + """ + Kuwaiti Dinar (KWD). + """ + KWD + + """ + Cayman Dollars (KYD). + """ + KYD + + """ + Kazakhstani Tenge (KZT). + """ + KZT + + """ + Laotian Kip (LAK). + """ + LAK + + """ + Lebanese Pounds (LBP). + """ + LBP + + """ + Sri Lankan Rupees (LKR). + """ + LKR + + """ + Liberian Dollar (LRD). + """ + LRD + + """ + Lesotho Loti (LSL). + """ + LSL + + """ + Lithuanian Litai (LTL). + """ + LTL + + """ + Latvian Lati (LVL). + """ + LVL + + """ + Libyan Dinar (LYD). + """ + LYD + + """ + Moroccan Dirham. + """ + MAD + + """ + Moldovan Leu (MDL). + """ + MDL + + """ + Malagasy Ariary (MGA). + """ + MGA + + """ + Macedonia Denar (MKD). + """ + MKD + + """ + Burmese Kyat (MMK). + """ + MMK + + """ + Mongolian Tugrik. + """ + MNT + + """ + Macanese Pataca (MOP). + """ + MOP + + """ + Mauritanian Ouguiya (MRU). + """ + MRU + + """ + Mauritian Rupee (MUR). + """ + MUR + + """ + Maldivian Rufiyaa (MVR). + """ + MVR + + """ + Malawian Kwacha (MWK). + """ + MWK + + """ + Mexican Pesos (MXN). + """ + MXN + + """ + Malaysian Ringgits (MYR). + """ + MYR + + """ + Mozambican Metical. + """ + MZN + + """ + Namibian Dollar. + """ + NAD + + """ + Nigerian Naira (NGN). + """ + NGN + + """ + Nicaraguan Córdoba (NIO). + """ + NIO + + """ + Norwegian Kroner (NOK). + """ + NOK + + """ + Nepalese Rupee (NPR). + """ + NPR + + """ + New Zealand Dollars (NZD). + """ + NZD + + """ + Omani Rial (OMR). + """ + OMR + + """ + Panamian Balboa (PAB). + """ + PAB + + """ + Peruvian Nuevo Sol (PEN). + """ + PEN + + """ + Papua New Guinean Kina (PGK). + """ + PGK + + """ + Philippine Peso (PHP). + """ + PHP + + """ + Pakistani Rupee (PKR). + """ + PKR + + """ + Polish Zlotych (PLN). + """ + PLN + + """ + Paraguayan Guarani (PYG). + """ + PYG + + """ + Qatari Rial (QAR). + """ + QAR + + """ + Romanian Lei (RON). + """ + RON + + """ + Serbian dinar (RSD). + """ + RSD + + """ + Russian Rubles (RUB). + """ + RUB + + """ + Rwandan Franc (RWF). + """ + RWF + + """ + Saudi Riyal (SAR). + """ + SAR + + """ + Solomon Islands Dollar (SBD). + """ + SBD + + """ + Seychellois Rupee (SCR). + """ + SCR + + """ + Sudanese Pound (SDG). + """ + SDG + + """ + Swedish Kronor (SEK). + """ + SEK + + """ + Singapore Dollars (SGD). + """ + SGD + + """ + Saint Helena Pounds (SHP). + """ + SHP + + """ + Sierra Leonean Leone (SLL). + """ + SLL + + """ + Somali Shilling (SOS). + """ + SOS + + """ + Surinamese Dollar (SRD). + """ + SRD + + """ + South Sudanese Pound (SSP). + """ + SSP + + """ + Sao Tome And Principe Dobra (STD). + """ + STD @deprecated(reason: "`STD` is deprecated. Use `STN` available from version `2022-07` onwards instead.") + + """ + Sao Tome And Principe Dobra (STN). + """ + STN + + """ + Syrian Pound (SYP). + """ + SYP + + """ + Swazi Lilangeni (SZL). + """ + SZL + + """ + Thai baht (THB). + """ + THB + + """ + Tajikistani Somoni (TJS). + """ + TJS + + """ + Turkmenistani Manat (TMT). + """ + TMT + + """ + Tunisian Dinar (TND). + """ + TND + + """ + Tongan Pa'anga (TOP). + """ + TOP + + """ + Turkish Lira (TRY). + """ + TRY + + """ + Trinidad and Tobago Dollars (TTD). + """ + TTD + + """ + Taiwan Dollars (TWD). + """ + TWD + + """ + Tanzanian Shilling (TZS). + """ + TZS + + """ + Ukrainian Hryvnia (UAH). + """ + UAH + + """ + Ugandan Shilling (UGX). + """ + UGX + + """ + United States Dollars (USD). + """ + USD + + """ + Uruguayan Pesos (UYU). + """ + UYU + + """ + Uzbekistan som (UZS). + """ + UZS + + """ + Venezuelan Bolivares (VED). + """ + VED + + """ + Venezuelan Bolivares (VEF). + """ + VEF @deprecated(reason: "`VEF` is deprecated. Use `VES` available from version `2020-10` onwards instead.") + + """ + Venezuelan Bolivares Soberanos (VES). + """ + VES + + """ + Vietnamese đồng (VND). + """ + VND + + """ + Vanuatu Vatu (VUV). + """ + VUV + + """ + Samoan Tala (WST). + """ + WST + + """ + Central African CFA Franc (XAF). + """ + XAF + + """ + East Caribbean Dollar (XCD). + """ + XCD + + """ + West African CFA franc (XOF). + """ + XOF + + """ + CFP Franc (XPF). + """ + XPF + + """ + Unrecognized currency. + """ + XXX + + """ + Yemeni Rial (YER). + """ + YER + + """ + South African Rand (ZAR). + """ + ZAR + + """ + Zambian Kwacha (ZMW). + """ + ZMW +} + +""" +A custom product. +""" +type CustomProduct { + """ + Whether the merchandise is a gift card. + """ + isGiftCard: Boolean! + + """ + Whether the merchandise requires shipping. + """ + requiresShipping: Boolean! + + """ + The localized title of the product in the customer’s locale. + """ + title: String! + + """ + The weight of the product variant in the unit system specified with `weight_unit`. + """ + weight: Float + + """ + Unit of measurement for weight. + """ + weightUnit: WeightUnit! +} + +""" +Represents a customer with the shop. +""" +type Customer implements HasMetafields { + """ + The total amount of money spent by the customer. Converted from the shop's + currency to the currency of the cart using a market rate. + """ + amountSpent: MoneyV2! + + """ + The customer’s name, email or phone number. + """ + displayName: String! + + """ + The customer’s email address. + """ + email: String + + """ + The customer's first name. + """ + firstName: String + + """ + Whether the customer has any of the given tags. + """ + hasAnyTag( + """ + The tags to search for. + """ + tags: [String!]! = [] + ): Boolean! + + """ + Whether the customer has the given tags. + """ + hasTags( + """ + The tags to check. + """ + tags: [String!]! = [] + ): [HasTagResponse!]! + + """ + A unique identifier for the customer. + """ + id: ID! + + """ + The customer's last name. + """ + lastName: String + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The number of orders made by the customer. + """ + numberOfOrders: Int! +} + +""" +Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date string. +For example, September 7, 2019 is represented as `"2019-07-16"`. +""" +scalar Date + +""" +Represents an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601)-encoded date and time string. +For example, 3:50 pm on September 7, 2019 in the time zone of UTC (Coordinated Universal Time) is +represented as `"2019-09-07T15:50:00Z`". +""" +scalar DateTime + +""" +A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that +includes the date and time but not the timezone which is determined from context. + +For example, "2018-01-01T00:00:00". +""" +scalar DateTimeWithoutTimezone + +""" +A signed decimal number, which supports arbitrary precision and is serialized as a string. + +Example values: `"29.99"`, `"29.999"`. +""" +scalar Decimal + +""" +Represents information about the merchandise in the cart. +""" +type DeliverableCartLine { + """ + Retrieve a cart line attribute by key. + + Cart line attributes are also known as line item properties in Liquid. + """ + attribute( + """ + The key of the attribute to retrieve. + """ + key: String + ): Attribute + + """ + The ID of the cart line. + """ + id: ID! + + """ + The merchandise that the buyer intends to purchase. + """ + merchandise: Merchandise! + + """ + The quantity of the merchandise that the customer intends to purchase. + """ + quantity: Int! +} + +""" +The delivery discount candidate to be applied. +""" +input DeliveryDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The discount message. + """ + message: String + + """ + The targets of the delivery discount candidate. + """ + targets: [DeliveryDiscountCandidateTarget!]! + + """ + The value of the delivery discount candidate. + """ + value: DeliveryDiscountCandidateValue! +} + +""" +The target of the delivery discount candidate. +""" +input DeliveryDiscountCandidateTarget @oneOf { + """ + The target delivery group. + """ + deliveryGroup: DeliveryGroupTarget + + """ + The target delivery option. + """ + deliveryOption: DeliveryOptionTarget +} + +""" +The delivery discount candidate value. +""" +input DeliveryDiscountCandidateValue @oneOf { + """ + A fixed amount value. + """ + fixedAmount: FixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of delivery discount candidates. +""" +enum DeliveryDiscountSelectionStrategy { + """ + Apply all delivery discount candidates with conditions that are satisfied. This does not override + discount combination or stacking rules. + """ + ALL +} + +""" +A group of delivery discounts that share a selection strategy. +""" +input DeliveryDiscounts { + """ + The list of delivery discount candidates to be applied. + """ + candidates: [DeliveryDiscountCandidate!]! + + """ + The strategy that's applied to the list of discounts. + """ + selectionStrategy: DeliveryDiscountSelectionStrategy! +} + +""" +The target delivery group. +""" +input DeliveryGroupTarget { + """ + The ID of the target delivery group. + """ + id: ID! +} + +""" +List of different delivery method types. +""" +enum DeliveryMethod { + """ + Local Delivery. + """ + LOCAL + + """ + None. + """ + NONE + + """ + Shipping to a Pickup Point. + """ + PICKUP_POINT + + """ + Local Pickup. + """ + PICK_UP + + """ + Retail. + """ + RETAIL + + """ + Shipping. + """ + SHIPPING +} + +""" +The operations that can be performed to apply discounts to the delivery lines. +""" +input DeliveryOperation @oneOf { + """ + A group of delivery discounts that share a selection strategy. + """ + addDeliveryDiscounts: DeliveryDiscounts + + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes +} + +""" +The target delivery option. +""" +input DeliveryOptionTarget { + """ + The handle of the target delivery option. + """ + handle: Handle! +} + +""" +The discount that invoked the Function. +""" +type Discount implements HasMetafields { + """ + The discount classes supported by the discount node. + """ + discountClasses: [DiscountClass!]! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +The [discount class](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) +that's used to control how discounts can be combined. +""" +enum DiscountClass { + """ + The discount is combined with an + [order discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + ORDER + + """ + The discount is combined with a + [product discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + PRODUCT + + """ + The discount is combined with a + [shipping discount](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) + class. + """ + SHIPPING +} + +""" +A fixed amount value. +""" +input FixedAmount { + """ + The fixed amount value of the discount, in the currency of the cart. + + The amount must be greater than or equal to 0. + """ + amount: Decimal! +} + +""" +The cart.fetch target result. Refer to [network access] +(https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. +""" +input FunctionCartFetchResult { + """ + The http request. + """ + request: HttpRequest +} + +""" +The cart.run target result. +""" +input FunctionCartRunResult { + """ + The list of operations to apply discounts to the cart. + """ + operations: [CartOperation!]! +} + +""" +The delivery.fetch target result. Refer to +[network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. +""" +input FunctionDeliveryFetchResult { + """ + The http request. + """ + request: HttpRequest +} + +""" +The delivery.run target result. +""" +input FunctionDeliveryRunResult { + """ + The list of operations to apply discounts to the delivery lines. + """ + operations: [DeliveryOperation!]! +} + +""" +Represents a gate configuration. +""" +type GateConfiguration implements HasMetafields { + """ + An optional string identifier. + """ + appId: String + + """ + A non-unique string used to group gate configurations. + """ + handle: Handle + + """ + The ID of the gate configuration. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +Represents a connection from a subject to a gate configuration. +""" +type GateSubject { + """ + The bound gate configuration. + """ + configuration( + """ + The appId of the gate configurations to search for. + """ + appId: String @deprecated(reason: "Use GateSubject.handle to filter gates instead.") + ): GateConfiguration! + + """ + The ID of the gate subject. + """ + id: ID! +} + +""" +A function-scoped handle to a refer a resource. +The Handle type appears in a JSON response as a String, but it is not intended to be human-readable. +Example value: `"10079785100"` +""" +scalar Handle + +""" +Gate subjects associated to the specified resource. +""" +interface HasGates { + """ + Returns active gate subjects bound to the resource. + """ + gates( + """ + The handle of the gate configurations to search for. + """ + handle: Handle + ): [GateSubject!]! +} + +""" +Represents information about the metafields associated to the specified resource. +""" +interface HasMetafields { + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +Represents whether the current object has the given tag. +""" +type HasTagResponse { + """ + Whether the current object has the tag. + """ + hasTag: Boolean! + + """ + The tag. + """ + tag: String! +} + +""" +The attributes associated with an HTTP request. +""" +input HttpRequest { + """ + The HTTP request body as a plain string. + Use this field when the body isn't in JSON format. + """ + body: String + + """ + The HTTP headers. + """ + headers: [HttpRequestHeader!]! + + """ + The HTTP request body as a JSON object. + Use this field when the body's in JSON format, to reduce function instruction consumption + and to ensure the body's formatted in logs. + Don't use this field together with the `body` field. If both are provided, then the `body` field + will take precedence. + If this field is specified and no `Content-Type` header is included, then the header will + automatically be set to `application/json`. + """ + jsonBody: JSON + + """ + The HTTP method. + """ + method: HttpRequestMethod! + + """ + Policy attached to the HTTP request. + """ + policy: HttpRequestPolicy! + + """ + The HTTP url (eg.: https://example.com). The scheme needs to be HTTPS. + """ + url: URL! +} + +""" +The attributes associated with an HTTP request header. +""" +input HttpRequestHeader { + """ + Header name. + """ + name: String! + + """ + Header value. + """ + value: String! +} + +""" +The HTTP request available methods. +""" +enum HttpRequestMethod { + """ + Http GET. + """ + GET + + """ + Http POST. + """ + POST +} + +""" +The attributes associated with an HTTP request policy. +""" +input HttpRequestPolicy { + """ + Read timeout in milliseconds. + """ + readTimeoutMs: Int! +} + +""" +The attributes associated with an HTTP response. +""" +type HttpResponse { + """ + The HTTP response body as a plain string. + Use this field when the body is not in JSON format. + """ + body: String + + """ + An HTTP header. + """ + header( + """ + A case-insensitive header name. + """ + name: String! + ): HttpResponseHeader + + """ + The HTTP headers. + """ + headers: [HttpResponseHeader!]! @deprecated(reason: "Use `header` instead.") + + """ + The HTTP response body parsed as JSON. + If the body is valid JSON, it will be parsed and returned as a JSON object. + If parsing fails, then raw body is returned as a string. + Use this field when you expect the response to be JSON, or when you're dealing + with mixed response types, meaning both JSON and non-JSON. + Using this field reduces function instruction consumption and ensures that the data is formatted in logs. + To prevent increasing the function target input size unnecessarily, avoid querying + both `body` and `jsonBody` simultaneously. + """ + jsonBody: JSON + + """ + The HTTP status code. + """ + status: Int! +} + +""" +The attributes associated with an HTTP response header. +""" +type HttpResponseHeader { + """ + Header name. + """ + name: String! + + """ + Header value. + """ + value: String! +} + +""" +Represents a unique identifier, often used to refetch an object. +The ID type appears in a JSON response as a String, but it is not intended to be human-readable. + +Example value: `"gid://shopify/Product/10079785100"` +""" +scalar ID + +""" +The input object for the Function. +""" +type Input { + """ + The cart. + """ + cart: Cart! + + """ + The discount node executing the Function. + """ + discount: Discount! + + """ + Discount codes entered by the buyer as an array of strings, excluding gift cards. + Codes are not validated in any way other than gift card filtering. + """ + enteredDiscountCodes: [String!]! @restrictTarget(only: ["cart.lines.discounts.generate.fetch", "cart.delivery-options.discounts.generate.fetch"]) + + """ + The result of the fetch target. Refer to [network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) + for Shopify Functions. + """ + fetchResult: HttpResponse @restrictTarget(only: ["cart.lines.discounts.generate.run", "cart.delivery-options.discounts.generate.run"]) + + """ + The localization of the Function execution context. + """ + localization: Localization! + + """ + The conversion rate between the shop's currency and the currency of the cart. + """ + presentmentCurrencyRate: Decimal! + + """ + Information about the shop. + """ + shop: Shop! + + """ + The discount code entered by the buyer that caused the Function to run. + This input is only available in the cart.lines.discounts.generate.run + and cart.delivery-options.discounts.generate.run extension targets. + """ + triggeringDiscountCode: String @restrictTarget(only: ["cart.lines.discounts.generate.run", "cart.delivery-options.discounts.generate.run"]) +} + +""" +A [JSON](https://www.json.org/json-en.html) object. + +Example value: +`{ + "product": { + "id": "gid://shopify/Product/1346443542550", + "title": "White T-shirt", + "options": [{ + "name": "Size", + "values": ["M", "L"] + }] + } +}` +""" +scalar JSON + +""" +A language. +""" +type Language { + """ + The ISO code. + """ + isoCode: LanguageCode! +} + +""" +Language codes supported by Shopify. +""" +enum LanguageCode { + """ + Afrikaans. + """ + AF + + """ + Akan. + """ + AK + + """ + Amharic. + """ + AM + + """ + Arabic. + """ + AR + + """ + Assamese. + """ + AS + + """ + Azerbaijani. + """ + AZ + + """ + Belarusian. + """ + BE + + """ + Bulgarian. + """ + BG + + """ + Bambara. + """ + BM + + """ + Bangla. + """ + BN + + """ + Tibetan. + """ + BO + + """ + Breton. + """ + BR + + """ + Bosnian. + """ + BS + + """ + Catalan. + """ + CA + + """ + Chechen. + """ + CE + + """ + Central Kurdish. + """ + CKB + + """ + Czech. + """ + CS + + """ + Church Slavic. + """ + CU + + """ + Welsh. + """ + CY + + """ + Danish. + """ + DA + + """ + German. + """ + DE + + """ + Dzongkha. + """ + DZ + + """ + Ewe. + """ + EE + + """ + Greek. + """ + EL + + """ + English. + """ + EN + + """ + Esperanto. + """ + EO + + """ + Spanish. + """ + ES + + """ + Estonian. + """ + ET + + """ + Basque. + """ + EU + + """ + Persian. + """ + FA + + """ + Fulah. + """ + FF + + """ + Finnish. + """ + FI + + """ + Filipino. + """ + FIL + + """ + Faroese. + """ + FO + + """ + French. + """ + FR + + """ + Western Frisian. + """ + FY + + """ + Irish. + """ + GA + + """ + Scottish Gaelic. + """ + GD + + """ + Galician. + """ + GL + + """ + Gujarati. + """ + GU + + """ + Manx. + """ + GV + + """ + Hausa. + """ + HA + + """ + Hebrew. + """ + HE + + """ + Hindi. + """ + HI + + """ + Croatian. + """ + HR + + """ + Hungarian. + """ + HU + + """ + Armenian. + """ + HY + + """ + Interlingua. + """ + IA + + """ + Indonesian. + """ + ID + + """ + Igbo. + """ + IG + + """ + Sichuan Yi. + """ + II + + """ + Icelandic. + """ + IS + + """ + Italian. + """ + IT + + """ + Japanese. + """ + JA + + """ + Javanese. + """ + JV + + """ + Georgian. + """ + KA + + """ + Kikuyu. + """ + KI + + """ + Kazakh. + """ + KK + + """ + Kalaallisut. + """ + KL + + """ + Khmer. + """ + KM + + """ + Kannada. + """ + KN + + """ + Korean. + """ + KO + + """ + Kashmiri. + """ + KS + + """ + Kurdish. + """ + KU + + """ + Cornish. + """ + KW + + """ + Kyrgyz. + """ + KY + + """ + Luxembourgish. + """ + LB + + """ + Ganda. + """ + LG + + """ + Lingala. + """ + LN + + """ + Lao. + """ + LO + + """ + Lithuanian. + """ + LT + + """ + Luba-Katanga. + """ + LU + + """ + Latvian. + """ + LV + + """ + Malagasy. + """ + MG + + """ + Māori. + """ + MI + + """ + Macedonian. + """ + MK + + """ + Malayalam. + """ + ML + + """ + Mongolian. + """ + MN + + """ + Marathi. + """ + MR + + """ + Malay. + """ + MS + + """ + Maltese. + """ + MT + + """ + Burmese. + """ + MY + + """ + Norwegian (Bokmål). + """ + NB + + """ + North Ndebele. + """ + ND + + """ + Nepali. + """ + NE + + """ + Dutch. + """ + NL + + """ + Norwegian Nynorsk. + """ + NN + + """ + Norwegian. + """ + NO + + """ + Oromo. + """ + OM + + """ + Odia. + """ + OR + + """ + Ossetic. + """ + OS + + """ + Punjabi. + """ + PA + + """ + Polish. + """ + PL + + """ + Pashto. + """ + PS + + """ + Portuguese. + """ + PT + + """ + Portuguese (Brazil). + """ + PT_BR + + """ + Portuguese (Portugal). + """ + PT_PT + + """ + Quechua. + """ + QU + + """ + Romansh. + """ + RM + + """ + Rundi. + """ + RN + + """ + Romanian. + """ + RO + + """ + Russian. + """ + RU + + """ + Kinyarwanda. + """ + RW + + """ + Sanskrit. + """ + SA + + """ + Sardinian. + """ + SC + + """ + Sindhi. + """ + SD + + """ + Northern Sami. + """ + SE + + """ + Sango. + """ + SG + + """ + Sinhala. + """ + SI + + """ + Slovak. + """ + SK + + """ + Slovenian. + """ + SL + + """ + Shona. + """ + SN + + """ + Somali. + """ + SO + + """ + Albanian. + """ + SQ + + """ + Serbian. + """ + SR + + """ + Sundanese. + """ + SU + + """ + Swedish. + """ + SV + + """ + Swahili. + """ + SW + + """ + Tamil. + """ + TA + + """ + Telugu. + """ + TE + + """ + Tajik. + """ + TG + + """ + Thai. + """ + TH + + """ + Tigrinya. + """ + TI + + """ + Turkmen. + """ + TK + + """ + Tongan. + """ + TO + + """ + Turkish. + """ + TR + + """ + Tatar. + """ + TT + + """ + Uyghur. + """ + UG + + """ + Ukrainian. + """ + UK + + """ + Urdu. + """ + UR + + """ + Uzbek. + """ + UZ + + """ + Vietnamese. + """ + VI + + """ + Volapük. + """ + VO + + """ + Wolof. + """ + WO + + """ + Xhosa. + """ + XH + + """ + Yiddish. + """ + YI + + """ + Yoruba. + """ + YO + + """ + Chinese. + """ + ZH + + """ + Chinese (Simplified). + """ + ZH_CN + + """ + Chinese (Traditional). + """ + ZH_TW + + """ + Zulu. + """ + ZU +} + +""" +Represents limited information about the current time relative to the parent object. +""" +type LocalTime { + """ + The current date relative to the parent object. + """ + date: Date! + + """ + Returns true if the current date and time is at or past the given date and time, and false otherwise. + """ + dateTimeAfter( + """ + The date and time to compare against, assumed to be in the timezone of the parent object. + """ + dateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current date and time is before the given date and time, and false otherwise. + """ + dateTimeBefore( + """ + The date and time to compare against, assumed to be in the timezone of the parent timezone. + """ + dateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current date and time is between the two given date and times, and false otherwise. + """ + dateTimeBetween( + """ + The upper bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + endDateTime: DateTimeWithoutTimezone! + + """ + The lower bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + startDateTime: DateTimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is at or past the given time, and false otherwise. + """ + timeAfter( + """ + The time to compare against, assumed to be in the timezone of the parent timezone. + """ + time: TimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is at or past the given time, and false otherwise. + """ + timeBefore( + """ + The time to compare against, assumed to be in the timezone of the parent timezone. + """ + time: TimeWithoutTimezone! + ): Boolean! + + """ + Returns true if the current time is between the two given times, and false otherwise. + """ + timeBetween( + """ + The upper bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + endTime: TimeWithoutTimezone! + + """ + The lower bound time to compare against, assumed to be in the timezone of the parent timezone. + """ + startTime: TimeWithoutTimezone! + ): Boolean! +} + +""" +Information about the localized experiences configured for the shop. +""" +type Localization { + """ + The country of the active localized experience. + """ + country: Country! + + """ + The language of the active localized experience. + """ + language: Language! + + """ + The market of the active localized experience. + """ + market: Market! @deprecated(reason: "This `market` field will be removed in a future version of the API.") +} + +""" +Represents the value captured by a localized field. Localized fields are +additional fields required by certain countries on international orders. For +example, some countries require additional fields for customs information or tax +identification numbers. +""" +type LocalizedField { + """ + The key of the localized field. + """ + key: LocalizedFieldKey! + + """ + The title of the localized field. + """ + title: String! + + """ + The value of the localized field. + """ + value: String +} + +""" +Unique key identifying localized fields. +""" +enum LocalizedFieldKey { + """ + Localized field key 'shipping_credential_br' for country Brazil. + """ + SHIPPING_CREDENTIAL_BR + + """ + Localized field key 'shipping_credential_cl' for country Chile. + """ + SHIPPING_CREDENTIAL_CL + + """ + Localized field key 'shipping_credential_cn' for country China. + """ + SHIPPING_CREDENTIAL_CN + + """ + Localized field key 'shipping_credential_co' for country Colombia. + """ + SHIPPING_CREDENTIAL_CO + + """ + Localized field key 'shipping_credential_cr' for country Costa Rica. + """ + SHIPPING_CREDENTIAL_CR + + """ + Localized field key 'shipping_credential_ec' for country Ecuador. + """ + SHIPPING_CREDENTIAL_EC + + """ + Localized field key 'shipping_credential_es' for country Spain. + """ + SHIPPING_CREDENTIAL_ES + + """ + Localized field key 'shipping_credential_gt' for country Guatemala. + """ + SHIPPING_CREDENTIAL_GT + + """ + Localized field key 'shipping_credential_id' for country Indonesia. + """ + SHIPPING_CREDENTIAL_ID + + """ + Localized field key 'shipping_credential_kr' for country South Korea. + """ + SHIPPING_CREDENTIAL_KR + + """ + Localized field key 'shipping_credential_mx' for country Mexico. + """ + SHIPPING_CREDENTIAL_MX + + """ + Localized field key 'shipping_credential_my' for country Malaysia. + """ + SHIPPING_CREDENTIAL_MY + + """ + Localized field key 'shipping_credential_pe' for country Peru. + """ + SHIPPING_CREDENTIAL_PE + + """ + Localized field key 'shipping_credential_pt' for country Portugal. + """ + SHIPPING_CREDENTIAL_PT + + """ + Localized field key 'shipping_credential_py' for country Paraguay. + """ + SHIPPING_CREDENTIAL_PY + + """ + Localized field key 'shipping_credential_tr' for country Turkey. + """ + SHIPPING_CREDENTIAL_TR + + """ + Localized field key 'shipping_credential_tw' for country Taiwan. + """ + SHIPPING_CREDENTIAL_TW + + """ + Localized field key 'shipping_credential_type_co' for country Colombia. + """ + SHIPPING_CREDENTIAL_TYPE_CO + + """ + Localized field key 'tax_credential_br' for country Brazil. + """ + TAX_CREDENTIAL_BR + + """ + Localized field key 'tax_credential_cl' for country Chile. + """ + TAX_CREDENTIAL_CL + + """ + Localized field key 'tax_credential_co' for country Colombia. + """ + TAX_CREDENTIAL_CO + + """ + Localized field key 'tax_credential_cr' for country Costa Rica. + """ + TAX_CREDENTIAL_CR + + """ + Localized field key 'tax_credential_ec' for country Ecuador. + """ + TAX_CREDENTIAL_EC + + """ + Localized field key 'tax_credential_es' for country Spain. + """ + TAX_CREDENTIAL_ES + + """ + Localized field key 'tax_credential_gt' for country Guatemala. + """ + TAX_CREDENTIAL_GT + + """ + Localized field key 'tax_credential_id' for country Indonesia. + """ + TAX_CREDENTIAL_ID + + """ + Localized field key 'tax_credential_it' for country Italy. + """ + TAX_CREDENTIAL_IT + + """ + Localized field key 'tax_credential_mx' for country Mexico. + """ + TAX_CREDENTIAL_MX + + """ + Localized field key 'tax_credential_my' for country Malaysia. + """ + TAX_CREDENTIAL_MY + + """ + Localized field key 'tax_credential_pe' for country Peru. + """ + TAX_CREDENTIAL_PE + + """ + Localized field key 'tax_credential_pt' for country Portugal. + """ + TAX_CREDENTIAL_PT + + """ + Localized field key 'tax_credential_py' for country Paraguay. + """ + TAX_CREDENTIAL_PY + + """ + Localized field key 'tax_credential_tr' for country Turkey. + """ + TAX_CREDENTIAL_TR + + """ + Localized field key 'tax_credential_type_co' for country Colombia. + """ + TAX_CREDENTIAL_TYPE_CO + + """ + Localized field key 'tax_credential_type_mx' for country Mexico. + """ + TAX_CREDENTIAL_TYPE_MX + + """ + Localized field key 'tax_credential_use_mx' for country Mexico. + """ + TAX_CREDENTIAL_USE_MX + + """ + Localized field key 'tax_email_it' for country Italy. + """ + TAX_EMAIL_IT +} + +""" +Represents a mailing address. +""" +type MailingAddress { + """ + The first line of the address. Typically the street address or PO Box number. + """ + address1: String + + """ + The second line of the address. Typically the number of the apartment, suite, or unit. + """ + address2: String + + """ + The name of the city, district, village, or town. + """ + city: String + + """ + The name of the customer's company or organization. + """ + company: String + + """ + The two-letter code for the country of the address. For example, US. + """ + countryCode: CountryCode + + """ + The first name of the customer. + """ + firstName: String + + """ + The last name of the customer. + """ + lastName: String + + """ + The approximate latitude of the address. + """ + latitude: Float + + """ + The approximate longitude of the address. + """ + longitude: Float + + """ + The market of the address. + """ + market: Market @deprecated(reason: "This `market` field will be removed in a future version of the API.") + + """ + The full name of the customer, based on firstName and lastName. + """ + name: String + + """ + A unique phone number for the customer. Formatted using E.164 standard. For example, +16135551111. + """ + phone: String + + """ + The alphanumeric code for the region. For example, ON. + """ + provinceCode: String + + """ + The zip or postal code of the address. + """ + zip: String +} + +""" +A market is a group of one or more regions that you want to target for international sales. +By creating a market, you can configure a distinct, localized shopping experience for +customers from a specific area of the world. For example, you can +[change currency](https://shopify.dev/api/admin-graphql/current/mutations/marketCurrencySettingsUpdate), +[configure international pricing](https://shopify.dev/api/examples/product-price-lists), +or [add market-specific domains or subfolders](https://shopify.dev/api/admin-graphql/current/objects/MarketWebPresence). +""" +type Market implements HasMetafields { + """ + A human-readable unique string for the market automatically generated from its title. + """ + handle: Handle! + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + A geographic region which comprises a market. + """ + regions: [MarketRegion!]! +} + +""" +Represents a region. +""" +interface MarketRegion { + """ + The name of the region in the language of the current localization. + """ + name: String +} + +""" +A country which comprises a market. +""" +type MarketRegionCountry implements MarketRegion { + """ + The two-letter code for the country. + """ + code: CountryCode! + + """ + The country name in the language of the current localization. + """ + name: String! +} + +""" +The merchandise to be purchased at checkout. +""" +union Merchandise = CustomProduct | ProductVariant + +""" +[Metafields](https://shopify.dev/apps/metafields) +enable you to attach additional information to a +Shopify resource, such as a [Product](https://shopify.dev/api/admin-graphql/latest/objects/product) +or a [Collection](https://shopify.dev/api/admin-graphql/latest/objects/collection). +For more information about the Shopify resources that you can attach metafields to, refer to +[HasMetafields](https://shopify.dev/api/admin/graphql/reference/common-objects/HasMetafields). +""" +type Metafield { + """ + The data stored in the metafield in JSON format. + """ + jsonValue: JSON! + + """ + The type of data that the metafield stores in the `value` field. + Refer to the list of [supported types](https://shopify.dev/apps/metafields/types). + """ + type: String! + + """ + The data stored in the metafield. Always stored as a string, regardless of the metafield's type. + """ + value: String! +} + +""" +A monetary value with currency. +""" +type MoneyV2 { + """ + Decimal money amount. + """ + amount: Decimal! + + """ + Currency of the money. + """ + currencyCode: CurrencyCode! +} + +""" +The root mutation for the API. +""" +type MutationRoot { + """ + Handles the Function result for the cart.delivery-options.discounts.generate.fetch target. + """ + cartDeliveryOptionsDiscountsGenerateFetch( + """ + The result of the Function. + """ + result: FunctionDeliveryFetchResult! + ): Void! + + """ + Handles the Function result for the cart.delivery-options.discounts.generate.run target. + """ + cartDeliveryOptionsDiscountsGenerateRun( + """ + The result of the Function. + """ + result: FunctionDeliveryRunResult! + ): Void! + + """ + Handles the Function result for the cart.lines.discounts.generate.fetch target. + """ + cartLinesDiscountsGenerateFetch( + """ + The result of the Function. + """ + result: FunctionCartFetchResult! + ): Void! + + """ + Handles the Function result for the cart.lines.discounts.generate.run target. + """ + cartLinesDiscountsGenerateRun( + """ + The result of the Function. + """ + result: FunctionCartRunResult! + ): Void! +} + +""" +The order discount candidate to be applied. +""" +input OrderDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The conditions that must be satisfied to apply the order discount candidate. + """ + conditions: [Condition!] + + """ + The discount message. + """ + message: String + + """ + The targets of the order discount candidate. + """ + targets: [OrderDiscountCandidateTarget!]! + + """ + The value of the order discount candidate. + """ + value: OrderDiscountCandidateValue! +} + +""" +A target of a order discount candidate. +""" +input OrderDiscountCandidateTarget @oneOf { + """ + If used, the discount targets the entire order subtotal after product discounts are applied. + """ + orderSubtotal: OrderSubtotalTarget +} + +""" +The order discount candidate value. +""" +input OrderDiscountCandidateValue @oneOf { + """ + A fixed amount value. + """ + fixedAmount: FixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of order discount candidates. +""" +enum OrderDiscountSelectionStrategy { + """ + Only apply the first order discount candidate with conditions that are satisfied. + """ + FIRST + + """ + Only apply the order discount candidate that offers the maximum reduction. + """ + MAXIMUM +} + +""" +A group of order discounts that share a selection strategy. +""" +input OrderDiscounts { + """ + The list of order discount candidates to be applied. + """ + candidates: [OrderDiscountCandidate!]! + + """ + The strategy that's applied to the list of discounts. + """ + selectionStrategy: OrderDiscountSelectionStrategy! +} + +""" +The condition for checking the minimum subtotal amount of the order. +""" +input OrderMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's excluded to calculate the minimum subtotal amount of the order. + """ + excludedCartLineIds: [ID!]! + + """ + The minimum subtotal amount of the order. + """ + minimumAmount: Decimal! +} + +""" +If used, the discount targets the entire order subtotal after product discounts are applied. +""" +input OrderSubtotalTarget { + """ + The list of excluded cart line IDs. These cart lines are excluded from the order + subtotal calculation when calculating the maximum value of the discount. + """ + excludedCartLineIds: [ID!]! +} + +""" +A percentage value. +""" +input Percentage { + """ + The percentage value. + + The value is validated against: >= 0 and <= 100. + """ + value: Decimal! +} + +""" +Represents a product. +""" +type Product implements HasGates & HasMetafields { + """ + Returns active gate subjects bound to the resource. + """ + gates( + """ + The handle of the gate configurations to search for. + """ + handle: Handle + ): [GateSubject!]! + + """ + A unique human-friendly string of the product's title. + """ + handle: Handle! + + """ + Whether the product has any of the given tags. + """ + hasAnyTag( + """ + The tags to check. + """ + tags: [String!]! = [] + ): Boolean! + + """ + Whether the product has the given tags. + """ + hasTags( + """ + The tags to check. + """ + tags: [String!]! = [] + ): [HasTagResponse!]! + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Whether the product is in any of the given collections. + """ + inAnyCollection( + """ + The IDs of the collections to check. + """ + ids: [ID!]! = [] + ): Boolean! + + """ + Whether the product is in the given collections. + """ + inCollections( + """ + The IDs of the collections to check. + """ + ids: [ID!]! = [] + ): [CollectionMembership!]! + + """ + Whether the product is a gift card. + """ + isGiftCard: Boolean! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The product type specified by the merchant. + """ + productType: String + + """ + The localized title of the product in the customer’s locale. + """ + title: String! + + """ + The name of the product's vendor. + """ + vendor: String +} + +""" +The product discount candidate to be applied. +""" +input ProductDiscountCandidate { + """ + The discount code associated with this discount candidate, for code-based discounts. + """ + associatedDiscountCode: AssociatedDiscountCode + + """ + The discount message. + """ + message: String + + """ + The targets of the product discount candidate. + """ + targets: [ProductDiscountCandidateTarget!]! + + """ + The value of the product discount candidate. + """ + value: ProductDiscountCandidateValue! +} + +""" +A product discount candidate fixed amount value. +""" +input ProductDiscountCandidateFixedAmount { + """ + The fixed amount value of the product discount candidate, in the currency of the cart. + + The amount must be greater than or equal to 0. + """ + amount: Decimal! + + """ + Whether to apply the value to each entitled item. + + The default value is `false`, which causes the value to be applied once across the entitled items. + When the value is `true`, the value will be applied to each of the entitled items. + """ + appliesToEachItem: Boolean = false +} + +""" +A target of a product discount candidate, which determines which cart line(s) the discount will affect. + +Multiple targets with the same type and ID are the same as a single target of that type and ID with their +quantities added together, or `null` if any of those targets have a quantity of `null`. + +See the [Discounts API reference](https://shopify.dev/docs/api/functions/reference/product-discounts/graphql#functionrunresult) for examples. +""" +input ProductDiscountCandidateTarget @oneOf { + """ + A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. + """ + cartLine: CartLineTarget +} + +""" +The value of the product discount candidate. +""" +input ProductDiscountCandidateValue @oneOf { + """ + A product discount candidate fixed amount value. + """ + fixedAmount: ProductDiscountCandidateFixedAmount + + """ + A percentage value. + """ + percentage: Percentage +} + +""" +The strategy that's applied to the list of product discount candidates. +""" +enum ProductDiscountSelectionStrategy { + """ + Apply all product discount candidates with conditions that are satisfied. This + does not override discount combination or stacking rules. + """ + ALL + + """ + Only apply the first product discount candidate with conditions that are satisfied. + """ + FIRST + + """ + Only apply the product discount candidate that offers the maximum reduction. + """ + MAXIMUM +} + +""" +A group of product discounts that share a selection strategy. +""" +input ProductDiscounts { + """ + The list of product discount candidates to be applied. + """ + candidates: [ProductDiscountCandidate!]! + + """ + The strategy that's applied to the list of product discount candidates. + """ + selectionStrategy: ProductDiscountSelectionStrategy! +} + +""" +Represents a product variant. +""" +type ProductVariant implements HasMetafields { + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The product that this variant belongs to. + """ + product: Product! + + """ + Whether the merchandise requires shipping. + """ + requiresShipping: Boolean! + + """ + An identifier for the product variant in the shop. Required in order to connect to a fulfillment service. + """ + sku: String + + """ + The localized title of the product variant in the customer’s locale. + """ + title: String + + """ + The weight of the product variant in the unit system specified with `weight_unit`. + """ + weight: Float + + """ + Unit of measurement for weight. + """ + weightUnit: WeightUnit! +} + +""" +Represents information about the buyer that is interacting with the cart. +""" +type PurchasingCompany { + """ + The company associated to the order or draft order. + """ + company: Company! + + """ + The company contact associated to the order or draft order. + """ + contact: CompanyContact + + """ + The company location associated to the order or draft order. + """ + location: CompanyLocation! +} + +""" +Represents how products and variants can be sold and purchased. +""" +type SellingPlan implements HasMetafields { + """ + The description of the selling plan. + """ + description: String + + """ + A globally-unique identifier. + """ + id: ID! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield + + """ + The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. + """ + name: String! + + """ + Whether purchasing the selling plan will result in multiple deliveries. + """ + recurringDeliveries: Boolean! +} + +""" +Represents an association between a variant and a selling plan. Selling plan +allocations describe the options offered for each variant, and the price of the +variant when purchased with a selling plan. +""" +type SellingPlanAllocation { + """ + A list of price adjustments, with a maximum of two. When there are two, the + first price adjustment goes into effect at the time of purchase, while the + second one starts after a certain number of orders. A price adjustment + represents how a selling plan affects pricing when a variant is purchased with + a selling plan. Prices display in the customer's currency if the shop is + configured for it. + """ + priceAdjustments: [SellingPlanAllocationPriceAdjustment!]! + + """ + A representation of how products and variants can be sold and purchased. For + example, an individual selling plan could be '6 weeks of prepaid granola, + delivered weekly'. + """ + sellingPlan: SellingPlan! +} + +""" +The resulting prices for variants when they're purchased with a specific selling plan. +""" +type SellingPlanAllocationPriceAdjustment { + """ + The effective price for a single delivery. For example, for a prepaid + subscription plan that includes 6 deliveries at the price of $48.00, the per + delivery price is $8.00. + """ + perDeliveryPrice: MoneyV2! + + """ + The price of the variant when it's purchased with a selling plan For example, + for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, + where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. + """ + price: MoneyV2! +} + +""" +Information about the shop. +""" +type Shop implements HasMetafields { + """ + Information about the current time relative to the shop's timezone setting. + """ + localTime: LocalTime! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + +""" +A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that +includes the time but not the date or timezone which is determined from context. +For example, "05:43:21". +""" +scalar TimeWithoutTimezone + +""" +Represents an [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) and +[RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987)-compliant URI string. + +For example, `"https://example.myshopify.com"` is a valid URL. It includes a scheme (`https`) and a host +(`example.myshopify.com`). +""" +scalar URL + +""" +A discount code that corresponds to a valid external discount. +This can only be used by Functions with network access. +""" +input ValidDiscountCode { + """ + The discount code. + """ + code: String! +} + +""" +A list of valid discount codes that correspond to external discounts. This can +only be used by Functions with network access. +""" +input ValidDiscountCodes { + """ + The list of valid discount codes. + """ + codes: [ValidDiscountCode!]! +} + +""" +A void type that can be used to return a null value from a mutation. +""" +scalar Void + +""" +Units of measurement for weight. +""" +enum WeightUnit { + """ + Metric system unit of mass. + """ + GRAMS + + """ + 1 kilogram equals 1000 grams. + """ + KILOGRAMS + + """ + Imperial system unit of mass. + """ + OUNCES + + """ + 1 pound equals 16 ounces. + """ + POUNDS +} diff --git a/discounts/rust/discount/default/shopify.extension.toml.liquid b/discounts/rust/discount/default/shopify.extension.toml.liquid new file mode 100644 index 00000000..a75ec515 --- /dev/null +++ b/discounts/rust/discount/default/shopify.extension.toml.liquid @@ -0,0 +1,24 @@ +api_version = "2025-04" + +[[extensions]] +name = "t:name" +handle = "{{handle}}" +type = "function" +{% if uid %}uid = "{{ uid }}"{% endif %} +description = "t:description" + + [[extensions.targeting]] + target = "cart.lines.discounts.generate.run" + input_query = "src/generate_cart_run.graphql" + export = "generate_cart_run" + + [[extensions.targeting]] + target = "cart.delivery-options.discounts.generate.run" + input_query = "src/generate_delivery_run.graphql" + export = "generate_delivery_run" + + [extensions.build] + command = "cargo build --target=wasm32-wasip1 --release" + path = "target/wasm32-wasip1/release/{{handle | replace: " ", "-" | downcase}}.wasm" + watch = [ "src/**/*.rs" ] + diff --git a/discounts/rust/discount/default/src/generate_cart_run.graphql.liquid b/discounts/rust/discount/default/src/generate_cart_run.graphql.liquid new file mode 100644 index 00000000..43e918a4 --- /dev/null +++ b/discounts/rust/discount/default/src/generate_cart_run.graphql.liquid @@ -0,0 +1,12 @@ +query Input { + cart { + lines { + id + cost { + subtotalAmount { + amount + } + } + } + } +} diff --git a/discounts/rust/discount/default/src/generate_cart_run.rs b/discounts/rust/discount/default/src/generate_cart_run.rs new file mode 100644 index 00000000..5318921b --- /dev/null +++ b/discounts/rust/discount/default/src/generate_cart_run.rs @@ -0,0 +1,67 @@ +use shopify_function::prelude::*; +use shopify_function::Result; + +use cart_lines_discounts_generate_run::output::{ + CartLineTarget, CartOperation, FunctionCartRunResult, OrderDiscountCandidate, + OrderDiscountCandidateTarget, OrderDiscountCandidateValue, OrderDiscountSelectionStrategy, + OrderDiscounts, OrderSubtotalTarget, Percentage, ProductDiscountCandidate, + ProductDiscountCandidateTarget, ProductDiscountCandidateValue, + ProductDiscountSelectionStrategy, ProductDiscounts, +}; + +use cart_lines_discounts_generate_run::input::ResponseData; + +#[shopify_function_target( + target = "cartLinesDiscountsGenerateRun", + query_path = "src/generate_cart_run.graphql", + schema_path = "schema.graphql" +)] +fn generate_cart_run(input: ResponseData) -> Result { + let max_cart_line = input + .cart + .lines + .iter() + .max_by(|a, b| { + a.cost + .subtotal_amount + .amount + .partial_cmp(&b.cost.subtotal_amount.amount) + .unwrap_or(std::cmp::Ordering::Equal) + }) + .ok_or("No cart lines found")?; + + Ok(FunctionCartRunResult { + operations: vec![ + CartOperation::AddOrderDiscounts(OrderDiscounts { + selection_strategy: OrderDiscountSelectionStrategy::FIRST, + candidates: vec![OrderDiscountCandidate { + targets: vec![OrderDiscountCandidateTarget::OrderSubtotal( + OrderSubtotalTarget { + excluded_cart_line_ids: vec![], + }, + )], + message: Some("10% OFF ORDER".to_string()), + value: OrderDiscountCandidateValue::Percentage(Percentage { + value: Decimal(10.0), + }), + conditions: None, + associated_discount_code: None, + }], + }), + CartOperation::AddProductDiscounts(ProductDiscounts { + selection_strategy: ProductDiscountSelectionStrategy::FIRST, + candidates: vec![ProductDiscountCandidate { + targets: vec![ProductDiscountCandidateTarget::CartLine(CartLineTarget { + id: max_cart_line.id.clone(), + quantity: None, + })], + message: Some("20% OFF PRODUCT".to_string()), + value: ProductDiscountCandidateValue::Percentage(Percentage { + value: Decimal(20.0), + }), + associated_discount_code: None, + }], + }), + ], + }) +} diff --git a/discounts/rust/discount/default/src/generate_delivery_run.graphql.liquid b/discounts/rust/discount/default/src/generate_delivery_run.graphql.liquid new file mode 100644 index 00000000..66a4d60d --- /dev/null +++ b/discounts/rust/discount/default/src/generate_delivery_run.graphql.liquid @@ -0,0 +1,7 @@ +query Input { + cart { + deliveryGroups { + id + } + } +} diff --git a/discounts/rust/discount/default/src/generate_delivery_run.rs b/discounts/rust/discount/default/src/generate_delivery_run.rs new file mode 100644 index 00000000..6575c467 --- /dev/null +++ b/discounts/rust/discount/default/src/generate_delivery_run.rs @@ -0,0 +1,41 @@ +use shopify_function::prelude::*; +use shopify_function::Result; + +use cart_delivery_options_discounts_generate_run::output::{ + DeliveryDiscountCandidate, DeliveryDiscountCandidateTarget, DeliveryDiscountCandidateValue, + DeliveryDiscountSelectionStrategy, DeliveryDiscounts, DeliveryGroupTarget, DeliveryOperation, + FunctionDeliveryRunResult, Percentage, +}; + +use cart_delivery_options_discounts_generate_run::input::ResponseData; + +#[shopify_function_target( + target = "cartDeliveryOptionsDiscountsGenerateRun", + query_path = "src/generate_delivery_run.graphql", + schema_path = "schema.graphql" +)] +fn generate_delivery_run(input: ResponseData) -> Result { + let first_delivery_group = input + .cart + .delivery_groups + .first() + .ok_or("No delivery groups found")?; + + Ok(FunctionDeliveryRunResult { + operations: vec![DeliveryOperation::AddDeliveryDiscounts(DeliveryDiscounts { + selection_strategy: DeliveryDiscountSelectionStrategy::ALL, + candidates: vec![DeliveryDiscountCandidate { + targets: vec![DeliveryDiscountCandidateTarget::DeliveryGroup( + DeliveryGroupTarget { + id: first_delivery_group.id.clone(), + }, + )], + value: DeliveryDiscountCandidateValue::Percentage(Percentage { + value: Decimal(100.0), + }), + message: Some("FREE DELIVERY".to_string()), + associated_discount_code: None, + }], + })], + }) +} diff --git a/discounts/rust/discounts/default/src/main.rs b/discounts/rust/discount/default/src/main.rs similarity index 63% rename from discounts/rust/discounts/default/src/main.rs rename to discounts/rust/discount/default/src/main.rs index 2aeeaddf..966e529d 100644 --- a/discounts/rust/discounts/default/src/main.rs +++ b/discounts/rust/discount/default/src/main.rs @@ -1,6 +1,6 @@ use std::process; -pub mod fetch; -pub mod run; +pub mod generate_cart_run; +pub mod generate_delivery_run; fn main() { eprintln!("Please invoke a named export."); diff --git a/discounts/rust/discounts/default/shopify.extension.toml.liquid b/discounts/rust/discounts/default/shopify.extension.toml.liquid deleted file mode 100644 index 26721382..00000000 --- a/discounts/rust/discounts/default/shopify.extension.toml.liquid +++ /dev/null @@ -1,37 +0,0 @@ -api_version = "unstable" - -[[extensions]] -name = "t:name" -handle = "{{handle}}" -type = "function" -{% if uid %}uid = "{{ uid }}"{% endif %} -description = "t:description" - - [[extensions.targeting]] - target = "purchase.discount.cart_run" - input_query = "src/run.graphql" - export = "cart_run" - - [[extensions.targeting]] - target = "purchase.discount.cart_fetch" - input_query = "src/run.graphql" - export = "cart_fetch" - - [[extensions.targeting]] - target = "purchase.discount.delivery_run" - input_query = "src/fetch.graphql" - export = "delivery_run" - - [[extensions.targeting]] - target = "purchase.discount.delivery_fetch" - input_query = "src/fetch.graphql" - export = "delivery_fetch" - - [extensions.build] - command = "cargo build --target=wasm32-wasip1 --release" - path = "target/wasm32-wasip1/release/{{handle | replace: " ", "-" | downcase}}.wasm" - watch = [ "src/**/*.rs" ] - - [extensions.ui.paths] - create = "/app/discounts/:functionId/new" - details = "/app/discounts/:functionId/:id" diff --git a/discounts/rust/discounts/default/src/fetch.rs b/discounts/rust/discounts/default/src/fetch.rs deleted file mode 100644 index 52f6ca91..00000000 --- a/discounts/rust/discounts/default/src/fetch.rs +++ /dev/null @@ -1,146 +0,0 @@ -use serde::Serialize; -use shopify_function::prelude::*; -use shopify_function::Result; - -use cart_fetch::output::{ - FunctionCartFetchResult, HttpRequest as CartHttpRequest, - HttpRequestMethod as CartHttpRequestMethod, HttpRequestPolicy as CartHttpRequestPolicy, -}; - -use delivery_fetch::output::FunctionDeliveryFetchResult; -use delivery_fetch::output::{ - HttpRequest as DeliveryHttpRequest, HttpRequestMethod as DeliveryHttpRequestMethod, - HttpRequestPolicy as DeliveryHttpRequestPolicy, -}; - -type CartFetchResponseData = cart_fetch::input::ResponseData; -type DeliveryFetchResponseData = delivery_fetch::input::ResponseData; -type CartHttpRequestHeader = cart_fetch::output::HttpRequestHeader; -type DeliveryHttpRequestHeader = delivery_fetch::output::HttpRequestHeader; - -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -struct RequestBody { - entered_discount_codes: Vec, -} - -#[shopify_function_target( - target = "cart_fetch", - query_path = "src/fetch.graphql", - schema_path = "schema.graphql" -)] -fn cart_fetch(input: CartFetchResponseData) -> Result { - let request_body = RequestBody { - entered_discount_codes: input.entered_discount_codes, - }; - - Ok(FunctionCartFetchResult { - request: Some(CartHttpRequest { - body: Some(serde_json::to_string(&request_body)?), - headers: vec![CartHttpRequestHeader { - name: "Accept".to_string(), - value: "application/json; charset=utf-8".to_string(), - }], - json_body: Some(serde_json::to_value(&request_body)?), - method: CartHttpRequestMethod::POST, - policy: CartHttpRequestPolicy { - read_timeout_ms: 2000, - }, - url: "http://localhost:3000".to_string(), - }), - }) -} - -#[shopify_function_target( - target = "delivery_fetch", - query_path = "src/fetch.graphql", - schema_path = "schema.graphql" -)] -fn delivery_fetch(input: DeliveryFetchResponseData) -> Result { - let request_body = RequestBody { - entered_discount_codes: input.entered_discount_codes, - }; - - Ok(FunctionDeliveryFetchResult { - request: Some(DeliveryHttpRequest { - body: Some(serde_json::to_string(&request_body)?), - headers: vec![DeliveryHttpRequestHeader { - name: "Accept".to_string(), - value: "application/json; charset=utf-8".to_string(), - }], - json_body: Some(serde_json::to_value(&request_body)?), - method: DeliveryHttpRequestMethod::POST, - policy: DeliveryHttpRequestPolicy { - read_timeout_ms: 2000, - }, - url: "http://localhost:3000".to_string(), - }), - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use serde_json::json; - use shopify_function::{run_function_with_input, Result}; - - fn get_fetch_input_json() -> serde_json::Value { - json!({ - "enteredDiscountCodes": ["WELCOME10"] - }) - } - - #[test] - fn test_cart_fetch() -> Result<()> { - let fetch_input = get_fetch_input_json(); - - let expected_fetch_result = FunctionCartFetchResult { - request: Some(CartHttpRequest { - body: Some(fetch_input.to_string()), - headers: vec![CartHttpRequestHeader { - name: "Accept".to_string(), - value: "application/json; charset=utf-8".to_string(), - }], - json_body: Some(fetch_input.clone()), - method: CartHttpRequestMethod::POST, - policy: CartHttpRequestPolicy { - read_timeout_ms: 2000, - }, - url: "http://localhost:3000".to_string(), - }), - }; - - assert_eq!( - run_function_with_input(cart_fetch, &fetch_input.to_string())?, - expected_fetch_result - ); - Ok(()) - } - - #[test] - fn test_delivery_fetch() -> Result<()> { - let fetch_input = get_fetch_input_json(); - - let expected_fetch_result = FunctionDeliveryFetchResult { - request: Some(DeliveryHttpRequest { - body: Some(fetch_input.to_string()), - headers: vec![DeliveryHttpRequestHeader { - name: "Accept".to_string(), - value: "application/json; charset=utf-8".to_string(), - }], - json_body: Some(fetch_input.clone()), - method: DeliveryHttpRequestMethod::POST, - policy: DeliveryHttpRequestPolicy { - read_timeout_ms: 2000, - }, - url: "http://localhost:3000".to_string(), - }), - }; - - assert_eq!( - run_function_with_input(delivery_fetch, &fetch_input.to_string())?, - expected_fetch_result - ); - Ok(()) - } -} diff --git a/discounts/rust/discounts/default/src/run.graphql.liquid b/discounts/rust/discounts/default/src/run.graphql.liquid deleted file mode 100644 index 397fa5c5..00000000 --- a/discounts/rust/discounts/default/src/run.graphql.liquid +++ /dev/null @@ -1,24 +0,0 @@ -query Input { - fetchResult { - body - status - } - cart { - deliveryGroups { - id - } - lines { - id - cost { - subtotalAmount { - amount - } - } - } - } - discountNode { - metafield(namespace: "$app:{{handle | replace: " ", "-" | downcase}}", key: "function-configuration") { - value - } - } -} diff --git a/discounts/rust/discounts/default/src/run.rs b/discounts/rust/discounts/default/src/run.rs deleted file mode 100644 index 37bed336..00000000 --- a/discounts/rust/discounts/default/src/run.rs +++ /dev/null @@ -1,367 +0,0 @@ -use serde::Deserialize; - -use shopify_function::prelude::*; -use shopify_function::Result; - -use cart_run::output::{ - AssociatedDiscountCode as CartAssociatedDiscountCode, CartLineTarget, CartOperation, - FunctionCartRunResult, OrderDiscountCandidate, OrderDiscountCandidateTarget, - OrderDiscountCandidateValue, OrderDiscountSelectionStrategy, OrderDiscounts, - OrderSubtotalTarget, Percentage as CartPercentage, ProductDiscountCandidate, - ProductDiscountCandidateTarget, ProductDiscountCandidateValue, - ProductDiscountSelectionStrategy, ProductDiscounts, ValidDiscountCode as CartValidDiscountCode, - ValidDiscountCodes as CartValidDiscountCodes, -}; - -use delivery_run::output::{ - AssociatedDiscountCode as DeliveryAssociatedDiscountCode, DeliveryDiscountCandidate, - DeliveryDiscountCandidateTarget, DeliveryDiscountCandidateValue, - DeliveryDiscountSelectionStrategy, DeliveryDiscounts, DeliveryGroupTarget, DeliveryOperation, - FunctionDeliveryRunResult, Percentage as DeliveryPercentage, - ValidDiscountCode as DeliveryValidDiscountCode, - ValidDiscountCodes as DeliveryValidDiscountCodes, -}; - -type CartResponseData = cart_run::input::ResponseData; -type DeliveryResponseData = delivery_run::input::ResponseData; - -impl CartResponseData { - fn metafield(&self) -> Result { - let metafield = self - .discount_node - .metafield - .as_ref() - .ok_or("Missing metafield")?; - serde_json::from_str(&metafield.value) - .map_err(|_| "Metafield value cannot be parsed".into()) - } - fn valid_discount_codes(&self) -> Result> { - let fetch_result = self.fetch_result.as_ref().ok_or("Missing fetch result")?; - let body = fetch_result.body.as_ref().ok_or("Missing body")?; - serde_json::from_str(body).map_err(|_| "Fetch result body cannot be parsed".into()) - } -} - -impl DeliveryResponseData { - fn metafield(&self) -> Result { - let metafield = self - .discount_node - .metafield - .as_ref() - .ok_or("Missing metafield")?; - serde_json::from_str(&metafield.value) - .map_err(|_| "Metafield value cannot be parsed".into()) - } - - fn valid_discount_codes(&self) -> Result> { - let fetch_result = self.fetch_result.as_ref().ok_or("Missing fetch result")?; - let body = fetch_result.body.as_ref().ok_or("Missing body")?; - serde_json::from_str(body).map_err(|_| "Fetch result body cannot be parsed".into()) - } -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -struct Metafield { - order_percentage: Option, - product_percentage: Option, - delivery_percentage: Option, -} - -#[shopify_function_target( - target = "cart_run", - query_path = "src/run.graphql", - schema_path = "schema.graphql" -)] -fn cart_run(input: CartResponseData) -> Result { - let codes = input.valid_discount_codes()?; - let available_discount_code = codes.first(); - - if available_discount_code.is_none() { - return Ok(FunctionCartRunResult { operations: vec![] }); - } - - let metafield = input.metafield()?; - let mut operations: Vec = vec![]; - let available_discount_code = available_discount_code.unwrap(); - - operations.push(CartOperation::AddValidDiscountCodes( - CartValidDiscountCodes { - codes: vec![CartValidDiscountCode { - code: available_discount_code.to_string(), - }], - }, - )); - - if metafield.order_percentage.is_some() { - operations.push(create_order_discount(&metafield, available_discount_code)); - } - - if metafield.product_percentage.is_some() { - let highest_priced_line = input - .cart - .lines - .iter() - .max_by(|a, b| { - let a_amount = a.cost.subtotal_amount.amount; - let b_amount = b.cost.subtotal_amount.amount; - a_amount.partial_cmp(&b_amount).unwrap() - }) - .unwrap(); - operations.push(create_product_discount( - &highest_priced_line.id, - &metafield, - available_discount_code, - )); - } - - Ok(FunctionCartRunResult { operations }) -} - -#[shopify_function_target( - target = "delivery_run", - query_path = "src/run.graphql", - schema_path = "schema.graphql" -)] -fn delivery_run(input: DeliveryResponseData) -> Result { - let codes = input.valid_discount_codes()?; - let available_discount_code = codes.first(); - let metafield = input.metafield()?; - - if available_discount_code.is_none() || metafield.delivery_percentage.is_none() { - return Ok(FunctionDeliveryRunResult { operations: vec![] }); - } - - let mut operations: Vec = vec![]; - let available_discount_code = available_discount_code.unwrap(); - - operations.push(DeliveryOperation::AddValidDiscountCodes( - DeliveryValidDiscountCodes { - codes: vec![DeliveryValidDiscountCode { - code: available_discount_code.to_string(), - }], - }, - )); - - let candidates = input - .cart - .delivery_groups - .iter() - .map(|group| { - create_delivery_discount_candidate(&group.id, &metafield, available_discount_code) - }) - .collect::>(); - - operations.push(DeliveryOperation::AddDeliveryDiscounts(DeliveryDiscounts { - selection_strategy: DeliveryDiscountSelectionStrategy::ALL, - candidates, - })); - - Ok(FunctionDeliveryRunResult { operations }) -} - -fn create_order_discount(metafield: &Metafield, available_discount_code: &str) -> CartOperation { - CartOperation::AddOrderDiscounts(OrderDiscounts { - selection_strategy: OrderDiscountSelectionStrategy::FIRST, - candidates: vec![OrderDiscountCandidate { - targets: vec![OrderDiscountCandidateTarget::OrderSubtotal( - OrderSubtotalTarget { - excluded_variant_ids: vec![], - }, - )], - associated_discount_code: Some(CartAssociatedDiscountCode { - code: available_discount_code.to_string(), - }), - message: None, - value: OrderDiscountCandidateValue::Percentage(CartPercentage { - value: metafield.order_percentage.unwrap(), - }), - conditions: None, - }], - }) -} - -fn create_product_discount( - cart_line_id: &str, - metafield: &Metafield, - available_discount_code: &str, -) -> CartOperation { - CartOperation::AddProductDiscounts(ProductDiscounts { - selection_strategy: ProductDiscountSelectionStrategy::FIRST, - candidates: vec![ProductDiscountCandidate { - targets: vec![ProductDiscountCandidateTarget::CartLine(CartLineTarget { - id: cart_line_id.to_string(), - quantity: Some(1), - })], - associated_discount_code: Some(CartAssociatedDiscountCode { - code: available_discount_code.to_string(), - }), - message: None, - value: ProductDiscountCandidateValue::Percentage(CartPercentage { - value: metafield.product_percentage.unwrap(), - }), - }], - }) -} - -fn create_delivery_discount_candidate( - delivery_group_id: &str, - metafield: &Metafield, - available_discount_code: &str, -) -> DeliveryDiscountCandidate { - DeliveryDiscountCandidate { - targets: vec![DeliveryDiscountCandidateTarget::DeliveryGroup( - DeliveryGroupTarget { - id: delivery_group_id.to_string(), - }, - )], - value: DeliveryDiscountCandidateValue::Percentage(DeliveryPercentage { - value: metafield.delivery_percentage.unwrap(), - }), - message: None, - associated_discount_code: Some(DeliveryAssociatedDiscountCode { - code: available_discount_code.to_string(), - }), - } -} - -#[cfg(test)] -mod tests { - use super::*; - use cart_run::output::{ - CartOperation, OrderDiscountSelectionStrategy, OrderDiscounts, - ProductDiscountSelectionStrategy, ProductDiscounts, - }; - use delivery_run::output::{ - DeliveryDiscountSelectionStrategy, DeliveryDiscounts, DeliveryOperation, - FunctionDeliveryRunResult, - }; - use serde_json::json; - use shopify_function::prelude::Decimal; - use shopify_function::{run_function_with_input, Result}; - - fn get_run_input() -> String { - json!({ - "cart": { - "lines": [ - { - "id": "gid://shopify/CartLine/123", - "cost": { - "subtotalAmount": { - "amount": "100.00" - } - } - } - ], - "deliveryGroups": [ - { - "id": "gid://shopify/DeliveryGroup/123" - } - ] - }, - "discountNode": { - "metafield": { - "value": json!({ - "orderPercentage": "10", - "productPercentage": "20", - "deliveryPercentage": "30", - }).to_string(), - } - }, - "fetchResult": { - "body": "[\"WELCOME10\"]", - "status": 200 - } - }) - .to_string() - } - - #[test] - fn test_cart_run() -> Result<()> { - let expected = FunctionCartRunResult { - operations: vec![ - CartOperation::AddValidDiscountCodes(CartValidDiscountCodes { - codes: vec![CartValidDiscountCode { - code: "WELCOME10".to_string(), - }], - }), - CartOperation::AddOrderDiscounts(OrderDiscounts { - selection_strategy: OrderDiscountSelectionStrategy::FIRST, - candidates: vec![OrderDiscountCandidate { - targets: vec![OrderDiscountCandidateTarget::OrderSubtotal( - OrderSubtotalTarget { - excluded_variant_ids: vec![], - }, - )], - associated_discount_code: Some(CartAssociatedDiscountCode { - code: "WELCOME10".to_string(), - }), - message: None, - value: OrderDiscountCandidateValue::Percentage(CartPercentage { - value: Decimal(10.0), - }), - conditions: None, - }], - }), - CartOperation::AddProductDiscounts(ProductDiscounts { - selection_strategy: ProductDiscountSelectionStrategy::FIRST, - candidates: vec![ProductDiscountCandidate { - targets: vec![ProductDiscountCandidateTarget::CartLine(CartLineTarget { - id: "gid://shopify/CartLine/123".to_string(), - quantity: Some(1), - })], - associated_discount_code: Some(CartAssociatedDiscountCode { - code: "WELCOME10".to_string(), - }), - message: None, - value: ProductDiscountCandidateValue::Percentage(CartPercentage { - value: Decimal(20.0), - }), - }], - }), - ], - }; - - assert_eq!( - run_function_with_input(cart_run, &get_run_input())?, - expected - ); - Ok(()) - } - - #[test] - fn test_delivery_run() -> Result<()> { - let expected = FunctionDeliveryRunResult { - operations: vec![ - DeliveryOperation::AddValidDiscountCodes(DeliveryValidDiscountCodes { - codes: vec![DeliveryValidDiscountCode { - code: "WELCOME10".to_string(), - }], - }), - DeliveryOperation::AddDeliveryDiscounts(DeliveryDiscounts { - selection_strategy: DeliveryDiscountSelectionStrategy::ALL, - candidates: vec![DeliveryDiscountCandidate { - targets: vec![DeliveryDiscountCandidateTarget::DeliveryGroup( - DeliveryGroupTarget { - id: "gid://shopify/DeliveryGroup/123".to_string(), - }, - )], - value: DeliveryDiscountCandidateValue::Percentage(DeliveryPercentage { - value: Decimal(30.0), - }), - message: None, - associated_discount_code: Some(DeliveryAssociatedDiscountCode { - code: "WELCOME10".to_string(), - }), - }], - }), - ], - }; - - assert_eq!( - run_function_with_input(delivery_run, &get_run_input())?, - expected - ); - Ok(()) - } -} diff --git a/discounts/rust/network/default/.gitignore b/discounts/rust/network/default/.gitignore new file mode 100644 index 00000000..96ef6c0b --- /dev/null +++ b/discounts/rust/network/default/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/discounts/rust/network/default/Cargo.toml.liquid b/discounts/rust/network/default/Cargo.toml.liquid new file mode 100644 index 00000000..72bdfcd7 --- /dev/null +++ b/discounts/rust/network/default/Cargo.toml.liquid @@ -0,0 +1,18 @@ +[package] +name = "{{handle | replace: " ", "-" | downcase}}" +version = "1.0.0" +edition = "2021" + +[dependencies] +serde_json = "1.0" +shopify_function = "0.8.1" +graphql_client = "0.14.0" + + [dependencies.serde] + version = "1.0.13" + features = [ "derive" ] + +[profile.release] +lto = true +opt-level = "z" +strip = true diff --git a/discounts/rust/network/default/README.md b/discounts/rust/network/default/README.md new file mode 100644 index 00000000..574afb9c --- /dev/null +++ b/discounts/rust/network/default/README.md @@ -0,0 +1,16 @@ +# Shopify Function development with Rust + +## Dependencies + +- [Install Rust](https://www.rust-lang.org/tools/install) + - On Windows, Rust requires the [Microsoft C++ Build Tools](https://docs.microsoft.com/en-us/windows/dev-environment/rust/setup). Be sure to select the _Desktop development with C++_ workload when installing them. + +## Building the function + +You can build this individual function using `cargo build`. + +```shell +cargo build --target=wasm32-wasip1 --release +``` + +The Shopify CLI `build` command will also execute this, based on the configuration in `shopify.extension.toml`. diff --git a/discounts/rust/discounts/default/schema.graphql b/discounts/rust/network/default/schema.graphql similarity index 93% rename from discounts/rust/discounts/default/schema.graphql rename to discounts/rust/network/default/schema.graphql index cd29eb35..f57d2769 100644 --- a/discounts/rust/discounts/default/schema.graphql +++ b/discounts/rust/network/default/schema.graphql @@ -71,19 +71,12 @@ type BuyerIdentity { The purchasing company associated with the cart. """ purchasingCompany: PurchasingCompany - - """ - Represents the [Shop User](https://help.shopify.com/en/manual/online-sales-channels/shop/sign-in-features) - corresponding to the customer within the shop, if the buyer is a Shop User. Can be used to request [Shop User - metafields](https://shopify.dev/docs/api/shop-user-custom-data). - """ - shopUser: ShopUser } """ A cart represents the merchandise that a buyer intends to purchase, and the cost associated with the cart. """ -type Cart implements HasMetafields { +type Cart { """ The attributes associated with the cart. Attributes are represented as key-value pairs. """ @@ -128,21 +121,6 @@ type Cart implements HasMetafields { """ keys: [LocalizedFieldKey!]! = [] ): [LocalizedField!]! - - """ - Returns a metafield by namespace and key that belongs to the resource. - """ - metafield( - """ - The key for the metafield. - """ - key: String! - - """ - The container the metafield belongs to. If omitted, the app-reserved namespace will be used. - """ - namespace: String - ): Metafield } """ @@ -304,6 +282,38 @@ type CartLineCost { totalAmount: MoneyV2! } +""" +The condition for checking the minimum quantity of products across a group of cart lines. +""" +input CartLineMinimumQuantity { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum quantity purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum quantity of a product. + """ + minimumQuantity: Int! +} + +""" +The condition for checking the minimum subtotal of products across a group of cart lines. +""" +input CartLineMinimumSubtotal { + """ + Cart line IDs with a merchandise line price that's included to calculate the + minimum subtotal purchased to receive the discount. + """ + ids: [ID!]! + + """ + The minimum subtotal amount of the product. + """ + minimumAmount: Decimal! +} + """ A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. """ @@ -326,6 +336,12 @@ input CartLineTarget { The operations that can be performed to apply discounts to the cart. """ input CartOperation @oneOf { + """ + A list of valid discount codes that correspond to external discounts. This can + only be used by Functions with network access. + """ + addDiscountCodeValidations: ValidDiscountCodes + """ A group of order discounts that share a selection strategy. """ @@ -335,12 +351,6 @@ input CartOperation @oneOf { A group of product discounts that share a selection strategy. """ addProductDiscounts: ProductDiscounts - - """ - A list of valid discount codes that correspond to external discounts. This can - only be used by Functions with network access. - """ - addValidDiscountCodes: ValidDiscountCodes } """ @@ -480,11 +490,6 @@ type CompanyLocation implements HasMetafields { """ name: String! - """ - The number of orders placed at this company location. - """ - orderCount: Int! - """ The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company location was last modified. @@ -497,19 +502,19 @@ The condition to apply the discount candidate. """ input Condition @oneOf { """ - The condition for checking the minimum subtotal amount of the order. + The condition for checking the minimum quantity of products across a group of cart lines. """ - orderMinimumSubtotal: OrderMinimumSubtotal + cartLineMinimumQuantity: CartLineMinimumQuantity """ - The condition for checking the minimum quantity of a product. + The condition for checking the minimum subtotal of products across a group of cart lines. """ - productMinimumQuantity: ProductMinimumQuantity + cartLineMinimumSubtotal: CartLineMinimumSubtotal """ - The condition for checking the minimum subtotal amount of the product. + The condition for checking the minimum subtotal amount of the order. """ - productMinimumSubtotal: ProductMinimumSubtotal + orderMinimumSubtotal: OrderMinimumSubtotal } """ @@ -1664,11 +1669,6 @@ enum CountryCode { """ UM - """ - Unknown country code. - """ - UNKNOWN__ - """ United States. """ @@ -2886,7 +2886,7 @@ input DeliveryOperation @oneOf { A list of valid discount codes that correspond to external discounts. This can only be used by Functions with network access. """ - addValidDiscountCodes: ValidDiscountCodes + addDiscountCodeValidations: ValidDiscountCodes } """ @@ -2899,6 +2899,31 @@ input DeliveryOptionTarget { handle: Handle! } +""" +The discount that invoked the Function. +""" +type Discount implements HasMetafields { + """ + The discount classes supported by the discount node. + """ + discountClasses: [DiscountClass!]! + + """ + Returns a metafield by namespace and key that belongs to the resource. + """ + metafield( + """ + The key for the metafield. + """ + key: String! + + """ + The container the metafield belongs to. If omitted, the app-reserved namespace will be used. + """ + namespace: String + ): Metafield +} + """ The [discount class](https://help.shopify.com/manual/discounts/combining-discounts/discount-combinations) that's used to control how discounts can be combined. @@ -2926,31 +2951,6 @@ enum DiscountClass { SHIPPING } -""" -A discount wrapper node. -""" -type DiscountNode implements HasMetafields { - """ - The discount classes supported by the discount node. - """ - discountClasses: [DiscountClass!]! - - """ - Returns a metafield by namespace and key that belongs to the resource. - """ - metafield( - """ - The key for the metafield. - """ - key: String! - - """ - The container the metafield belongs to. If omitted, the app-reserved namespace will be used. - """ - namespace: String - ): Metafield -} - """ A fixed amount value. """ @@ -3278,7 +3278,7 @@ type Input { """ The discount node executing the Function. """ - discountNode: DiscountNode! + discount: Discount! """ Discount codes entered by the buyer as an array of strings, excluding gift cards. @@ -3286,7 +3286,10 @@ type Input { """ enteredDiscountCodes: [String!]! @restrictTarget( - only: ["purchase.discount.cart_fetch", "purchase.discount.delivery_fetch"] + only: [ + "cart.lines.discounts.generate.fetch" + "cart.delivery-options.discounts.generate.fetch" + ] ) """ @@ -3295,7 +3298,10 @@ type Input { """ fetchResult: HttpResponse @restrictTarget( - only: ["purchase.discount.cart_run", "purchase.discount.delivery_run"] + only: [ + "cart.lines.discounts.generate.run" + "cart.delivery-options.discounts.generate.run" + ] ) """ @@ -3312,6 +3318,19 @@ type Input { Information about the shop. """ shop: Shop! + + """ + The discount code entered by the buyer that caused the Function to run. + This input is only available in the cart.lines.discounts.generate.run + and cart.delivery-options.discounts.generate.run extension targets. + """ + triggeringDiscountCode: String + @restrictTarget( + only: [ + "cart.lines.discounts.generate.run" + "cart.delivery-options.discounts.generate.run" + ] + ) } """ @@ -4149,6 +4168,9 @@ type Localization { The market of the active localized experience. """ market: Market! + @deprecated( + reason: "This `market` field will be removed in a future version of the API." + ) } """ @@ -4417,6 +4439,9 @@ type MailingAddress { The market of the address. """ market: Market + @deprecated( + reason: "This `market` field will be removed in a future version of the API." + ) """ The full name of the customer, based on firstName and lastName. @@ -4458,11 +4483,6 @@ type Market implements HasMetafields { """ id: ID! - """ - The manager of the market, if the accessing app is the market’s manager. Otherwise, this will be null. - """ - manager: MarketManager - """ Returns a metafield by namespace and key that belongs to the resource. """ @@ -4484,17 +4504,6 @@ type Market implements HasMetafields { regions: [MarketRegion!]! } -""" -The entity that manages a particular market. -""" -type MarketManager { - """ - The identity of the manager. This can either be `merchant` if the market is - manually managed by the merchant or an ID of the app responsible for managing the market. - """ - identifier: String! -} - """ Represents a region. """ @@ -4571,43 +4580,43 @@ The root mutation for the API. """ type MutationRoot { """ - Handles the Function result for the purchase.discount.cart_fetch target. + Handles the Function result for the cart.delivery-options.discounts.generate.fetch target. """ - cartFetch( + cartDeliveryOptionsDiscountsGenerateFetch( """ The result of the Function. """ - result: FunctionCartFetchResult! + result: FunctionDeliveryFetchResult! ): Void! """ - Handles the Function result for the purchase.discount.cart_run target. + Handles the Function result for the cart.delivery-options.discounts.generate.run target. """ - cartRun( + cartDeliveryOptionsDiscountsGenerateRun( """ The result of the Function. """ - result: FunctionCartRunResult! + result: FunctionDeliveryRunResult! ): Void! """ - Handles the Function result for the purchase.discount.delivery_fetch target. + Handles the Function result for the cart.lines.discounts.generate.fetch target. """ - deliveryFetch( + cartLinesDiscountsGenerateFetch( """ The result of the Function. """ - result: FunctionDeliveryFetchResult! + result: FunctionCartFetchResult! ): Void! """ - Handles the Function result for the purchase.discount.delivery_run target. + Handles the Function result for the cart.lines.discounts.generate.run target. """ - deliveryRun( + cartLinesDiscountsGenerateRun( """ The result of the Function. """ - result: FunctionDeliveryRunResult! + result: FunctionCartRunResult! ): Void! } @@ -4632,10 +4641,6 @@ input OrderDiscountCandidate { """ The targets of the order discount candidate. - - The value is validated against: targets should contain only one type of `OrderDiscountCandidateTarget`. - Only a list that contains either a single `OrderSubtotalTarget` or one or more - `ProductVariantTarget`s is valid. """ targets: [OrderDiscountCandidateTarget!]! @@ -4647,20 +4652,12 @@ input OrderDiscountCandidate { """ A target of a order discount candidate. - -An `OrderDiscountCandidate` can either have a single `OrderSubtotalTarget`, or one or more `ProductVariantTarget`s. """ input OrderDiscountCandidateTarget @oneOf { """ If used, the discount targets the entire order subtotal after product discounts are applied. """ orderSubtotal: OrderSubtotalTarget - - """ - A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that can apply to any cart lines for a specific product variant, up to an - optional quantity limit. - """ - productVariant: ProductVariantTarget } """ @@ -4713,9 +4710,9 @@ The condition for checking the minimum subtotal amount of the order. """ input OrderMinimumSubtotal { """ - Variant IDs with a merchandise line price that's excluded to calculate the minimum subtotal amount of the order. + Cart line IDs with a merchandise line price that's excluded to calculate the minimum subtotal amount of the order. """ - excludedVariantIds: [ID!]! + excludedCartLineIds: [ID!]! """ The minimum subtotal amount of the order. @@ -4728,10 +4725,10 @@ If used, the discount targets the entire order subtotal after product discounts """ input OrderSubtotalTarget { """ - The list of excluded product variant IDs. Cart lines for these product variants are excluded from the order + The list of excluded cart line IDs. These cart lines are excluded from the order subtotal calculation when calculating the maximum value of the discount. """ - excludedVariantIds: [ID!]! + excludedCartLineIds: [ID!]! } """ @@ -4862,7 +4859,6 @@ input ProductDiscountCandidate { """ The targets of the product discount candidate. - This argument accepts a collection of either `ProductVariantTarget`s or `CartLineTarget`s, but not both. """ targets: [ProductDiscountCandidateTarget!]! @@ -4895,8 +4891,6 @@ input ProductDiscountCandidateFixedAmount { """ A target of a product discount candidate, which determines which cart line(s) the discount will affect. -A `ProductDiscountCandidate` can have a collection of either `ProductVariantTarget`s or `CartLineTarget`s, but not both. - Multiple targets with the same type and ID are the same as a single target of that type and ID with their quantities added together, or `null` if any of those targets have a quantity of `null`. @@ -4907,12 +4901,6 @@ input ProductDiscountCandidateTarget @oneOf { A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that applies to a specific cart line, up to an optional quantity limit. """ cartLine: CartLineTarget - - """ - A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that can apply to any cart lines for a specific product variant, up to an - optional quantity limit. - """ - productVariant: ProductVariantTarget } """ @@ -4966,36 +4954,6 @@ input ProductDiscounts { selectionStrategy: ProductDiscountSelectionStrategy! } -""" -The condition for checking the minimum quantity of a product. -""" -input ProductMinimumQuantity { - """ - Variant IDs with a merchandise line price that's included to calculate the minimum quantity of the product. - """ - ids: [ID!]! - - """ - The minimum quantity of a product. - """ - minimumQuantity: Int! -} - -""" -The condition for checking the minimum subtotal amount of the product. -""" -input ProductMinimumSubtotal { - """ - Variant IDs with a merchandise line price that's included to calculate the minimum subtotal amount of a product. - """ - ids: [ID!]! - - """ - The minimum subtotal amount of the product. - """ - minimumAmount: Decimal! -} - """ Represents a product variant. """ @@ -5051,25 +5009,6 @@ type ProductVariant implements HasMetafields { weightUnit: WeightUnit! } -""" -A discount [Target](https://shopify.dev/api/functions/reference/product-discounts/graphql/common-objects/target) that can apply to any cart lines for a specific product variant, up to an -optional quantity limit. -""" -input ProductVariantTarget { - """ - The ID of the targeted product variant. - """ - id: ID! - - """ - The maximum number of line item units to be discounted. - The default value is `null`, which represents the total quantity of the matching line items. - - The value is validated against: > 0. - """ - quantity: Int -} - """ Represents information about the buyer that is interacting with the cart. """ @@ -5198,26 +5137,6 @@ type Shop implements HasMetafields { ): Metafield } -""" -Represents information about the buyer that is interacting with the cart. -""" -type ShopUser implements HasMetafields { - """ - Returns a metafield by namespace and key that belongs to the resource. - """ - metafield( - """ - The key for the metafield. - """ - key: String! - - """ - The container the metafield belongs to. If omitted, the app-reserved namespace will be used. - """ - namespace: String - ): Metafield -} - """ A subset of the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format that includes the time but not the date or timezone which is determined from context. diff --git a/discounts/rust/network/default/shopify.extension.toml.liquid b/discounts/rust/network/default/shopify.extension.toml.liquid new file mode 100644 index 00000000..bc62ca2d --- /dev/null +++ b/discounts/rust/network/default/shopify.extension.toml.liquid @@ -0,0 +1,34 @@ +api_version = "2025-04" + +[[extensions]] +name = "t:name" +handle = "{{handle}}" +type = "function" +{% if uid %}uid = "{{ uid }}"{% endif %} +description = "t:description" + + [[extensions.targeting]] + target = "cart.lines.discounts.generate.run" + input_query = "src/generate_cart_run.graphql" + export = "generate_cart_run" + + [[extensions.targeting]] + target = "cart.delivery-options.discounts.generate.run" + input_query = "src/generate_delivery_run.graphql" + export = "generate_delivery_run" + + [[extensions.targeting]] + target = "cart.lines.discounts.generate.fetch" + input_query = "src/generate_cart_fetch.graphql" + export = "generate_cart_fetch" + + [[extensions.targeting]] + target = "cart.delivery-options.discounts.generate.fetch" + input_query = "src/generate_delivery_fetch.graphql" + export = "generate_delivery_fetch" + + [extensions.build] + command = "cargo build --target=wasm32-wasip1 --release" + path = "target/wasm32-wasip1/release/{{handle | replace: " ", "-" | downcase}}.wasm" + watch = [ "src/**/*.rs" ] + diff --git a/discounts/rust/discounts/default/src/fetch.graphql.liquid b/discounts/rust/network/default/src/generate_cart_fetch.graphql.liquid similarity index 100% rename from discounts/rust/discounts/default/src/fetch.graphql.liquid rename to discounts/rust/network/default/src/generate_cart_fetch.graphql.liquid diff --git a/discounts/rust/network/default/src/generate_cart_fetch.rs b/discounts/rust/network/default/src/generate_cart_fetch.rs new file mode 100644 index 00000000..1d88ded5 --- /dev/null +++ b/discounts/rust/network/default/src/generate_cart_fetch.rs @@ -0,0 +1,79 @@ +use serde_json::json; +use shopify_function; +use shopify_function::prelude::*; + +use cart_lines_discounts_generate_fetch::input::ResponseData as CartFetchResponseData; +use cart_lines_discounts_generate_fetch::output::{ + FunctionCartFetchResult, HttpRequest as CartFetchHttpRequest, + HttpRequestHeader as CartFetchHttpRequestHeader, + HttpRequestMethod as CartFetchHttpRequestMethod, + HttpRequestPolicy as CartFetchHttpRequestPolicy, +}; + +#[shopify_function_target( + query_path = "src/generate_cart_fetch.graphql", + schema_path = "schema.graphql", + target = "cartLinesDiscountsGenerateFetch" +)] +fn generate_cart_fetch( + input: CartFetchResponseData, +) -> shopify_function::Result { + let entered_discount_codes = &input.entered_discount_codes; + let json_body = json!({ "enteredDiscountCodes": entered_discount_codes }); + + let request = CartFetchHttpRequest { + headers: vec![CartFetchHttpRequestHeader { + name: "accept".to_string(), + value: "application/json".to_string(), + }], + method: CartFetchHttpRequestMethod::GET, + policy: CartFetchHttpRequestPolicy { + read_timeout_ms: 2000, + }, + url: "".to_string(), + body: Some(json_body.to_string()), + json_body: Some(json_body.clone()), + }; + + Ok(FunctionCartFetchResult { + request: Some(request), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use cart_lines_discounts_generate_fetch::output::{ + FunctionCartFetchResult, HttpRequest as CartFetchHttpRequest, + HttpRequestHeader as CartFetchHttpRequestHeader, + HttpRequestMethod as CartFetchHttpRequestMethod, + HttpRequestPolicy as CartFetchHttpRequestPolicy, + }; + use shopify_function::{run_function_with_input, Result}; + + #[test] + fn adds_entered_discount_codes_to_json_body_for_cart() -> Result<()> { + let input = json!({"enteredDiscountCodes": []}).to_string(); + + let result = run_function_with_input(generate_cart_fetch, &input)?; + let json_body = json!({ "enteredDiscountCodes": [] }); + let expected = FunctionCartFetchResult { + request: Some(CartFetchHttpRequest { + headers: vec![CartFetchHttpRequestHeader { + name: "accept".to_string(), + value: "application/json".to_string(), + }], + method: CartFetchHttpRequestMethod::GET, + policy: CartFetchHttpRequestPolicy { + read_timeout_ms: 2000, + }, + url: "".to_string(), + json_body: Some(json_body.clone()), + body: Some(json_body.to_string()), + }), + }; + + assert_eq!(result, expected); + Ok(()) + } +} diff --git a/discounts/rust/network/default/src/generate_cart_run.graphql.liquid b/discounts/rust/network/default/src/generate_cart_run.graphql.liquid new file mode 100644 index 00000000..b0a15fa9 --- /dev/null +++ b/discounts/rust/network/default/src/generate_cart_run.graphql.liquid @@ -0,0 +1,17 @@ +query Input { + fetchResult { + body + status + } + cart { + lines { + id + cost { + subtotalAmount { + amount + } + } + } + } +} + diff --git a/discounts/rust/network/default/src/generate_cart_run.rs b/discounts/rust/network/default/src/generate_cart_run.rs new file mode 100644 index 00000000..81ffda10 --- /dev/null +++ b/discounts/rust/network/default/src/generate_cart_run.rs @@ -0,0 +1,57 @@ +use serde::Deserialize; +use shopify_function::prelude::*; +use shopify_function::Result; + +use cart_lines_discounts_generate_run::output::{ + CartOperation, FunctionCartRunResult, OrderDiscounts, ProductDiscounts, ValidDiscountCodes, +}; + +use cart_lines_discounts_generate_run::input::ResponseData; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct DiscountResponse { + operations: Operations, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct Operations { + #[serde(default)] + add_product_discounts: Option, + #[serde(default)] + add_order_discounts: Option, + #[serde(default)] + add_discount_code_validations: Option, +} + +#[shopify_function_target( + target = "cartLinesDiscountsGenerateRun", + query_path = "src/generate_cart_run.graphql", + schema_path = "schema.graphql" +)] +fn generate_cart_run(input: ResponseData) -> Result { + let fetch_result = input.fetch_result.ok_or("Missing fetch result")?; + let body = fetch_result.body.ok_or("Missing response body")?; + + // Parse the response body directly into our types + let response: DiscountResponse = + serde_json::from_str(&body).map_err(|e| format!("Failed to parse JSON: {}", e))?; + + // Convert the response into operations + let mut operations = Vec::new(); + + if let Some(validations) = response.operations.add_discount_code_validations { + operations.push(CartOperation::AddDiscountCodeValidations(validations)); + } + + if let Some(product_discounts) = response.operations.add_product_discounts { + operations.push(CartOperation::AddProductDiscounts(product_discounts)); + } + + if let Some(order_discounts) = response.operations.add_order_discounts { + operations.push(CartOperation::AddOrderDiscounts(order_discounts)); + } + + Ok(FunctionCartRunResult { operations }) +} diff --git a/discounts/rust/network/default/src/generate_delivery_fetch.graphql.liquid b/discounts/rust/network/default/src/generate_delivery_fetch.graphql.liquid new file mode 100644 index 00000000..890973d8 --- /dev/null +++ b/discounts/rust/network/default/src/generate_delivery_fetch.graphql.liquid @@ -0,0 +1,3 @@ +query Input { + enteredDiscountCodes +} diff --git a/discounts/rust/network/default/src/generate_delivery_fetch.rs b/discounts/rust/network/default/src/generate_delivery_fetch.rs new file mode 100644 index 00000000..8123fb38 --- /dev/null +++ b/discounts/rust/network/default/src/generate_delivery_fetch.rs @@ -0,0 +1,79 @@ +use serde_json::json; +use shopify_function; +use shopify_function::prelude::*; + +use cart_delivery_options_discounts_generate_fetch::input::ResponseData as DeliveryFetchResponseData; +use cart_delivery_options_discounts_generate_fetch::output::{ + FunctionDeliveryFetchResult, HttpRequest as DeliveryFetchHttpRequest, + HttpRequestHeader as DeliveryFetchHttpRequestHeader, + HttpRequestMethod as DeliveryFetchHttpRequestMethod, + HttpRequestPolicy as DeliveryFetchHttpRequestPolicy, +}; + +#[shopify_function_target( + query_path = "src/generate_delivery_fetch.graphql", + schema_path = "schema.graphql", + target = "cartDeliveryOptionsDiscountsGenerateFetch" +)] +fn generate_delivery_fetch( + input: DeliveryFetchResponseData, +) -> shopify_function::Result { + let entered_discount_codes = &input.entered_discount_codes; + let json_body = json!({ "enteredDiscountCodes": entered_discount_codes }); + + let request = DeliveryFetchHttpRequest { + headers: vec![DeliveryFetchHttpRequestHeader { + name: "accept".to_string(), + value: "application/json".to_string(), + }], + method: DeliveryFetchHttpRequestMethod::GET, + policy: DeliveryFetchHttpRequestPolicy { + read_timeout_ms: 2000, + }, + url: "".to_string(), + body: Some(json_body.to_string()), + json_body: Some(json_body.clone()), + }; + + Ok(FunctionDeliveryFetchResult { + request: Some(request), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use cart_delivery_options_discounts_generate_fetch::output::{ + FunctionDeliveryFetchResult, HttpRequest as DeliveryFetchHttpRequest, + HttpRequestHeader as DeliveryFetchHttpRequestHeader, + HttpRequestMethod as DeliveryFetchHttpRequestMethod, + HttpRequestPolicy as DeliveryFetchHttpRequestPolicy, + }; + use shopify_function::{run_function_with_input, Result}; + + #[test] + fn adds_entered_discount_codes_to_body_for_delivery() -> Result<()> { + let input = json!({ "enteredDiscountCodes": ["ABC"] }).to_string(); + + let result = run_function_with_input(generate_delivery_fetch, &input)?; + let json_body = json!({ "enteredDiscountCodes": ["ABC"] }); + let expected = FunctionDeliveryFetchResult { + request: Some(DeliveryFetchHttpRequest { + headers: vec![DeliveryFetchHttpRequestHeader { + name: "accept".to_string(), + value: "application/json".to_string(), + }], + method: DeliveryFetchHttpRequestMethod::GET, + policy: DeliveryFetchHttpRequestPolicy { + read_timeout_ms: 2000, + }, + url: "".to_string(), + json_body: Some(json_body.clone()), + body: Some(json_body.to_string()), + }), + }; + + assert_eq!(result, expected); + Ok(()) + } +} diff --git a/discounts/rust/network/default/src/generate_delivery_run.graphql.liquid b/discounts/rust/network/default/src/generate_delivery_run.graphql.liquid new file mode 100644 index 00000000..3f136325 --- /dev/null +++ b/discounts/rust/network/default/src/generate_delivery_run.graphql.liquid @@ -0,0 +1,11 @@ +query Input { + fetchResult { + body + status + } + cart { + deliveryGroups { + id + } + } +} diff --git a/discounts/rust/network/default/src/generate_delivery_run.rs b/discounts/rust/network/default/src/generate_delivery_run.rs new file mode 100644 index 00000000..ea7a8d02 --- /dev/null +++ b/discounts/rust/network/default/src/generate_delivery_run.rs @@ -0,0 +1,51 @@ +use serde::Deserialize; +use shopify_function::prelude::*; +use shopify_function::Result; + +use cart_delivery_options_discounts_generate_run::output::{ + DeliveryDiscounts, DeliveryOperation, FunctionDeliveryRunResult, ValidDiscountCodes, +}; + +use cart_delivery_options_discounts_generate_run::input::ResponseData; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct DiscountResponse { + operations: Operations, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct Operations { + #[serde(default)] + add_delivery_discounts: Option, + #[serde(default)] + add_discount_code_validations: Option, +} + +#[shopify_function_target( + target = "cartDeliveryOptionsDiscountsGenerateRun", + query_path = "src/generate_delivery_run.graphql", + schema_path = "schema.graphql" +)] +fn generate_delivery_run(input: ResponseData) -> Result { + let fetch_result = input.fetch_result.ok_or("Missing fetch result")?; + let body = fetch_result.body.ok_or("Missing response body")?; + + // Parse the response body directly into our types + let response: DiscountResponse = + serde_json::from_str(&body).map_err(|e| format!("Failed to parse JSON: {}", e))?; + + // Convert the response into operations + let mut operations = Vec::new(); + + if let Some(validations) = response.operations.add_discount_code_validations { + operations.push(DeliveryOperation::AddDiscountCodeValidations(validations)); + } + + if let Some(delivery_discounts) = response.operations.add_delivery_discounts { + operations.push(DeliveryOperation::AddDeliveryDiscounts(delivery_discounts)); + } + + Ok(FunctionDeliveryRunResult { operations }) +} diff --git a/discounts/rust/network/default/src/main.rs b/discounts/rust/network/default/src/main.rs new file mode 100644 index 00000000..e3dc67e8 --- /dev/null +++ b/discounts/rust/network/default/src/main.rs @@ -0,0 +1,10 @@ +use std::process; +pub mod generate_cart_fetch; +pub mod generate_cart_run; +pub mod generate_delivery_fetch; +pub mod generate_delivery_run; + +fn main() { + eprintln!("Please invoke a named export."); + process::exit(1); +}