Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ query GetProducts($first: Int = 20, $country: CountryCode!, $language: LanguageC
handle
description
vendor
requiresSellingPlan
featuredImage {
url
}
Expand All @@ -20,6 +21,14 @@ query GetProducts($first: Int = 20, $country: CountryCode!, $language: LanguageC
id
title
availableForSale
sellingPlanAllocations(first: 10) {
nodes {
sellingPlan {
id
name
}
}
}
price {
amount
currencyCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,20 @@ class StorefrontInputFactory {
case invariant(String)
}

public func createCartInput(_ items: [String] = [], customerAccessToken: String? = nil) -> Storefront.CartInput {
func createCartLineInput(variantID: String, sellingPlanID: String? = nil) -> Storefront.CartLineInput {
Storefront.CartLineInput(
merchandiseId: variantID,
sellingPlanId: sellingPlanID.map(GraphQLNullable.some) ?? .none
)
}

public func createCartInput(
_ items: [String] = [],
sellingPlanID: String? = nil,
customerAccessToken: String? = nil
) -> Storefront.CartInput {
let lines: GraphQLNullable<[Storefront.CartLineInput]> = .some(
items.map { Storefront.CartLineInput(merchandiseId: $0) }
items.map { createCartLineInput(variantID: $0, sellingPlanID: sellingPlanID) }
)

switch appConfiguration.buyerIdentityMode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,20 @@ class CartManager: ObservableObject {

// MARK: Cart Actions

func performCartLinesAdd(variant: String) async throws -> Storefront.CartFragment {
func performCartLinesAdd(
variant: String,
sellingPlanID: String? = nil
) async throws -> Storefront.CartFragment {
guard let cartId = cart?.id else {
return try await performCartCreate(items: [variant])
return try await performCartCreate(items: [variant], sellingPlanID: sellingPlanID)
}

let lines = [Storefront.CartLineInput(merchandiseId: variant)]
let lines = [
StorefrontInputFactory.shared.createCartLineInput(
variantID: variant,
sellingPlanID: sellingPlanID
)
]
let network = Network.shared

let mutation = Storefront.CartLinesAddMutation(
Expand Down Expand Up @@ -120,12 +128,19 @@ class CartManager: ObservableObject {
}
}

private func performCartCreate(items: [String] = []) async throws -> Storefront.CartFragment {
private func performCartCreate(
items: [String] = [],
sellingPlanID: String? = nil
) async throws -> Storefront.CartFragment {
var customerAccessToken: String?
if CustomerAccountManager.shared.isAuthenticated {
customerAccessToken = try? await CustomerAccountManager.shared.getValidAccessToken()
}
let input = StorefrontInputFactory.shared.createCartInput(items, customerAccessToken: customerAccessToken)
let input = StorefrontInputFactory.shared.createCartInput(
items,
sellingPlanID: sellingPlanID,
customerAccessToken: customerAccessToken
)
let network = Network.shared

let mutation = Storefront.CartCreateMutation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extension Storefront {
static let operationName: String = "GetProducts"
static let operationDocument: ApolloAPI.OperationDocument = .init(
definition: .init(
#"query GetProducts($first: Int = 20, $country: CountryCode!, $language: LanguageCode!) @inContext(country: $country, language: $language) { products(first: $first) { __typename nodes { __typename id title handle description vendor featuredImage { __typename url } collections(first: 1) { __typename nodes { __typename id title } } variants(first: 1) { __typename nodes { __typename id title availableForSale price { __typename amount currencyCode } } } } } }"#
#"query GetProducts($first: Int = 20, $country: CountryCode!, $language: LanguageCode!) @inContext(country: $country, language: $language) { products(first: $first) { __typename nodes { __typename id title handle description vendor requiresSellingPlan featuredImage { __typename url } collections(first: 1) { __typename nodes { __typename id title } } variants(first: 1) { __typename nodes { __typename id title availableForSale sellingPlanAllocations(first: 10) { __typename nodes { __typename sellingPlan { __typename id name } } } price { __typename amount currencyCode } } } } } }"#
))

public var first: GraphQLNullable<Int32>
Expand Down Expand Up @@ -83,6 +83,7 @@ extension Storefront {
.field("handle", String.self),
.field("description", String.self),
.field("vendor", String.self),
.field("requiresSellingPlan", Bool.self),
.field("featuredImage", FeaturedImage?.self),
.field("collections", Collections.self, arguments: ["first": 1]),
.field("variants", Variants.self, arguments: ["first": 1]),
Expand All @@ -104,6 +105,8 @@ extension Storefront {
var description: String { __data["description"] }
/// The name of the product's vendor.
var vendor: String { __data["vendor"] }
/// Whether the product can only be purchased with a [selling plan](/docs/apps/build/purchase-options/subscriptions/selling-plans). Products that are sold on subscription (`requiresSellingPlan: true`) can be updated only for online stores. If you update a product to be subscription-only (`requiresSellingPlan:false`), then the product is unpublished from all channels, except the online store.
var requiresSellingPlan: Bool { __data["requiresSellingPlan"] }
/// The featured image for the product.
///
/// This field is functionally equivalent to `images(first: 1)`.
Expand Down Expand Up @@ -214,6 +217,7 @@ extension Storefront {
.field("id", Storefront.ID.self),
.field("title", String.self),
.field("availableForSale", Bool.self),
.field("sellingPlanAllocations", SellingPlanAllocations.self, arguments: ["first": 10]),
.field("price", Price.self),
] }
static var __fulfilledFragments: [any ApolloAPI.SelectionSet.Type] { [
Expand All @@ -226,9 +230,74 @@ extension Storefront {
var title: String { __data["title"] }
/// Indicates if the product variant is available for sale.
var availableForSale: Bool { __data["availableForSale"] }
/// Represents an association between a variant and a selling plan. Selling plan allocations describe which selling plans are available for each variant, and what their impact is on pricing.
var sellingPlanAllocations: SellingPlanAllocations { __data["sellingPlanAllocations"] }
/// The product variant’s price.
var price: Price { __data["price"] }

/// Products.Node.Variants.Node.SellingPlanAllocations
///
/// Parent Type: `SellingPlanAllocationConnection`
nonisolated struct SellingPlanAllocations: Storefront.SelectionSet {
let __data: DataDict
init(_dataDict: DataDict) { __data = _dataDict }

static var __parentType: any ApolloAPI.ParentType { Storefront.Objects.SellingPlanAllocationConnection }
static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("nodes", [Node].self),
] }
static var __fulfilledFragments: [any ApolloAPI.SelectionSet.Type] { [
GetProductsQuery.Data.Products.Node.Variants.Node.SellingPlanAllocations.self
] }

/// A list of the nodes contained in SellingPlanAllocationEdge.
var nodes: [Node] { __data["nodes"] }

/// Products.Node.Variants.Node.SellingPlanAllocations.Node
///
/// Parent Type: `SellingPlanAllocation`
nonisolated struct Node: Storefront.SelectionSet {
let __data: DataDict
init(_dataDict: DataDict) { __data = _dataDict }

static var __parentType: any ApolloAPI.ParentType { Storefront.Objects.SellingPlanAllocation }
static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("sellingPlan", SellingPlan.self),
] }
static var __fulfilledFragments: [any ApolloAPI.SelectionSet.Type] { [
GetProductsQuery.Data.Products.Node.Variants.Node.SellingPlanAllocations.Node.self
] }

/// 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'.
var sellingPlan: SellingPlan { __data["sellingPlan"] }

/// Products.Node.Variants.Node.SellingPlanAllocations.Node.SellingPlan
///
/// Parent Type: `SellingPlan`
nonisolated struct SellingPlan: Storefront.SelectionSet {
let __data: DataDict
init(_dataDict: DataDict) { __data = _dataDict }

static var __parentType: any ApolloAPI.ParentType { Storefront.Objects.SellingPlan }
static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("id", Storefront.ID.self),
.field("name", String.self),
] }
static var __fulfilledFragments: [any ApolloAPI.SelectionSet.Type] { [
GetProductsQuery.Data.Products.Node.Variants.Node.SellingPlanAllocations.Node.SellingPlan.self
] }

/// A globally-unique ID.
var id: Storefront.ID { __data["id"] }
/// The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'.
var name: String { __data["name"] }
}
}
}

/// Products.Node.Variants.Node.Price
///
/// Parent Type: `MoneyV2`
Expand Down Expand Up @@ -258,4 +327,4 @@ extension Storefront {
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @generated
// This file was automatically generated and should not be edited.

import ApolloAPI

extension Storefront.Objects {
/// Links a [`ProductVariant`](https://shopify.dev/docs/api/storefront/current/objects/ProductVariant) to a [`SellingPlan`](https://shopify.dev/docs/api/storefront/current/objects/SellingPlan), providing the pricing details for that specific combination. Each allocation includes the checkout charge amount, any remaining balance due for the purchase, and up to two price adjustments that show how the selling plan affects the variant's price.
///
/// Selling plan allocations are available on product variants and [cart lines](https://shopify.dev/docs/api/storefront/current/objects/CartLine), enabling storefronts to display information such as subscription or purchase option pricing before and during checkout.
static let SellingPlanAllocation = ApolloAPI.Object(
typename: "SellingPlanAllocation",
implementedInterfaces: [],
keyFields: nil
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @generated
// This file was automatically generated and should not be edited.

import ApolloAPI

extension Storefront.Objects {
/// An auto-generated type for paginating through multiple SellingPlanAllocations.
static let SellingPlanAllocationConnection = ApolloAPI.Object(
typename: "SellingPlanAllocationConnection",
implementedInterfaces: [],
keyFields: nil
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ extension Storefront {
"QueryRoot": Storefront.Objects.QueryRoot,
"SearchQuerySuggestion": Storefront.Objects.SearchQuerySuggestion,
"SellingPlan": Storefront.Objects.SellingPlan,
"SellingPlanAllocation": Storefront.Objects.SellingPlanAllocation,
"SellingPlanAllocationConnection": Storefront.Objects.SellingPlanAllocationConnection,
"Shop": Storefront.Objects.Shop,
"ShopPayInstallmentsFinancingPlan": Storefront.Objects.ShopPayInstallmentsFinancingPlan,
"ShopPayInstallmentsFinancingPlanTerm": Storefront.Objects.ShopPayInstallmentsFinancingPlanTerm,
Expand All @@ -102,4 +104,4 @@ extension Storefront {
nonisolated enum Interfaces {}
nonisolated enum Unions {}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
"OK" : {
"comment" : "Default action"
},
"One-time purchase" : {
"comment" : "A label for a purchase option that allows a user to purchase a product only once.",
"isCommentAutoGenerated" : true
},
"Populates the Cart Buyer Identity with values from Storefront.xcconfig" : {
"comment" : "A description of how the \"Hardcoded\" buyer identity mode populates the cart buyer identity.",
"isCommentAutoGenerated" : true
Expand All @@ -70,6 +74,10 @@
"comment" : "A description of the \"Prefills buyer identity at checkout\" setting in the Settings view.",
"isCommentAutoGenerated" : true
},
"Purchase option" : {
"comment" : "A label displayed above a picker for selecting a purchase option.",
"isCommentAutoGenerated" : true
},
"Sample app version" : {

},
Expand Down
Loading
Loading