@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.
- package/CHANGELOG.md +172 -0
- package/README.md +47 -16
- package/lib/commonjs/adapter/createStoreProvider.js +110 -0
- package/lib/commonjs/adapter/createStoreProvider.js.map +1 -0
- package/lib/commonjs/adapter/iap-adapter.js +393 -0
- package/lib/commonjs/adapter/iap-adapter.js.map +1 -0
- package/lib/commonjs/adapter/iapShapes.js +169 -0
- package/lib/commonjs/adapter/iapShapes.js.map +1 -0
- package/lib/commonjs/adapter/port.js +6 -0
- package/lib/commonjs/adapter/port.js.map +1 -0
- package/lib/commonjs/config/types.js +2 -0
- package/lib/commonjs/config/types.js.map +1 -0
- package/lib/commonjs/config/validate.js +181 -0
- package/lib/commonjs/config/validate.js.map +1 -0
- package/lib/commonjs/core/mutex.js +31 -0
- package/lib/commonjs/core/mutex.js.map +1 -0
- package/lib/commonjs/core/retry.js +37 -0
- package/lib/commonjs/core/retry.js.map +1 -0
- package/lib/commonjs/core/timers.js +207 -0
- package/lib/commonjs/core/timers.js.map +1 -0
- package/lib/commonjs/diagnostics/errors.js +83 -0
- package/lib/commonjs/diagnostics/errors.js.map +1 -0
- package/lib/commonjs/diagnostics/events.js +126 -0
- package/lib/commonjs/diagnostics/events.js.map +1 -0
- package/lib/commonjs/diagnostics/messageKeys.js +70 -0
- package/lib/commonjs/diagnostics/messageKeys.js.map +1 -0
- package/lib/commonjs/engine/connection.js +189 -0
- package/lib/commonjs/engine/connection.js.map +1 -0
- package/lib/commonjs/engine/engine.js +279 -0
- package/lib/commonjs/engine/engine.js.map +1 -0
- package/lib/commonjs/engine/finalize.js +325 -0
- package/lib/commonjs/engine/finalize.js.map +1 -0
- package/lib/commonjs/engine/foreground.js +26 -0
- package/lib/commonjs/engine/foreground.js.map +1 -0
- package/lib/commonjs/engine/internals.js +31 -0
- package/lib/commonjs/engine/internals.js.map +1 -0
- package/lib/commonjs/engine/pending.js +102 -0
- package/lib/commonjs/engine/pending.js.map +1 -0
- package/lib/commonjs/engine/products.js +198 -0
- package/lib/commonjs/engine/products.js.map +1 -0
- package/lib/commonjs/engine/purchase.js +395 -0
- package/lib/commonjs/engine/purchase.js.map +1 -0
- package/lib/commonjs/engine/purchaseFailure.js +77 -0
- package/lib/commonjs/engine/purchaseFailure.js.map +1 -0
- package/lib/commonjs/engine/receiptValidation.js +90 -0
- package/lib/commonjs/engine/receiptValidation.js.map +1 -0
- package/lib/commonjs/engine/state.js +201 -0
- package/lib/commonjs/engine/state.js.map +1 -0
- package/lib/commonjs/engine/subscriptions.js +122 -0
- package/lib/commonjs/engine/subscriptions.js.map +1 -0
- package/lib/commonjs/engine/sync.js +163 -0
- package/lib/commonjs/engine/sync.js.map +1 -0
- package/lib/commonjs/entitlements/aggregate.js +212 -0
- package/lib/commonjs/entitlements/aggregate.js.map +1 -0
- package/lib/commonjs/entitlements/mapping.js +41 -0
- package/lib/commonjs/entitlements/mapping.js.map +1 -0
- package/lib/commonjs/entitlements/policy.js +110 -0
- package/lib/commonjs/entitlements/policy.js.map +1 -0
- package/lib/commonjs/index.js +266 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/persistence/mmkv-store.js +149 -0
- package/lib/commonjs/persistence/mmkv-store.js.map +1 -0
- package/lib/commonjs/persistence/snapshot.js +229 -0
- package/lib/commonjs/persistence/snapshot.js.map +1 -0
- package/lib/commonjs/react/PaymentProvider.js +96 -0
- package/lib/commonjs/react/PaymentProvider.js.map +1 -0
- package/lib/commonjs/react/hooks.js +202 -0
- package/lib/commonjs/react/hooks.js.map +1 -0
- package/lib/commonjs/testing/conformance.js +136 -0
- package/lib/commonjs/testing/conformance.js.map +1 -0
- package/lib/commonjs/testing/fakeStore.js +281 -0
- package/lib/commonjs/testing/fakeStore.js.map +1 -0
- package/lib/commonjs/testing/index.js +45 -0
- package/lib/commonjs/testing/index.js.map +1 -0
- package/lib/module/adapter/createStoreProvider.js +106 -0
- package/lib/module/adapter/createStoreProvider.js.map +1 -0
- package/lib/module/adapter/iap-adapter.js +383 -0
- package/lib/module/adapter/iap-adapter.js.map +1 -0
- package/lib/module/adapter/iapShapes.js +160 -0
- package/lib/module/adapter/iapShapes.js.map +1 -0
- package/lib/module/adapter/port.js +4 -0
- package/lib/module/adapter/port.js.map +1 -0
- package/lib/module/config/types.js +2 -0
- package/lib/module/config/types.js.map +1 -0
- package/lib/module/config/validate.js +175 -0
- package/lib/module/config/validate.js.map +1 -0
- package/lib/module/core/mutex.js +22 -0
- package/lib/module/core/mutex.js.map +1 -0
- package/lib/module/core/retry.js +33 -0
- package/lib/module/core/retry.js.map +1 -0
- package/lib/module/core/timers.js +198 -0
- package/lib/module/core/timers.js.map +1 -0
- package/lib/module/diagnostics/errors.js +76 -0
- package/lib/module/diagnostics/errors.js.map +1 -0
- package/lib/module/diagnostics/events.js +117 -0
- package/lib/module/diagnostics/events.js.map +1 -0
- package/lib/module/diagnostics/messageKeys.js +64 -0
- package/lib/module/diagnostics/messageKeys.js.map +1 -0
- package/lib/module/engine/connection.js +185 -0
- package/lib/module/engine/connection.js.map +1 -0
- package/lib/module/engine/engine.js +274 -0
- package/lib/module/engine/engine.js.map +1 -0
- package/lib/module/engine/finalize.js +322 -0
- package/lib/module/engine/finalize.js.map +1 -0
- package/lib/module/engine/foreground.js +21 -0
- package/lib/module/engine/foreground.js.map +1 -0
- package/lib/module/engine/internals.js +26 -0
- package/lib/module/engine/internals.js.map +1 -0
- package/lib/module/engine/pending.js +95 -0
- package/lib/module/engine/pending.js.map +1 -0
- package/lib/module/engine/products.js +195 -0
- package/lib/module/engine/products.js.map +1 -0
- package/lib/module/engine/purchase.js +390 -0
- package/lib/module/engine/purchase.js.map +1 -0
- package/lib/module/engine/purchaseFailure.js +72 -0
- package/lib/module/engine/purchaseFailure.js.map +1 -0
- package/lib/module/engine/receiptValidation.js +87 -0
- package/lib/module/engine/receiptValidation.js.map +1 -0
- package/lib/module/engine/state.js +196 -0
- package/lib/module/engine/state.js.map +1 -0
- package/lib/module/engine/subscriptions.js +119 -0
- package/lib/module/engine/subscriptions.js.map +1 -0
- package/lib/module/engine/sync.js +158 -0
- package/lib/module/engine/sync.js.map +1 -0
- package/lib/module/entitlements/aggregate.js +204 -0
- package/lib/module/entitlements/aggregate.js.map +1 -0
- package/lib/module/entitlements/mapping.js +35 -0
- package/lib/module/entitlements/mapping.js.map +1 -0
- package/lib/module/entitlements/policy.js +104 -0
- package/lib/module/entitlements/policy.js.map +1 -0
- package/lib/module/index.js +59 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/persistence/mmkv-store.js +144 -0
- package/lib/module/persistence/mmkv-store.js.map +1 -0
- package/lib/module/persistence/snapshot.js +221 -0
- package/lib/module/persistence/snapshot.js.map +1 -0
- package/lib/module/react/PaymentProvider.js +90 -0
- package/lib/module/react/PaymentProvider.js.map +1 -0
- package/lib/module/react/hooks.js +192 -0
- package/lib/module/react/hooks.js.map +1 -0
- package/lib/module/testing/conformance.js +130 -0
- package/lib/module/testing/conformance.js.map +1 -0
- package/lib/module/testing/fakeStore.js +276 -0
- package/lib/module/testing/fakeStore.js.map +1 -0
- package/lib/module/testing/index.js +13 -0
- package/lib/module/testing/index.js.map +1 -0
- package/lib/typescript/commonjs/adapter/createStoreProvider.d.ts +45 -0
- package/lib/typescript/commonjs/adapter/createStoreProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/adapter/iap-adapter.d.ts +80 -0
- package/lib/typescript/commonjs/adapter/iap-adapter.d.ts.map +1 -0
- package/lib/typescript/commonjs/adapter/iapShapes.d.ts +94 -0
- package/lib/typescript/commonjs/adapter/iapShapes.d.ts.map +1 -0
- package/lib/typescript/commonjs/adapter/port.d.ts +184 -0
- package/lib/typescript/commonjs/adapter/port.d.ts.map +1 -0
- package/lib/typescript/commonjs/config/types.d.ts +326 -0
- package/lib/typescript/commonjs/config/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/config/validate.d.ts +63 -0
- package/lib/typescript/commonjs/config/validate.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/mutex.d.ts +17 -0
- package/lib/typescript/commonjs/core/mutex.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/retry.d.ts +19 -0
- package/lib/typescript/commonjs/core/retry.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/timers.d.ts +142 -0
- package/lib/typescript/commonjs/core/timers.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts +55 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/events.d.ts +158 -0
- package/lib/typescript/commonjs/diagnostics/events.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts +54 -0
- package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/connection.d.ts +30 -0
- package/lib/typescript/commonjs/engine/connection.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/engine.d.ts +93 -0
- package/lib/typescript/commonjs/engine/engine.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/finalize.d.ts +53 -0
- package/lib/typescript/commonjs/engine/finalize.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/foreground.d.ts +15 -0
- package/lib/typescript/commonjs/engine/foreground.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/internals.d.ts +28 -0
- package/lib/typescript/commonjs/engine/internals.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/pending.d.ts +51 -0
- package/lib/typescript/commonjs/engine/pending.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/products.d.ts +82 -0
- package/lib/typescript/commonjs/engine/products.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/purchase.d.ts +61 -0
- package/lib/typescript/commonjs/engine/purchase.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/purchaseFailure.d.ts +15 -0
- package/lib/typescript/commonjs/engine/purchaseFailure.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/receiptValidation.d.ts +42 -0
- package/lib/typescript/commonjs/engine/receiptValidation.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/state.d.ts +46 -0
- package/lib/typescript/commonjs/engine/state.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/subscriptions.d.ts +61 -0
- package/lib/typescript/commonjs/engine/subscriptions.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/sync.d.ts +36 -0
- package/lib/typescript/commonjs/engine/sync.d.ts.map +1 -0
- package/lib/typescript/commonjs/entitlements/aggregate.d.ts +97 -0
- package/lib/typescript/commonjs/entitlements/aggregate.d.ts.map +1 -0
- package/lib/typescript/commonjs/entitlements/mapping.d.ts +27 -0
- package/lib/typescript/commonjs/entitlements/mapping.d.ts.map +1 -0
- package/lib/typescript/commonjs/entitlements/policy.d.ts +75 -0
- package/lib/typescript/commonjs/entitlements/policy.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +44 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/persistence/mmkv-store.d.ts +45 -0
- package/lib/typescript/commonjs/persistence/mmkv-store.d.ts.map +1 -0
- package/lib/typescript/commonjs/persistence/snapshot.d.ts +106 -0
- package/lib/typescript/commonjs/persistence/snapshot.d.ts.map +1 -0
- package/lib/typescript/commonjs/react/PaymentProvider.d.ts +57 -0
- package/lib/typescript/commonjs/react/PaymentProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/react/hooks.d.ts +80 -0
- package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
- package/lib/typescript/commonjs/testing/conformance.d.ts +41 -0
- package/lib/typescript/commonjs/testing/conformance.d.ts.map +1 -0
- package/lib/typescript/commonjs/testing/fakeStore.d.ts +69 -0
- package/lib/typescript/commonjs/testing/fakeStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/testing/index.d.ts +12 -0
- package/lib/typescript/commonjs/testing/index.d.ts.map +1 -0
- package/lib/typescript/module/adapter/createStoreProvider.d.ts +45 -0
- package/lib/typescript/module/adapter/createStoreProvider.d.ts.map +1 -0
- package/lib/typescript/module/adapter/iap-adapter.d.ts +80 -0
- package/lib/typescript/module/adapter/iap-adapter.d.ts.map +1 -0
- package/lib/typescript/module/adapter/iapShapes.d.ts +94 -0
- package/lib/typescript/module/adapter/iapShapes.d.ts.map +1 -0
- package/lib/typescript/module/adapter/port.d.ts +184 -0
- package/lib/typescript/module/adapter/port.d.ts.map +1 -0
- package/lib/typescript/module/config/types.d.ts +326 -0
- package/lib/typescript/module/config/types.d.ts.map +1 -0
- package/lib/typescript/module/config/validate.d.ts +63 -0
- package/lib/typescript/module/config/validate.d.ts.map +1 -0
- package/lib/typescript/module/core/mutex.d.ts +17 -0
- package/lib/typescript/module/core/mutex.d.ts.map +1 -0
- package/lib/typescript/module/core/retry.d.ts +19 -0
- package/lib/typescript/module/core/retry.d.ts.map +1 -0
- package/lib/typescript/module/core/timers.d.ts +142 -0
- package/lib/typescript/module/core/timers.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/errors.d.ts +55 -0
- package/lib/typescript/module/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/events.d.ts +158 -0
- package/lib/typescript/module/diagnostics/events.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/messageKeys.d.ts +54 -0
- package/lib/typescript/module/diagnostics/messageKeys.d.ts.map +1 -0
- package/lib/typescript/module/engine/connection.d.ts +30 -0
- package/lib/typescript/module/engine/connection.d.ts.map +1 -0
- package/lib/typescript/module/engine/engine.d.ts +93 -0
- package/lib/typescript/module/engine/engine.d.ts.map +1 -0
- package/lib/typescript/module/engine/finalize.d.ts +53 -0
- package/lib/typescript/module/engine/finalize.d.ts.map +1 -0
- package/lib/typescript/module/engine/foreground.d.ts +15 -0
- package/lib/typescript/module/engine/foreground.d.ts.map +1 -0
- package/lib/typescript/module/engine/internals.d.ts +28 -0
- package/lib/typescript/module/engine/internals.d.ts.map +1 -0
- package/lib/typescript/module/engine/pending.d.ts +51 -0
- package/lib/typescript/module/engine/pending.d.ts.map +1 -0
- package/lib/typescript/module/engine/products.d.ts +82 -0
- package/lib/typescript/module/engine/products.d.ts.map +1 -0
- package/lib/typescript/module/engine/purchase.d.ts +61 -0
- package/lib/typescript/module/engine/purchase.d.ts.map +1 -0
- package/lib/typescript/module/engine/purchaseFailure.d.ts +15 -0
- package/lib/typescript/module/engine/purchaseFailure.d.ts.map +1 -0
- package/lib/typescript/module/engine/receiptValidation.d.ts +42 -0
- package/lib/typescript/module/engine/receiptValidation.d.ts.map +1 -0
- package/lib/typescript/module/engine/state.d.ts +46 -0
- package/lib/typescript/module/engine/state.d.ts.map +1 -0
- package/lib/typescript/module/engine/subscriptions.d.ts +61 -0
- package/lib/typescript/module/engine/subscriptions.d.ts.map +1 -0
- package/lib/typescript/module/engine/sync.d.ts +36 -0
- package/lib/typescript/module/engine/sync.d.ts.map +1 -0
- package/lib/typescript/module/entitlements/aggregate.d.ts +97 -0
- package/lib/typescript/module/entitlements/aggregate.d.ts.map +1 -0
- package/lib/typescript/module/entitlements/mapping.d.ts +27 -0
- package/lib/typescript/module/entitlements/mapping.d.ts.map +1 -0
- package/lib/typescript/module/entitlements/policy.d.ts +75 -0
- package/lib/typescript/module/entitlements/policy.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +44 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/persistence/mmkv-store.d.ts +45 -0
- package/lib/typescript/module/persistence/mmkv-store.d.ts.map +1 -0
- package/lib/typescript/module/persistence/snapshot.d.ts +106 -0
- package/lib/typescript/module/persistence/snapshot.d.ts.map +1 -0
- package/lib/typescript/module/react/PaymentProvider.d.ts +57 -0
- package/lib/typescript/module/react/PaymentProvider.d.ts.map +1 -0
- package/lib/typescript/module/react/hooks.d.ts +80 -0
- package/lib/typescript/module/react/hooks.d.ts.map +1 -0
- package/lib/typescript/module/testing/conformance.d.ts +41 -0
- package/lib/typescript/module/testing/conformance.d.ts.map +1 -0
- package/lib/typescript/module/testing/fakeStore.d.ts +69 -0
- package/lib/typescript/module/testing/fakeStore.d.ts.map +1 -0
- package/lib/typescript/module/testing/index.d.ts +12 -0
- package/lib/typescript/module/testing/index.d.ts.map +1 -0
- package/package.json +49 -13
- package/skills/sdk-rn-payment/SKILL.md +4 -4
- package/src/adapter/iap-adapter.ts +12 -216
- package/src/adapter/iapShapes.ts +232 -0
- package/src/config/types.ts +8 -0
- package/src/config/validate.ts +19 -4
- package/src/core/retry.ts +1 -58
- package/src/diagnostics/events.ts +1 -1
- package/src/engine/connection.ts +194 -0
- package/src/engine/engine.ts +140 -700
- package/src/engine/internals.ts +40 -0
- package/src/engine/products.ts +39 -17
- package/src/engine/purchase.ts +22 -130
- package/src/engine/purchaseFailure.ts +48 -0
- package/src/engine/receiptValidation.ts +101 -0
- package/src/engine/state.ts +253 -0
- package/src/engine/sync.ts +161 -0
- package/src/entitlements/aggregate.ts +3 -5
- package/src/entitlements/mapping.ts +0 -22
- package/src/persistence/mmkv-store.ts +10 -3
- package/src/persistence/snapshot.ts +102 -27
- package/src/react/PaymentProvider.tsx +73 -24
- package/src/react/hooks.ts +13 -3
|
@@ -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';
|
|
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,iBAAiB,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';
|
|
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';
|
|
26
|
+
export type { MissingProduct, MissingProductReason, Offer, ProductInfo, ProductQueryResult, } from './engine/products';
|
|
27
|
+
export type { PriceChangeResult, ProrationMode } from './engine/subscriptions';
|
|
28
|
+
export type { EntitlementMap, EntitlementState, EntitlementStatus, SubscriptionDetail, } from './entitlements/aggregate';
|
|
29
|
+
export type { RenewalState } from './entitlements/policy';
|
|
30
|
+
export { createStoreProvider } from './adapter/createStoreProvider';
|
|
31
|
+
export type { StoreProviderOptions } from './adapter/createStoreProvider';
|
|
32
|
+
export { createEngine } from './engine/engine';
|
|
33
|
+
export type { EngineDeps, InitOutcome, PaymentEngine, RestoreOutcome, SyncOutcome, } from './engine/engine';
|
|
34
|
+
export { syncOnForeground } from './engine/foreground';
|
|
35
|
+
export { PaymentProvider, usePaymentEngine } from './react/PaymentProvider';
|
|
36
|
+
export type { PaymentProviderProps } from './react/PaymentProvider';
|
|
37
|
+
export { useEntitlement, useEntitlements, usePaymentStatus, usePendingPurchases, useProducts, usePurchase, useSync, } from './react/hooks';
|
|
38
|
+
export type { UseProductsResult, UsePurchaseResult, UseSyncResult } from './react/hooks';
|
|
39
|
+
export { PaymentConfigError, PaymentError, PAYMENT_ERROR_CODES } from './diagnostics/errors';
|
|
40
|
+
export type { PaymentErrorCode, PaymentOperation } from './diagnostics/errors';
|
|
41
|
+
export type { PaymentEvent, PaymentEventListener, PaymentEventType, SyncTrigger, } from './diagnostics/events';
|
|
42
|
+
export { DEFAULT_DEVELOPER_MESSAGES, DEFAULT_MESSAGES, paymentMessages, DEFAULT_USER_MESSAGES, DEVELOPER_MESSAGE_KEYS, USER_MESSAGE_KEYS, isUserMessageKey, } from './diagnostics/messageKeys';
|
|
43
|
+
export type { PaymentDeveloperMessageKey, PaymentDeveloperMessageMap, PaymentMessageKey, PaymentMessageMap, PaymentUserMessageKey, PaymentUserMessageMap, } from './diagnostics/messageKeys';
|
|
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,gBAAgB,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,eAAe,CAAC;AAGvB,YAAY,EACX,cAAc,EACd,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,kBAAkB,GAClB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG/E,YAAY,EACX,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAO1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EACX,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,WAAW,GACX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACN,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,OAAO,GACP,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGzF,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,YAAY,EACX,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,GACX,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EACN,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACX,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACrB,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -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';
|
|
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,YAAY,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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The persisted snapshot: schema, versioning, and migration.
|
|
3
|
+
*
|
|
4
|
+
* What is stored here is **exhaustively** what the package keeps on the device,
|
|
5
|
+
* and the README repeats this list so an app owner can complete a Data safety
|
|
6
|
+
* declaration accurately (FR-056, POL-002).
|
|
7
|
+
*
|
|
8
|
+
* Deliberately absent: payment details, card data, billing address, user
|
|
9
|
+
* identity, raw receipts, verification payloads, and backend tokens.
|
|
10
|
+
*/
|
|
11
|
+
import type { ProductKey, ProductType } from '../config/types';
|
|
12
|
+
/**
|
|
13
|
+
* 2 since 0.6.0: the never-written `entitlements` map and `finalized` state are
|
|
14
|
+
* gone (PAY-12). Entitlements are always derived from purchases, never stored.
|
|
15
|
+
*/
|
|
16
|
+
export declare const SNAPSHOT_SCHEMA_VERSION = 2;
|
|
17
|
+
/** Where a transaction stands with the store. */
|
|
18
|
+
export type PersistedPurchaseState = 'pending' | 'purchased' | 'consumed' | 'revoked';
|
|
19
|
+
/**
|
|
20
|
+
* Where a transaction stands in the finalization queue.
|
|
21
|
+
*
|
|
22
|
+
* `queued` is the load-bearing value: it is written **before** the store call is
|
|
23
|
+
* attempted, so an app killed mid-finalize leaves a recoverable record rather
|
|
24
|
+
* than a paid purchase that Google will auto-refund (FR-041, FR-042).
|
|
25
|
+
*/
|
|
26
|
+
export type PersistedFinalizeState = 'not_required' | 'queued' | 'in_flight' | 'done' | 'failed';
|
|
27
|
+
/** Whether the app's backend has ruled on this transaction (FR-072a). */
|
|
28
|
+
export type PersistedValidationState = 'not_required' | 'approved' | 'rejected' | 'queued_for_revalidation';
|
|
29
|
+
export interface PersistedPurchase {
|
|
30
|
+
transactionId: string;
|
|
31
|
+
productKey: ProductKey;
|
|
32
|
+
productType: ProductType;
|
|
33
|
+
token: string;
|
|
34
|
+
state: PersistedPurchaseState;
|
|
35
|
+
purchasedAt: number;
|
|
36
|
+
finalizeState: PersistedFinalizeState;
|
|
37
|
+
/** Attempts consumed. Carried across sessions so retry stays bounded per session. */
|
|
38
|
+
attempts: number;
|
|
39
|
+
validationState: PersistedValidationState;
|
|
40
|
+
expiresAt?: number;
|
|
41
|
+
willAutoRenew?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface PersistedSnapshot {
|
|
44
|
+
schemaVersion: number;
|
|
45
|
+
/** Opaque partition key. Stored only to scope this record (FR-057a). */
|
|
46
|
+
scopeToken?: string;
|
|
47
|
+
purchases: PersistedPurchase[];
|
|
48
|
+
lastSyncedAt?: number;
|
|
49
|
+
}
|
|
50
|
+
export declare function emptySnapshot(scopeToken?: string): PersistedSnapshot;
|
|
51
|
+
/**
|
|
52
|
+
* A migration from one schema version to the next.
|
|
53
|
+
*
|
|
54
|
+
* Kept as an ordered chain rather than a switch so each step stays small and
|
|
55
|
+
* independently testable, and so a device several versions behind is carried
|
|
56
|
+
* forward one hop at a time (NFR-009).
|
|
57
|
+
*/
|
|
58
|
+
export interface SnapshotMigration {
|
|
59
|
+
from: number;
|
|
60
|
+
to: number;
|
|
61
|
+
migrate(input: Record<string, unknown>): Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
/** Registered migrations, one hop each. */
|
|
64
|
+
export declare const SNAPSHOT_MIGRATIONS: readonly SnapshotMigration[];
|
|
65
|
+
export type MigrationOutcome = {
|
|
66
|
+
ok: true;
|
|
67
|
+
snapshot: PersistedSnapshot;
|
|
68
|
+
migrated: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Unreadable records are discarded, not repaired.
|
|
72
|
+
*
|
|
73
|
+
* Safe because discarding yields `unknown`, never a false `not_entitled`
|
|
74
|
+
* (FR-055a), and the next sync rebuilds from the store — the authoritative
|
|
75
|
+
* source anyway. Guessing at a corrupt record risks granting or withholding
|
|
76
|
+
* wrongly, which is worse than a short `unknown` window.
|
|
77
|
+
*/
|
|
78
|
+
| {
|
|
79
|
+
ok: false;
|
|
80
|
+
reason: 'unreadable' | 'unsupported_version';
|
|
81
|
+
};
|
|
82
|
+
export declare function migrateSnapshot(raw: unknown): MigrationOutcome;
|
|
83
|
+
/**
|
|
84
|
+
* Decides a purchase's finalization state from the store's view plus what we
|
|
85
|
+
* already knew.
|
|
86
|
+
*
|
|
87
|
+
* Shared by the sync path and the purchase path so they cannot drift — and they
|
|
88
|
+
* must not, because a disagreement here is how a paid transaction goes
|
|
89
|
+
* unacknowledged and gets auto-refunded three days later.
|
|
90
|
+
*
|
|
91
|
+
* The subtle case is a **pending purchase that settles**. Its record was written
|
|
92
|
+
* with `not_required`, which was correct while the money had not arrived. Once the
|
|
93
|
+
* store reports it `purchased`, that value must be re-evaluated rather than
|
|
94
|
+
* preserved — otherwise the transaction is never queued, never acknowledged, and
|
|
95
|
+
* Google revokes it. Progress is preserved only for a transaction that was
|
|
96
|
+
* already in the queue.
|
|
97
|
+
*/
|
|
98
|
+
export declare function resolveFinalizeState(incoming: {
|
|
99
|
+
state: 'purchased' | 'pending' | 'unspecified';
|
|
100
|
+
isAcknowledged: boolean;
|
|
101
|
+
}, existing: {
|
|
102
|
+
finalizeState: PersistedFinalizeState;
|
|
103
|
+
} | undefined): PersistedFinalizeState;
|
|
104
|
+
/** Transactions still owed a finalize call, drained at startup and on foreground (FR-042). */
|
|
105
|
+
export declare function pendingFinalizations(snapshot: PersistedSnapshot): PersistedPurchase[];
|
|
106
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../../../src/persistence/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC,iDAAiD;AACjD,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG,cAAc,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjG,yEAAyE;AACzE,MAAM,MAAM,wBAAwB,GACnC,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,yBAAyB,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,sBAAsB,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,sBAAsB,CAAC;IACtC,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,wBAAwB,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAOpE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjE;AAED,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,EAAE,SAAS,iBAAiB,EAsB3D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE;AAC9D;;;;;;;GAOG;GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,qBAAqB,CAAA;CAAE,CAAC;AAE/D,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAgC9D;AAgGD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE;IAAE,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE,EACrF,QAAQ,EAAE;IAAE,aAAa,EAAE,sBAAsB,CAAA;CAAE,GAAG,SAAS,GAC7D,sBAAsB,CAoBxB;AAED,8FAA8F;AAC9F,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,iBAAiB,EAAE,CAQrF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React integration.
|
|
3
|
+
*
|
|
4
|
+
* The provider owns the engine's lifecycle so an app does not have to remember to
|
|
5
|
+
* clean up. It renders nothing of its own — no paywall, no price table, no
|
|
6
|
+
* button. Every surface belongs to the app (UX-001).
|
|
7
|
+
*/
|
|
8
|
+
import React, { type PropsWithChildren } from 'react';
|
|
9
|
+
import { type EngineDeps, type PaymentEngine } from '../engine/engine';
|
|
10
|
+
import type { PaymentConfig } from '../config/types';
|
|
11
|
+
interface OwnedEngineProps {
|
|
12
|
+
config: PaymentConfig;
|
|
13
|
+
/**
|
|
14
|
+
* The store provider and storage. Usually `{ provider: createStoreProvider() }`;
|
|
15
|
+
* a test or the demo app supplies the fake store here.
|
|
16
|
+
*/
|
|
17
|
+
deps: EngineDeps;
|
|
18
|
+
/**
|
|
19
|
+
* When this changes, the provider builds a new engine. Defaults to
|
|
20
|
+
* `config.scopeToken`, so switching accounts gets a fresh one. `config` and
|
|
21
|
+
* `deps` themselves are read when an engine is built and may be inline objects:
|
|
22
|
+
* a new object on every render no longer reconnects to the store (PAY-07).
|
|
23
|
+
*/
|
|
24
|
+
engineKey?: string;
|
|
25
|
+
engine?: undefined;
|
|
26
|
+
}
|
|
27
|
+
interface ExternalEngineProps {
|
|
28
|
+
/**
|
|
29
|
+
* An engine the app created and owns. The provider shares it with the tree and
|
|
30
|
+
* neither initializes nor cleans it up.
|
|
31
|
+
*/
|
|
32
|
+
engine: PaymentEngine;
|
|
33
|
+
config?: undefined;
|
|
34
|
+
deps?: undefined;
|
|
35
|
+
engineKey?: undefined;
|
|
36
|
+
}
|
|
37
|
+
export type PaymentProviderProps = (OwnedEngineProps | ExternalEngineProps) & {
|
|
38
|
+
/** Skip automatic initialization when the app wants to control the moment. */
|
|
39
|
+
autoInitialize?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Call `handleForeground()` each time the app returns from the background, through
|
|
42
|
+
* rn-core's shared lifecycle port. Off by default: what counts as a foreground
|
|
43
|
+
* return is the app's decision (FR-059).
|
|
44
|
+
*/
|
|
45
|
+
syncOnForeground?: boolean;
|
|
46
|
+
};
|
|
47
|
+
export declare function PaymentProvider(props: PropsWithChildren<PaymentProviderProps>): React.ReactElement;
|
|
48
|
+
/**
|
|
49
|
+
* The engine from context.
|
|
50
|
+
*
|
|
51
|
+
* Throws when used outside a provider, deliberately: returning null would push a
|
|
52
|
+
* null check into every consumer and let a genuine wiring mistake read as "no
|
|
53
|
+
* entitlement" — the exact conflation this package exists to prevent.
|
|
54
|
+
*/
|
|
55
|
+
export declare function usePaymentEngine(): PaymentEngine;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=PaymentProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PaymentProvider.d.ts","sourceRoot":"","sources":["../../../../src/react/PaymentProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,EAMb,KAAK,iBAAiB,EACtB,MAAM,OAAO,CAAC;AACf,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAErF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,UAAU,gBAAgB;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,IAAI,EAAE,UAAU,CAAC;IACjB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,UAAU,mBAAmB;IAC5B;;;OAGG;IACH,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,GAAG;IAC7E,8EAA8E;IAC9E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,wBAAgB,eAAe,CAC9B,KAAK,EAAE,iBAAiB,CAAC,oBAAoB,CAAC,GAC5C,KAAK,CAAC,YAAY,CAyDpB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAShD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hooks over the engine.
|
|
3
|
+
*
|
|
4
|
+
* Each subscribes on mount and unsubscribes on unmount, so repeated mount/unmount
|
|
5
|
+
* leaves no duplicate subscription and no surviving listener (FR-006, PERF-002).
|
|
6
|
+
*
|
|
7
|
+
* Reads are synchronous: the engine holds entitlements in memory, so a hook never
|
|
8
|
+
* returns a loading placeholder for an entitlement it already knows (PERF-001).
|
|
9
|
+
*/
|
|
10
|
+
import type { EntitlementKey, FinalizeResult, PaymentStatus, PendingPurchasesState, ProductKey, PurchaseOptions, PurchaseResult, TransactionRef } from '../config/types';
|
|
11
|
+
import type { EntitlementMap, EntitlementState } from '../entitlements/aggregate';
|
|
12
|
+
import type { PaymentError } from '../diagnostics/errors';
|
|
13
|
+
import type { MissingProduct, ProductInfo } from '../engine/products';
|
|
14
|
+
import type { RestoreOutcome, SyncOutcome } from '../engine/engine';
|
|
15
|
+
/**
|
|
16
|
+
* One entitlement, re-rendering only when that one changes.
|
|
17
|
+
*
|
|
18
|
+
* The returned `status` is `unknown` until the first sync completes. That is the
|
|
19
|
+
* point: an app must be able to tell "not yet known" from "not entitled" so a
|
|
20
|
+
* paying user never sees the unpaid experience flash (FR-047).
|
|
21
|
+
*/
|
|
22
|
+
export declare function useEntitlement(key: EntitlementKey): EntitlementState;
|
|
23
|
+
/** Every entitlement at once, for a screen that shows overall plan state. */
|
|
24
|
+
export declare function useEntitlements(): EntitlementMap;
|
|
25
|
+
/**
|
|
26
|
+
* Pending purchases, in this session or an earlier one (FR-101). Added in 0.2.0.
|
|
27
|
+
*
|
|
28
|
+
* Pass product keys to narrow it to the products one screen sells. Read
|
|
29
|
+
* `status` before the list: under `unknown`, an empty list is not "nothing
|
|
30
|
+
* pending", and a Buy button shown on it could charge a user twice.
|
|
31
|
+
*/
|
|
32
|
+
export declare function usePendingPurchases(productKeys?: readonly string[]): PendingPurchasesState;
|
|
33
|
+
/** Package status, so an app can tell "cannot sell here" from "not paid" (FR-022). */
|
|
34
|
+
export declare function usePaymentStatus(): PaymentStatus;
|
|
35
|
+
export interface UsePurchaseResult {
|
|
36
|
+
purchase: (productKey: ProductKey, options?: PurchaseOptions) => Promise<PurchaseResult>;
|
|
37
|
+
consume: (ref: TransactionRef) => Promise<FinalizeResult>;
|
|
38
|
+
isPurchasing: boolean;
|
|
39
|
+
/** The last outcome, so a screen can render cancellation differently from failure. */
|
|
40
|
+
lastResult: PurchaseResult | undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Starting a purchase.
|
|
44
|
+
*
|
|
45
|
+
* `lastResult` is the full typed union rather than a boolean, because a screen has
|
|
46
|
+
* to treat `user_cancelled` differently from `store_error` — showing an error
|
|
47
|
+
* banner to someone who simply changed their mind is the most common paywall bug.
|
|
48
|
+
*/
|
|
49
|
+
export declare function usePurchase(): UsePurchaseResult;
|
|
50
|
+
export interface UseProductsResult {
|
|
51
|
+
products: ProductInfo[];
|
|
52
|
+
/** Reported so a paywall explains an absent row instead of rendering a blank. */
|
|
53
|
+
missing: MissingProduct[];
|
|
54
|
+
isLoading: boolean;
|
|
55
|
+
error: PaymentError | undefined;
|
|
56
|
+
refresh: () => Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Store-supplied product information for a paywall.
|
|
60
|
+
*
|
|
61
|
+
* Every price here is already formatted by the store for the user's locale. An app
|
|
62
|
+
* must render `formattedPrice` and never build its own string from
|
|
63
|
+
* `priceAmountMicros` — that field exists for sorting and comparison only
|
|
64
|
+
* (FR-028).
|
|
65
|
+
*/
|
|
66
|
+
export declare function useProducts(productKeys: readonly string[]): UseProductsResult;
|
|
67
|
+
export interface UseSyncResult {
|
|
68
|
+
sync: () => Promise<SyncOutcome>;
|
|
69
|
+
restore: () => Promise<RestoreOutcome>;
|
|
70
|
+
isSyncing: boolean;
|
|
71
|
+
lastSyncedAt: number | undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Sync and restore, for a "Restore purchases" control.
|
|
75
|
+
*
|
|
76
|
+
* `restore`'s outcome distinguishes "restored" from "nothing found", so the app
|
|
77
|
+
* can avoid telling a user their purchases came back when none existed (FR-061).
|
|
78
|
+
*/
|
|
79
|
+
export declare function useSync(): UseSyncResult;
|
|
80
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,UAAU,EACV,eAAe,EACf,cAAc,EACd,cAAc,EACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,gBAAgB,CASpE;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,IAAI,cAAc,CAGhD;AAWD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,qBAAqB,CAe1F;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IACzF,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1D,YAAY,EAAE,OAAO,CAAC;IACtB,sFAAsF;IACtF,UAAU,EAAE,cAAc,GAAG,SAAS,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,iBAAiB,CAyB/C;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,iFAAiF;IACjF,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,YAAY,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAoD7E;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,IAAI,aAAa,CA4BvC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What any `ProviderPort` must do (IOS-12, PAY-13).
|
|
3
|
+
*
|
|
4
|
+
* The same checks run against the fake store and against the Play adapter over a
|
|
5
|
+
* simulated binding (or the real one, from a demo screen on a device), so a test
|
|
6
|
+
* that drives the fake proves something about the device path. Each check builds
|
|
7
|
+
* its own port over the same small store, through a harness.
|
|
8
|
+
*/
|
|
9
|
+
import { type Check, type ConformanceReport } from '@chipmobilesdk/rn-core/testing';
|
|
10
|
+
import type { ProviderPort } from '../adapter/port';
|
|
11
|
+
import type { ProductType } from '../config/types';
|
|
12
|
+
export interface StoreProductSpec {
|
|
13
|
+
readonly storeProductId: string;
|
|
14
|
+
readonly productType: ProductType;
|
|
15
|
+
/** As the store formats it; the port must pass it through untouched. */
|
|
16
|
+
readonly formattedPrice: string;
|
|
17
|
+
}
|
|
18
|
+
export interface OwnedPurchaseSpec {
|
|
19
|
+
readonly storeProductId: string;
|
|
20
|
+
readonly token: string;
|
|
21
|
+
readonly state: 'purchased' | 'pending';
|
|
22
|
+
}
|
|
23
|
+
export interface StoreScenario {
|
|
24
|
+
readonly products: readonly StoreProductSpec[];
|
|
25
|
+
readonly owned: readonly OwnedPurchaseSpec[];
|
|
26
|
+
}
|
|
27
|
+
export interface ProviderSubject {
|
|
28
|
+
readonly port: ProviderPort;
|
|
29
|
+
/** How the next purchase flow the user starts ends. */
|
|
30
|
+
nextPurchaseEnds(outcome: 'bought' | 'cancelled'): void;
|
|
31
|
+
/** The billing service goes away underneath the app. */
|
|
32
|
+
dropService(): void;
|
|
33
|
+
}
|
|
34
|
+
export interface ProviderHarness {
|
|
35
|
+
create(scenario: StoreScenario): ProviderSubject;
|
|
36
|
+
}
|
|
37
|
+
/** The store every check runs against. */
|
|
38
|
+
export declare const CONFORMANCE_STORE: StoreScenario;
|
|
39
|
+
export declare const providerPortChecks: readonly Check<ProviderHarness>[];
|
|
40
|
+
export declare function runProviderPortConformance(harness: ProviderHarness): Promise<ConformanceReport>;
|
|
41
|
+
//# sourceMappingURL=conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../../../src/testing/conformance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAGN,KAAK,KAAK,EACV,KAAK,iBAAiB,EACtB,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,wEAAwE;IACxE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,uDAAuD;IACvD,gBAAgB,CAAC,OAAO,EAAE,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAC;IACxD,wDAAwD;IACxD,WAAW,IAAI,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,QAAQ,EAAE,aAAa,GAAG,eAAe,CAAC;CACjD;AAED,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,EAAE,aAiB/B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAAS,KAAK,CAAC,eAAe,CAAC,EAgG/D,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAE/F"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fake store — a full `ProviderPort` implementation for automated tests.
|
|
3
|
+
*
|
|
4
|
+
* Lives behind `@chipmobilesdk/rn-payment/testing` so test doubles cannot reach a
|
|
5
|
+
* production bundle.
|
|
6
|
+
*
|
|
7
|
+
* Nearly every requirement in this package concerns a rare ordering or failure
|
|
8
|
+
* path — a pending purchase settling two sessions later, an app killed between
|
|
9
|
+
* payment and acknowledgement, a billing connection dropping mid-sync. None of
|
|
10
|
+
* those are reachable on a real device on demand, so this is what makes them
|
|
11
|
+
* testable at all (NFR-007, SC-008).
|
|
12
|
+
*/
|
|
13
|
+
import type { ProviderCapabilities, ProviderConnectOutcome, ProviderFailureReason, ProviderPort, ProviderProduct, ProviderPurchase, ProviderToken, StoreProductId } from '../adapter/port';
|
|
14
|
+
export interface FakeStoreOptions {
|
|
15
|
+
/** Fails `connect` until `setConnectOutcome` says otherwise. */
|
|
16
|
+
connectOutcome?: ProviderConnectOutcome;
|
|
17
|
+
capabilities?: Partial<ProviderCapabilities>;
|
|
18
|
+
products?: ProviderProduct[];
|
|
19
|
+
owned?: ProviderPurchase[];
|
|
20
|
+
/**
|
|
21
|
+
* `'android-16.7'` mirrors the Play binding the real adapter wraps: a launched
|
|
22
|
+
* purchase is also delivered through `observePurchases`, so the engine sees it
|
|
23
|
+
* twice, and capabilities match Android's. The default delivers it once, which
|
|
24
|
+
* is simpler but hides any double-settle on the device path.
|
|
25
|
+
*/
|
|
26
|
+
mode?: 'default' | 'android-16.7';
|
|
27
|
+
}
|
|
28
|
+
export interface FakeStore extends ProviderPort {
|
|
29
|
+
/** Next `launchPurchase` succeeds and yields this purchase. */
|
|
30
|
+
scriptPurchaseSuccess(overrides?: Partial<ProviderPurchase>): void;
|
|
31
|
+
/** Next `launchPurchase` fails with this reason — cancellation included (FR-032). */
|
|
32
|
+
scriptPurchaseFailure(reason: ProviderFailureReason): void;
|
|
33
|
+
/** Next `launchPurchase` returns a purchase in the pending state (FR-037). */
|
|
34
|
+
scriptPurchasePending(overrides?: Partial<ProviderPurchase>): void;
|
|
35
|
+
setOwned(purchases: ProviderPurchase[]): void;
|
|
36
|
+
/** Push a purchase through `observePurchases`, as a settling pending one does. */
|
|
37
|
+
pushPurchaseUpdate(purchase: ProviderPurchase): void;
|
|
38
|
+
/** Stop reporting a transaction as valid — a refund or revocation (FR-064). */
|
|
39
|
+
revoke(transactionId: string): void;
|
|
40
|
+
/** The money arrives: the owned record turns `purchased` (FR-039). */
|
|
41
|
+
settlePending(transactionId: string): void;
|
|
42
|
+
/** The payment is declined or abandoned: the store stops reporting it (FR-040). */
|
|
43
|
+
cancelPending(transactionId: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* The pending window runs out. Reported through `pendingEndReason`, which a
|
|
46
|
+
* store that knows implements — Play does not, so on device this is
|
|
47
|
+
* indistinguishable from `cancelPending` (FR-102).
|
|
48
|
+
*/
|
|
49
|
+
expirePending(transactionId: string): void;
|
|
50
|
+
setProducts(products: ProviderProduct[]): void;
|
|
51
|
+
setConnectOutcome(outcome: ProviderConnectOutcome): void;
|
|
52
|
+
/** Drop the connection, as the billing service does (FR-020). */
|
|
53
|
+
dropConnection(reason?: string): void;
|
|
54
|
+
restoreConnection(): void;
|
|
55
|
+
/** Make `acknowledge`/`consume` fail, to exercise bounded retry (FR-045). */
|
|
56
|
+
setFinalizeFailure(failing: boolean): void;
|
|
57
|
+
acknowledged(): ProviderToken[];
|
|
58
|
+
consumed(): ProviderToken[];
|
|
59
|
+
connectCount(): number;
|
|
60
|
+
launchCount(): number;
|
|
61
|
+
queryOwnedCount(): number;
|
|
62
|
+
disconnectCount(): number;
|
|
63
|
+
subscriptionManagementOpenedFor(): (StoreProductId | undefined)[];
|
|
64
|
+
reset(): void;
|
|
65
|
+
}
|
|
66
|
+
/** A purchase with sensible defaults, so tests state only what they care about. */
|
|
67
|
+
export declare function makePurchase(overrides?: Partial<ProviderPurchase>): ProviderPurchase;
|
|
68
|
+
export declare function createFakeStore(options?: FakeStoreOptions): FakeStore;
|
|
69
|
+
//# sourceMappingURL=fakeStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fakeStore.d.ts","sourceRoot":"","sources":["../../../../src/testing/fakeStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EACX,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,EAEZ,eAAe,EACf,gBAAgB,EAGhB,aAAa,EACb,cAAc,EACd,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,gBAAgB;IAChC,gEAAgE;IAChE,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC3B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,cAAc,CAAC;CAClC;AAED,MAAM,WAAW,SAAU,SAAQ,YAAY;IAE9C,+DAA+D;IAC/D,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IACnE,qFAAqF;IACrF,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC3D,8EAA8E;IAC9E,qBAAqB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAGnE,QAAQ,CAAC,SAAS,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC;IAC9C,kFAAkF;IAClF,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrD,+EAA+E;IAC/E,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAMpC,sEAAsE;IACtE,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,mFAAmF;IACnF,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C;;;;OAIG;IACH,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,WAAW,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC;IAG/C,iBAAiB,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACzD,iEAAiE;IACjE,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iBAAiB,IAAI,IAAI,CAAC;IAG1B,6EAA6E;IAC7E,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAG3C,YAAY,IAAI,aAAa,EAAE,CAAC;IAChC,QAAQ,IAAI,aAAa,EAAE,CAAC;IAC5B,YAAY,IAAI,MAAM,CAAC;IACvB,WAAW,IAAI,MAAM,CAAC;IACtB,eAAe,IAAI,MAAM,CAAC;IAC1B,eAAe,IAAI,MAAM,CAAC;IAC1B,+BAA+B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC,EAAE,CAAC;IAClE,KAAK,IAAI,IAAI,CAAC;CACd;AAoBD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,SAAS,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,gBAAgB,CAaxF;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CAmOzE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@chipmobilesdk/rn-payment/testing` — test doubles.
|
|
3
|
+
*
|
|
4
|
+
* A separate entrypoint so the fake store cannot reach a production bundle
|
|
5
|
+
* (LIB-003). Nothing here is part of the package's public runtime contract.
|
|
6
|
+
*/
|
|
7
|
+
export { createFakeStore, makePurchase } from './fakeStore';
|
|
8
|
+
export type { FakeStore, FakeStoreOptions } from './fakeStore';
|
|
9
|
+
export { createMemorySnapshotStore } from '../persistence/mmkv-store';
|
|
10
|
+
export { CONFORMANCE_STORE, providerPortChecks, runProviderPortConformance } from './conformance';
|
|
11
|
+
export type { OwnedPurchaseSpec, ProviderHarness, ProviderSubject, StoreProductSpec, StoreScenario, } from './conformance';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAClG,YAAY,EACX,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,aAAa,GACb,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform selection for the store adapter.
|
|
3
|
+
*
|
|
4
|
+
* This exists so the public surface never names a store. An app writes
|
|
5
|
+
* `createStoreProvider()`, not `createIapAdapter()` — the same call will pick the
|
|
6
|
+
* StoreKit adapter once iOS exists, and no consumer line changes (FR-002, FR-004,
|
|
7
|
+
* FR-007).
|
|
8
|
+
*
|
|
9
|
+
* On a platform with no adapter the result is a stub that reports
|
|
10
|
+
* `platform_unsupported` rather than throwing. That is what lets a host app start
|
|
11
|
+
* and run normally where selling is impossible, losing only the ability to sell
|
|
12
|
+
* (FR-021, FR-023).
|
|
13
|
+
*/
|
|
14
|
+
import type { ProductType } from '../config/types.js';
|
|
15
|
+
import type { ProviderPort } from './port.js';
|
|
16
|
+
/**
|
|
17
|
+
* The no-adapter stub.
|
|
18
|
+
*
|
|
19
|
+
* Every operation fails safely and predictably. Notably `queryOwned` returns an
|
|
20
|
+
* empty list rather than throwing: the engine then computes `not_entitled` after a
|
|
21
|
+
* successful-but-empty sync, which is honest — on a platform with no store, the
|
|
22
|
+
* user genuinely holds nothing this package can verify.
|
|
23
|
+
*/
|
|
24
|
+
declare function createUnsupportedProvider(): ProviderPort;
|
|
25
|
+
export interface StoreProviderOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Force the unsupported stub regardless of platform.
|
|
28
|
+
*
|
|
29
|
+
* Useful for an app that wants to ship one build with selling switched off at
|
|
30
|
+
* the provider level rather than through the `enabled` flag.
|
|
31
|
+
*/
|
|
32
|
+
forceUnsupported?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The platform's store adapter.
|
|
36
|
+
*
|
|
37
|
+
* iOS deliberately returns the stub today rather than throwing: the contract is
|
|
38
|
+
* prepared for StoreKit, the implementation is not, and an app running on iOS
|
|
39
|
+
* should degrade to "cannot sell here" instead of crashing.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createStoreProvider(options?: StoreProviderOptions): ProviderPort;
|
|
42
|
+
/** Exported for a test or a screen that needs the stub explicitly. */
|
|
43
|
+
export { createUnsupportedProvider };
|
|
44
|
+
export type { ProductType };
|
|
45
|
+
//# sourceMappingURL=createStoreProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createStoreProvider.d.ts","sourceRoot":"","sources":["../../../../src/adapter/createStoreProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,oBAAiB,CAAC;AAEhE,OAAO,KAAK,EAGX,YAAY,EAKZ,MAAM,WAAQ,CAAC;AAahB;;;;;;;GAOG;AACH,iBAAS,yBAAyB,IAAI,YAAY,CAqCjD;AAED,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,YAAY,CAQpF;AAED,sEAAsE;AACtE,OAAO,EAAE,yBAAyB,EAAE,CAAC;AAErC,YAAY,EAAE,WAAW,EAAE,CAAC"}
|