[Swift] Make protocol agnostic to usage#307
Conversation
| epCartReady.method, | ||
| epCartAuth.method, | ||
| epCartError.method, | ||
| epCartStart.method, | ||
| epCartComplete.method, | ||
| epCartLineItemsChange.method, | ||
| epCartBuyerChange.method, | ||
| epCartMessagesChange.method, |
There was a problem hiding this comment.
TBD on whether these events should be part of the generated API surface. They're part of the spec so arguably they should.
There was a problem hiding this comment.
I've dropped them. The EmbeddedCheckoutProtocol should only be concerned with ec events. We might consider adding an EmbeddedCartProtocol submodule later for ep events if needed
| import Foundation | ||
|
|
||
| public enum CheckoutProtocol { | ||
| public static let specVersion = "2026-04-08" | ||
|
|
||
| public static let defaultDelegations: [String] = ["window.open"] | ||
|
|
||
| package static let readyMethod = "ec.ready" | ||
| package static let parseErrorCode = -32700 | ||
| package static let parseErrorMessage = "Parse error" | ||
| package static let methodNotFoundCode = -32601 | ||
| package static let methodNotFoundMessage = "Method not found" | ||
|
|
||
| public static let complete = NotificationDescriptor<Checkout>(method: "ec.complete") | ||
| public static let error = NotificationDescriptor<ErrorResponse>(method: "ec.error") | ||
| public static let lineItemsChange = NotificationDescriptor<Checkout>( | ||
| method: "ec.line_items.change" | ||
| ) | ||
| public static let messagesChange = NotificationDescriptor<Checkout>( | ||
| method: "ec.messages.change" | ||
| ) | ||
| public static let start = NotificationDescriptor<Checkout>(method: "ec.start") | ||
| public static let totalsChange = NotificationDescriptor<Checkout>(method: "ec.totals.change") | ||
|
|
||
| package static let supportedProtocolMethods: Set<String> = [ | ||
| readyMethod, | ||
| start.method, | ||
| complete.method, | ||
| error.method, | ||
| lineItemsChange.method, | ||
| messagesChange.method, | ||
| totalsChange.method, | ||
| windowOpen.method | ||
| ] |
There was a problem hiding this comment.
This change lifts the curation out of the protocol into the kit - since that's where the abstraction should live
9b8bfaf to
a5da2b9
Compare
|
Marking as ready for review to run CI |
e27325e to
4aa6560
Compare
| public enum CheckoutProtocol { | ||
| public typealias Client = CheckoutTransport.Client | ||
|
|
||
| public static func url(for url: URL) -> URL { | ||
| CheckoutTransport.url(for: url, delegations: defaultDelegations) | ||
| } | ||
|
|
||
| static let defaultDelegations: [String] = ["window.open"] | ||
|
|
||
| static let methodNotFoundCode = -32601 | ||
| static let methodNotFoundMessage = "Method not found" | ||
|
|
||
| public static let complete = GeneratedProtocolCatalog.ecComplete | ||
| public static let error = GeneratedProtocolCatalog.ecError | ||
| public static let lineItemsChange = GeneratedProtocolCatalog.ecLineItemsChange | ||
| public static let messagesChange = GeneratedProtocolCatalog.ecMessagesChange | ||
| public static let start = GeneratedProtocolCatalog.ecStart | ||
| public static let totalsChange = GeneratedProtocolCatalog.ecTotalsChange | ||
|
|
||
| static let supportedProtocolMethods: Set<String> = [ | ||
| CheckoutTransport.readyMethod, | ||
| start.method, | ||
| complete.method, | ||
| error.method, | ||
| lineItemsChange.method, | ||
| messagesChange.method, | ||
| totalsChange.method, | ||
| windowOpen.method | ||
| ] |
There was a problem hiding this comment.
This is essentially a facade which curates the set of supported events and lives in the kit itself
Package Size
Measured from the PR base SHA and PR head SHA. This comment reports package artifact sizes only; it is not a final app binary-size report. |
| /// Returns the given checkout URL with the query parameters required to | ||
| /// initiate the Embedded Checkout Protocol handshake (`ec_version`, | ||
| /// `ec_delegate`). | ||
| public static func url( | ||
| for url: URL, | ||
| delegations: [String] = defaultDelegations | ||
| delegations: [String] = [] |
There was a problem hiding this comment.
CheckoutProtocol now uses this under the hood and supplies the defaults in the kit. This function is constrained to the package
2403a3c to
979df1e
Compare
979df1e to
c8cf90e
Compare
214a61f to
ff95bae
Compare
| public enum EmbeddedCheckoutProtocol { | ||
| public static let specVersion = "2026-04-08" | ||
|
|
||
| package static let readyMethod = "ec.ready" | ||
| package static let parseErrorCode = -32700 | ||
| package static let parseErrorMessage = "Parse error" | ||
|
|
||
| /// Returns the given checkout URL with the query parameters required to | ||
| /// initiate the Embedded Checkout Protocol handshake (`ec_version`, | ||
| /// `ec_delegate`). | ||
| public static func url( | ||
| for url: URL, | ||
| delegations: [String] = defaultDelegations | ||
| delegations: [String] = [] | ||
| ) -> URL { | ||
| guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { | ||
| return url | ||
| } | ||
| var queryItems = components.queryItems ?? [] | ||
| queryItems.removeAll { $0.name == "ec_version" || $0.name == "ec_delegate" } | ||
|
|
||
| queryItems.append(URLQueryItem(name: "ec_version", value: specVersion)) | ||
| if !delegations.isEmpty { | ||
| queryItems.append(URLQueryItem(name: "ec_delegate", value: delegations.joined(separator: ","))) | ||
| } | ||
|
|
There was a problem hiding this comment.
Heads up that I'm going to add support for ec_auth and ec_color_scheme here in a follow-up so that non-kit consumers can use the fully compliant protocol
The
protocol/package previously baked in opinions about which checkout events matter and how their payloads should be shaped, so every platform inherited the same curation and any tweak rippled through the shared layer. This splits the concerns:protocol/becomes purely agnostic — transport (EmbeddedCheckoutProtocol, renamed fromCheckoutProtocol), the full generated payload types, and a generated catalog of events, describing every OpenRPC method with no view on which surface — while each platform's CheckoutKit now owns curation and consumer-facing transformation. Swift's kit reclaims theCheckoutProtocolname as its curated namespace, exposing the sixec.*events pluswindow.openand rejecting everything else with a JSON-RPC method-not-found response.Look at
platforms/swift/Sources/ShopifyCheckoutKit/CheckoutProtocol.swiftfor the curation surface and run the Swift suite —CheckoutProtocolTestscovers supported/unsupported method handling andwindow.opendelegation.Before —
protocol/owns the curationAfter —
protocol/is agnostic, the kit curatesCall sites move from baked-in defaults to explicit curation