|
| 1 | +# Contributing |
| 2 | + |
| 3 | +## Podspec naming convention |
| 4 | + |
| 5 | +Capacitor CLI derives the CocoaPods pod name from the npm package name: |
| 6 | + |
| 7 | +``` |
| 8 | +npm: capacitor-plugin-cdv-purchase → pod: CapacitorPluginCdvPurchase |
| 9 | +``` |
| 10 | + |
| 11 | +The podspec filename and `s.name` must match this derived name exactly. A mismatch causes "No podspec found" during `pod install`. |
| 12 | + |
| 13 | +There are two podspecs: |
| 14 | +- `CapacitorPluginCdvPurchase.podspec` — root-level, used by Capacitor CLI (paths relative to package root) |
| 15 | +- `ios/CapacitorPluginPurchase.podspec` — legacy (paths relative to `ios/`) |
| 16 | + |
| 17 | +## iOS availability guards |
| 18 | + |
| 19 | +The plugin targets iOS 15.0 but some APIs require newer versions: |
| 20 | + |
| 21 | +- `AppTransaction.shared` — requires `#available(iOS 16.0, *)` |
| 22 | +- `AppStore.presentOfferCodeRedeemSheet` — requires `#available(iOS 16.0, *)` |
| 23 | +- `Locale.region` — requires `#available(iOS 16.0, *)` |
| 24 | + |
| 25 | +Always wrap these in availability checks with a fallback. |
| 26 | + |
| 27 | +## SPM (Swift Package Manager) compatibility |
| 28 | + |
| 29 | +The plugin builds with CocoaPods. SPM support is provided via `Package.swift` but has known limitations with Capacitor's precompiled xcframework. |
| 30 | + |
| 31 | +### The problem |
| 32 | + |
| 33 | +Capacitor distributes its iOS framework as a precompiled `.xcframework` via `capacitor-swift-pm`. Swift extension methods on Objective-C types are not exported from binary frameworks. This means common Capacitor APIs are invisible when built via SPM: |
| 34 | + |
| 35 | +| API | SPM status | Workaround | |
| 36 | +|-----|-----------|------------| |
| 37 | +| `call.resolve()` | Works | (zero-arg overload) | |
| 38 | +| `call.resolve(data)` | Works | | |
| 39 | +| `call.reject(msg)` | Not available | None reliable — method is invisible | |
| 40 | +| `call.getString("key")` | Not available | `call.options["key"] as? String` | |
| 41 | +| `call.getArray("key")` | Not available | `call.options["key"] as? [Type]` | |
| 42 | +| `call.getBool("key")` | Not available | `call.getBool("key", false)` | |
| 43 | +| `CAPPluginCallError(...)` | Not available | Init is inaccessible | |
| 44 | + |
| 45 | +### Impact |
| 46 | + |
| 47 | +This is a Capacitor-level issue affecting **all** third-party plugins, not specific to this one. It needs to be resolved upstream in `ionic-team/capacitor` by either shipping source via SPM instead of precompiled binaries, or moving APIs to ObjC headers. SPM became the default in Capacitor 8. |
| 48 | + |
| 49 | +### CI strategy |
| 50 | + |
| 51 | +The CI tests against Capacitor 6 and 7 using CocoaPods (the default for those versions). Once the upstream SPM issue is resolved, Capacitor 8 can be added to the test matrix. |
| 52 | + |
| 53 | +## CI environment notes |
| 54 | + |
| 55 | +- **macOS-15 + Xcode 16.2** may report "no destinations" with `-sdk iphoneos`. Use `-destination 'generic/platform=iOS'` instead. |
| 56 | +- **`@capacitor/create-app`** always scaffolds the latest template (Cap 8 / SPM) regardless of CLI version. For testing older versions, scaffold manually with `npm init` + pinned deps. |
| 57 | +- **Ruby version conflicts** on macOS: `pod` (Homebrew) and `gem` (system) may point to different Ruby versions. Install gems with the Homebrew Ruby if needed. |
0 commit comments