@chipmobilesdk/rn-payment 0.5.0 → 0.7.0

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 (317) hide show
  1. package/CHANGELOG.md +172 -0
  2. package/README.md +47 -16
  3. package/lib/commonjs/adapter/createStoreProvider.js +110 -0
  4. package/lib/commonjs/adapter/createStoreProvider.js.map +1 -0
  5. package/lib/commonjs/adapter/iap-adapter.js +393 -0
  6. package/lib/commonjs/adapter/iap-adapter.js.map +1 -0
  7. package/lib/commonjs/adapter/iapShapes.js +169 -0
  8. package/lib/commonjs/adapter/iapShapes.js.map +1 -0
  9. package/lib/commonjs/adapter/port.js +6 -0
  10. package/lib/commonjs/adapter/port.js.map +1 -0
  11. package/lib/commonjs/config/types.js +2 -0
  12. package/lib/commonjs/config/types.js.map +1 -0
  13. package/lib/commonjs/config/validate.js +181 -0
  14. package/lib/commonjs/config/validate.js.map +1 -0
  15. package/lib/commonjs/core/mutex.js +31 -0
  16. package/lib/commonjs/core/mutex.js.map +1 -0
  17. package/lib/commonjs/core/retry.js +37 -0
  18. package/lib/commonjs/core/retry.js.map +1 -0
  19. package/lib/commonjs/core/timers.js +207 -0
  20. package/lib/commonjs/core/timers.js.map +1 -0
  21. package/lib/commonjs/diagnostics/errors.js +83 -0
  22. package/lib/commonjs/diagnostics/errors.js.map +1 -0
  23. package/lib/commonjs/diagnostics/events.js +126 -0
  24. package/lib/commonjs/diagnostics/events.js.map +1 -0
  25. package/lib/commonjs/diagnostics/messageKeys.js +70 -0
  26. package/lib/commonjs/diagnostics/messageKeys.js.map +1 -0
  27. package/lib/commonjs/engine/connection.js +189 -0
  28. package/lib/commonjs/engine/connection.js.map +1 -0
  29. package/lib/commonjs/engine/engine.js +279 -0
  30. package/lib/commonjs/engine/engine.js.map +1 -0
  31. package/lib/commonjs/engine/finalize.js +325 -0
  32. package/lib/commonjs/engine/finalize.js.map +1 -0
  33. package/lib/commonjs/engine/foreground.js +26 -0
  34. package/lib/commonjs/engine/foreground.js.map +1 -0
  35. package/lib/commonjs/engine/internals.js +31 -0
  36. package/lib/commonjs/engine/internals.js.map +1 -0
  37. package/lib/commonjs/engine/pending.js +102 -0
  38. package/lib/commonjs/engine/pending.js.map +1 -0
  39. package/lib/commonjs/engine/products.js +198 -0
  40. package/lib/commonjs/engine/products.js.map +1 -0
  41. package/lib/commonjs/engine/purchase.js +395 -0
  42. package/lib/commonjs/engine/purchase.js.map +1 -0
  43. package/lib/commonjs/engine/purchaseFailure.js +77 -0
  44. package/lib/commonjs/engine/purchaseFailure.js.map +1 -0
  45. package/lib/commonjs/engine/receiptValidation.js +90 -0
  46. package/lib/commonjs/engine/receiptValidation.js.map +1 -0
  47. package/lib/commonjs/engine/state.js +201 -0
  48. package/lib/commonjs/engine/state.js.map +1 -0
  49. package/lib/commonjs/engine/subscriptions.js +122 -0
  50. package/lib/commonjs/engine/subscriptions.js.map +1 -0
  51. package/lib/commonjs/engine/sync.js +163 -0
  52. package/lib/commonjs/engine/sync.js.map +1 -0
  53. package/lib/commonjs/entitlements/aggregate.js +212 -0
  54. package/lib/commonjs/entitlements/aggregate.js.map +1 -0
  55. package/lib/commonjs/entitlements/mapping.js +41 -0
  56. package/lib/commonjs/entitlements/mapping.js.map +1 -0
  57. package/lib/commonjs/entitlements/policy.js +110 -0
  58. package/lib/commonjs/entitlements/policy.js.map +1 -0
  59. package/lib/commonjs/index.js +266 -0
  60. package/lib/commonjs/index.js.map +1 -0
  61. package/lib/commonjs/package.json +1 -0
  62. package/lib/commonjs/persistence/mmkv-store.js +149 -0
  63. package/lib/commonjs/persistence/mmkv-store.js.map +1 -0
  64. package/lib/commonjs/persistence/snapshot.js +229 -0
  65. package/lib/commonjs/persistence/snapshot.js.map +1 -0
  66. package/lib/commonjs/react/PaymentProvider.js +96 -0
  67. package/lib/commonjs/react/PaymentProvider.js.map +1 -0
  68. package/lib/commonjs/react/hooks.js +202 -0
  69. package/lib/commonjs/react/hooks.js.map +1 -0
  70. package/lib/commonjs/testing/conformance.js +136 -0
  71. package/lib/commonjs/testing/conformance.js.map +1 -0
  72. package/lib/commonjs/testing/fakeStore.js +281 -0
  73. package/lib/commonjs/testing/fakeStore.js.map +1 -0
  74. package/lib/commonjs/testing/index.js +45 -0
  75. package/lib/commonjs/testing/index.js.map +1 -0
  76. package/lib/module/adapter/createStoreProvider.js +106 -0
  77. package/lib/module/adapter/createStoreProvider.js.map +1 -0
  78. package/lib/module/adapter/iap-adapter.js +383 -0
  79. package/lib/module/adapter/iap-adapter.js.map +1 -0
  80. package/lib/module/adapter/iapShapes.js +160 -0
  81. package/lib/module/adapter/iapShapes.js.map +1 -0
  82. package/lib/module/adapter/port.js +4 -0
  83. package/lib/module/adapter/port.js.map +1 -0
  84. package/lib/module/config/types.js +2 -0
  85. package/lib/module/config/types.js.map +1 -0
  86. package/lib/module/config/validate.js +175 -0
  87. package/lib/module/config/validate.js.map +1 -0
  88. package/lib/module/core/mutex.js +22 -0
  89. package/lib/module/core/mutex.js.map +1 -0
  90. package/lib/module/core/retry.js +33 -0
  91. package/lib/module/core/retry.js.map +1 -0
  92. package/lib/module/core/timers.js +198 -0
  93. package/lib/module/core/timers.js.map +1 -0
  94. package/lib/module/diagnostics/errors.js +76 -0
  95. package/lib/module/diagnostics/errors.js.map +1 -0
  96. package/lib/module/diagnostics/events.js +117 -0
  97. package/lib/module/diagnostics/events.js.map +1 -0
  98. package/lib/module/diagnostics/messageKeys.js +64 -0
  99. package/lib/module/diagnostics/messageKeys.js.map +1 -0
  100. package/lib/module/engine/connection.js +185 -0
  101. package/lib/module/engine/connection.js.map +1 -0
  102. package/lib/module/engine/engine.js +274 -0
  103. package/lib/module/engine/engine.js.map +1 -0
  104. package/lib/module/engine/finalize.js +322 -0
  105. package/lib/module/engine/finalize.js.map +1 -0
  106. package/lib/module/engine/foreground.js +21 -0
  107. package/lib/module/engine/foreground.js.map +1 -0
  108. package/lib/module/engine/internals.js +26 -0
  109. package/lib/module/engine/internals.js.map +1 -0
  110. package/lib/module/engine/pending.js +95 -0
  111. package/lib/module/engine/pending.js.map +1 -0
  112. package/lib/module/engine/products.js +195 -0
  113. package/lib/module/engine/products.js.map +1 -0
  114. package/lib/module/engine/purchase.js +390 -0
  115. package/lib/module/engine/purchase.js.map +1 -0
  116. package/lib/module/engine/purchaseFailure.js +72 -0
  117. package/lib/module/engine/purchaseFailure.js.map +1 -0
  118. package/lib/module/engine/receiptValidation.js +87 -0
  119. package/lib/module/engine/receiptValidation.js.map +1 -0
  120. package/lib/module/engine/state.js +196 -0
  121. package/lib/module/engine/state.js.map +1 -0
  122. package/lib/module/engine/subscriptions.js +119 -0
  123. package/lib/module/engine/subscriptions.js.map +1 -0
  124. package/lib/module/engine/sync.js +158 -0
  125. package/lib/module/engine/sync.js.map +1 -0
  126. package/lib/module/entitlements/aggregate.js +204 -0
  127. package/lib/module/entitlements/aggregate.js.map +1 -0
  128. package/lib/module/entitlements/mapping.js +35 -0
  129. package/lib/module/entitlements/mapping.js.map +1 -0
  130. package/lib/module/entitlements/policy.js +104 -0
  131. package/lib/module/entitlements/policy.js.map +1 -0
  132. package/lib/module/index.js +59 -0
  133. package/lib/module/index.js.map +1 -0
  134. package/lib/module/package.json +1 -0
  135. package/lib/module/persistence/mmkv-store.js +144 -0
  136. package/lib/module/persistence/mmkv-store.js.map +1 -0
  137. package/lib/module/persistence/snapshot.js +221 -0
  138. package/lib/module/persistence/snapshot.js.map +1 -0
  139. package/lib/module/react/PaymentProvider.js +90 -0
  140. package/lib/module/react/PaymentProvider.js.map +1 -0
  141. package/lib/module/react/hooks.js +192 -0
  142. package/lib/module/react/hooks.js.map +1 -0
  143. package/lib/module/testing/conformance.js +130 -0
  144. package/lib/module/testing/conformance.js.map +1 -0
  145. package/lib/module/testing/fakeStore.js +276 -0
  146. package/lib/module/testing/fakeStore.js.map +1 -0
  147. package/lib/module/testing/index.js +13 -0
  148. package/lib/module/testing/index.js.map +1 -0
  149. package/lib/typescript/commonjs/adapter/createStoreProvider.d.ts +45 -0
  150. package/lib/typescript/commonjs/adapter/createStoreProvider.d.ts.map +1 -0
  151. package/lib/typescript/commonjs/adapter/iap-adapter.d.ts +80 -0
  152. package/lib/typescript/commonjs/adapter/iap-adapter.d.ts.map +1 -0
  153. package/lib/typescript/commonjs/adapter/iapShapes.d.ts +94 -0
  154. package/lib/typescript/commonjs/adapter/iapShapes.d.ts.map +1 -0
  155. package/lib/typescript/commonjs/adapter/port.d.ts +184 -0
  156. package/lib/typescript/commonjs/adapter/port.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/config/types.d.ts +326 -0
  158. package/lib/typescript/commonjs/config/types.d.ts.map +1 -0
  159. package/lib/typescript/commonjs/config/validate.d.ts +63 -0
  160. package/lib/typescript/commonjs/config/validate.d.ts.map +1 -0
  161. package/lib/typescript/commonjs/core/mutex.d.ts +17 -0
  162. package/lib/typescript/commonjs/core/mutex.d.ts.map +1 -0
  163. package/lib/typescript/commonjs/core/retry.d.ts +19 -0
  164. package/lib/typescript/commonjs/core/retry.d.ts.map +1 -0
  165. package/lib/typescript/commonjs/core/timers.d.ts +142 -0
  166. package/lib/typescript/commonjs/core/timers.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/diagnostics/errors.d.ts +55 -0
  168. package/lib/typescript/commonjs/diagnostics/errors.d.ts.map +1 -0
  169. package/lib/typescript/commonjs/diagnostics/events.d.ts +158 -0
  170. package/lib/typescript/commonjs/diagnostics/events.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts +54 -0
  172. package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts.map +1 -0
  173. package/lib/typescript/commonjs/engine/connection.d.ts +30 -0
  174. package/lib/typescript/commonjs/engine/connection.d.ts.map +1 -0
  175. package/lib/typescript/commonjs/engine/engine.d.ts +93 -0
  176. package/lib/typescript/commonjs/engine/engine.d.ts.map +1 -0
  177. package/lib/typescript/commonjs/engine/finalize.d.ts +53 -0
  178. package/lib/typescript/commonjs/engine/finalize.d.ts.map +1 -0
  179. package/lib/typescript/commonjs/engine/foreground.d.ts +15 -0
  180. package/lib/typescript/commonjs/engine/foreground.d.ts.map +1 -0
  181. package/lib/typescript/commonjs/engine/internals.d.ts +28 -0
  182. package/lib/typescript/commonjs/engine/internals.d.ts.map +1 -0
  183. package/lib/typescript/commonjs/engine/pending.d.ts +51 -0
  184. package/lib/typescript/commonjs/engine/pending.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/engine/products.d.ts +82 -0
  186. package/lib/typescript/commonjs/engine/products.d.ts.map +1 -0
  187. package/lib/typescript/commonjs/engine/purchase.d.ts +61 -0
  188. package/lib/typescript/commonjs/engine/purchase.d.ts.map +1 -0
  189. package/lib/typescript/commonjs/engine/purchaseFailure.d.ts +15 -0
  190. package/lib/typescript/commonjs/engine/purchaseFailure.d.ts.map +1 -0
  191. package/lib/typescript/commonjs/engine/receiptValidation.d.ts +42 -0
  192. package/lib/typescript/commonjs/engine/receiptValidation.d.ts.map +1 -0
  193. package/lib/typescript/commonjs/engine/state.d.ts +46 -0
  194. package/lib/typescript/commonjs/engine/state.d.ts.map +1 -0
  195. package/lib/typescript/commonjs/engine/subscriptions.d.ts +61 -0
  196. package/lib/typescript/commonjs/engine/subscriptions.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/engine/sync.d.ts +36 -0
  198. package/lib/typescript/commonjs/engine/sync.d.ts.map +1 -0
  199. package/lib/typescript/commonjs/entitlements/aggregate.d.ts +97 -0
  200. package/lib/typescript/commonjs/entitlements/aggregate.d.ts.map +1 -0
  201. package/lib/typescript/commonjs/entitlements/mapping.d.ts +27 -0
  202. package/lib/typescript/commonjs/entitlements/mapping.d.ts.map +1 -0
  203. package/lib/typescript/commonjs/entitlements/policy.d.ts +75 -0
  204. package/lib/typescript/commonjs/entitlements/policy.d.ts.map +1 -0
  205. package/lib/typescript/commonjs/index.d.ts +44 -0
  206. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  207. package/lib/typescript/commonjs/package.json +1 -0
  208. package/lib/typescript/commonjs/persistence/mmkv-store.d.ts +45 -0
  209. package/lib/typescript/commonjs/persistence/mmkv-store.d.ts.map +1 -0
  210. package/lib/typescript/commonjs/persistence/snapshot.d.ts +106 -0
  211. package/lib/typescript/commonjs/persistence/snapshot.d.ts.map +1 -0
  212. package/lib/typescript/commonjs/react/PaymentProvider.d.ts +57 -0
  213. package/lib/typescript/commonjs/react/PaymentProvider.d.ts.map +1 -0
  214. package/lib/typescript/commonjs/react/hooks.d.ts +80 -0
  215. package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
  216. package/lib/typescript/commonjs/testing/conformance.d.ts +41 -0
  217. package/lib/typescript/commonjs/testing/conformance.d.ts.map +1 -0
  218. package/lib/typescript/commonjs/testing/fakeStore.d.ts +69 -0
  219. package/lib/typescript/commonjs/testing/fakeStore.d.ts.map +1 -0
  220. package/lib/typescript/commonjs/testing/index.d.ts +12 -0
  221. package/lib/typescript/commonjs/testing/index.d.ts.map +1 -0
  222. package/lib/typescript/module/adapter/createStoreProvider.d.ts +45 -0
  223. package/lib/typescript/module/adapter/createStoreProvider.d.ts.map +1 -0
  224. package/lib/typescript/module/adapter/iap-adapter.d.ts +80 -0
  225. package/lib/typescript/module/adapter/iap-adapter.d.ts.map +1 -0
  226. package/lib/typescript/module/adapter/iapShapes.d.ts +94 -0
  227. package/lib/typescript/module/adapter/iapShapes.d.ts.map +1 -0
  228. package/lib/typescript/module/adapter/port.d.ts +184 -0
  229. package/lib/typescript/module/adapter/port.d.ts.map +1 -0
  230. package/lib/typescript/module/config/types.d.ts +326 -0
  231. package/lib/typescript/module/config/types.d.ts.map +1 -0
  232. package/lib/typescript/module/config/validate.d.ts +63 -0
  233. package/lib/typescript/module/config/validate.d.ts.map +1 -0
  234. package/lib/typescript/module/core/mutex.d.ts +17 -0
  235. package/lib/typescript/module/core/mutex.d.ts.map +1 -0
  236. package/lib/typescript/module/core/retry.d.ts +19 -0
  237. package/lib/typescript/module/core/retry.d.ts.map +1 -0
  238. package/lib/typescript/module/core/timers.d.ts +142 -0
  239. package/lib/typescript/module/core/timers.d.ts.map +1 -0
  240. package/lib/typescript/module/diagnostics/errors.d.ts +55 -0
  241. package/lib/typescript/module/diagnostics/errors.d.ts.map +1 -0
  242. package/lib/typescript/module/diagnostics/events.d.ts +158 -0
  243. package/lib/typescript/module/diagnostics/events.d.ts.map +1 -0
  244. package/lib/typescript/module/diagnostics/messageKeys.d.ts +54 -0
  245. package/lib/typescript/module/diagnostics/messageKeys.d.ts.map +1 -0
  246. package/lib/typescript/module/engine/connection.d.ts +30 -0
  247. package/lib/typescript/module/engine/connection.d.ts.map +1 -0
  248. package/lib/typescript/module/engine/engine.d.ts +93 -0
  249. package/lib/typescript/module/engine/engine.d.ts.map +1 -0
  250. package/lib/typescript/module/engine/finalize.d.ts +53 -0
  251. package/lib/typescript/module/engine/finalize.d.ts.map +1 -0
  252. package/lib/typescript/module/engine/foreground.d.ts +15 -0
  253. package/lib/typescript/module/engine/foreground.d.ts.map +1 -0
  254. package/lib/typescript/module/engine/internals.d.ts +28 -0
  255. package/lib/typescript/module/engine/internals.d.ts.map +1 -0
  256. package/lib/typescript/module/engine/pending.d.ts +51 -0
  257. package/lib/typescript/module/engine/pending.d.ts.map +1 -0
  258. package/lib/typescript/module/engine/products.d.ts +82 -0
  259. package/lib/typescript/module/engine/products.d.ts.map +1 -0
  260. package/lib/typescript/module/engine/purchase.d.ts +61 -0
  261. package/lib/typescript/module/engine/purchase.d.ts.map +1 -0
  262. package/lib/typescript/module/engine/purchaseFailure.d.ts +15 -0
  263. package/lib/typescript/module/engine/purchaseFailure.d.ts.map +1 -0
  264. package/lib/typescript/module/engine/receiptValidation.d.ts +42 -0
  265. package/lib/typescript/module/engine/receiptValidation.d.ts.map +1 -0
  266. package/lib/typescript/module/engine/state.d.ts +46 -0
  267. package/lib/typescript/module/engine/state.d.ts.map +1 -0
  268. package/lib/typescript/module/engine/subscriptions.d.ts +61 -0
  269. package/lib/typescript/module/engine/subscriptions.d.ts.map +1 -0
  270. package/lib/typescript/module/engine/sync.d.ts +36 -0
  271. package/lib/typescript/module/engine/sync.d.ts.map +1 -0
  272. package/lib/typescript/module/entitlements/aggregate.d.ts +97 -0
  273. package/lib/typescript/module/entitlements/aggregate.d.ts.map +1 -0
  274. package/lib/typescript/module/entitlements/mapping.d.ts +27 -0
  275. package/lib/typescript/module/entitlements/mapping.d.ts.map +1 -0
  276. package/lib/typescript/module/entitlements/policy.d.ts +75 -0
  277. package/lib/typescript/module/entitlements/policy.d.ts.map +1 -0
  278. package/lib/typescript/module/index.d.ts +44 -0
  279. package/lib/typescript/module/index.d.ts.map +1 -0
  280. package/lib/typescript/module/package.json +1 -0
  281. package/lib/typescript/module/persistence/mmkv-store.d.ts +45 -0
  282. package/lib/typescript/module/persistence/mmkv-store.d.ts.map +1 -0
  283. package/lib/typescript/module/persistence/snapshot.d.ts +106 -0
  284. package/lib/typescript/module/persistence/snapshot.d.ts.map +1 -0
  285. package/lib/typescript/module/react/PaymentProvider.d.ts +57 -0
  286. package/lib/typescript/module/react/PaymentProvider.d.ts.map +1 -0
  287. package/lib/typescript/module/react/hooks.d.ts +80 -0
  288. package/lib/typescript/module/react/hooks.d.ts.map +1 -0
  289. package/lib/typescript/module/testing/conformance.d.ts +41 -0
  290. package/lib/typescript/module/testing/conformance.d.ts.map +1 -0
  291. package/lib/typescript/module/testing/fakeStore.d.ts +69 -0
  292. package/lib/typescript/module/testing/fakeStore.d.ts.map +1 -0
  293. package/lib/typescript/module/testing/index.d.ts +12 -0
  294. package/lib/typescript/module/testing/index.d.ts.map +1 -0
  295. package/package.json +49 -13
  296. package/skills/sdk-rn-payment/SKILL.md +4 -4
  297. package/src/adapter/iap-adapter.ts +12 -216
  298. package/src/adapter/iapShapes.ts +232 -0
  299. package/src/config/types.ts +8 -0
  300. package/src/config/validate.ts +19 -4
  301. package/src/core/retry.ts +1 -58
  302. package/src/diagnostics/events.ts +1 -1
  303. package/src/engine/connection.ts +194 -0
  304. package/src/engine/engine.ts +140 -700
  305. package/src/engine/internals.ts +40 -0
  306. package/src/engine/products.ts +39 -17
  307. package/src/engine/purchase.ts +22 -130
  308. package/src/engine/purchaseFailure.ts +48 -0
  309. package/src/engine/receiptValidation.ts +101 -0
  310. package/src/engine/state.ts +253 -0
  311. package/src/engine/sync.ts +161 -0
  312. package/src/entitlements/aggregate.ts +3 -5
  313. package/src/entitlements/mapping.ts +0 -22
  314. package/src/persistence/mmkv-store.ts +10 -3
  315. package/src/persistence/snapshot.ts +102 -27
  316. package/src/react/PaymentProvider.tsx +73 -24
  317. package/src/react/hooks.ts +13 -3
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The engine: status, initialization, entitlement reads, and sync.
5
+ *
6
+ * Owns the concurrency guarantees that make three requirements structurally true
7
+ * rather than hoped for — one connection under concurrent init (FR-018), one
8
+ * store request under concurrent sync (FR-063), and a rate-limited foreground
9
+ * sync (PERF-002).
10
+ *
11
+ * It never imports a store type. The only thing it talks to is `ProviderPort`,
12
+ * which is what keeps the binding replaceable and iOS additive (FR-002, FR-007).
13
+ *
14
+ * This file composes (PAY-10): state and its publication live in `state.ts`, the
15
+ * connection in `connection.ts`, sync in `sync.ts`, and the internals tests reach
16
+ * for in `internals.ts`, off the public type (PAY-11).
17
+ */
18
+
19
+ import { currentPlatform } from '@chipmobilesdk/rn-core';
20
+ import { assertEnvironmentSafe, mayCreateRealTransaction, validateConfig } from "../config/validate.js";
21
+ import { createExclusive, createSingleFlight } from "../core/mutex.js";
22
+ import { PaymentError } from "../diagnostics/errors.js";
23
+ import { createCorrelationId } from "../diagnostics/events.js";
24
+ import { createSnapshotStore } from "../persistence/mmkv-store.js";
25
+ import { createConnection } from "./connection.js";
26
+ import { createFinalizer } from "./finalize.js";
27
+ import { attachEngineInternals } from "./internals.js";
28
+ import { createProducts } from "./products.js";
29
+ import { createPurchaseFlow } from "./purchase.js";
30
+ import { createEngineState } from "./state.js";
31
+ import { createSubscriptions } from "./subscriptions.js";
32
+ import { createSync } from "./sync.js";
33
+ /** How many refused operations `status.blockedOperations` keeps. */
34
+ export const MAX_BLOCKED_OPERATIONS = 20;
35
+ export function createEngine(config, deps) {
36
+ // Both run before anything connects: a bad catalog or an unsafe environment
37
+ // must fail at configuration time, not when a user taps Buy.
38
+ assertEnvironmentSafe(config);
39
+ // rn-core's one platform source (CORE-09). Where neither OS applies, the store
40
+ // provider refuses everything as unsupported anyway.
41
+ const platform = deps.platform ?? (currentPlatform() === 'ios' ? 'ios' : 'android');
42
+ const resolved = validateConfig(config, platform);
43
+ const now = deps.now ?? (() => Date.now());
44
+ const provider = deps.provider;
45
+ const state = createEngineState(config, resolved, provider, deps.snapshotStore ?? createSnapshotStore(), now);
46
+ const {
47
+ emit,
48
+ commit
49
+ } = state;
50
+ const correlationCounter = {
51
+ next: 1
52
+ };
53
+ const nextCorrelationId = () => createCorrelationId(correlationCounter);
54
+ const initFlight = createSingleFlight();
55
+ // Exclusive rather than single-flight: a second purchase is refused, not joined
56
+ // onto the first, and never queued (FR-031).
57
+ const purchaseLock = createExclusive();
58
+
59
+ /** Written into status, not just logged, so a test can assert the block (FR-014). */
60
+ const recordBlockedOperation = productKey => {
61
+ const blocked = {
62
+ productKey,
63
+ environment: config.environment,
64
+ at: now()
65
+ };
66
+ // The most recent ones only: an app retrying a blocked purchase in a loop
67
+ // must not grow status without bound (PAY-20).
68
+ state.setStatus({
69
+ blockedOperations: [...state.status.blockedOperations, blocked].slice(-MAX_BLOCKED_OPERATIONS)
70
+ });
71
+ emit({
72
+ type: 'environment_blocked',
73
+ productKey,
74
+ environment: config.environment
75
+ });
76
+ };
77
+ const finalizer = createFinalizer({
78
+ provider,
79
+ retry: resolved.retry,
80
+ attemptTimeoutMs: resolved.timeouts.finalizeAttemptMs,
81
+ snapshot: () => state.snapshot,
82
+ commit,
83
+ emit,
84
+ now,
85
+ disposed: () => state.disposed
86
+ });
87
+ const products = createProducts({
88
+ resolved,
89
+ provider,
90
+ emit,
91
+ now
92
+ });
93
+ // Every sync also settles what an earlier session left owed, and re-asks the
94
+ // backend about grants it deferred (FR-039, FR-042, FR-072a).
95
+ const syncer = createSync(state, async () => {
96
+ await finalizer.drain();
97
+ await purchaseFlow.revalidate();
98
+ });
99
+ const purchaseFlow = createPurchaseFlow({
100
+ config,
101
+ resolved,
102
+ provider,
103
+ platform,
104
+ finalizer,
105
+ snapshot: () => state.snapshot,
106
+ commit,
107
+ emit,
108
+ now,
109
+ nextCorrelationId,
110
+ statusKind: () => state.status.kind,
111
+ mayCreateRealTransaction: () => mayCreateRealTransaction(config),
112
+ recordBlockedOperation,
113
+ // `already_owned` re-syncs rather than surfacing an error, which is how a
114
+ // reinstall repairs itself (FR-033); the entitlement arrives via the change
115
+ // signal.
116
+ requestSync: trigger => {
117
+ syncer.sync(trigger).catch(() => undefined);
118
+ },
119
+ runExclusive: operation => purchaseLock.run(operation)
120
+ });
121
+ const subscriptions = createSubscriptions({
122
+ resolved,
123
+ provider,
124
+ snapshot: () => state.snapshot,
125
+ purchase: (productKey, options) => purchaseFlow.purchase(productKey, options)
126
+ });
127
+ const connection = createConnection(state, purchase => {
128
+ purchaseFlow.ingest(purchase).catch(() => undefined);
129
+ });
130
+
131
+ /** A subscription that is a no-op once the engine is cleaned up. */
132
+ function subscriber(listeners) {
133
+ return listener => state.disposed ? () => undefined : listeners.add(listener);
134
+ }
135
+ const engine = {
136
+ async initialize() {
137
+ if (!resolved.enabled) {
138
+ // Selling is off, but entitlements already held stay readable (FR-012):
139
+ // hydration runs here too, or they would read `unknown` forever.
140
+ state.setStatus({
141
+ kind: 'disabled'
142
+ });
143
+ state.hydrate();
144
+ return {
145
+ ok: false,
146
+ error: new PaymentError({
147
+ code: 'PAYMENT_DISABLED',
148
+ message: 'Payments are disabled by configuration',
149
+ operation: 'initialize'
150
+ })
151
+ };
152
+ }
153
+ // Checked before the shortcut below: a cleaned-up engine that had been
154
+ // ready used to answer `ok` while nothing behind it worked any more.
155
+ if (state.disposed) {
156
+ return {
157
+ ok: false,
158
+ error: new PaymentError({
159
+ code: 'PAYMENT_NOT_CONFIGURED',
160
+ message: 'Engine has been cleaned up',
161
+ operation: 'initialize'
162
+ })
163
+ };
164
+ }
165
+ // Already up: answered without reconnecting, or a later sequential call
166
+ // would leave a second set of native listeners behind.
167
+ if (state.status.kind === 'ready') {
168
+ return {
169
+ ok: true
170
+ };
171
+ }
172
+ return initFlight.run(async () => {
173
+ state.setStatus({
174
+ kind: 'connecting'
175
+ });
176
+ // Before connecting, so a warm start answers from the last good sync
177
+ // while the network is still in flight (FR-053).
178
+ state.hydrate();
179
+ const connected = await connection.connect();
180
+ if (!connected.ok) {
181
+ return connected;
182
+ }
183
+ await syncer.sync('initialize');
184
+ // After syncing, so a transaction the store still reports owned has been
185
+ // re-queued first: this catches a purchase the previous session paid for
186
+ // but was killed before acknowledging (FR-042).
187
+ await finalizer.drain();
188
+ return {
189
+ ok: true
190
+ };
191
+ });
192
+ },
193
+ cleanup() {
194
+ state.disposed = true;
195
+ connection.dispose();
196
+ finalizer.dispose();
197
+ state.statusListeners.clear();
198
+ state.entitlementListeners.clear();
199
+ state.pendingListeners.clear();
200
+ // Disarmed last: after this nothing is emitted, and a late store callback
201
+ // is dropped safely (FR-082).
202
+ state.emitter.dispose();
203
+ provider.disconnect().catch(() => undefined);
204
+ },
205
+ getStatus: () => state.status,
206
+ subscribeStatus: subscriber(state.statusListeners),
207
+ /** Synchronous, in-memory, zero I/O — it is read on render paths (PERF-001). */
208
+ getEntitlement(key) {
209
+ return state.entitlements[key] ?? {
210
+ key,
211
+ status: 'unknown',
212
+ sources: [],
213
+ isStale: false
214
+ };
215
+ },
216
+ getAllEntitlements: () => state.entitlements,
217
+ subscribeEntitlements: subscriber(state.entitlementListeners),
218
+ getPendingPurchases: () => state.pending,
219
+ subscribePendingPurchases: subscriber(state.pendingListeners),
220
+ sync: trigger => syncer.sync(trigger),
221
+ async restore() {
222
+ const outcome = await syncer.sync('manual');
223
+ if (!outcome.ok) {
224
+ return {
225
+ ok: false,
226
+ error: outcome.error
227
+ };
228
+ }
229
+ const held = Object.values(state.entitlements).filter(e => e.status === 'entitled').map(e => e.key);
230
+ // "Nothing found" is a distinct success, so an app never claims to have
231
+ // restored purchases that do not exist (FR-061).
232
+ return held.length > 0 ? {
233
+ ok: true,
234
+ restored: true,
235
+ entitlements: held
236
+ } : {
237
+ ok: true,
238
+ restored: false
239
+ };
240
+ },
241
+ getLastSyncedAt: () => state.snapshot.lastSyncedAt,
242
+ async clearLocalData() {
243
+ state.forget();
244
+ // Prices are per account and storefront; a logout drops them too (PAY-12).
245
+ products.invalidate();
246
+ },
247
+ subscribeEvents: listener => state.emitter.subscribe(listener),
248
+ purchase: (productKey, options) => purchaseFlow.purchase(productKey, options),
249
+ consume: ref => finalizer.consume(ref),
250
+ getUnfinalized: () => finalizer.unfinalized(),
251
+ getProducts: productKeys => products.get(productKeys),
252
+ refreshProducts: productKeys => products.refresh(productKeys),
253
+ changePlan: (from, to, mode, options) => subscriptions.changePlan(from, to, mode, options),
254
+ openSubscriptionManagement: productKey => subscriptions.openManagement(productKey),
255
+ confirmPriceChange: productKey => subscriptions.confirmPriceChange(productKey),
256
+ async handleForeground() {
257
+ await connection.recover();
258
+ // Rate-limited inside sync: at most one request per interval however often
259
+ // the app calls this.
260
+ await syncer.sync('foreground');
261
+ }
262
+ };
263
+ attachEngineInternals(engine, {
264
+ resolvedConfig: () => resolved,
265
+ nextCorrelationId,
266
+ emitter: () => state.emitter,
267
+ snapshot: () => state.snapshot,
268
+ commitSnapshot: commit,
269
+ mayCreateRealTransaction: () => mayCreateRealTransaction(config),
270
+ recordBlockedOperation
271
+ });
272
+ return engine;
273
+ }
274
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["currentPlatform","assertEnvironmentSafe","mayCreateRealTransaction","validateConfig","createExclusive","createSingleFlight","PaymentError","createCorrelationId","createSnapshotStore","createConnection","createFinalizer","attachEngineInternals","createProducts","createPurchaseFlow","createEngineState","createSubscriptions","createSync","MAX_BLOCKED_OPERATIONS","createEngine","config","deps","platform","resolved","now","Date","provider","state","snapshotStore","emit","commit","correlationCounter","next","nextCorrelationId","initFlight","purchaseLock","recordBlockedOperation","productKey","blocked","environment","at","setStatus","blockedOperations","status","slice","type","finalizer","retry","attemptTimeoutMs","timeouts","finalizeAttemptMs","snapshot","disposed","products","syncer","drain","purchaseFlow","revalidate","statusKind","kind","requestSync","trigger","sync","catch","undefined","runExclusive","operation","run","subscriptions","purchase","options","connection","ingest","subscriber","listeners","listener","add","engine","initialize","enabled","hydrate","ok","error","code","message","connected","connect","cleanup","dispose","statusListeners","clear","entitlementListeners","pendingListeners","emitter","disconnect","getStatus","subscribeStatus","getEntitlement","key","entitlements","sources","isStale","getAllEntitlements","subscribeEntitlements","getPendingPurchases","pending","subscribePendingPurchases","restore","outcome","held","Object","values","filter","e","map","length","restored","getLastSyncedAt","lastSyncedAt","clearLocalData","forget","invalidate","subscribeEvents","subscribe","consume","ref","getUnfinalized","unfinalized","getProducts","productKeys","get","refreshProducts","refresh","changePlan","from","to","mode","openSubscriptionManagement","openManagement","confirmPriceChange","handleForeground","recover","resolvedConfig","commitSnapshot"],"sourceRoot":"../../../src","sources":["engine/engine.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,322 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The finalization queue — the package's hardest invariant (FR-041, FR-042).
5
+ *
6
+ * Google auto-refunds and revokes a purchase that is not acknowledged within
7
+ * **three days**. So finalization cannot be a step the app might forget, and it
8
+ * cannot live only in memory: the failure case FR-042 names is the app being
9
+ * force-killed in the instant between payment and acknowledgement.
10
+ *
11
+ * The ordering that makes this work is: **write the intent, then call the store.**
12
+ * A crash before the write means the purchase is still owned and the next sync
13
+ * re-queues it from `queryOwned`. A crash after the write means the queue has a
14
+ * record and the next startup drains it. There is no window where a paid
15
+ * transaction is forgotten.
16
+ *
17
+ * Consumption stays app-triggered (FR-043), because only the app knows whether
18
+ * the item was actually banked in its own data.
19
+ */
20
+
21
+ import { backoffDelayMs } from "../core/retry.js";
22
+ import { withTimeout } from "../core/mutex.js";
23
+ import { PaymentError } from "../diagnostics/errors.js";
24
+ import { pendingFinalizations } from "../persistence/snapshot.js";
25
+
26
+ /** A Node `Timeout` and a browser numeric id are both valid here. */
27
+
28
+ export function createFinalizer(deps) {
29
+ const setTimeoutFn = deps.setTimeoutFn ?? setTimeout;
30
+ const clearTimeoutFn = deps.clearTimeoutFn ?? clearTimeout;
31
+
32
+ /** One timer per transaction, so two transactions retry independently. */
33
+ const timers = new Map();
34
+ /** Guards against two drains racing the same transaction. */
35
+ const inFlight = new Set();
36
+ const find = transactionId => deps.snapshot().purchases.find(p => p.transactionId === transactionId);
37
+ const patch = (transactionId, changes) => {
38
+ const snapshot = deps.snapshot();
39
+ deps.commit({
40
+ ...snapshot,
41
+ purchases: snapshot.purchases.map(p => p.transactionId === transactionId ? {
42
+ ...p,
43
+ ...changes
44
+ } : p)
45
+ });
46
+ };
47
+
48
+ /**
49
+ * One store call under `attemptTimeoutMs`. A call that never settles used to
50
+ * hold this transaction's in-flight guard and, through `drain`, the sync that
51
+ * awaited it. Timing out counts as a failed attempt, so the retry schedule and
52
+ * the next-session drain both still apply.
53
+ */
54
+ const bounded = (call, operation) => withTimeout(call, deps.attemptTimeoutMs, () => new PaymentError({
55
+ code: 'PAYMENT_TIMEOUT',
56
+ message: `The store did not answer the ${operation} call in time`,
57
+ operation,
58
+ retryable: true
59
+ }));
60
+ const clearTimer = transactionId => {
61
+ const timer = timers.get(transactionId);
62
+ if (timer !== undefined) {
63
+ clearTimeoutFn(timer);
64
+ timers.delete(transactionId);
65
+ }
66
+ };
67
+
68
+ /**
69
+ * Attempts one finalize call.
70
+ *
71
+ * A consumable is **not** acknowledged here: it waits for the app's explicit
72
+ * `consume`. Acknowledging it now would tell the store the entitlement was
73
+ * delivered before the app has recorded the item, and a crash in between would
74
+ * lose a paid item with no way to recover it.
75
+ */
76
+ const attempt = async transactionId => {
77
+ if (deps.disposed()) {
78
+ return {
79
+ kind: 'failed',
80
+ code: 'PAYMENT_NOT_CONFIGURED'
81
+ };
82
+ }
83
+ const record = find(transactionId);
84
+ if (!record) {
85
+ return {
86
+ kind: 'unknown_transaction'
87
+ };
88
+ }
89
+ if (record.finalizeState === 'done') {
90
+ // Idempotent by design: calling twice is a success, not an error (FR-044).
91
+ return {
92
+ kind: 'already_finalized'
93
+ };
94
+ }
95
+ if (record.productType === 'one_time_consumable') {
96
+ // The app owns this moment. Nothing to do until it calls consume().
97
+ return {
98
+ kind: 'already_finalized'
99
+ };
100
+ }
101
+ if (inFlight.has(transactionId)) {
102
+ return {
103
+ kind: 'retry_scheduled',
104
+ attempts: record.attempts
105
+ };
106
+ }
107
+ inFlight.add(transactionId);
108
+ patch(transactionId, {
109
+ finalizeState: 'in_flight'
110
+ });
111
+ let failed = false;
112
+ try {
113
+ await bounded(deps.provider.acknowledge(record.token), 'finalize');
114
+ } catch {
115
+ failed = true;
116
+ } finally {
117
+ // Released before scheduling the retry, deliberately. The guard exists to
118
+ // stop two concurrent store calls for one transaction, nothing more — if
119
+ // it were still held here, the next scheduled attempt would be refused by
120
+ // our own lock and the retry schedule would silently stall after one try.
121
+ inFlight.delete(transactionId);
122
+ }
123
+ const attempts = record.attempts + 1;
124
+ if (!failed) {
125
+ clearTimer(transactionId);
126
+ patch(transactionId, {
127
+ finalizeState: 'done',
128
+ state: 'purchased',
129
+ attempts
130
+ });
131
+ deps.emit({
132
+ type: 'transaction_finalized',
133
+ productKey: record.productKey,
134
+ attempts
135
+ });
136
+ return {
137
+ kind: 'finalized'
138
+ };
139
+ }
140
+ patch(transactionId, {
141
+ finalizeState: 'failed',
142
+ attempts
143
+ });
144
+ return scheduleRetry(transactionId, record.productKey, attempts, 'acknowledge');
145
+ };
146
+
147
+ /**
148
+ * One consume call for a consumable the app has banked (FR-043).
149
+ *
150
+ * Refuses anything that is not a settled consumable. Consuming a subscription
151
+ * or a permanent unlock would tell the store the user used it up, and a
152
+ * pending purchase has nothing to consume yet.
153
+ */
154
+ const consumeAttempt = async transactionId => {
155
+ if (deps.disposed()) {
156
+ return {
157
+ kind: 'failed',
158
+ code: 'PAYMENT_NOT_CONFIGURED'
159
+ };
160
+ }
161
+ const record = find(transactionId);
162
+ if (!record) {
163
+ return {
164
+ kind: 'unknown_transaction'
165
+ };
166
+ }
167
+ if (record.productType !== 'one_time_consumable') {
168
+ return {
169
+ kind: 'failed',
170
+ code: 'PAYMENT_NOT_CONSUMABLE'
171
+ };
172
+ }
173
+ if (record.state === 'pending') {
174
+ return {
175
+ kind: 'failed',
176
+ code: 'PAYMENT_PENDING'
177
+ };
178
+ }
179
+ if (record.state === 'consumed') {
180
+ // Consuming twice must grant the item once (FR-044).
181
+ return {
182
+ kind: 'already_finalized'
183
+ };
184
+ }
185
+ if (inFlight.has(transactionId)) {
186
+ // Concurrent consume calls collapse to one, for the same reason.
187
+ return {
188
+ kind: 'already_finalized'
189
+ };
190
+ }
191
+ inFlight.add(transactionId);
192
+ patch(transactionId, {
193
+ finalizeState: 'in_flight'
194
+ });
195
+ let failed = false;
196
+ try {
197
+ await bounded(deps.provider.consume(record.token), 'consume');
198
+ } catch {
199
+ failed = true;
200
+ } finally {
201
+ // Released before scheduling, for the same reason as in `attempt`.
202
+ inFlight.delete(transactionId);
203
+ }
204
+ const attempts = record.attempts + 1;
205
+ if (failed) {
206
+ patch(transactionId, {
207
+ finalizeState: 'failed',
208
+ attempts
209
+ });
210
+ return scheduleRetry(transactionId, record.productKey, attempts, 'consume');
211
+ }
212
+ clearTimer(transactionId);
213
+ // `consumed` is what stops it being an entitlement source, so a
214
+ // consumable never becomes a permanent unlock.
215
+ patch(transactionId, {
216
+ state: 'consumed',
217
+ finalizeState: 'done',
218
+ attempts
219
+ });
220
+ deps.emit({
221
+ type: 'transaction_consumed',
222
+ productKey: record.productKey
223
+ });
224
+ return {
225
+ kind: 'finalized'
226
+ };
227
+ };
228
+
229
+ /**
230
+ * Schedules the next attempt inside the per-session budget.
231
+ *
232
+ * Exhausting the budget is **not** giving up. The record stays `failed`, which
233
+ * `pendingFinalizations` still returns, so the next startup or foreground drain
234
+ * picks it up again. That is what keeps the package inside Play's three-day
235
+ * window without hammering a store that is currently refusing.
236
+ */
237
+ const scheduleRetry = (transactionId, productKey, attempts, operation) => {
238
+ if (deps.disposed()) {
239
+ return {
240
+ kind: 'failed',
241
+ code: 'PAYMENT_FINALIZE_FAILED'
242
+ };
243
+ }
244
+ if (attempts >= deps.retry.finalize.maxAttempts) {
245
+ // Left queued deliberately — resumed next session, never abandoned.
246
+ return {
247
+ kind: 'failed',
248
+ code: 'PAYMENT_FINALIZE_FAILED'
249
+ };
250
+ }
251
+ const delayMs = backoffDelayMs(attempts + 1, deps.retry.finalize);
252
+ clearTimer(transactionId);
253
+ timers.set(transactionId, setTimeoutFn(() => {
254
+ timers.delete(transactionId);
255
+ const retry = operation === 'consume' ? consumeAttempt : attempt;
256
+ retry(transactionId).catch(() => undefined);
257
+ }, delayMs));
258
+ deps.emit({
259
+ type: 'finalize_retry_scheduled',
260
+ productKey,
261
+ attempt: attempts + 1,
262
+ delayMs
263
+ });
264
+ return {
265
+ kind: 'retry_scheduled',
266
+ attempts
267
+ };
268
+ };
269
+ return {
270
+ async enqueue(transactionId) {
271
+ const record = find(transactionId);
272
+ if (!record) {
273
+ return {
274
+ kind: 'unknown_transaction'
275
+ };
276
+ }
277
+ if (record.finalizeState === 'done') {
278
+ return {
279
+ kind: 'already_finalized'
280
+ };
281
+ }
282
+
283
+ // The write happens BEFORE the store call. This single ordering is what
284
+ // makes a kill between payment and acknowledgement recoverable.
285
+ if (record.finalizeState !== 'in_flight') {
286
+ patch(transactionId, {
287
+ finalizeState: 'queued'
288
+ });
289
+ }
290
+ return attempt(transactionId);
291
+ },
292
+ async drain() {
293
+ // Runs regardless of whether a purchase happened this session: the record
294
+ // it is looking for was probably written by a session that died.
295
+ for (const record of pendingFinalizations(deps.snapshot())) {
296
+ if (deps.disposed()) {
297
+ return;
298
+ }
299
+ await attempt(record.transactionId).catch(() => undefined);
300
+ }
301
+ },
302
+ consume(ref) {
303
+ return consumeAttempt(ref.transactionId);
304
+ },
305
+ unfinalized() {
306
+ return pendingFinalizations(deps.snapshot()).map(p => ({
307
+ productKey: p.productKey,
308
+ transactionId: p.transactionId,
309
+ attempts: p.attempts,
310
+ purchasedAt: p.purchasedAt
311
+ }));
312
+ },
313
+ dispose() {
314
+ for (const timer of timers.values()) {
315
+ clearTimeoutFn(timer);
316
+ }
317
+ timers.clear();
318
+ inFlight.clear();
319
+ }
320
+ };
321
+ }
322
+ //# sourceMappingURL=finalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["backoffDelayMs","withTimeout","PaymentError","pendingFinalizations","createFinalizer","deps","setTimeoutFn","setTimeout","clearTimeoutFn","clearTimeout","timers","Map","inFlight","Set","find","transactionId","snapshot","purchases","p","patch","changes","commit","map","bounded","call","operation","attemptTimeoutMs","code","message","retryable","clearTimer","timer","get","undefined","delete","attempt","disposed","kind","record","finalizeState","productType","has","attempts","add","failed","provider","acknowledge","token","state","emit","type","productKey","scheduleRetry","consumeAttempt","consume","retry","finalize","maxAttempts","delayMs","set","catch","enqueue","drain","ref","unfinalized","purchasedAt","dispose","values","clear"],"sourceRoot":"../../../src","sources":["engine/finalize.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Opt-in foreground sync over rn-core's shared lifecycle port (PERF-07, FR-059).
5
+ *
6
+ * `handleForeground()` stays the app's to call: the engine does not decide what a
7
+ * foreground return is. An app that is happy with "back from the background" calls
8
+ * this once instead of wiring `AppState` itself, and shares the one native
9
+ * subscription every package uses. A trip through `inactive` alone (a biometric
10
+ * prompt, iOS Control Center) is not a return. On Android the Play purchase sheet
11
+ * does send the app to the background, so a purchase is followed by a sync; the
12
+ * engine's foreground rate limit keeps that to one request per interval.
13
+ */
14
+ import { appLifecycle, onForeground } from '@chipmobilesdk/rn-core';
15
+ export function syncOnForeground(engine, lifecycle = appLifecycle()) {
16
+ return onForeground(() => {
17
+ // Sync reports its own failures through status and diagnostics.
18
+ engine.handleForeground().catch(() => undefined);
19
+ }, lifecycle);
20
+ }
21
+ //# sourceMappingURL=foreground.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["appLifecycle","onForeground","syncOnForeground","engine","lifecycle","handleForeground","catch","undefined"],"sourceRoot":"../../../src","sources":["engine/foreground.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SACCA,YAAY,EACZC,YAAY,QAGN,wBAAwB;AAI/B,OAAO,SAASC,gBAAgBA,CAC/BC,MAA+C,EAC/CC,SAA2B,GAAGJ,YAAY,CAAC,CAAC,EAC9B;EACd,OAAOC,YAAY,CAAC,MAAM;IACzB;IACAE,MAAM,CAACE,gBAAgB,CAAC,CAAC,CAACC,KAAK,CAAC,MAAMC,SAAS,CAAC;EACjD,CAAC,EAAEH,SAAS,CAAC;AACd","ignoreList":[]}