@tinkerlandai/indiana-react-native 0.9.2 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/IndianaReactNative.podspec +19 -0
  2. package/README.md +61 -4
  3. package/THIRD_PARTY_NOTICES.md +74 -0
  4. package/android/build.gradle +24 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/java/ai/tinkerland/indiana/reactnative/IndianaBridgeModule.kt +237 -0
  7. package/android/src/main/java/ai/tinkerland/indiana/reactnative/IndianaBridgePackage.kt +11 -0
  8. package/dist/index.cjs +17 -1
  9. package/dist/index.d.cts +57408 -604
  10. package/dist/index.d.ts +57408 -604
  11. package/dist/index.js +17 -1
  12. package/ios/IndianaBridge.m +11 -0
  13. package/ios/IndianaBridge.swift +275 -0
  14. package/native-sdk/android/assets/indiana/index.html +268 -0
  15. package/native-sdk/android/java/ai/tinkerland/indiana/BillingAuthorizationTerms.kt +55 -0
  16. package/native-sdk/android/java/ai/tinkerland/indiana/BundledWebView.kt +90 -0
  17. package/native-sdk/android/java/ai/tinkerland/indiana/ContentSession.kt +45 -0
  18. package/native-sdk/android/java/ai/tinkerland/indiana/ContentView.kt +36 -0
  19. package/native-sdk/android/java/ai/tinkerland/indiana/CustomerOperations.generated.kt +84 -0
  20. package/native-sdk/android/java/ai/tinkerland/indiana/CustomerResponseSemantics.kt +193 -0
  21. package/native-sdk/android/java/ai/tinkerland/indiana/CustomerSemantics.kt +120 -0
  22. package/native-sdk/android/java/ai/tinkerland/indiana/CustomerSession.kt +106 -0
  23. package/native-sdk/android/java/ai/tinkerland/indiana/FeatureClient.kt +65 -0
  24. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelCommandStorage.kt +163 -0
  25. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelConfigurationRelay.kt +50 -0
  26. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelSession.kt +208 -0
  27. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelView.kt +71 -0
  28. package/native-sdk/android/java/ai/tinkerland/indiana/GeneratedProtocol.kt +16 -0
  29. package/native-sdk/android/java/ai/tinkerland/indiana/GoogleStorefront.kt +165 -0
  30. package/native-sdk/android/java/ai/tinkerland/indiana/HTTPTransport.kt +43 -0
  31. package/native-sdk/android/java/ai/tinkerland/indiana/IndianaClient.kt +526 -0
  32. package/native-sdk/android/java/ai/tinkerland/indiana/NativePendingKeystore.kt +81 -0
  33. package/native-sdk/android/java/ai/tinkerland/indiana/NativeReceiptRelay.kt +28 -0
  34. package/native-sdk/android/java/ai/tinkerland/indiana/NativeStoreOffer.kt +24 -0
  35. package/native-sdk/android/java/ai/tinkerland/indiana/PaywallContent.kt +75 -0
  36. package/native-sdk/android/java/ai/tinkerland/indiana/PaywallSession.kt +144 -0
  37. package/native-sdk/android/java/ai/tinkerland/indiana/PaywallView.kt +74 -0
  38. package/native-sdk/android/java/ai/tinkerland/indiana/Protocol.kt +28 -0
  39. package/native-sdk/android/java/ai/tinkerland/indiana/PushInstallation.kt +170 -0
  40. package/native-sdk/android/java/ai/tinkerland/indiana/RendererNavigation.kt +13 -0
  41. package/native-sdk/android/java/ai/tinkerland/indiana/SDKVersion.kt +6 -0
  42. package/native-sdk/android/java/ai/tinkerland/indiana/StoreSubscriptionManagement.kt +19 -0
  43. package/native-sdk/android/java/ai/tinkerland/indiana/WireSchema.kt +76 -0
  44. package/native-sdk/android/resources/funnel-wire-schemas.json +1 -0
  45. package/native-sdk/android/resources/indiana-third-party-notices.txt +101 -0
  46. package/native-sdk/android/resources/renderer-data-url.txt +1 -0
  47. package/native-sdk/ios/AnalyticsReceipt.swift +10 -0
  48. package/native-sdk/ios/AppleStorefront.swift +218 -0
  49. package/native-sdk/ios/BillingAuthorizationTerms.swift +57 -0
  50. package/native-sdk/ios/BundledWebView.swift +87 -0
  51. package/native-sdk/ios/ContentSession.swift +48 -0
  52. package/native-sdk/ios/ContentView.swift +51 -0
  53. package/native-sdk/ios/CustomerOperations.generated.swift +166 -0
  54. package/native-sdk/ios/CustomerResponseSemantics.swift +232 -0
  55. package/native-sdk/ios/CustomerSemantics.swift +145 -0
  56. package/native-sdk/ios/CustomerSession.swift +129 -0
  57. package/native-sdk/ios/FeatureClient.swift +86 -0
  58. package/native-sdk/ios/FunnelCommandStorage.swift +163 -0
  59. package/native-sdk/ios/FunnelConfigurationRelay.swift +48 -0
  60. package/native-sdk/ios/FunnelSession.swift +232 -0
  61. package/native-sdk/ios/FunnelView.swift +125 -0
  62. package/native-sdk/ios/GeneratedProtocol.swift +16 -0
  63. package/native-sdk/ios/HTTPTransport.swift +74 -0
  64. package/native-sdk/ios/IndianaClient.swift +601 -0
  65. package/native-sdk/ios/NativePendingKeychain.swift +52 -0
  66. package/native-sdk/ios/NativeReceiptRelay.swift +28 -0
  67. package/native-sdk/ios/NativeStoreOffer.swift +34 -0
  68. package/native-sdk/ios/PaywallContent.swift +75 -0
  69. package/native-sdk/ios/PaywallSession.swift +124 -0
  70. package/native-sdk/ios/PaywallView.swift +87 -0
  71. package/native-sdk/ios/Protocol.swift +49 -0
  72. package/native-sdk/ios/PushInstallation.swift +154 -0
  73. package/native-sdk/ios/RendererNavigation.swift +8 -0
  74. package/native-sdk/ios/Resources.swift +15 -0
  75. package/native-sdk/ios/SDKVersion.swift +4 -0
  76. package/native-sdk/ios/StoreSubscriptionManagement.swift +11 -0
  77. package/native-sdk/ios/WebView/THIRD_PARTY_NOTICES.txt +101 -0
  78. package/native-sdk/ios/WebView/index.html +268 -0
  79. package/native-sdk/ios/WebView/renderer-data-url.txt +1 -0
  80. package/native-sdk/ios/WireSchema.swift +107 -0
  81. package/native-sdk/ios/funnel-wire-schemas.json +1 -0
  82. package/package.json +8 -3
  83. package/react-native.config.cjs +12 -0
@@ -0,0 +1,57 @@
1
+ import Foundation
2
+
3
+ /// Current immutable Stripe authorization terms. They contain no payment credential.
4
+ internal enum IndianaBillingAuthorizationTerms {
5
+ static func validate(_ terms: [String: IndianaJSON]) throws {
6
+ func text(_ object: [String: IndianaJSON], _ key: String) throws -> String {
7
+ guard let value = object[key]?.string else { throw IndianaFunnelError.invalidResponse }; return value
8
+ }
9
+ func quantity(_ value: IndianaJSON?, positive: Bool = false) throws -> Decimal {
10
+ guard let raw = value?.string, raw.range(of: "^(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$", options: .regularExpression) != nil,
11
+ let amount = Decimal(string: raw, locale: Locale(identifier: "en_US_POSIX")), !positive || amount > 0 else { throw IndianaFunnelError.invalidResponse }; return amount
12
+ }
13
+ func amount(_ key: String) throws {
14
+ let raw = try text(terms, key)
15
+ guard raw.range(of: "^[1-9][0-9]{0,14}$", options: .regularExpression) != nil else { throw IndianaFunnelError.invalidResponse }
16
+ }
17
+ let kind = try text(terms, "kind"), currency = try text(terms, "currency")
18
+ guard ["auto_topup", "postpaid"].contains(kind), currency.range(of: "^[A-Z]{3}$", options: .regularExpression) != nil else { throw IndianaFunnelError.invalidResponse }
19
+ for key in ["productVersionId", "internal_feature_id"] { guard UUID(uuidString: try text(terms, key)) != nil else { throw IndianaFunnelError.invalidResponse } }
20
+ let base: Set<String> = ["kind", "productVersionId", "internal_feature_id", "currency"]
21
+ if kind == "auto_topup" {
22
+ guard Set(terms.keys) == base.union(["threshold", "quantity", "purchaseAmountMinor", "purchaseUnits"]).union(terms["purchaseLimit"] == nil ? [] : ["purchaseLimit"]),
23
+ let threshold=terms["threshold"]?.string,threshold.range(of:"^-?(0|[1-9][0-9]{0,11})(\\.[0-9]{1,6})?$",options:.regularExpression) != nil else {throw IndianaFunnelError.invalidResponse}
24
+ if let value=terms["purchaseLimit"] {
25
+ guard let limit=value.object,Set(limit.keys)==Set(["interval","intervalCount","limit"]),["hour","day","week","month"].contains(try text(limit,"interval")),
26
+ case .number(let count)?=limit["intervalCount"],count>=1,count<=12,count.rounded()==count,
27
+ case .number(let cap)?=limit["limit"],cap>=1,cap<=1000000,cap.rounded()==cap else {throw IndianaFunnelError.invalidResponse}
28
+ }
29
+ guard try quantity(terms["quantity"],positive:true)>=1 else {throw IndianaFunnelError.invalidResponse}
30
+ _=try quantity(terms["purchaseUnits"],positive:true);try amount("purchaseAmountMinor");return
31
+ }
32
+ try amount("maxAmountMinorPerPeriod")
33
+ guard Set(terms.keys) == base.union(["maxAmountMinorPerPeriod","maxOutstandingMinor", "cashPrice"]),
34
+ let price = terms["cashPrice"]?.object, Set(price.keys) == Set(["currency", "pricing"]).union(price["billingCycle"] == nil ? [] : ["billingCycle"]), try text(price, "currency") == currency,
35
+ let pricing = price["pricing"]?.object else { throw IndianaFunnelError.invalidResponse }
36
+ if let value = price["billingCycle"] {
37
+ guard let cycle=value.object, Set(cycle.keys) == Set(["interval","count","anchor"]),
38
+ ["month","year"].contains(try text(cycle,"interval")), ["membership","calendar"].contains(try text(cycle,"anchor")),
39
+ case .number(let count)?=cycle["count"], count >= 1, count <= 12, count.rounded() == count else { throw IndianaFunnelError.invalidResponse }
40
+ }
41
+ try amount("maxOutstandingMinor"); _ = try quantity(pricing["units"], positive: true)
42
+ let pricingKind = try text(pricing, "kind")
43
+ if pricingKind == "flat" {
44
+ guard Set(pricing.keys) == Set(["kind", "units", "unitAmountMinor"]) else { throw IndianaFunnelError.invalidResponse }
45
+ _ = try quantity(pricing["unitAmountMinor"]); return
46
+ }
47
+ guard ["graduated", "volume"].contains(pricingKind), Set(pricing.keys) == Set(["kind", "units", "tiers"]),
48
+ case .array(let tiers)? = pricing["tiers"], (1...12).contains(tiers.count) else { throw IndianaFunnelError.invalidResponse }
49
+ var previous: Decimal = 0
50
+ for (index, row) in tiers.enumerated() {
51
+ guard let tier = row.object, Set(tier.keys) == Set(["upTo", "unitAmountMinor"]) else { throw IndianaFunnelError.invalidResponse }
52
+ _ = try quantity(tier["unitAmountMinor"])
53
+ if index == tiers.count - 1 { guard tier["upTo"] == .null else { throw IndianaFunnelError.invalidResponse } }
54
+ else { let ceiling = try quantity(tier["upTo"], positive: true); guard ceiling > previous else { throw IndianaFunnelError.invalidResponse }; previous = ceiling }
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,87 @@
1
+ import Foundation
2
+
3
+ enum IndianaBundledWebViewResources {
4
+ static let origin = URL(string: "https://indiana-sdk.invalid/")!
5
+ static func rendererURL() throws -> String {
6
+ guard let file = IndianaResources.bundle.url(forResource: "renderer-data-url", withExtension: "txt", subdirectory: "WebView") else { throw IndianaClientError.invalidResponse }
7
+ return try String(contentsOf: file, encoding: .utf8)
8
+ }
9
+ static func html() throws -> String {
10
+ guard let file = IndianaResources.bundle.url(forResource: "index", withExtension: "html", subdirectory: "WebView") else { throw IndianaClientError.invalidResponse }
11
+ return try String(contentsOf: file, encoding: .utf8)
12
+ }
13
+ }
14
+
15
+ #if canImport(UIKit)
16
+ import UIKit
17
+ @preconcurrency import WebKit
18
+
19
+ /// Shared local renderer transport for Funnel and independent Paywall. No network code loading.
20
+ @MainActor final class IndianaBundledWebView: NSObject, @preconcurrency WKNavigationDelegate, @preconcurrency WKScriptMessageHandler {
21
+ let webView: WKWebView
22
+ private let dispatch: @MainActor (String, IndianaJSON) async throws -> IndianaJSON
23
+ private let onError: @MainActor (Error) -> Void
24
+ private var requests = Set<UUID>()
25
+ private var stopped = false
26
+ init(label: String, dispatch: @escaping @MainActor (String, IndianaJSON) async throws -> IndianaJSON, onError: @escaping @MainActor (Error) -> Void) {
27
+ self.dispatch = dispatch; self.onError = onError
28
+ let config = WKWebViewConfiguration()
29
+ config.websiteDataStore = .nonPersistent()
30
+ config.defaultWebpagePreferences.allowsContentJavaScript = true
31
+ webView = WKWebView(frame: .zero, configuration: config)
32
+ super.init()
33
+ config.userContentController.add(WeakBundledHandler(self), name: "indianaFunnel")
34
+ webView.navigationDelegate = self; webView.isOpaque = false; webView.backgroundColor = .clear
35
+ webView.scrollView.backgroundColor = .clear; webView.accessibilityLabel = label
36
+ }
37
+ func start() {
38
+ guard !stopped else { return }
39
+ do { webView.loadHTMLString(try IndianaBundledWebViewResources.html(), baseURL: IndianaBundledWebViewResources.origin) }
40
+ catch { onError(error) }
41
+ }
42
+ func send(_ value: IndianaJSON) {
43
+ guard !stopped, let data=try? JSONEncoder().encode(value), let text=String(data:data,encoding:.utf8) else { return }
44
+ webView.evaluateJavaScript("window.__indianaFunnelReceive(\(text))", completionHandler: nil)
45
+ }
46
+ func event(_ name: String) { send(.object(["event":.string(name)])) }
47
+ func destroy() {
48
+ guard !stopped else { return }; event("invalidated"); stopped = true; requests.removeAll()
49
+ webView.stopLoading(); webView.configuration.userContentController.removeScriptMessageHandler(forName:"indianaFunnel")
50
+ webView.isHidden = true; webView.loadHTMLString("", baseURL:nil)
51
+ }
52
+ func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
53
+ guard !stopped, message.webView === webView, message.frameInfo.isMainFrame,
54
+ message.frameInfo.securityOrigin.protocol == "https", message.frameInfo.securityOrigin.host == "indiana-sdk.invalid",
55
+ [0,443].contains(message.frameInfo.securityOrigin.port),
56
+ let data=try? JSONSerialization.data(withJSONObject:message.body), data.count <= 262144,
57
+ let value=try? JSONDecoder().decode(IndianaJSON.self,from:data).object,
58
+ Set(value.keys) == Set(["id","method","payload"]), let id=value["id"]?.string.flatMap(UUID.init(uuidString:)),
59
+ let method=value["method"]?.string, requests.count < 8, requests.insert(id).inserted else { return }
60
+ Task {
61
+ defer { requests.remove(id) }
62
+ do {
63
+ let result=try await dispatch(method,value["payload"] ?? .object([:]))
64
+ guard !stopped else { return }; send(.object(["id":.string(id.uuidString.lowercased()),"result":result]))
65
+ } catch {
66
+ guard !stopped else { return }
67
+ var detail:[String:IndianaJSON] = ["code":.string("NATIVE_OPERATION_FAILED")]
68
+ if let e=error as? IndianaClientError, case .requestFailed(let status)=e { detail["status"] = .number(Double(status)) }
69
+ if let e=error as? IndianaFunnelError, case .commandPending=e { detail["code"] = .string("COMMAND_PENDING") }
70
+ send(.object(["id":.string(id.uuidString.lowercased()),"error":.object(detail)])); onError(error)
71
+ }
72
+ }
73
+ }
74
+ func webView(_ webView: WKWebView, decidePolicyFor action: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
75
+ guard !stopped, let url=action.request.url else { decisionHandler(.cancel); return }
76
+ if action.targetFrame?.isMainFrame == true {
77
+ decisionHandler(url == IndianaBundledWebViewResources.origin || url.absoluteString == "about:blank" ? .allow : .cancel)
78
+ } else { decisionHandler(indianaAllowsFunnelRendererNavigation(url,baseURL:IndianaBundledWebViewResources.origin) ? .allow : .cancel) }
79
+ }
80
+ func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { if !stopped { onError(error) } }
81
+ }
82
+ @MainActor private final class WeakBundledHandler: NSObject, @preconcurrency WKScriptMessageHandler {
83
+ weak var owner: IndianaBundledWebView?
84
+ init(_ owner:IndianaBundledWebView) { self.owner=owner }
85
+ func userContentController(_ controller:WKUserContentController,didReceive message:WKScriptMessage) { owner?.userContentController(controller,didReceive:message) }
86
+ }
87
+ #endif
@@ -0,0 +1,48 @@
1
+ import Foundation
2
+
3
+ /// An independent, version-pinned Page, Popup or Banner; it creates no Funnel Run.
4
+ public actor IndianaContentSession {
5
+ private let configuration: IndianaConfiguration
6
+ private let send: @Sendable ([String: IndianaJSON]) async throws -> IndianaJSON
7
+ private var input: [String: IndianaJSON]
8
+ private let locale: String
9
+ private let inputs: [String: IndianaJSON]
10
+ public private(set) var current: IndianaJSON?
11
+ private var stopped = false
12
+ private var invalidation: (@Sendable () -> Void)?
13
+ init(configuration: IndianaConfiguration, input: [String: IndianaJSON], locale: String, inputs: [String: IndianaJSON], send: @escaping @Sendable ([String: IndianaJSON]) async throws -> IndianaJSON) throws {
14
+ guard !locale.isEmpty, locale.count <= 35, inputs.count <= 40 else { throw IndianaClientError.invalidConfiguration }
15
+ self.configuration = configuration; self.input = input; self.locale = locale; self.inputs = inputs; self.send = send
16
+ }
17
+ public func close() { guard !stopped else { return }; stopped = true; current = nil; invalidation?(); invalidation = nil }
18
+ public func refresh() async throws -> IndianaJSON {
19
+ guard !stopped else { throw IndianaClientError.identityChanged }
20
+ let result = try await send(input)
21
+ guard !stopped, let content = result.object?["content"]?.object, let id = content["id"]?.string,
22
+ content["kind"] == input["kind"], content["projectId"]?.string == configuration.scope.projectId.uuidString.lowercased() else { throw IndianaClientError.invalidResponse }
23
+ if let current, current.object?["id"]?.string != id { throw IndianaClientError.invalidResponse }
24
+ input["selector"] = .object(["type": .string("version"), "id": .string(id)])
25
+ current = .object(content); return .object(content)
26
+ }
27
+ func onInvalidation(_ callback: @escaping @Sendable () -> Void) { invalidation = callback; if stopped { callback() } }
28
+ func hostInit() -> IndianaJSON { .object(["event": .string("init"), "surface": .string("content"), "scope": .object(["projectId": .string(configuration.scope.projectId.uuidString.lowercased()), "environment": .string(configuration.scope.environment.rawValue)]), "apiOrigin": .string(configuration.apiOrigin)]) }
29
+ func hostContent() async throws -> IndianaJSON {
30
+ guard !stopped else { throw IndianaClientError.identityChanged }
31
+ let content: IndianaJSON
32
+ if let current { content = current } else { content = try await refresh() }
33
+ return .object(["content": content, "locale": .string(locale), "inputs": .object(inputs)])
34
+ }
35
+ func trustedAction(_ intent: IndianaJSON) throws -> IndianaJSON {
36
+ guard !stopped, let value = intent.object, Set(value.keys) == Set(["requestId", "contentVersionId", "actionId", "event", "value", "answers", "selection", "requestedClose"]),
37
+ let request = value["requestId"]?.string, UUID(uuidString: request) != nil,
38
+ let current = current?.object, value["contentVersionId"] == current["id"],
39
+ let actionID = value["actionId"]?.string, let document = current["document"]?.object,
40
+ document["contract"]?.object?["outputs"]?.object?[actionID] != nil,
41
+ case .array(let actions)? = document["screen"]?.object?["actions"],
42
+ let action = actions.compactMap(\.object).first(where: { $0["id"]?.string == actionID }),
43
+ action["type"]?.string == "event", action["event"] == value["event"], action["close"] == value["requestedClose"],
44
+ let properties = action["properties"]?.object, value["value"] == (properties["value"] ?? .object(properties)),
45
+ value["answers"]?.object != nil, value["selection"]?.object != nil else { throw IndianaFunnelError.invalidCommand }
46
+ return intent
47
+ }
48
+ }
@@ -0,0 +1,51 @@
1
+ #if canImport(UIKit)
2
+ import UIKit
3
+ import SwiftUI
4
+
5
+ /// Independent content presented through the same isolated packaged renderer as Funnel.
6
+ @MainActor public final class IndianaContentViewController: UIViewController {
7
+ public let session: IndianaContentSession
8
+ public var onAction: (@MainActor (IndianaJSON) async throws -> Void)?
9
+ public var onDismiss: (@MainActor () -> Void)?
10
+ public var onError: (@MainActor (Error) -> Void)?
11
+ private var host: IndianaBundledWebView!
12
+ private var stopped = false
13
+ public init(session: IndianaContentSession) { self.session = session; super.init(nibName: nil, bundle: nil) }
14
+ required init?(coder: NSCoder) { fatalError("Use init(session:)") }
15
+ public override func viewDidLoad() {
16
+ super.viewDidLoad()
17
+ host = IndianaBundledWebView(label: "Indiana content", dispatch: { [weak self] method, payload in
18
+ guard let self else { throw IndianaClientError.identityChanged }; return try await self.dispatch(method, payload)
19
+ }, onError: { [weak self] error in self?.onError?(error) })
20
+ host.webView.frame = view.bounds; host.webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]; view.addSubview(host.webView)
21
+ Task { [weak self, session] in await session.onInvalidation { [weak self] in Task { @MainActor in self?.invalidate() } } }
22
+ host.start()
23
+ }
24
+ public func close() async { await session.close(); invalidate() }
25
+ private func invalidate() { guard !stopped else { return }; stopped = true; host?.destroy(); onDismiss?() }
26
+ private func dispatch(_ method: String, _ payload: IndianaJSON) async throws -> IndianaJSON {
27
+ switch method {
28
+ case "ready": host.send(await session.hostInit()); return .null
29
+ case "content": return try await session.hostContent()
30
+ case "contentAction":
31
+ let trusted = try await session.trustedAction(payload)
32
+ guard let onAction else { throw IndianaClientError.unsupportedCapability }
33
+ try await onAction(trusted); return .null
34
+ case "dismiss": await close(); return .null
35
+ case "error": onError?(IndianaClientError.invalidResponse); return .null
36
+ default: throw IndianaFunnelError.invalidCommand
37
+ }
38
+ }
39
+ }
40
+
41
+ @MainActor public struct IndianaContentView: UIViewControllerRepresentable {
42
+ public let session: IndianaContentSession
43
+ public var onAction: (@MainActor (IndianaJSON) async throws -> Void)?
44
+ public var onDismiss: (@MainActor () -> Void)?
45
+ public var onError: (@MainActor (Error) -> Void)?
46
+ public init(session: IndianaContentSession, onAction: (@MainActor (IndianaJSON) async throws -> Void)? = nil, onDismiss: (@MainActor () -> Void)? = nil, onError: (@MainActor (Error) -> Void)? = nil) { self.session = session; self.onAction = onAction; self.onDismiss = onDismiss; self.onError = onError }
47
+ public func makeUIViewController(context: Context) -> IndianaContentViewController { let view = IndianaContentViewController(session: session); updateUIViewController(view, context: context); return view }
48
+ public func updateUIViewController(_ view: IndianaContentViewController, context: Context) { view.onAction = onAction; view.onDismiss = onDismiss; view.onError = onError }
49
+ public static func dismantleUIViewController(_ view: IndianaContentViewController, coordinator: ()) { Task { await view.close() } }
50
+ }
51
+ #endif
@@ -0,0 +1,166 @@
1
+ // Generated by scripts/sdk/generate-native-protocol.mjs. Do not edit.
2
+ import Foundation
3
+ public enum IndianaCustomerOperation: String, CaseIterable, Sendable {
4
+ case bindPushInstallation
5
+ case readPushInstallation
6
+ case updatePushAddress
7
+ case readMessagingPreference
8
+ case setMessagingPreference
9
+ case getFeatures
10
+ case evaluateFeatures
11
+ case trackEvents
12
+ case restoreNativePurchase
13
+ case setupPayment
14
+ case readPaymentSetup
15
+ case previewAttach
16
+ case attach
17
+ case readSubscriptionOperation
18
+ case previewUpdate
19
+ case update
20
+ case readSubscriptionUpdate
21
+ case readBillingControls
22
+ case prepareBillingAuthorization
23
+ case confirmBillingAuthorization
24
+ case setBillingCoupons
25
+ case revokeBillingAuthorization
26
+ case listBillingInvoices
27
+ case confirmBillingAdjustment
28
+ case checkEntitlement
29
+ case resolveContent
30
+ case resolvePaywall
31
+ case resolveOffering
32
+ case readHoldings
33
+ case readLedger
34
+ case readBillingInvoice
35
+ case readCreditStatement
36
+ case quoteBalance
37
+ case redeemReward
38
+ case createReferralCode
39
+ case claimRewardProduct
40
+ case redeemCoupon
41
+ case listOffers
42
+ case grantOffer
43
+ var path: String { switch self {
44
+ case .bindPushInstallation: return "push/installations/bind"
45
+ case .readPushInstallation: return "push/installations/read"
46
+ case .updatePushAddress: return "push/installations/address"
47
+ case .readMessagingPreference: return "messaging/preferences/read"
48
+ case .setMessagingPreference: return "messaging/preferences/set"
49
+ case .getFeatures: return "features"
50
+ case .evaluateFeatures: return "features/evaluate"
51
+ case .trackEvents: return "events"
52
+ case .restoreNativePurchase: return "subscriptions/native/restore"
53
+ case .setupPayment: return "billing/setup-payment"
54
+ case .readPaymentSetup: return "billing/payment-setup"
55
+ case .previewAttach: return "subscriptions/preview-attach"
56
+ case .attach: return "subscriptions/attach"
57
+ case .readSubscriptionOperation: return "subscriptions/operations/read"
58
+ case .previewUpdate: return "subscriptions/preview-update"
59
+ case .update: return "subscriptions/update"
60
+ case .readSubscriptionUpdate: return "subscriptions/updates/read"
61
+ case .readBillingControls: return "billing/controls/read"
62
+ case .prepareBillingAuthorization: return "billing/authorizations/prepare"
63
+ case .confirmBillingAuthorization: return "billing/authorizations/confirm"
64
+ case .setBillingCoupons: return "billing/coupons"
65
+ case .revokeBillingAuthorization: return "billing/authorizations/revoke"
66
+ case .listBillingInvoices: return "billing/invoices/read"
67
+ case .confirmBillingAdjustment: return "billing/invoices/confirm-adjustment"
68
+ case .checkEntitlement: return "entitlements/check"
69
+ case .resolveContent: return "content/resolve"
70
+ case .resolvePaywall: return "paywalls/resolve"
71
+ case .resolveOffering: return "offerings/resolve"
72
+ case .readHoldings: return "customer-holdings"
73
+ case .readLedger: return "customer-ledger"
74
+ case .readBillingInvoice: return "billing/invoices/detail"
75
+ case .readCreditStatement: return "credit-statements/read"
76
+ case .quoteBalance: return "balances/quote"
77
+ case .redeemReward: return "rewards/redeem"
78
+ case .createReferralCode: return "rewards/referral-code"
79
+ case .claimRewardProduct: return "rewards/product/claim"
80
+ case .redeemCoupon: return "offers/redeem"
81
+ case .listOffers: return "offers"
82
+ case .grantOffer: return "offers/grant"
83
+ } }
84
+ var method: String { switch self {
85
+ case .bindPushInstallation: return "POST"
86
+ case .readPushInstallation: return "POST"
87
+ case .updatePushAddress: return "POST"
88
+ case .readMessagingPreference: return "POST"
89
+ case .setMessagingPreference: return "POST"
90
+ case .getFeatures: return "GET"
91
+ case .evaluateFeatures: return "POST"
92
+ case .trackEvents: return "POST"
93
+ case .restoreNativePurchase: return "POST"
94
+ case .setupPayment: return "POST"
95
+ case .readPaymentSetup: return "POST"
96
+ case .previewAttach: return "POST"
97
+ case .attach: return "POST"
98
+ case .readSubscriptionOperation: return "POST"
99
+ case .previewUpdate: return "POST"
100
+ case .update: return "POST"
101
+ case .readSubscriptionUpdate: return "POST"
102
+ case .readBillingControls: return "POST"
103
+ case .prepareBillingAuthorization: return "POST"
104
+ case .confirmBillingAuthorization: return "POST"
105
+ case .setBillingCoupons: return "POST"
106
+ case .revokeBillingAuthorization: return "POST"
107
+ case .listBillingInvoices: return "POST"
108
+ case .confirmBillingAdjustment: return "POST"
109
+ case .checkEntitlement: return "POST"
110
+ case .resolveContent: return "POST"
111
+ case .resolvePaywall: return "POST"
112
+ case .resolveOffering: return "POST"
113
+ case .readHoldings: return "POST"
114
+ case .readLedger: return "POST"
115
+ case .readBillingInvoice: return "POST"
116
+ case .readCreditStatement: return "POST"
117
+ case .quoteBalance: return "POST"
118
+ case .redeemReward: return "POST"
119
+ case .createReferralCode: return "POST"
120
+ case .claimRewardProduct: return "POST"
121
+ case .redeemCoupon: return "POST"
122
+ case .listOffers: return "GET"
123
+ case .grantOffer: return "POST"
124
+ } }
125
+ }
126
+ extension IndianaClient {
127
+ public func bindPushInstallation(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.bindPushInstallation, input: input) }
128
+ public func readPushInstallation(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readPushInstallation, input: input) }
129
+ public func updatePushAddress(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.updatePushAddress, input: input) }
130
+ public func readMessagingPreference(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readMessagingPreference, input: input) }
131
+ public func setMessagingPreference(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.setMessagingPreference, input: input) }
132
+ public func getFeatures(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.getFeatures, input: input) }
133
+ public func evaluateFeatures(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.evaluateFeatures, input: input) }
134
+ public func trackEvents(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.trackEvents, input: input) }
135
+ public func restoreNativePurchase(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.restoreNativePurchase, input: input) }
136
+ public func setupPayment(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.setupPayment, input: input) }
137
+ public func readPaymentSetup(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readPaymentSetup, input: input) }
138
+ public func previewAttach(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.previewAttach, input: input) }
139
+ public func attach(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.attach, input: input) }
140
+ public func readSubscriptionOperation(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readSubscriptionOperation, input: input) }
141
+ public func previewUpdate(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.previewUpdate, input: input) }
142
+ public func update(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.update, input: input) }
143
+ public func readSubscriptionUpdate(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readSubscriptionUpdate, input: input) }
144
+ public func readBillingControls(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readBillingControls, input: input) }
145
+ public func prepareBillingAuthorization(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.prepareBillingAuthorization, input: input) }
146
+ public func confirmBillingAuthorization(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.confirmBillingAuthorization, input: input) }
147
+ public func setBillingCoupons(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.setBillingCoupons, input: input) }
148
+ public func revokeBillingAuthorization(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.revokeBillingAuthorization, input: input) }
149
+ public func listBillingInvoices(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.listBillingInvoices, input: input) }
150
+ public func confirmBillingAdjustment(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.confirmBillingAdjustment, input: input) }
151
+ public func checkEntitlement(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.checkEntitlement, input: input) }
152
+ public func resolveContent(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.resolveContent, input: input) }
153
+ public func resolvePaywall(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.resolvePaywall, input: input) }
154
+ public func resolveOffering(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.resolveOffering, input: input) }
155
+ public func readHoldings(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readHoldings, input: input) }
156
+ public func readLedger(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readLedger, input: input) }
157
+ public func readBillingInvoice(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readBillingInvoice, input: input) }
158
+ public func readCreditStatement(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.readCreditStatement, input: input) }
159
+ public func quoteBalance(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.quoteBalance, input: input) }
160
+ public func redeemReward(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.redeemReward, input: input) }
161
+ public func createReferralCode(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.createReferralCode, input: input) }
162
+ public func claimRewardProduct(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.claimRewardProduct, input: input) }
163
+ public func redeemCoupon(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.redeemCoupon, input: input) }
164
+ public func listOffers(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.listOffers, input: input) }
165
+ public func grantOffer(_ input: [String: IndianaJSON]) async throws -> IndianaJSON { try await customerOperation(.grantOffer, input: input) }
166
+ }