Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6cee6ed
feat(types): add REDEMPTION_CONSUMED / REDEMPTION_FAILED and the rede…
kherembourg Sep 3, 2026
7ce24fa
feat(js): add anonymousUserId / proxy / appHandlesRedemptionAlert bui…
kherembourg Sep 3, 2026
36a364c
feat(ios): bridge anonymousUserId and the web redemption delegate
kherembourg Sep 3, 2026
717bb73
feat(android): bridge anonymousUserId, proxy and the web redemption l…
kherembourg Sep 3, 2026
f9036a1
test: cover the 6.1.0 builder modifiers, the redemption events and th…
kherembourg Sep 3, 2026
1bdf52f
feat(example): show the 6.1.0 redemption listener and the new start m…
kherembourg Sep 3, 2026
1205ba4
chore(release): bump the five packages, the bridge version and the do…
kherembourg Sep 3, 2026
5368762
chore(deps): pin the native iOS and Android SDKs to 6.1.0
kherembourg Sep 3, 2026
f71cfc3
docs: remove em-dashes from the 6.1.0 prose
kherembourg Sep 3, 2026
ec90bdc
refactor(android): rename the redemption locals so they never read as…
kherembourg Sep 3, 2026
ffb78d3
test(ios): assert the bridge exposes the web redemption event and del…
kherembourg Sep 3, 2026
094b93c
style(ios): match the [Purchasely] log prefix convention
kherembourg Sep 3, 2026
b567783
chore(ios): regenerate Podfile.lock for Purchasely 6.1.0
kherembourg Sep 7, 2026
e28c37c
fix(types): purchaseToken and the subscription dates are optional on iOS
kherembourg Sep 7, 2026
baa95aa
docs: document anonymousUserId, proxy and the Web2App redemption list…
kherembourg Sep 7, 2026
118a9c3
feat(ios): wire proxy, which iOS 6.1.0 does support
kherembourg Sep 7, 2026
10bfacd
feat(proxy): accept null to clear the proxy on both platforms
kherembourg Sep 7, 2026
368e5db
feat(js): put the web redemption listener on the start builder
kherembourg Sep 7, 2026
f8b2820
fix(js): the chain listener replaces instead of stacking, and never l…
kherembourg Sep 7, 2026
2701f90
test(ios): cover the web redemption payload policy
kherembourg Sep 7, 2026
d142c71
fix(test): guard an indexed access so the definition build passes
kherembourg Sep 7, 2026
e7c3849
fix(js): clear the chain handle when redemption listeners are removed
kherembourg Sep 7, 2026
5a0c60e
fix(bridge): report the web checkout subscription source
kherembourg Sep 7, 2026
dc17087
docs: the masked email hint reaches the listener on Android too
kherembourg Sep 7, 2026
d2ba578
fix(ios): warn instead of red-boxing a host app on a bad option
kherembourg Sep 7, 2026
194b1a0
docs: document the nullable subscription fields and the web checkout …
kherembourg Sep 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 40 additions & 19 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@

| Property | Value |
|----------|-------|
| Current Version | 6.0.0 |
| Current Version | 6.1.0 |
| React Native | 0.86.0 |
| TypeScript | 5.8.3 (strict mode) |
| Node.js | v22 (see `.nvmrc`) |
| Package Manager | Yarn 3.6.1 (workspaces) |
| Native iOS SDK | 6.0.0 |
| Native Android SDK | 6.0.1 |
| Native iOS SDK | 6.1.0 |
| Native Android SDK | 6.1.0 |

### Supported App Stores
- Apple App Store (iOS)
Expand Down Expand Up @@ -404,11 +404,11 @@ Android and iOS jobs invoke Gradle and `xcodebuild` directly.
### Native Dependencies

**iOS (CocoaPods):**
- Purchasely SDK v6.0.0
- Purchasely SDK v6.1.0
- Deployment target: iOS 15.1

**Android (Gradle):**
- io.purchasely:core:6.0.1
- io.purchasely:core:6.1.0
- Min SDK: 23
- Kotlin: 2.3.21+
- Java: 11
Expand Down Expand Up @@ -478,19 +478,28 @@ yarn test # All tests
yarn test --coverage # With coverage
yarn test --watch # Watch mode

# iOS tests (XCTest) - Run locally or in example app context
# Native tests require React Native dependencies from the example app
cd packages/purchasely/ios
xcodebuild test -workspace Purchasely.xcworkspace -scheme Purchasely -destination 'platform=iOS Simulator,name=iPhone 15'
# iOS tests (XCTest) - CI-enabled, via the example workspace
cd example/ios
UDID=$(xcrun simctl list devices booted -j | jq -r '[.devices[][]][0].udid')
xcodebuild test -workspace example.xcworkspace \
-scheme react-native-purchasely-Unit-Tests \
-destination "id=$UDID" CODE_SIGNING_ALLOWED=NO

# Android tests (JUnit) - Run locally or in example app context
# Native tests require React Native dependencies from the example app
cd packages/purchasely/android
./gradlew test # Run unit tests
./gradlew testDebugUnitTest # Run debug variant tests
# Android tests (JUnit) - CI-enabled, via the example project
cd example/android
./gradlew :react-native-purchasely:testDebugUnitTest
```

**Note:** Native tests (iOS XCTest and Android JUnit) require React Native dependencies and should be run locally or within the example app context. They cannot run in CI as standalone jobs. TypeScript tests run in CI automatically.
**Native tests run in CI.** Both suites need the React Native dependencies, so
neither runs from its own package directory: `cd packages/purchasely/android &&
./gradlew test` fails with `Could not find any matches for
com.facebook.react:react-native:+`. Drive them through the example project
instead, which is exactly what CI does:

- Android JUnit runs in the `build-android` job, step "Run Purchasely Android
native unit tests" (`:react-native-purchasely:testDebugUnitTest`).
- iOS XCTest runs in its own `iOS Unit Tests (bridge)` job, on the
`react-native-purchasely-Unit-Tests` scheme against a booted simulator.

### Test Guidelines

Expand Down Expand Up @@ -531,10 +540,20 @@ When adding new features:

1. **lint** (ubuntu-latest) - TypeScript + ESLint checks, type checking
2. **test** (ubuntu-latest) - TypeScript/Jest unit tests with coverage
3. **build-android** (ubuntu-latest) - Build Android example app with Gradle caching
4. **build-ios** (macos-latest) - Build iOS example app with CocoaPods caching

**Note:** Native tests (Android JUnit and iOS XCTest) are not included in CI as they require React Native dependencies from the example app context. Run these tests locally during development.
3. **build-android** (ubuntu-latest) - Build the Android example app, then run the
Android JUnit suite (`:react-native-purchasely:testDebugUnitTest`)
4. **build-rn-0-86-android** (ubuntu-latest) - Build against the supported RN version
5. **build-ios** (macos-latest) - Build iOS example app with CocoaPods caching
6. **build-rn-0-86-ios** (macos-latest) - Build against the supported RN version
7. **iOS Build (use_frameworks!)** (macos-latest) - Build the bridge pod under
`use_frameworks!`
8. **iOS Unit Tests (bridge)** (macos-latest) - Run the XCTest bundle on a simulator

**Native tests are part of CI**, both platforms. They run through the example
project rather than from their own package directory, because they need the
React Native dependencies. E2E (`e2e-android.yml`, `e2e-ios.yml`) runs nightly
and on a pull request that touches the bridge paths, and must never gate
`publish.yml`.

### Publish (publish.yml)

Expand Down Expand Up @@ -646,6 +665,8 @@ See `VERSIONS.md` for native SDK version mapping:

| React Native SDK | iOS SDK | Android SDK |
|------------------|---------|-------------|
| 6.1.0 | 6.1.0 | 6.1.0 |
| 6.0.0 | 6.0.0 | 6.0.1 |
| 5.7.3 | 5.7.4 | 5.7.4 |
| 5.7.2 | 5.7.2 | 5.7.3 |
| 5.7.1 | 5.7.1 | 5.7.1 |
Expand Down
1 change: 1 addition & 0 deletions VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,4 @@ This file provides the underlying native SDK versions that the React Native SDK
| 6.0.0-rc.2 | 6.0.0-rc.2 | 6.0.0-rc.2 |
| 6.0.0-rc.3 | 6.0.0-rc.3 | 6.0.0-rc.3 |
| 6.0.0 | 6.0.0 | 6.0.1 |
| 6.1.0 | 6.1.0 | 6.1.0 |
14 changes: 7 additions & 7 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PODS:
- hermes-engine (250829098.0.14):
- hermes-engine/Pre-built (= 250829098.0.14)
- hermes-engine/Pre-built (250829098.0.14)
- Purchasely (6.0.0)
- Purchasely (6.1.0)
- RCTDeprecation (0.86.0)
- RCTRequired (0.86.0)
- RCTSwiftUI (0.86.0)
Expand Down Expand Up @@ -1450,11 +1450,11 @@ PODS:
- ReactNativeDependencies
- SwiftUIIntrospect (~> 1.0)
- Yoga
- react-native-purchasely (6.0.0):
- Purchasely (= 6.0.0)
- react-native-purchasely (6.1.0):
- Purchasely (= 6.1.0)
- React-Core
- react-native-purchasely/Tests (6.0.0):
- Purchasely (= 6.0.0)
- react-native-purchasely/Tests (6.1.0):
- Purchasely (= 6.1.0)
- React-Core
- react-native-safe-area-context (5.5.2):
- hermes-engine
Expand Down Expand Up @@ -2229,7 +2229,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
FBLazyVector: b3e7ad108f0d882e30445c5527d774e3fd432f3d
hermes-engine: 7fa7794edc84e91e759bb4fe5095fe8bc63f8ceb
Purchasely: 4309bcf9d139c40dcad8ebe3d93751c8d6ae02cd
Purchasely: c80ea99b186314d8980ff6a6c57de6c0ea626920
RCTDeprecation: 2a74a2c57675e64419bd89078efde81f7c1de90b
RCTRequired: 30451112e6fef4e6f31b4e7eee0845156e35e4b0
RCTSwiftUI: 5aaf0b07e747ba749dc6acc94d8bd41eea4b570f
Expand Down Expand Up @@ -2268,7 +2268,7 @@ SPEC CHECKSUMS:
React-microtasksnativemodule: 2eb3f49d0d8e77b5343455eccd057010b8d38b6b
React-mutationobservernativemodule: f0a0d5ae9b51caf7becbeabf836d716cfedb6bf2
react-native-pager-view: e91b5624568fda9e4c0fb0c44ed9669c2335e212
react-native-purchasely: 662d42a2c30aac229d9eb5c0a902be86e768d8a9
react-native-purchasely: eb3a758ca2d76ea404d369206e5f8b40b85dd9c4
react-native-safe-area-context: 3836dc43241ba89903508a442029e57f7491539f
React-NativeModulesApple: a092d89b58f635ebfab88048b0eda9fb516819fd
React-networking: 968bbbe73590149feb1e72b2af4f6a68e4796ece
Expand Down
26 changes: 26 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const Stack = createNativeStackNavigator()
function App(): React.JSX.Element {
async function setupPurchasely() {
let configured = false

try {
// chained builder — the only supported way to start the SDK.
// `allowDeeplink(true)` replaces the legacy `readyToOpenDeeplink`.
Expand All @@ -32,6 +33,31 @@ function App(): React.JSX.Element {
.allowCampaigns(true)
.storekitVersion('storeKit2') // iOS: 'storeKit2' or 'storeKit1'
.stores(['google']) // Android stores
// 6.1.0, Web2App redemption. On the chain, so the listener
// exists before start() runs: a redemption can settle during
// start(), from a cold start the `ply/redeem` link triggered
// or a token a previous launch left pending.
.webRedemptionListener((result) => {
if (result.isSuccess) {
console.log(
'Redemption granted. replay=' +
result.replay +
' subscription=' +
result.context?.subscription?.plan?.vendorId
)
} else {
// On BOTH platforms, errorMessage for an expired link
// can carry a masked email address. Show it to the
// user. Do not send it to analytics or to a crash
// reporter.
console.log(
'Redemption failed. code=' +
result.errorCode +
' message=' +
result.errorMessage
)
}
})
.start()
} catch (e) {
console.log('Purchasely SDK configuration error:', e)
Expand Down
2 changes: 1 addition & 1 deletion packages/amazon/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ dependencies {
api 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

implementation 'io.purchasely:amazon:6.0.1'
implementation 'io.purchasely:amazon:6.1.0'
}
2 changes: 1 addition & 1 deletion packages/amazon/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@purchasely/react-native-purchasely-amazon",
"version": "6.0.0",
"version": "6.1.0",
"description": "Purchasely Amazon In-App Purchases dependency",
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/android-player/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ dependencies {
api 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

implementation 'io.purchasely:player:6.0.1'
implementation 'io.purchasely:player:6.1.0'
}
2 changes: 1 addition & 1 deletion packages/android-player/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@purchasely/react-native-purchasely-android-player",
"version": "6.0.0",
"version": "6.1.0",
"description": "Player Android",
"source": "./src/index.ts",
"main": "./lib/commonjs/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/google/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ dependencies {
api 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

implementation 'io.purchasely:google-play:6.0.1'
implementation 'io.purchasely:google-play:6.1.0'
}
2 changes: 1 addition & 1 deletion packages/google/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@purchasely/react-native-purchasely-google",
"version": "6.0.0",
"version": "6.1.0",
"description": "Purchasely Google Play Billing dependency",
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/huawei/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,5 @@ dependencies {
api 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

implementation 'io.purchasely:huawei-services:6.0.1'
implementation 'io.purchasely:huawei-services:6.1.0'
}
2 changes: 1 addition & 1 deletion packages/huawei/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@purchasely/react-native-purchasely-huawei",
"version": "6.0.0",
"version": "6.1.0",
"description": "Purchasely Huawei Mobile Services dependencies",
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/purchasely/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'

api 'io.purchasely:core:6.0.1'
api 'io.purchasely:core:6.1.0'
Comment thread
kherembourg marked this conversation as resolved.
api 'androidx.lifecycle:lifecycle-common-java8:2.2.0'

// Test dependencies
Expand Down
Loading
Loading