@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,61 @@
1
+ /**
2
+ * The purchase flow.
3
+ *
4
+ * Ordering here is deliberate and load-bearing:
5
+ *
6
+ * 1. Refuse early and cheaply — disabled, not ready, already busy, environment
7
+ * blocked, unknown product — so nothing reaches the store that should not.
8
+ * 2. Launch, and map every store outcome onto a typed result (FR-005).
9
+ * 3. Pending stops here: it is persisted and signalled, but **never granted**
10
+ * (FR-037).
11
+ * 4. Validate with the app's backend, if one is configured, and only for a
12
+ * **newly completed** purchase (FR-069a).
13
+ * 5. Grant the entitlement, then finalize. In that order — the user gets what
14
+ * they paid for before the bookkeeping completes, so a finalize failure never
15
+ * withholds a paid entitlement. Finalization is still guaranteed, by the
16
+ * persisted queue.
17
+ */
18
+ import type { PaymentConfig, PaymentStatusKind, ProductKey, PurchaseOptions, PurchaseResult } from '../config/types.js';
19
+ import type { ResolvedConfig, TargetPlatform } from '../config/validate.js';
20
+ import type { ProviderPort, ProviderPurchase } from '../adapter/port.js';
21
+ import type { ExclusiveOutcome } from '../core/mutex.js';
22
+ import type { PaymentEventInput } from '../diagnostics/events.js';
23
+ import type { PersistedSnapshot } from '../persistence/snapshot.js';
24
+ import type { Finalizer } from './finalize.js';
25
+ export interface PurchaseFlowDeps {
26
+ config: PaymentConfig;
27
+ resolved: ResolvedConfig;
28
+ provider: ProviderPort;
29
+ platform: TargetPlatform;
30
+ finalizer: Finalizer;
31
+ snapshot: () => PersistedSnapshot;
32
+ commit: (next: PersistedSnapshot) => void;
33
+ emit: (event: PaymentEventInput) => void;
34
+ now: () => number;
35
+ nextCorrelationId: () => string;
36
+ statusKind: () => PaymentStatusKind;
37
+ mayCreateRealTransaction: () => boolean;
38
+ recordBlockedOperation: (productKey: ProductKey) => void;
39
+ requestSync: (trigger: 'already_owned') => void;
40
+ runExclusive: <T>(operation: () => Promise<T>) => Promise<ExclusiveOutcome<T>>;
41
+ }
42
+ export interface InternalPurchaseOptions extends PurchaseOptions {
43
+ replaceProductKey?: ProductKey;
44
+ prorationMode?: string;
45
+ }
46
+ export interface PurchaseFlow {
47
+ purchase(productKey: ProductKey, options?: InternalPurchaseOptions): Promise<PurchaseResult>;
48
+ /** Handles a store-pushed update, e.g. a pending purchase settling (FR-039). */
49
+ ingest(purchase: ProviderPurchase): Promise<void>;
50
+ /**
51
+ * Re-runs the backend check for transactions granted under the
52
+ * failure-fallback (FR-072a).
53
+ *
54
+ * Called on sync, so recovery happens on the app's own rhythm rather than on a
55
+ * timer of ours. A rejection here revokes, which is what bounds the exposure
56
+ * that `grant_and_queue` accepts.
57
+ */
58
+ revalidate(): Promise<void>;
59
+ }
60
+ export declare function createPurchaseFlow(deps: PurchaseFlowDeps): PurchaseFlow;
61
+ //# sourceMappingURL=purchase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"purchase.d.ts","sourceRoot":"","sources":["../../../../src/engine/purchase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EACX,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,cAAc,EAEd,MAAM,oBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzE,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAIhB,MAAM,oBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAe,CAAC;AAItD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAAuB,CAAC;AAC/D,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,4BAAyB,CAAC;AAEpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAY,CAAC;AAG5C,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;IAClC,MAAM,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC1C,IAAI,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACzC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC,UAAU,EAAE,MAAM,iBAAiB,CAAC;IACpC,wBAAwB,EAAE,MAAM,OAAO,CAAC;IACxC,sBAAsB,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACzD,WAAW,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAChD,YAAY,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/E;AAMD,MAAM,WAAW,uBAAwB,SAAQ,eAAe;IAC/D,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7F,gFAAgF;IAChF,MAAM,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD;;;;;;;OAOG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CA0YvE"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * What a refused purchase means to the app (PAY-19).
3
+ *
4
+ * The store answers with a reason of its own; this turns it into the result the
5
+ * app sees, under the code it can branch on, so no store vocabulary leaks out.
6
+ * Split from the flow next door, which is about the sequence of calls.
7
+ */
8
+ import type { ProviderFailureReason } from '../adapter/port.js';
9
+ import type { PaymentStatusKind, ProductKey, PurchaseResult } from '../config/types.js';
10
+ import type { PaymentErrorCode } from '../diagnostics/errors.js';
11
+ export declare const FAILURE_CODES: Partial<Record<PurchaseResult['kind'], PaymentErrorCode>>;
12
+ /** Maps a provider failure onto the public vocabulary, so no store code leaks out. */
13
+ export declare function mapFailure(reason: ProviderFailureReason, productKey: ProductKey, status: PaymentStatusKind): PurchaseResult;
14
+ /** Plan-change parameters, which only `subscriptions.ts` supplies. */
15
+ //# sourceMappingURL=purchaseFailure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"purchaseFailure.d.ts","sourceRoot":"","sources":["../../../../src/engine/purchaseFailure.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAiB,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAAuB,CAAC;AAE9D,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAKnF,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,UAAU,CACzB,MAAM,EAAE,qBAAqB,EAC7B,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,iBAAiB,GACvB,cAAc,CAsBhB;AAED,sEAAsE"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Asking the app's backend whether a purchase is real (FR-069a, FR-072b).
3
+ *
4
+ * The hook is optional and bounded by a timeout, and its answer decides whether
5
+ * an entitlement is granted — so what happens when it throws, times out, or is
6
+ * absent is the whole point of this module. Split from the flow next door,
7
+ * which is about the sequence of store calls.
8
+ *
9
+ * A hook that could not answer is never an implicit approval: the configured
10
+ * `onValidationUnavailable` decides, and the default refuses.
11
+ */
12
+ import type { ProviderPurchase } from '../adapter/port.js';
13
+ import type { PaymentConfig, ProductKey } from '../config/types.js';
14
+ import type { ResolvedConfig, TargetPlatform } from '../config/validate.js';
15
+ import type { PaymentEventInput } from '../diagnostics/events.js';
16
+ export interface ReceiptValidationDeps {
17
+ config: PaymentConfig;
18
+ platform: TargetPlatform;
19
+ resolved: ResolvedConfig;
20
+ emit: (event: PaymentEventInput) => void;
21
+ }
22
+ /** What the backend decided about one purchase. */
23
+ export type ValidationOutcome = {
24
+ outcome: 'approved';
25
+ } | {
26
+ outcome: 'rejected';
27
+ reason?: string;
28
+ } | {
29
+ outcome: 'granted_pending_revalidation';
30
+ };
31
+ export declare function createReceiptValidation(deps: ReceiptValidationDeps): {
32
+ askHook: (hook: NonNullable<PaymentConfig["validateTransaction"]>, candidate: Parameters<NonNullable<PaymentConfig["validateTransaction"]>>[0]) => Promise<import("../index.js").ValidationDecision>;
33
+ validate: (purchase: ProviderPurchase, productKey: ProductKey, correlationId: string) => Promise<{
34
+ outcome: "approved";
35
+ } | {
36
+ outcome: "rejected";
37
+ reason?: string;
38
+ } | {
39
+ outcome: "granted_pending_revalidation";
40
+ }>;
41
+ };
42
+ //# sourceMappingURL=receiptValidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receiptValidation.d.ts","sourceRoot":"","sources":["../../../../src/engine/receiptValidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAiB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAAuB,CAAC;AAI/D,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACzC;AAED,mDAAmD;AACnD,MAAM,MAAM,iBAAiB,GAC1B;IAAE,OAAO,EAAE,UAAU,CAAA;CAAE,GACvB;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,OAAO,EAAE,8BAA8B,CAAA;CAAE,CAAC;AAE/C,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,qBAAqB;oBAI3D,WAAW,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,aAC5C,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;yBAsBjE,gBAAgB,cACd,UAAU,iBACP,MAAM,KACnB,OAAO,CACP;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,GACvB;QAAE,OAAO,EAAE,UAAU,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACxC;QAAE,OAAO,EAAE,8BAA8B,CAAA;KAAE,CAC7C;EAmCD"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The engine's state and the one way it changes (PAY-10).
3
+ *
4
+ * Status, the persisted snapshot, entitlements and pending purchases live here
5
+ * with the listeners that hear about them. Every change goes through `commit`
6
+ * (the snapshot) or `setStatus`, so diffing and emission are written once:
7
+ * an entitlement is granted or revoked exactly once however many sources it has
8
+ * (FR-079), a renewal that changes nothing emits nothing (FR-068), and an
9
+ * unchanged map is the same object (PERF-03).
10
+ */
11
+ import { type ListenerSet } from '@chipmobilesdk/rn-core';
12
+ import type { ProviderPort } from '../adapter/port.js';
13
+ import type { ResolvedConfig } from '../config/validate.js';
14
+ import type { PaymentConfig, PaymentStatus, PendingPurchasesState } from '../config/types.js';
15
+ import { type PaymentEmitter, type PaymentEventInput } from '../diagnostics/events.js';
16
+ import { type EntitlementMap } from '../entitlements/aggregate.js';
17
+ import type { SnapshotStore } from '../persistence/mmkv-store.js';
18
+ import { type PersistedSnapshot } from '../persistence/snapshot.js';
19
+ export interface EngineState {
20
+ readonly config: PaymentConfig;
21
+ readonly resolved: ResolvedConfig;
22
+ readonly provider: ProviderPort;
23
+ readonly store: SnapshotStore;
24
+ readonly now: () => number;
25
+ readonly emitter: PaymentEmitter;
26
+ readonly statusListeners: ListenerSet<[PaymentStatus]>;
27
+ readonly entitlementListeners: ListenerSet<[EntitlementMap]>;
28
+ readonly pendingListeners: ListenerSet<[PendingPurchasesState]>;
29
+ disposed: boolean;
30
+ /** Whether the snapshot comes from a sync that succeeded; until then entitlements are `unknown`. */
31
+ hasSynced: boolean;
32
+ snapshot: PersistedSnapshot;
33
+ entitlements: EntitlementMap;
34
+ status: PaymentStatus;
35
+ pending: PendingPurchasesState;
36
+ emit(event: PaymentEventInput): void;
37
+ setStatus(next: Partial<PaymentStatus>): void;
38
+ /** Writes the snapshot, reports pending purchases that ended, and recomputes. */
39
+ commit(next: PersistedSnapshot): void;
40
+ /** Loads the persisted snapshot at startup (FR-053). */
41
+ hydrate(): void;
42
+ /** Forgets everything local, back to `unknown` (FR-057). */
43
+ forget(): void;
44
+ }
45
+ export declare function createEngineState(config: PaymentConfig, resolved: ResolvedConfig, provider: ProviderPort, store: SnapshotStore, now: () => number): EngineState;
46
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/engine/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,oBAAiB,CAAC;AAE3F,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,iBAAiB,EACtB,MAAM,0BAAuB,CAAC;AAC/B,OAAO,EAKN,KAAK,cAAc,EACnB,MAAM,8BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA2B,CAAC;AAC/D,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,4BAAyB,CAAC;AAKhF,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;IAC7D,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAEhE,QAAQ,EAAE,OAAO,CAAC;IAClB,oGAAoG;IACpG,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,YAAY,EAAE,cAAc,CAAC;IAC7B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,qBAAqB,CAAC;IAE/B,IAAI,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAC9C,iFAAiF;IACjF,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,wDAAwD;IACxD,OAAO,IAAI,IAAI,CAAC;IAChB,4DAA4D;IAC5D,MAAM,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,MAAM,GACf,WAAW,CAsLb"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Subscription plan changes and the route to the store's management screen (US12).
3
+ *
4
+ * Two platform rules drive this module:
5
+ *
6
+ * - **Proration is the app's decision, inside what the store permits** (FR-065).
7
+ * Whether a user who upgrades gets charged immediately, keeps their remaining
8
+ * time, or starts a fresh period is a product and pricing choice, so the
9
+ * package forwards it rather than picking.
10
+ * - **Cancellation belongs to the store.** Platforms forbid an app presenting its
11
+ * own cancellation screen, so this module offers only a route to the store's
12
+ * (FR-066) — there is deliberately no self-built alternative anywhere in the
13
+ * package.
14
+ */
15
+ import type { ProductKey, PurchaseOptions, PurchaseResult } from '../config/types.js';
16
+ import type { ResolvedConfig } from '../config/validate.js';
17
+ import type { ProviderPort } from '../adapter/port.js';
18
+ import type { PersistedSnapshot } from '../persistence/snapshot.js';
19
+ /**
20
+ * How already-paid time is handled when a plan changes.
21
+ *
22
+ * Named for the user-visible effect rather than mirroring a store's enum, so the
23
+ * same vocabulary will map onto StoreKit later (FR-004).
24
+ */
25
+ export type ProrationMode =
26
+ /** Switch now; credit unused time against the new plan. The usual upgrade. */
27
+ 'immediate_with_time_proration'
28
+ /** Switch now; charge the full new price immediately and restart the period. */
29
+ | 'immediate_and_charge_full_price'
30
+ /** Switch now; charge the prorated difference for the current period. */
31
+ | 'immediate_and_charge_prorated_price'
32
+ /** Keep the current plan until it expires, then start the new one. Usual downgrade. */
33
+ | 'deferred';
34
+ export type PriceChangeResult = {
35
+ kind: 'confirmed';
36
+ } | {
37
+ kind: 'dismissed';
38
+ }
39
+ /** The platform has no client-side flow; it notifies the user itself (FR-067). */
40
+ | {
41
+ kind: 'unsupported';
42
+ } | {
43
+ kind: 'failed';
44
+ code: string;
45
+ };
46
+ export interface SubscriptionsDeps {
47
+ resolved: ResolvedConfig;
48
+ provider: ProviderPort;
49
+ snapshot: () => PersistedSnapshot;
50
+ purchase: (productKey: ProductKey, options?: PurchaseOptions & {
51
+ replaceProductKey?: ProductKey;
52
+ prorationMode?: string;
53
+ }) => Promise<PurchaseResult>;
54
+ }
55
+ export interface Subscriptions {
56
+ changePlan(fromProductKey: ProductKey, toProductKey: ProductKey, mode: ProrationMode, options?: PurchaseOptions): Promise<PurchaseResult>;
57
+ openManagement(productKey?: ProductKey): Promise<void>;
58
+ confirmPriceChange(productKey: ProductKey): Promise<PriceChangeResult>;
59
+ }
60
+ export declare function createSubscriptions(deps: SubscriptionsDeps): Subscriptions;
61
+ //# sourceMappingURL=subscriptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../../../src/engine/subscriptions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAiB,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAiB,CAAC;AAEpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAAyB,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,aAAa;AACxB,8EAA8E;AAC5E,+BAA+B;AACjC,gFAAgF;GAC9E,iCAAiC;AACnC,yEAAyE;GACvE,qCAAqC;AACvC,uFAAuF;GACrF,UAAU,CAAC;AAUd,MAAM,MAAM,iBAAiB,GAC1B;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE;AACvB,kFAAkF;GAChF;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;IAClC,QAAQ,EAAE,CACT,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,iBAAiB,CAAC,EAAE,UAAU,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,KAClF,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC7B,UAAU,CACT,cAAc,EAAE,UAAU,EAC1B,YAAY,EAAE,UAAU,EACxB,IAAI,EAAE,aAAa,EACnB,OAAO,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3B,cAAc,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACvE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAwE1E"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Syncing with the store, and the one translation from a store purchase to a
3
+ * persisted record (PAY-10).
4
+ *
5
+ * The purchase flow and sync both build records here, so they cannot disagree
6
+ * about what a transaction still owes: a disagreement is how a paid purchase
7
+ * goes unacknowledged and is refunded three days later.
8
+ */
9
+ import type { ProviderPurchase } from '../adapter/port.js';
10
+ import type { ProductKey } from '../config/types.js';
11
+ import type { ResolvedConfig } from '../config/validate.js';
12
+ import { PaymentError } from '../diagnostics/errors.js';
13
+ import type { SyncTrigger } from '../diagnostics/events.js';
14
+ import { type PersistedPurchase } from '../persistence/snapshot.js';
15
+ import type { EngineState } from './state.js';
16
+ export type SyncOutcome = {
17
+ ok: true;
18
+ restoredCount: number;
19
+ revokedCount: number;
20
+ } | {
21
+ ok: false;
22
+ error: PaymentError;
23
+ };
24
+ /** The persisted record for one store purchase, keeping what we already knew about it. */
25
+ export declare function toPersistedRecord(resolved: ResolvedConfig, purchase: ProviderPurchase, productKey: ProductKey, existing: PersistedPurchase | undefined): PersistedPurchase;
26
+ export interface Sync {
27
+ sync(trigger?: SyncTrigger): Promise<SyncOutcome>;
28
+ }
29
+ /**
30
+ * `settle` runs after every successful sync, outside the sync flight: the finalize
31
+ * drain and backend revalidation (FR-039, FR-042, FR-072a). Inside the flight, one
32
+ * store call or hook that never answered held it, and every later sync joined
33
+ * that stuck promise for the rest of the session.
34
+ */
35
+ export declare function createSync(state: EngineState, settle: () => Promise<void>): Sync;
36
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/engine/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAAuB,CAAC;AAGzD,OAAO,EAAwB,KAAK,iBAAiB,EAAE,MAAM,4BAAyB,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAS,CAAC;AAE3C,MAAM,MAAM,WAAW,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAEhG,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,gBAAgB,EAC1B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,iBAAiB,GAAG,SAAS,GACrC,iBAAiB,CAgBnB;AAkCD,MAAM,WAAW,IAAI;IACpB,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAyEhF"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Entitlement aggregation — the package's primary output.
3
+ *
4
+ * Everything else exists to make this one answer correct. The most damaging
5
+ * defect class in a payment SDK lives here: collapsing "not yet synced" into "not
6
+ * entitled" makes a paying user watch ads flash on cold start or see a purchased
7
+ * feature sit locked.
8
+ *
9
+ * Two rules do most of the work:
10
+ *
11
+ * - **A pending purchase is never a source** (FR-037). Enforced here, in
12
+ * aggregation, rather than at each call site, so no future code path can grant
13
+ * on money that has not arrived.
14
+ * - **Uncertainty resolves to `unknown`, never `not_entitled`** (FR-047,
15
+ * FR-055a). Never synced, stale, or scope-changed all mean "we do not know",
16
+ * and the package says so rather than asserting the user did not pay.
17
+ */
18
+ import type { ResolvedConfig } from '../config/validate.js';
19
+ import type { EntitlementKey, ProductKey } from '../config/types.js';
20
+ import type { PersistedSnapshot } from '../persistence/snapshot.js';
21
+ import { type RenewalState } from './policy.js';
22
+ export type EntitlementStatus = 'unknown' | 'entitled' | 'not_entitled';
23
+ export interface SubscriptionDetail {
24
+ expiresAt?: number;
25
+ willAutoRenew: boolean;
26
+ isCancelledButValid: boolean;
27
+ renewalState: RenewalState;
28
+ }
29
+ export interface EntitlementState {
30
+ key: EntitlementKey;
31
+ status: EntitlementStatus;
32
+ /** The app's own product keys currently granting this. Never raw transactions (FR-051). */
33
+ sources: ProductKey[];
34
+ subscription?: SubscriptionDetail;
35
+ lastSyncedAt?: number;
36
+ /** True once the snapshot is older than `staleAfterMs`; status is then `unknown`. */
37
+ isStale: boolean;
38
+ }
39
+ export type EntitlementMap = Record<EntitlementKey, EntitlementState>;
40
+ export interface AggregateInput {
41
+ config: ResolvedConfig;
42
+ snapshot: PersistedSnapshot;
43
+ /** False until the first successful sync of this session or a hydrated one. */
44
+ hasSynced: boolean;
45
+ reportsGraceAndHoldDistinctly: boolean;
46
+ now: number;
47
+ }
48
+ /**
49
+ * Computes the full entitlement map.
50
+ *
51
+ * Pure and synchronous by design: it runs on render paths, so it must never
52
+ * touch I/O (PERF-001). The engine calls it after any state change and caches the
53
+ * result.
54
+ */
55
+ /**
56
+ * How far the snapshot can be trusted right now.
57
+ *
58
+ * Shared by entitlements and the pending set (FR-103) so the two can never
59
+ * disagree about whether the package knows anything — a paywall that showed
60
+ * "not entitled" next to "nothing pending" from one stale snapshot would offer
61
+ * Buy to a user whose payment is in flight.
62
+ */
63
+ export declare function snapshotCertainty(input: {
64
+ config: Pick<ResolvedConfig, 'staleAfterMs'>;
65
+ snapshot: Pick<PersistedSnapshot, 'lastSyncedAt'>;
66
+ hasSynced: boolean;
67
+ now: number;
68
+ }): {
69
+ isStale: boolean;
70
+ undetermined: boolean;
71
+ };
72
+ export declare function aggregate(input: AggregateInput): EntitlementMap;
73
+ /** The initial map, before anything is known. Every key starts at `unknown` (FR-047). */
74
+ export declare function initialEntitlements(config: ResolvedConfig): EntitlementMap;
75
+ export interface EntitlementChange {
76
+ key: EntitlementKey;
77
+ previous: EntitlementStatus;
78
+ next: EntitlementStatus;
79
+ sources: ProductKey[];
80
+ }
81
+ /**
82
+ * Diffs two maps to produce change signals.
83
+ *
84
+ * Emitting from a diff rather than from grant call sites is what makes the
85
+ * exactly-once guarantees structural (FR-079): a successful subscription renewal
86
+ * changes no status, so it produces no event and cannot double-signal (FR-068);
87
+ * and an entitlement with three sources fires once on transition, not once per
88
+ * source.
89
+ */
90
+ export declare function diffEntitlements(previous: EntitlementMap, next: EntitlementMap): EntitlementChange[];
91
+ /**
92
+ * `next`, with every entitlement that did not change replaced by the object it
93
+ * replaces, and `previous` itself when nothing changed (PERF-03, PAY-08). A hook
94
+ * selecting one entitlement then sees the same object and does not re-render.
95
+ */
96
+ export declare function shareUnchanged(previous: EntitlementMap, next: EntitlementMap): EntitlementMap;
97
+ //# sourceMappingURL=aggregate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../../src/entitlements/aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAiB,CAAC;AAClE,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,4BAAyB,CAAC;AAEpF,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,aAAU,CAAC;AAEhG,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,cAAc,CAAC;AAExE,MAAM,WAAW,kBAAkB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,YAAY,EAAE,YAAY,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAChC,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,2FAA2F;IAC3F,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,+EAA+E;IAC/E,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B,EAAE,OAAO,CAAC;IACvC,GAAG,EAAE,MAAM,CAAC;CACZ;AAkED;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IAC7C,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;IAClD,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACZ,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAS9C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAuB/D;AAED,yFAAyF;AACzF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAY1E;AAED,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,cAAc,CAAC;IACpB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,cAAc,GAClB,iBAAiB,EAAE,CAerB;AAaD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc,CAe7F"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Product ↔ entitlement indexing.
3
+ *
4
+ * The relation is many-to-many (FR-010): monthly, yearly, and lifetime products
5
+ * may all grant `no_ads`, and one bundle product may grant several entitlements.
6
+ *
7
+ * Both directions are indexed once at configure time. The reverse direction is
8
+ * what makes two requirements cheap on hot paths: naming which product currently
9
+ * grants an entitlement (FR-051), and keeping an entitlement valid while *any*
10
+ * source remains (FR-052).
11
+ */
12
+ import type { ResolvedConfig } from '../config/validate.js';
13
+ import type { EntitlementKey, ProductKey } from '../config/types.js';
14
+ /** Entitlements a product confers. Empty for an unknown key rather than throwing. */
15
+ export declare function entitlementsFor(config: ResolvedConfig, productKey: ProductKey): readonly EntitlementKey[];
16
+ /**
17
+ * Translates a store product id back to the app's own product key.
18
+ *
19
+ * Needed because store callbacks and `queryOwned` speak in store ids, while
20
+ * everything above the adapter speaks in product keys (FR-003). Returns
21
+ * `undefined` for an id absent from the catalog — which happens legitimately when
22
+ * a user owns something from a build whose catalog has since changed, so it must
23
+ * be handled rather than treated as impossible.
24
+ */
25
+ export declare function productKeyForStoreId(config: ResolvedConfig, storeProductId: string): ProductKey | undefined;
26
+ export declare function storeIdForProductKey(config: ResolvedConfig, productKey: ProductKey): string | undefined;
27
+ //# sourceMappingURL=mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/entitlements/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAiB,CAAC;AAElE,qFAAqF;AACrF,wBAAgB,eAAe,CAC9B,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,UAAU,GACpB,SAAS,cAAc,EAAE,CAE3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,cAAc,EACtB,cAAc,EAAE,MAAM,GACpB,UAAU,GAAG,SAAS,CAExB;AAED,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,UAAU,GACpB,MAAM,GAAG,SAAS,CAEpB"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Grace and hold entitlement policy.
3
+ *
4
+ * This is a **business decision, not a technical constant** (FR-049), so it is
5
+ * configurable with documented defaults.
6
+ *
7
+ * ## The defaults, and why
8
+ *
9
+ * `gracePolicy: 'grant'` — a grace period means the store is still retrying a
10
+ * payment method that failed for reasons usually outside the user's control: an
11
+ * expired card, a bank decline, a temporary hold. Revoking immediately punishes a
12
+ * paying customer for a billing hiccup they may not know about yet.
13
+ *
14
+ * `holdPolicy: 'withhold'` — account hold means the store has given up retrying.
15
+ * The subscription is effectively unpaid, and continuing to serve paid features
16
+ * indefinitely is giving away the product.
17
+ *
18
+ * ## What Android can actually tell us
19
+ *
20
+ * Client-side Play Billing **cannot** separate grace from hold: a grace-period
21
+ * subscription is still returned as active, and one in account hold stops being
22
+ * returned at all — indistinguishable from expired, cancelled, or refunded.
23
+ *
24
+ * Fortunately the platform's own behavior matches the defaults above. Play keeps
25
+ * returning a grace-period purchase, so the entitlement holds. Play stops
26
+ * returning a held one, so it lapses at the next sync. **The default policy is
27
+ * therefore correct with no backend at all.**
28
+ *
29
+ * What is *not* achievable client-side is a non-default policy — withholding
30
+ * during grace, or granting during hold — because that needs the state the client
31
+ * cannot see. Such an app supplies it through the validation hook (FR-069). This
32
+ * limitation is documented rather than papered over (FR-058).
33
+ */
34
+ import type { LapsePolicy } from '../config/types.js';
35
+ /**
36
+ * A subscription's renewal state as far as the package can honestly tell.
37
+ *
38
+ * `indeterminate` is not a failure — it is the truthful answer when the platform
39
+ * reports a subscription as active but cannot say whether that is a healthy
40
+ * renewal, a cancelled-but-still-paid period, or a grace period.
41
+ */
42
+ export type RenewalState = 'active' | 'cancelled_valid' | 'grace' | 'hold' | 'indeterminate';
43
+ export interface LapsePolicyConfig {
44
+ gracePolicy: LapsePolicy;
45
+ holdPolicy: LapsePolicy;
46
+ }
47
+ export interface SubscriptionFacts {
48
+ expiresAt?: number;
49
+ willAutoRenew?: boolean;
50
+ /** True only where the provider genuinely distinguishes grace/hold. */
51
+ reportsGraceAndHoldDistinctly: boolean;
52
+ /** Provider-reported, only meaningful when the flag above is true. */
53
+ providerRenewalState?: 'active' | 'grace' | 'hold';
54
+ }
55
+ /**
56
+ * Derives the renewal state without inventing information.
57
+ *
58
+ * The temptation is to read `willAutoRenew === false` as "grace period", but that
59
+ * same value is what a deliberate cancellation looks like. Guessing would mean
60
+ * showing "there's a problem with your payment method" to someone who simply
61
+ * chose not to renew — so when the provider cannot distinguish, neither do we.
62
+ */
63
+ export declare function deriveRenewalState(facts: SubscriptionFacts): RenewalState;
64
+ /**
65
+ * Whether a subscription in this state should confer its entitlement.
66
+ *
67
+ * `hold` reaching this function at all requires a provider that reports it,
68
+ * which Android does not. On Android a held subscription simply stops being
69
+ * returned, so it never becomes a source and the entitlement lapses — the same
70
+ * result the `withhold` default expresses.
71
+ */
72
+ export declare function grantsUnderPolicy(state: RenewalState, policy: LapsePolicyConfig): boolean;
73
+ /** True once a subscription's paid period has genuinely elapsed (FR-048). */
74
+ export declare function hasExpired(expiresAt: number | undefined, now: number): boolean;
75
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../../../src/entitlements/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAiB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,eAAe,CAAC;AAE7F,MAAM,WAAW,iBAAiB;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,6BAA6B,EAAE,OAAO,CAAC;IACvC,sEAAsE;IACtE,oBAAoB,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAwBzE;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAczF;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE9E"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * `@chipmobilesdk/rn-payment` — reusable in-app payment and entitlement
3
+ * capability for ChipMobileSdk-family React Native apps.
4
+ *
5
+ * This is the public entrypoint (LIB-003). Modules under `config/`, `core/`,
6
+ * `engine/`, `entitlements/`, `persistence/`, `adapter/`, `diagnostics/`, and
7
+ * `react/` are private; import them only through this file. The fake store lives
8
+ * behind `@chipmobilesdk/rn-payment/testing` so test doubles cannot reach a
9
+ * production bundle.
10
+ *
11
+ * Nothing exported here names Google, Play Billing, or `react-native-iap`
12
+ * (FR-002). `src/__tests__/public-api.test.ts` asserts that mechanically.
13
+ *
14
+ * The package owns **capability**: a safe, consistent way to sell, finalize,
15
+ * restore, and report entitlements. The consuming app owns **policy** — what is
16
+ * sold, at what price, on which screen, at which moment, what each entitlement
17
+ * unlocks, and how generous the grace policy is. There is no product identifier,
18
+ * no screen name, and no business rule in this package (FR-016).
19
+ *
20
+ * The one output that matters most is the **entitlement key**: an app-chosen key
21
+ * such as `no_ads`. Business logic asks about entitlement keys and never about
22
+ * store product identifiers, product types, or which store sold the thing.
23
+ */
24
+ export type { BackoffConfig, BlockedOperation, CatalogEntry, EntitlementKey, Environment, FinalizeResult, LapsePolicy, LoggerAdapter, PaymentConfig, PaymentStatus, PaymentStatusKind, PendingPurchase, PendingPurchasesState, PendingResolution, ProductKey, ProductType, PurchaseOptions, PurchaseResult, RetryConfig, StoreProductIds, TimeoutConfig, TransactionRef, UnavailableReason, UnfinalizedSummary, Unsubscribe, ValidationCandidate, ValidationDecision, ValidationHook, ValidationUnavailablePolicy, } from './config/types.js';
25
+ export { BACKOFF_ATTEMPT_BOUNDS, BACKOFF_MAX_DELAY_BOUNDS, CONNECT_TIMEOUT_BOUNDS, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_FINALIZE_ATTEMPT_TIMEOUT_MS, DEFAULT_FINALIZE_BACKOFF, DEFAULT_FOREGROUND_SYNC_MIN_INTERVAL_MS, DEFAULT_PRODUCT_CACHE_TTL_MS, DEFAULT_PRODUCT_QUERY_TIMEOUT_MS, DEFAULT_PURCHASE_LAUNCH_TIMEOUT_MS, DEFAULT_RECONNECT_BACKOFF, DEFAULT_STALE_AFTER_MS, DEFAULT_SYNC_TIMEOUT_MS, FINALIZE_ATTEMPT_TIMEOUT_BOUNDS, FOREGROUND_SYNC_MIN_INTERVAL_BOUNDS, PRODUCT_CACHE_TTL_BOUNDS, PRODUCT_QUERY_TIMEOUT_BOUNDS, PURCHASE_LAUNCH_TIMEOUT_BOUNDS, STALE_AFTER_BOUNDS, SYNC_TIMEOUT_BOUNDS, } from './core/timers.js';
26
+ export type { MissingProduct, MissingProductReason, Offer, ProductInfo, ProductQueryResult, } from './engine/products.js';
27
+ export type { PriceChangeResult, ProrationMode } from './engine/subscriptions.js';
28
+ export type { EntitlementMap, EntitlementState, EntitlementStatus, SubscriptionDetail, } from './entitlements/aggregate.js';
29
+ export type { RenewalState } from './entitlements/policy.js';
30
+ export { createStoreProvider } from './adapter/createStoreProvider.js';
31
+ export type { StoreProviderOptions } from './adapter/createStoreProvider.js';
32
+ export { createEngine } from './engine/engine.js';
33
+ export type { EngineDeps, InitOutcome, PaymentEngine, RestoreOutcome, SyncOutcome, } from './engine/engine.js';
34
+ export { syncOnForeground } from './engine/foreground.js';
35
+ export { PaymentProvider, usePaymentEngine } from './react/PaymentProvider.js';
36
+ export type { PaymentProviderProps } from './react/PaymentProvider.js';
37
+ export { useEntitlement, useEntitlements, usePaymentStatus, usePendingPurchases, useProducts, usePurchase, useSync, } from './react/hooks.js';
38
+ export type { UseProductsResult, UsePurchaseResult, UseSyncResult } from './react/hooks.js';
39
+ export { PaymentConfigError, PaymentError, PAYMENT_ERROR_CODES } from './diagnostics/errors.js';
40
+ export type { PaymentErrorCode, PaymentOperation } from './diagnostics/errors.js';
41
+ export type { PaymentEvent, PaymentEventListener, PaymentEventType, SyncTrigger, } from './diagnostics/events.js';
42
+ export { DEFAULT_DEVELOPER_MESSAGES, DEFAULT_MESSAGES, paymentMessages, DEFAULT_USER_MESSAGES, DEVELOPER_MESSAGE_KEYS, USER_MESSAGE_KEYS, isUserMessageKey, } from './diagnostics/messageKeys.js';
43
+ export type { PaymentDeveloperMessageKey, PaymentDeveloperMessageMap, PaymentMessageKey, PaymentMessageMap, PaymentUserMessageKey, PaymentUserMessageMap, } from './diagnostics/messageKeys.js';
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,YAAY,EACX,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,eAAe,EACf,cAAc,EACd,WAAW,EACX,eAAe,EACf,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,2BAA2B,GAC3B,MAAM,mBAAgB,CAAC;AAKxB,OAAO,EACN,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,mCAAmC,EACnC,wBAAwB,EACxB,uCAAuC,EACvC,4BAA4B,EAC5B,gCAAgC,EAChC,kCAAkC,EAClC,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAC/B,mCAAmC,EACnC,wBAAwB,EACxB,4BAA4B,EAC5B,8BAA8B,EAC9B,kBAAkB,EAClB,mBAAmB,GACnB,MAAM,kBAAe,CAAC;AAGvB,YAAY,EACX,cAAc,EACd,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,kBAAkB,GAClB,MAAM,sBAAmB,CAAC;AAG3B,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,2BAAwB,CAAC;AAG/E,YAAY,EACX,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,6BAA0B,CAAC;AAClC,YAAY,EAAE,YAAY,EAAE,MAAM,0BAAuB,CAAC;AAO1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAA+B,CAAC;AACpE,YAAY,EAAE,oBAAoB,EAAE,MAAM,kCAA+B,CAAC;AAG1E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAiB,CAAC;AAC/C,YAAY,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,WAAW,GACX,MAAM,oBAAiB,CAAC;AAEzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAqB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,4BAAyB,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,MAAM,4BAAyB,CAAC;AACpE,OAAO,EACN,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,OAAO,GACP,MAAM,kBAAe,CAAC;AACvB,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAe,CAAC;AAGzF,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAsB,CAAC;AAC7F,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,yBAAsB,CAAC;AAC/E,YAAY,EACX,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,GACX,MAAM,yBAAsB,CAAC;AAK9B,OAAO,EACN,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,8BAA2B,CAAC;AACnC,YAAY,EACX,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACrB,MAAM,8BAA2B,CAAC"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * MMKV-backed snapshot store.
3
+ *
4
+ * Every MMKV import is confined to this file, so the rest of the package stays
5
+ * testable without a native module.
6
+ *
7
+ * MMKV is chosen because it is **synchronous**, which is what lets
8
+ * `getEntitlement` be an in-memory read with no I/O on render paths (PERF-001).
9
+ * An async store would force either an async entitlement read or a hidden
10
+ * hydration race on every call.
11
+ *
12
+ * Records are partitioned by cache-scope token (FR-057a). The token is a
13
+ * partition key and nothing more: never interpreted, never transmitted, never
14
+ * attached to a transaction.
15
+ */
16
+ import { type MmkvLike } from '@chipmobilesdk/rn-core';
17
+ import { type PersistedSnapshot } from './snapshot.js';
18
+ export interface SnapshotStore {
19
+ load(scopeToken?: string): PersistedSnapshot;
20
+ /**
21
+ * Writes the snapshot. Returns false when the write failed, so the engine can
22
+ * say so; a store returning nothing is taken to have succeeded.
23
+ */
24
+ save(snapshot: PersistedSnapshot): boolean | void;
25
+ /** Clears every scope — for logout and data-deletion requests (FR-057). */
26
+ clearAll(): void;
27
+ /** Whether writes actually persist. False means the memory fallback is active. */
28
+ isDurable(): boolean;
29
+ }
30
+ /**
31
+ * Creates the store.
32
+ *
33
+ * The memory fallback is a **documented degradation**, not a silent one: without
34
+ * MMKV the snapshot does not survive a cold start, so entitlements read `unknown`
35
+ * until the first sync. That is safe by construction — `unknown`, never
36
+ * `not_entitled` (FR-047) — and FR-059's startup sync repairs it. `isDurable()`
37
+ * lets the engine warn, so the condition is visible rather than mysterious.
38
+ */
39
+ export declare function createSnapshotStore(injected?: {
40
+ backing: MmkvLike;
41
+ durable: boolean;
42
+ }): SnapshotStore;
43
+ /** Test seam for driving the store without the native module. */
44
+ export declare function createMemorySnapshotStore(): SnapshotStore;
45
+ //# sourceMappingURL=mmkv-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mmkv-store.d.ts","sourceRoot":"","sources":["../../../../src/persistence/mmkv-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAA+C,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEpG,OAAO,EAAkC,KAAK,iBAAiB,EAAE,MAAM,eAAY,CAAC;AAcpF,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAC7C;;;OAGG;IACH,IAAI,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,GAAG,IAAI,CAAC;IAClD,2EAA2E;IAC3E,QAAQ,IAAI,IAAI,CAAC;IACjB,kFAAkF;IAClF,SAAS,IAAI,OAAO,CAAC;CACrB;AAkCD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,CAAC,EAAE;IAC9C,OAAO,EAAE,QAAQ,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CACjB,GAAG,aAAa,CA4DhB;AAED,iEAAiE;AACjE,wBAAgB,yBAAyB,IAAI,aAAa,CAYzD"}