Skip to content

feat: deprecate platform field and ios/android props#49

Merged
hyochan merged 4 commits into
mainfrom
feat/1.3-purchase-fields
Dec 8, 2025
Merged

feat: deprecate platform field and ios/android props#49
hyochan merged 4 commits into
mainfrom
feat/1.3-purchase-fields

Conversation

@hyochan
Copy link
Copy Markdown
Member

@hyochan hyochan commented Dec 8, 2025

  • Add IapStore enum (Unknown, Apple, Google, Horizon)
  • Add store field to PurchaseCommon interface
  • Deprecate platform field in favor of store
  • Deprecate ios/android props in requestPurchase/requestSubscription
  • Add apple/google props as replacements
  • Update all example codes and documentation
  • Add v1.3.0 release notes with migration guide

Summary by CodeRabbit

  • New Features

    • Added a unified store property (apple/google/horizon/unknown) on purchases and request payloads; request payloads now use apple/google keys.
  • Deprecated

    • Legacy platform fields are deprecated — migrate to store.
  • Documentation

    • Docs updated with migration guidance and examples for v1.3.0.
  • Tests

    • Test fixtures updated to include the new store field.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add IapStore enum (Unknown, Apple, Google, Horizon)
- Add store field to PurchaseCommon interface
- Deprecate platform field in favor of store
- Deprecate ios/android props in requestPurchase/requestSubscription
- Add apple/google props as replacements
- Update all example codes and documentation
- Add v1.3.0 release notes with migration guide
@hyochan hyochan added the 🎯 feature New feature label Dec 8, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 8, 2025

Warning

Rate limit exceeded

@hyochan has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 17 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 34871eb and 93e0bbb.

📒 Files selected for processing (3)
  • packages/docs/src/pages/docs/apis.tsx (5 hunks)
  • packages/docs/src/pages/docs/types.tsx (12 hunks)
  • packages/google/openiap/src/test/java/dev/hyo/openiap/PurchaseVerificationValidatorTest.kt (3 hunks)

Walkthrough

This pull request introduces IapStore (replacing IapkitStore) with unknown and horizon variants, adds a unified store: IapStore property across purchase models (deprecating platform), updates purchase construction to set store values, and renames platform-specific request fields from ios/android to apple/google across code, tests, GraphQL schema, and docs.

Changes

Cohort / File(s) Summary
Core Store Type Definition
packages/apple/Sources/Models/Types.swift, packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt, packages/gql/src/type.graphql
Replaced IapkitStore with IapStore (adds unknown, horizon). Updated (de)serialization to use IapStore and switched result types to IapStore.
Purchase Models — Store Property Addition
packages/apple/Sources/Models/Types.swift, packages/apple/Sources/Helpers/StoreKitTypesBridge.swift, packages/apple/Sources/OpenIapModule+ObjC.swift, packages/apple/Sources/OpenIapModule.swift, packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt, packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt, packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt
Added store: IapStore to PurchaseCommon, PurchaseIOS, and PurchaseAndroid; marked platform as deprecated. Updated all purchase construction sites to set store (.apple, .google, .horizon) and added transactionDate in some Apple minimal constructions.
Platform → Store Request Structures
packages/apple/Sources/Models/Types.swift, packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt, packages/gql/src/type.graphql
Added apple and google fields to RequestPurchasePropsByPlatforms and RequestSubscriptionPropsByPlatforms; deprecated ios/android. Updated JSON parsing/serializing to accept both old and new keys.
GraphQL Schema Updates
packages/gql/src/type-ios.graphql, packages/gql/src/type-android.graphql, packages/gql/src/type.graphql
Added store: IapStore! to purchase types, deprecated platform with @deprecated annotations, expanded IapStore enum, and added store to relevant inputs/results.
Verification & Payload Building
packages/apple/Sources/OpenIapModule.swift, packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
Switched verification/payload builders to use IapStore. Extended handling to include .horizon and error on .unknown. Adjusted payload building and parsing to work with IapStore.
Kotlin Codegen Update
packages/gql/scripts/generate-kotlin-types.mjs
Added logic to detect interface-implemented fields and emit override for generated Kotlin data class fields (adds needsOverride tracking).
Tests
packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift, packages/apple/Tests/OpenIapTests/*.swift
Updated tests and sample constructors to include new store argument (e.g., .apple) and adjusted assertions to use IapStore.
Docs & Examples
packages/docs/src/pages/docs/apis.tsx, packages/docs/src/pages/docs/features/*.tsx, packages/docs/src/pages/docs/types.tsx, packages/docs/src/pages/docs/updates/notes.tsx
Replaced ios/android keys with apple/google in examples, renamed discriminator text to store, added migration notes and deprecation guidance for platform.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25–35 minutes

  • Pay attention to JSON (de)serialization paths in Kotlin/Java/Swift to ensure store is persisted and backwards-compatible with old keys.
  • Verify generated Kotlin override usage to prevent compilation errors.
  • Confirm all purchase construction sites set the correct IapStore variant (.apple, .google, .horizon).
  • Check GraphQL schema deprecation annotations and that client code consuming schema handles both platform (deprecated) and store.

Possibly related issues

  • [TODO] v1.3.0 #48 — Implements the migration checklist to deprecate platform in favor of store and rename ios/android to apple/google.

Possibly related PRs

Suggested labels

❄️ types, ⬡ gql

Poem

🐰 I hopped in code with nimble paws,

Replaced old stores with newer laws.
Apple, Google, Horizon in view,
Platform retires — store sees us through.
Hooray — small hops, big change anew!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.71% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective of the PR: deprecating the platform field and ios/android props in favor of the new store field and apple/google props.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/docs/src/pages/docs/types.tsx (1)

2719-2772: Update RequestVerifyPurchaseWithIapkitResult.store type from IapkitStore to IapStore

The generated types in packages/gql/src/generated/types.ts define RequestVerifyPurchaseWithIapkitResult.store as IapStore (which includes 'unknown' | 'apple' | 'google' | 'horizon'), but the documentation references IapkitStore with only 'apple' | 'google'. Update lines 2747 and the entire IapkitStore enum section (lines 2847-2872) to use IapStore instead to match the actual generated types.

🧹 Nitpick comments (5)
packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt (1)

136-145: Consider using transactionId for ActiveSubscription.transactionId for clarity.

Now that PurchaseAndroid has an explicit transactionId field, toActiveSubscription() still maps transactionId = id. If id can ever diverge from the gateway transaction identifier (e.g., fallback to purchaseToken), consider switching this to use the new transactionId property instead so the semantics are explicit and consistent.

Based on learnings, keeping these mappings aligned with the schema/docs will reduce confusion later.

packages/docs/src/pages/docs/features/subscription.tsx (1)

356-367: Docs examples now match apple/google request payloads

The updated requestPurchase examples using apple and google under request look consistent with the new per‑store props and store discriminator. As a follow‑up, ensure any other docs still showing ios/android payload keys (e.g. type tables or older examples) are updated or explicitly marked deprecated so readers don’t mix the two shapes.

Also applies to: 492-493, 761-766, 897-905

packages/gql/src/type-ios.graphql (1)

124-168: GraphQL: store field addition and platform deprecation look correct

Adding store: IapStore! on PurchaseIOS and deprecating platform matches the new store‑centric model while preserving backwards compatibility. Since store is non‑null, please ensure all resolvers always populate it (including legacy data paths), and rerun the GraphQL codegen so Swift/TS/Kotlin/Dart types stay in sync, as per the packages/gql guidelines.

packages/docs/src/pages/docs/types.tsx (1)

199-205: Align discriminator docs fully with the new store field

The additions of store to Product/Purchase common fields and the new “Store Discriminators” section clearly communicate the new apple/google/horizon/unknown enum and the deprecation of platform. That said, a few narrative bits still talk about platform as the primary discriminator:

  • Line 199–205: Product is described as “discriminated by the platform field”.
  • Line 681–689: Purchase likewise says it’s discriminated by platform.
  • Line 638–640: “Use the platform field to narrow the type…”

To avoid confusion, consider updating those sentences to say “discriminated by the store field” and recommend using store for narrowing, with platform called out only as a deprecated, backwards‑compat alias.

Also applies to: 272-289, 539-641, 681-689, 742-809

packages/docs/src/pages/docs/updates/notes.tsx (1)

79-81: Clarify all possible store values for completeness.

The comment shows purchase.store // 'apple' | 'google' but the IapStore enum includes four values: 'unknown', 'apple', 'google', and 'horizon'. Consider documenting all possible values or adding a note that 'apple' and 'google' are the common values users will encounter in typical usage.

 // Purchase store field
-purchase.store  // 'apple' | 'google'
+purchase.store  // 'apple' | 'google' | 'horizon' | 'unknown'
 purchase.platform  // deprecated
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b8cf46 and 9284b55.

⛔ Files ignored due to path filters (4)
  • packages/gql/src/generated/Types.kt is excluded by !**/generated/**
  • packages/gql/src/generated/Types.swift is excluded by !**/generated/**
  • packages/gql/src/generated/types.dart is excluded by !**/generated/**
  • packages/gql/src/generated/types.ts is excluded by !**/generated/**
📒 Files selected for processing (20)
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift (1 hunks)
  • packages/apple/Sources/Models/Types.swift (10 hunks)
  • packages/apple/Sources/OpenIapModule+ObjC.swift (1 hunks)
  • packages/apple/Sources/OpenIapModule.swift (4 hunks)
  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift (1 hunks)
  • packages/docs/src/pages/docs/apis.tsx (5 hunks)
  • packages/docs/src/pages/docs/features/external-purchase.tsx (2 hunks)
  • packages/docs/src/pages/docs/features/purchase.tsx (1 hunks)
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx (3 hunks)
  • packages/docs/src/pages/docs/features/subscription.tsx (5 hunks)
  • packages/docs/src/pages/docs/types.tsx (10 hunks)
  • packages/docs/src/pages/docs/updates/notes.tsx (1 hunks)
  • packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt (2 hunks)
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (13 hunks)
  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt (4 hunks)
  • packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt (2 hunks)
  • packages/gql/scripts/generate-kotlin-types.mjs (1 hunks)
  • packages/gql/src/type-android.graphql (1 hunks)
  • packages/gql/src/type-ios.graphql (1 hunks)
  • packages/gql/src/type.graphql (5 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: iOS-specific functions must end with IOS suffix (e.g., clearTransactionIOS, getAppTransactionIOS)
Android-specific functions must end with Android suffix (e.g., acknowledgePurchaseAndroid, consumePurchaseAndroid)
Use action prefixes for function naming: get for retrieval, request for async operations, clear for removal, is/has for boolean checks, show/present for UI display, begin/finish/end for process control

Prefer interface for defining object shapes in TypeScript

Files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/updates/notes.tsx
  • packages/docs/src/pages/docs/apis.tsx
  • packages/docs/src/pages/docs/features/subscription.tsx
  • packages/docs/src/pages/docs/features/external-purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/docs/src/pages/docs/types.tsx
packages/docs/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

packages/docs/**/*.{ts,tsx}: Use kebab-case for search modal IDs (e.g., id: 'request-products')
Modal state should be defined once at the app root level using Preact Signals (signal from '@preact/signals-react'), not instantiated multiple times
ALL components must fit within parent boundaries and never overflow outside parent containers; use overflow-hidden, break-words, and whitespace-nowrap as needed
Delete unused components, functions, and imports immediately; do not keep commented-out code or unused variables
ANY function that returns a Promise must be wrapped with void operator when used where a void return is expected (e.g., event handlers)

Files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/updates/notes.tsx
  • packages/docs/src/pages/docs/apis.tsx
  • packages/docs/src/pages/docs/features/subscription.tsx
  • packages/docs/src/pages/docs/features/external-purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/docs/src/pages/docs/types.tsx
packages/docs/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

packages/docs/**/*: Before committing, run npx prettier --write, npm run lint, bun run tsc or npm run typecheck, and npm run build to verify formatting, linting, types, and build success
Use conventional commit format with lowercase type prefix and lowercase description (e.g., feat: add user authentication)

Files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/updates/notes.tsx
  • packages/docs/src/pages/docs/apis.tsx
  • packages/docs/src/pages/docs/features/subscription.tsx
  • packages/docs/src/pages/docs/features/external-purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/docs/src/pages/docs/types.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (GEMINI.md)

**/*.{ts,tsx,js,jsx}: Use camelCase for variable and function names
Use PascalCase for class and component names
Always use async/await for handling promises instead of .then() chains
Add JSDoc comments for public functions and exported APIs
Use const by default, let if reassignment is needed, avoid var

Files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/updates/notes.tsx
  • packages/docs/src/pages/docs/apis.tsx
  • packages/docs/src/pages/docs/features/subscription.tsx
  • packages/docs/src/pages/docs/features/external-purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/docs/src/pages/docs/types.tsx
packages/apple/**/*.swift

📄 CodeRabbit inference engine (CLAUDE.md)

packages/apple/**/*.swift: iOS-specific functions MUST have IOS suffix (e.g., presentCodeRedemptionSheetIOS(), showManageSubscriptionsIOS())
Use Pascal case for acronyms at the beginning or middle of names (e.g., IapManager, IapPurchase), but ALL CAPS only when appearing as a suffix (e.g., ProductIAP, OpenIAP)

Files:

  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
  • packages/apple/Sources/OpenIapModule.swift
  • packages/apple/Sources/Models/Types.swift
  • packages/apple/Sources/OpenIapModule+ObjC.swift
packages/apple/Sources/Helpers/**/*.swift

📄 CodeRabbit inference engine (CLAUDE.md)

Place internal helper classes in Sources/Helpers/ (e.g., ProductManager.swift for thread-safe caching, IapStatus.swift for UI status); these are NOT official OpenIAP types

Files:

  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
packages/google/**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

DO NOT add Android suffix to function names in the Android-only package, even for Android-specific APIs (e.g., use acknowledgePurchase() not acknowledgePurchaseAndroid())

Files:

  • packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
  • packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
packages/google/openiap/src/main/java/dev/hyo/openiap/utils/**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

Place reusable Kotlin helper functions in openiap/src/main/java/dev/hyo/openiap/utils/

Files:

  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
packages/gql/**/*

📄 CodeRabbit inference engine (CLAUDE.md)

Run bun run generate to regenerate types for all platforms (TypeScript, Swift, Kotlin, Dart) from the GraphQL schema

Files:

  • packages/gql/src/type-android.graphql
  • packages/gql/scripts/generate-kotlin-types.mjs
  • packages/gql/src/type-ios.graphql
  • packages/gql/src/type.graphql
packages/apple/Sources/Models/Types.swift

📄 CodeRabbit inference engine (CLAUDE.md)

DO NOT edit Types.swift in Sources/Models/ as it is auto-generated from the OpenIAP GraphQL schema; regenerate using ./scripts/generate-types.sh

Files:

  • packages/apple/Sources/Models/Types.swift
packages/apple/Sources/Models/**/*.swift

📄 CodeRabbit inference engine (CLAUDE.md)

OpenIAP official types in Sources/Models/ must match types defined at openiap.dev/docs/types

Files:

  • packages/apple/Sources/Models/Types.swift
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/openiap-versions.json : To update OpenIAP GraphQL types in the iOS/macOS library, edit the `gql` field in `openiap-versions.json`, run `./scripts/generate-types.sh`, and run `swift test` to verify compatibility
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/Sources/Models/**/*.swift : OpenIAP official types in `Sources/Models/` must match types defined at [openiap.dev/docs/types](https://www.openiap.dev/docs/types)
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/Sources/Models/Types.swift : DO NOT edit `Types.swift` in `Sources/Models/` as it is auto-generated from the OpenIAP GraphQL schema; regenerate using `./scripts/generate-types.sh`
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/**/*.swift : Use Pascal case for acronyms at the beginning or middle of names (e.g., `IapManager`, `IapPurchase`), but ALL CAPS only when appearing as a suffix (e.g., `ProductIAP`, `OpenIAP`)
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to **/*.{ts,tsx} : Android-specific functions must end with `Android` suffix (e.g., `acknowledgePurchaseAndroid`, `consumePurchaseAndroid`)

Applied to files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/apis.tsx
  • packages/docs/src/pages/docs/features/subscription.tsx
  • packages/docs/src/pages/docs/features/external-purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/docs/src/pages/docs/types.tsx
  • packages/gql/src/type-android.graphql
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/openiap-versions.json : To update OpenIAP GraphQL types in the iOS/macOS library, edit the `gql` field in `openiap-versions.json`, run `./scripts/generate-types.sh`, and run `swift test` to verify compatibility

Applied to files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
  • packages/docs/src/pages/docs/updates/notes.tsx
  • packages/docs/src/pages/docs/apis.tsx
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
  • packages/gql/src/type-android.graphql
  • packages/gql/src/type-ios.graphql
  • packages/gql/src/type.graphql
  • packages/apple/Sources/OpenIapModule.swift
  • packages/apple/Sources/Models/Types.swift
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
  • packages/apple/Sources/OpenIapModule+ObjC.swift
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/google/**/*.kt : DO NOT add `Android` suffix to function names in the Android-only package, even for Android-specific APIs (e.g., use `acknowledgePurchase()` not `acknowledgePurchaseAndroid()`)

Applied to files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/features/external-purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
  • packages/gql/src/type-android.graphql
  • packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/docs/**/*.{ts,tsx} : Use kebab-case for search modal IDs (e.g., `id: 'request-products'`)

Applied to files:

  • packages/docs/src/pages/docs/features/purchase.tsx
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/google/openiap-versions.json : To update OpenIAP GraphQL types in the Android library, edit the `gql` field in `openiap-versions.json`, then run `./scripts/generate-types.sh` and compile to verify

Applied to files:

  • packages/docs/src/pages/docs/features/purchase.tsx
  • packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx
  • packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
  • packages/gql/src/type-android.graphql
  • packages/gql/scripts/generate-kotlin-types.mjs
  • packages/gql/src/type-ios.graphql
  • packages/gql/src/type.graphql
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to **/*.{ts,tsx} : iOS-specific functions must end with `IOS` suffix (e.g., `clearTransactionIOS`, `getAppTransactionIOS`)

Applied to files:

  • packages/docs/src/pages/docs/features/purchase.tsx
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/Sources/Models/**/*.swift : OpenIAP official types in `Sources/Models/` must match types defined at [openiap.dev/docs/types](https://www.openiap.dev/docs/types)

Applied to files:

  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
  • packages/docs/src/pages/docs/apis.tsx
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
  • packages/gql/src/type-ios.graphql
  • packages/gql/src/type.graphql
  • packages/apple/Sources/OpenIapModule.swift
  • packages/apple/Sources/Models/Types.swift
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
  • packages/apple/Sources/OpenIapModule+ObjC.swift
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/**/*.swift : Use Pascal case for acronyms at the beginning or middle of names (e.g., `IapManager`, `IapPurchase`), but ALL CAPS only when appearing as a suffix (e.g., `ProductIAP`, `OpenIAP`)

Applied to files:

  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
  • packages/gql/src/type.graphql
  • packages/apple/Sources/OpenIapModule.swift
  • packages/apple/Sources/Models/Types.swift
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/Sources/Models/Types.swift : DO NOT edit `Types.swift` in `Sources/Models/` as it is auto-generated from the OpenIAP GraphQL schema; regenerate using `./scripts/generate-types.sh`

Applied to files:

  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
  • packages/docs/src/pages/docs/apis.tsx
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
  • packages/docs/src/pages/docs/types.tsx
  • packages/gql/src/type-ios.graphql
  • packages/gql/src/type.graphql
  • packages/apple/Sources/OpenIapModule.swift
  • packages/apple/Sources/Models/Types.swift
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
  • packages/apple/Sources/OpenIapModule+ObjC.swift
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/Sources/Helpers/**/*.swift : Place internal helper classes in `Sources/Helpers/` (e.g., `ProductManager.swift` for thread-safe caching, `IapStatus.swift` for UI status); these are NOT official OpenIAP types

Applied to files:

  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
  • packages/apple/Sources/Helpers/StoreKitTypesBridge.swift
  • packages/apple/Sources/OpenIapModule.swift
  • packages/apple/Sources/Models/Types.swift
  • packages/apple/Sources/OpenIapModule+ObjC.swift
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/apple/**/*.swift : iOS-specific functions MUST have `IOS` suffix (e.g., `presentCodeRedemptionSheetIOS()`, `showManageSubscriptionsIOS()`)

Applied to files:

  • packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/google/openiap/src/main/Types.kt : DO NOT edit `openiap/src/main/Types.kt` as it is auto-generated from the GraphQL schema; regenerate it using `./scripts/generate-types.sh`

Applied to files:

  • packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
  • packages/gql/src/type-android.graphql
  • packages/gql/scripts/generate-kotlin-types.mjs
  • packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/gql/src/type.graphql
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/google/openiap/src/main/java/dev/hyo/openiap/utils/**/*.kt : Place reusable Kotlin helper functions in `openiap/src/main/java/dev/hyo/openiap/utils/`

Applied to files:

  • packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt
  • packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt
  • packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
📚 Learning: 2025-12-06T20:15:59.223Z
Learnt from: CR
Repo: hyodotdev/openiap PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T20:15:59.223Z
Learning: Applies to packages/gql/**/* : Run `bun run generate` to regenerate types for all platforms (TypeScript, Swift, Kotlin, Dart) from the GraphQL schema

Applied to files:

  • packages/gql/scripts/generate-kotlin-types.mjs
🧬 Code graph analysis (5)
packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift (1)
packages/gql/src/generated/types.ts (1)
  • IapStore (183-183)
packages/docs/src/pages/docs/updates/notes.tsx (2)
packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (2)
  • code (1290-1312)
  • code (1845-1864)
packages/gql/src/generated/Types.kt (2)
  • code (1357-1379)
  • code (1912-1931)
packages/gql/scripts/generate-kotlin-types.mjs (2)
packages/gql/scripts/generate-swift-types.mjs (10)
  • interfaceFields (623-623)
  • fields (272-272)
  • fields (281-281)
  • fields (356-356)
  • fields (388-388)
  • fields (542-542)
  • fields (615-615)
  • fields (652-654)
  • fields (687-689)
  • type (237-237)
packages/gql/scripts/generate-dart-types.mjs (10)
  • interfaceFields (767-767)
  • fields (196-196)
  • fields (296-296)
  • fields (437-437)
  • fields (480-480)
  • fields (626-626)
  • fields (759-759)
  • fields (805-805)
  • fields (813-815)
  • type (152-152)
packages/apple/Sources/OpenIapModule.swift (2)
packages/gql/src/generated/types.ts (2)
  • IapStore (183-183)
  • RequestVerifyPurchaseWithIapkitResult (798-804)
packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (19)
  • rawValue (15-44)
  • rawValue (46-166)
  • rawValue (171-194)
  • rawValue (196-221)
  • rawValue (226-289)
  • rawValue (291-307)
  • rawValue (309-330)
  • rawValue (332-353)
  • rawValue (355-373)
  • rawValue (375-390)
  • rawValue (392-413)
  • rawValue (415-442)
  • rawValue (444-456)
  • rawValue (458-473)
  • rawValue (475-499)
  • isValid (1571-1599)
  • isValid (1806-1843)
  • code (1290-1312)
  • code (1845-1864)
packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (1)
packages/gql/src/generated/types.ts (3)
  • RequestVerifyPurchaseWithIapkitResult (798-804)
  • RequestPurchasePropsByPlatforms (730-739)
  • RequestSubscriptionPropsByPlatforms (768-777)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test Android
🔇 Additional comments (30)
packages/google/openiap/src/horizon/java/dev/hyo/openiap/utils/BillingConverters.kt (1)

7-7: LGTM! Correct store assignment for Horizon purchases.

The addition of IapStore.Horizon is appropriate for Meta Horizon billing purchases and aligns with the PR's migration from platform-based to store-based identification.

Also applies to: 122-122

packages/google/openiap/src/play/java/dev/hyo/openiap/utils/BillingConverters.kt (1)

5-5: Correctly wiring Google purchases to IapStore.Google.

Importing IapStore (Line 5) and setting store = IapStore.Google in BillingPurchase.toPurchase() cleanly hooks Google Billing purchases into the new store enum without changing existing behavior of other fields. This is aligned with the PR’s migration away from platform while retaining backward compatibility.

Also applies to: 121-123

packages/gql/scripts/generate-kotlin-types.mjs (2)

488-494: LGTM! Efficient interface field collection.

The logic correctly collects all field names from implemented interfaces using a Set for efficient lookup. This handles edge cases properly (empty interfaces, overlapping fields across multiple interfaces).


500-501: Override keyword implementation for interface properties is correct and essential.

The code correctly adds the override keyword to data class properties that implement interface properties (lines 500-501, 504, 507-508), which is syntactically required for Kotlin compilation. The interfaceFields Set (lines 489-493) properly collects field names from all implemented interfaces, and the needsOverride flag ensures only matching properties receive the override modifier. This is critical for types implementing interfaces like PurchaseCommon with the new store field.

packages/docs/src/pages/docs/features/subscription-upgrade-downgrade.tsx (1)

1111-1116: Dart RequestPurchasePropsByPlatforms correctly exposes google field

The Dart bindings in packages/gql/src/generated/types.dart confirm that the type exposes both the deprecated android field and the current google: RequestPurchaseAndroidProps? field. The three Dart code examples in the documentation (lines 1111–1116, 1252–1257, 1540–1544) using google: RequestPurchaseAndroidProps(...) are correct and will compile as-is.

packages/apple/Sources/Helpers/StoreKitTypesBridge.swift (1)

127-173: Setting store: .apple on iOS purchases is correct and consistently applied

The store field is a required property in PurchaseIOS and has been properly set to .apple across all implementations: the primary StoreKitTypesBridge converter, all test fixtures (OpenIapTests, RenewalInfoTests), and the Objective-C bridge. The change maintains backwards compatibility with the existing platform: .ios field, which is now marked as deprecated in favor of the new store field.

packages/docs/src/pages/docs/features/external-purchase.tsx (2)

835-836: Documentation correctly updated for new google property key.

The TypeScript code example now uses google: { skus: [productId] } instead of the deprecated android key, aligning with the API migration from platform-based to store-based naming.


913-916: Kotlin example consistently updated.

The Kotlin example uses google = RequestPurchaseAndroidProps(...), matching the TypeScript changes and maintaining consistency across language examples.

packages/apple/Sources/Models/Types.swift (4)

189-195: New IapStore enum correctly generated.

The enum includes all expected cases (unknown, apple, google, horizon), matching the GraphQL schema type definition in packages/gql/src/generated/types.ts. Based on learnings, this file is auto-generated from the GraphQL schema.


271-279: PurchaseCommon protocol correctly extended with store property.

The deprecation comment on platform and the new store: IapStore property align with the migration strategy. The protocol now requires both for backward compatibility during the transition period.


937-958: RequestPurchasePropsByPlatforms correctly extended.

The struct now includes:

  • apple and google as the new preferred properties
  • ios and android retained with deprecation comments for backward compatibility
  • Initializer accepts all four parameters

This maintains API compatibility while guiding users toward the new naming convention.


1416-1424: Computed store property correctly added to Purchase enum.

The implementation properly delegates to the underlying PurchaseAndroid or PurchaseIOS variant's store property, maintaining consistency with the PurchaseCommon protocol.

packages/apple/Tests/OpenIapTests/VerifyPurchaseWithProviderTests.swift (2)

9-13: Test data correctly uses new IapStore enum.

The RequestVerifyPurchaseWithIapkitResult is constructed with store: .apple, which now refers to IapStore.apple rather than the previous IapkitStore.apple, aligning with the type migration.


43-43: Assertion correctly updated to use IapStore.apple.

The test now asserts against IapStore.apple, matching the updated type signature of RequestVerifyPurchaseWithIapkitResult.store.

packages/apple/Sources/OpenIapModule+ObjC.swift (1)

273-307: Minimal PurchaseIOS correctly includes required store field.

The store: .apple assignment is necessary to satisfy the updated PurchaseIOS struct requirements. This is the correct value for iOS transactions created in the Apple package.

packages/docs/src/pages/docs/features/purchase.tsx (1)

279-281: TypeScript purchase example correctly updated to new API.

The code example now uses apple: { sku: productId } and google: { skus: [productId] }, reflecting the migration from ios/android to apple/google property keys as per the v1.3.0 changes.

packages/google/openiap/src/main/java/dev/hyo/openiap/utils/PurchaseVerificationValidator.kt (2)

95-96: LGTM!

The migration from IapkitStore.Google to IapStore.Google is correct and aligns with the unified store taxonomy introduced in this PR.


169-189: Good addition of Horizon support and error handling.

The function correctly:

  • Accepts the new IapStore type
  • Handles both IapStore.Google and IapStore.Horizon in the same branch
  • Uses store.rawValue which matches the Kotlin enum property
  • Provides clear error handling for unsupported stores
packages/gql/src/type-android.graphql (1)

69-99: LGTM! Clean deprecation path with backward compatibility.

The schema update correctly:

  • Adds the new store: IapStore! field with clear documentation
  • Retains the deprecated platform: IapPlatform! field for backward compatibility
  • Uses proper GraphQL @deprecated directive syntax
  • Provides clear migration guidance via the deprecation reason

This approach ensures existing clients continue to work while new clients can adopt the preferred store field.

packages/apple/Sources/OpenIapModule.swift (2)

656-657: LGTM! Correct migration to IapStore.

The change from IapkitStore to IapStore aligns with the unified store taxonomy introduced across the codebase.


734-765: Excellent addition of Horizon support and error handling.

The function correctly:

  • Accepts the new IapStore type
  • Handles .google and .horizon in the same branch (both use Google-style payload)
  • Adds explicit error handling for .unknown store type
  • Maintains clean separation between Apple and Google/Horizon verification paths

The defensive programming with the .unknown case prevents silent failures if an invalid store type is passed.

packages/gql/src/type.graphql (2)

38-43: LGTM! Well-structured enum with clear taxonomy.

The new IapStore enum properly replaces IapkitStore and adds support for Unknown and Horizon stores. The enum values use PascalCase which is consistent with GraphQL conventions.


194-230: Excellent backward-compatible migration strategy.

The platform-specific request props correctly:

  • Introduce new apple and google fields with clear documentation
  • Retain deprecated ios and android fields for backward compatibility
  • Use proper GraphQL @deprecated directive syntax
  • Apply the same pattern consistently across both RequestPurchasePropsByPlatforms and RequestSubscriptionPropsByPlatforms

This ensures existing clients continue to function while providing a clear migration path to the new naming.

packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt (7)

309-330: Auto-generated IapStore enum looks correct.

The new enum with Unknown, Apple, Google, and Horizon variants follows the established pattern of other enums in this file and aligns with the GraphQL schema changes. Based on learnings, this file is auto-generated—ensure changes originate from the GraphQL schema and ./scripts/generate-types.sh.


527-541: Deprecation and new store field properly added to PurchaseCommon.

The platform field is correctly marked as deprecated with guidance to use store instead, and the new store: IapStore field is added. This matches the pattern in the relevant GraphQL types.


1221-1284: PurchaseAndroid correctly implements the new store field.

The data class properly adds the store property with deprecation notice on platform, and the fromJson/toJson methods correctly handle serialization. Implementation is consistent with the PurchaseCommon interface.


1331-1427: PurchaseIOS correctly implements the new store field.

Same pattern as PurchaseAndroid—the store field is added with proper deprecation of platform, and JSON serialization is handled correctly.


1580-1597: RequestVerifyPurchaseWithIapkitResult correctly adds store field.

The implementation matches the GraphQL types definition showing store: IapStore in this result type. Serialization is correctly handled.


2195-2230: RequestPurchasePropsByPlatforms correctly adds apple/google fields.

The implementation matches the GraphQL types definition:

  • android is deprecated in favor of google
  • ios is deprecated in favor of apple
  • Both new and deprecated fields are preserved for backward compatibility

This aligns with the relevant code snippet from packages/gql/src/generated/types.ts lines 729-738.


2315-2350: RequestSubscriptionPropsByPlatforms correctly adds apple/google fields.

Same pattern as RequestPurchasePropsByPlatforms—deprecated android/ios fields with new apple/google replacements. Matches the GraphQL types definition from packages/gql/src/generated/types.ts lines 767-776.

Comment thread packages/docs/src/pages/docs/apis.tsx
Comment thread packages/docs/src/pages/docs/types.tsx
@hyochan hyochan merged commit db9112f into main Dec 8, 2025
5 checks passed
@hyochan hyochan deleted the feat/1.3-purchase-fields branch December 8, 2025 18:52
hyochan added a commit to hyochan/expo-iap that referenced this pull request Dec 8, 2025
hyodotdev/openiap#49

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Added store field to purchase details for better tracking
* Enhanced error handling with detailed error information in
verification results

* **Bug Fixes**
  * Fixed verification result structure for improved data consistency

* **Documentation**
* Updated comprehensive API documentation and guides with latest
examples
  * Expanded setup guides for iOS, Android, and Horizon platforms
* Added detailed error handling, subscription, and purchase flow
documentation

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🎯 feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant