@tinkerlandai/longplay-react-native 0.10.8 → 0.10.13

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 (35) hide show
  1. package/dist/index.cjs +2 -2
  2. package/dist/index.d.cts +26549 -12669
  3. package/dist/index.d.ts +26549 -12669
  4. package/dist/index.js +2 -2
  5. package/native-sdk/android/assets/indiana/index.html +42 -42
  6. package/native-sdk/android/java/ai/tinkerland/indiana/BundledWebView.kt +6 -2
  7. package/native-sdk/android/java/ai/tinkerland/indiana/CustomerSession.kt +9 -3
  8. package/native-sdk/android/java/ai/tinkerland/indiana/FeatureClient.kt +46 -22
  9. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelConfigurationRelay.kt +47 -21
  10. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelProcess.kt +120 -0
  11. package/native-sdk/android/java/ai/tinkerland/indiana/FunnelSession.kt +57 -16
  12. package/native-sdk/android/java/ai/tinkerland/indiana/GoogleStorefront.kt +18 -2
  13. package/native-sdk/android/java/ai/tinkerland/indiana/HTTPTransport.kt +48 -20
  14. package/native-sdk/android/java/ai/tinkerland/indiana/IndianaClient.kt +36 -44
  15. package/native-sdk/android/java/ai/tinkerland/indiana/PaywallSession.kt +82 -59
  16. package/native-sdk/android/java/ai/tinkerland/indiana/SDKVersion.kt +1 -1
  17. package/native-sdk/android/java/ai/tinkerland/indiana/WireSchema.kt +3 -1
  18. package/native-sdk/android/java/ai/tinkerland/longplay/Longplay.kt +3 -0
  19. package/native-sdk/android/resources/funnel-wire-schemas.json +1 -1
  20. package/native-sdk/ios/BundledWebView.swift +5 -1
  21. package/native-sdk/ios/CustomerSession.swift +7 -3
  22. package/native-sdk/ios/FeatureClient.swift +75 -29
  23. package/native-sdk/ios/FunnelConfigurationRelay.swift +1 -0
  24. package/native-sdk/ios/FunnelProcess.swift +148 -0
  25. package/native-sdk/ios/FunnelSession.swift +37 -9
  26. package/native-sdk/ios/HTTPTransport.swift +2 -0
  27. package/native-sdk/ios/IndianaClient.swift +25 -60
  28. package/native-sdk/ios/NativeReceiptRelay.swift +3 -3
  29. package/native-sdk/ios/PaywallSession.swift +5 -4
  30. package/native-sdk/ios/SDKVersion.swift +1 -1
  31. package/native-sdk/ios/WebView/index.html +42 -42
  32. package/native-sdk/ios/funnel-wire-schemas.json +1 -1
  33. package/package.json +1 -1
  34. package/native-sdk/android/java/ai/tinkerland/indiana/NativePendingKeystore.kt +0 -81
  35. package/native-sdk/ios/NativePendingKeychain.swift +0 -52
@@ -1,22 +1,22 @@
1
1
  import Foundation
2
2
 
3
- struct IndianaNativeCompletion: Codable, Sendable { let orderId: UUID; let receiptId: UUID; let membership: Bool; let transactionIds: [String] }
4
-
5
3
  /// HTTPS endpoint on your own backend. It authenticates the customer and attaches the Indiana server key there.
6
4
  public final class IndianaNativeReceiptRelay: Sendable {
7
5
  private let endpoint: URL; private let session: URLSession
8
6
  public init(endpoint: URL) throws {
9
7
  guard endpoint.scheme == "https", endpoint.host != nil, endpoint.user == nil, endpoint.password == nil, endpoint.query == nil, endpoint.fragment == nil else { throw IndianaClientError.invalidConfiguration }
10
8
  self.endpoint = endpoint
11
- let config = URLSessionConfiguration.ephemeral; config.urlCache = nil; config.httpCookieStorage = nil; config.requestCachePolicy = .reloadIgnoringLocalCacheData; config.timeoutIntervalForRequest = 35
9
+ let config = URLSessionConfiguration.ephemeral; config.urlCache = nil; config.httpCookieStorage = nil; config.requestCachePolicy = .reloadIgnoringLocalCacheData; config.timeoutIntervalForRequest = 35; config.timeoutIntervalForResource = 35
12
10
  session = URLSession(configuration: config, delegate: NoRedirect(), delegateQueue: nil)
13
11
  }
12
+ deinit { session.invalidateAndCancel() }
14
13
  public func send(_ body: Data) async throws -> Data {
15
14
  guard body.count <= 262144, let input = try? JSONDecoder().decode(IndianaJSON.self, from: body).object, input["operation"] == .string("native_receipt"), let token = input["customerToken"]?.string, token.range(of: "^gg_ct_[A-Za-z0-9_-]{32,128}$", options: .regularExpression) != nil else { throw IndianaClientError.invalidConfiguration }
16
15
  var request = URLRequest(url: endpoint); request.httpMethod = "POST"; request.httpBody = body
17
16
  request.setValue("application/json", forHTTPHeaderField: "Content-Type"); request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
18
17
  do {
19
18
  let (stream, response) = try await session.bytes(for: request)
19
+ defer { stream.task.cancel() }
20
20
  guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else { throw IndianaClientError.requestFailed((response as? HTTPURLResponse)?.statusCode ?? 0) }
21
21
  guard response.expectedContentLength <= 262144 else { throw IndianaClientError.invalidResponse }
22
22
  var result = Data(); for try await byte in stream { guard result.count < 262144 else { throw IndianaClientError.invalidResponse }; result.append(byte) }; return result
@@ -52,7 +52,8 @@ public actor IndianaPaywallSession {
52
52
  private func canonical(_ value: IndianaJSON) throws -> Data { let encoder = JSONEncoder(); encoder.outputFormatting = .sortedKeys; return try encoder.encode(value) }
53
53
  public func refresh() async throws -> IndianaJSON { try await hostCommand(.object(["operation":.string("resolve"),"input":.object([:])])) }
54
54
  internal func hostCommand(_ payload: IndianaJSON) async throws -> IndianaJSON {
55
- guard !closed, !busy, let envelope = payload.object, Set(envelope.keys) == Set(["operation","input"]), let action = envelope["operation"]?.string, let input = envelope["input"]?.object else { throw IndianaFunnelError.invalidCommand }
55
+ guard !closed, let envelope = payload.object, Set(envelope.keys) == Set(["operation","input"]), let action = envelope["operation"]?.string, let input = envelope["input"]?.object else { throw IndianaFunnelError.invalidCommand }
56
+ guard !busy else { throw IndianaFunnelError.commandPending }
56
57
  busy = true; defer { busy = false }
57
58
  switch action {
58
59
  case "resolve":
@@ -78,7 +79,6 @@ public actor IndianaPaywallSession {
78
79
  let fingerprint = try canonical(payload)
79
80
  if let pendingPreview, pendingPreview != fingerprint {
80
81
  guard let status = operation?.object?["status"]?.string, status != "pending" else { throw IndianaFunnelError.commandPending }
81
- quote = nil; operation = nil
82
82
  }
83
83
  if pendingPreview == fingerprint, let quote { return quote }
84
84
  var selectedPlan: [String:IndianaJSON] = ["productVersionId":.string(product)]
@@ -87,6 +87,7 @@ public actor IndianaPaywallSession {
87
87
  fields["offerId"] = input["offerId"]; fields["nativeOffer"] = input["nativeOffer"]
88
88
  let body = IndianaJSON.object(fields)
89
89
  try IndianaSchema.validate("previewAttachRequest", data: JSONEncoder().encode(body))
90
+ if pendingPreview != fingerprint { quote = nil; operation = nil }
90
91
  pendingPreview = fingerprint
91
92
  let reply = try await send("previewAttach", path:"subscriptions/preview-attach",body:body)
92
93
  guard let value = reply.object?["quote"], let q = value.object, q["currency"]?.string == currency, q["provider"]?.string == provider.rawValue,
@@ -97,9 +98,9 @@ public actor IndianaPaywallSession {
97
98
  let body = action == "read" ? IndianaJSON.object(["operationId":id]) : .object(["operationId":id,"intent":.string(action)])
98
99
  let reply = try await send(action == "read" ? "readSubscriptionOperation" : "attach", path: action == "read" ? "subscriptions/operations/read" : "subscriptions/attach", body:body)
99
100
  guard let value = reply.object?["operation"], value.object?["operationId"] == id, value.object?["currency"]?.string == currency else { throw IndianaClientError.invalidResponse }
100
- if operation?.object?["status"]?.string == "complete" { return operation! }
101
+ if let previous = operation, let status = previous.object?["status"]?.string,
102
+ status == "complete" || status != "pending" && value.object?["status"]?.string == "pending" { return previous }
101
103
  operation = value
102
- if value.object?["status"]?.string != "pending" && value.object?["status"]?.string != "complete" { pendingPreview = nil; quote = nil }
103
104
  return value
104
105
  default: throw IndianaFunnelError.invalidCommand
105
106
  }
@@ -1,4 +1,4 @@
1
1
  // Generated by scripts/sdk/generate-native-protocol.mjs. Do not edit.
2
2
  public enum IndianaSDK {
3
- public static let version = "0.10.8"
3
+ public static let version = "0.10.13"
4
4
  }