Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These are supported funding model platforms

github: gabriel-sisjr # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]

82 changes: 65 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
merge_group:
types:
- checks_requested
Expand Down Expand Up @@ -62,6 +64,7 @@ jobs:

env:
TURBO_CACHE_DIR: .turbo/android
turbo_cache_hit: ''

steps:
- name: Checkout
Expand Down Expand Up @@ -127,6 +130,7 @@ jobs:
TURBO_CACHE_DIR: .turbo/ios
RCT_USE_RN_DEP: 1
RCT_USE_PREBUILT_RNCORE: 1
turbo_cache_hit: ''

steps:
- name: Checkout
Expand Down Expand Up @@ -160,6 +164,17 @@ jobs:
with:
xcode-version: ${{ env.XCODE_VERSION }}

- name: Cache cocoapods
id: cocoapods-cache
if: env.turbo_cache_hit != 1
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: |
**/ios/Pods
key: ${{ runner.os }}-cocoapods-${{ hashFiles('example/ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-cocoapods-

- name: Install cocoapods
if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true'
run: |
Expand Down Expand Up @@ -262,26 +277,59 @@ jobs:
xcrun xcodebuild -workspace SyncProviderExample.xcworkspace -list || \
xcrun xcodebuild -list

# Diagnostic: dumps the simulator catalog the runner actually ships with.
# Non-blocking so a transient simctl failure can never fail the job.
- name: Show available iOS simulators
continue-on-error: true
run: |
xcrun simctl list devices iOS available

- name: Run iOS unit tests
run: |
cd example/ios
set -o pipefail
xcrun xcodebuild test \
-workspace SyncProviderExample.xcworkspace \
-scheme "${IOS_TEST_SCHEME}" \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
-resultBundlePath build/SyncProviderTests.xcresult \
-enableCodeCoverage YES \
CODE_SIGNING_ALLOWED=NO \
CODE_SIGNING_REQUIRED=NO || \
xcrun xcodebuild test \
-workspace SyncProviderExample.xcworkspace \
-scheme "${IOS_TEST_SCHEME}" \
-destination 'platform=iOS Simulator,name=iPhone 15,OS=latest' \
-resultBundlePath build/SyncProviderTests.xcresult \
-enableCodeCoverage YES \
CODE_SIGNING_ALLOWED=NO \
CODE_SIGNING_REQUIRED=NO
cd example/ios

# Pipe xcodebuild output through xcbeautify when present (it ships on
# the GitHub macos-latest image). Fallback to raw output otherwise.
if command -v xcbeautify >/dev/null 2>&1; then
PRETTIFY=(xcbeautify --renderer github-actions)
else
PRETTIFY=(cat)
fi

# Destinations are tried in order. iPhone 16 is the primary target on
# the current Xcode 26 image; iPhone 17 is forward-looking for image
# bumps; iPhone 16 Pro is a safety net within the same generation.
DESTINATIONS=(
"platform=iOS Simulator,name=iPhone 16,OS=latest"
"platform=iOS Simulator,name=iPhone 17,OS=latest"
"platform=iOS Simulator,name=iPhone 16 Pro,OS=latest"
)

for destination in "${DESTINATIONS[@]}"; do
echo "::group::xcodebuild test on $destination"
# xcodebuild errors out if -resultBundlePath already exists, so we
# always start each attempt from a clean slate.
rm -rf build/SyncProviderTests.xcresult
if xcrun xcodebuild test \
-workspace SyncProviderExample.xcworkspace \
-scheme "${IOS_TEST_SCHEME}" \
-destination "$destination" \
-resultBundlePath build/SyncProviderTests.xcresult \
-enableCodeCoverage YES \
-skipPackagePluginValidation \
-skipMacroValidation \
CODE_SIGNING_ALLOWED=NO \
CODE_SIGNING_REQUIRED=NO | "${PRETTIFY[@]}"; then
echo "::endgroup::"
exit 0
fi
echo "::endgroup::"
echo "::warning::xcodebuild test failed on $destination — trying next destination"
done

echo "::error::xcodebuild test failed on every destination"
exit 1

- name: Upload iOS test results
if: always()
Expand Down
25 changes: 24 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

> **Pre-1.0 notice:** while the library is on `0.x`, minor version bumps (`0.x.0`) may include breaking changes. Every breaking change is summarized in [`BREAKING_CHANGES.md`](./BREAKING_CHANGES.md) and ships with a dedicated migration guide under `website/docs/migration/`.

## [Unreleased]
## v0.1.1 - 2025-05-19

### Fixed

- **iOS / Swift↔C++ name collision in the Nitro-generated bridging header.** Renamed the Swift implementation class from `SyncProvider` to `HybridSyncProvider` in `ios/SyncProvider.swift` and updated `nitro.json → autolinking.SyncProvider.ios.implementationClassName` accordingly. The previous name collided with the C++ `SyncProvider::SyncProvider` class generated by Nitro inside the `margelo::nitro::syncprovider` namespace, surfacing as `SyncProvider-Swift.h:12942: no member named '_impl' in 'SyncProvider::SyncProvider'`. **No JS-facing change** — the Nitro `iosModuleName` (`SyncProvider`) and the JS lookup (`NitroModules.createHybridObject<SyncProvider>('SyncProvider')`) are unchanged, the Android Kotlin class name (`SyncProvider`) is unchanged, and the public TypeScript surface is unaffected. After pulling this fix, run `yarn nitrogen` to regenerate the C++ glue with the new class name.
- **iOS / Swift 6 strict-concurrency compliance.** Replaced every `NSLock.lock()` / `defer { lock.unlock() }` (and bare `lock()` / `unlock()`) pattern inside `Promise.async { @Sendable in ... }` closures with `lock.withLock { ... }`. The previous pattern captured a non-`Sendable` `NSLock` reference into a `@Sendable` closure, which is a hard error under Swift 6. Affected files: `ios/SyncProvider.swift` (2 sites), `ios/Background/BackgroundSyncManager.swift` (4 sites), `ios/Connectivity/ConnectivityMonitor.swift` (6 sites — snapshot-then-notify-outside-lock pattern preserved), `ios/Events/SyncEventEmitter.swift` (4 sites — snapshot-then-emit-outside-lock pattern preserved), `ios/HTTP/BackgroundURLSessionDelegate.swift` (5 sites — lock released before invoking captured completion handlers). `NSLock` retained as the primitive (no `OSAllocatedUnfairLock` / `actor` migration) to preserve the iOS 13.0 deployment target floor declared in the podspec.

### Chore

- **ci:** wire iOS unit tests into CI via the existing `SyncProvider-Unit-Tests` CocoaPods test_spec scheme. CocoaPods 1.10+ auto-prefixes `:test_type => :unit` (the default) with `Unit-`, so the `s.test_spec 'Tests'` block in `SyncProvider.podspec` produces the scheme name `SyncProvider-Unit-Tests` (not `SyncProvider-Tests`) — the `test-ios` job in `.github/workflows/ci.yml` was rewritten to target that scheme with a destination fallback loop (`iPhone 16` → `iPhone 17` → `iPhone 16 Pro`, all `OS=latest`), `rm -rf build/SyncProviderTests.xcresult` before each attempt (recovers from the previous `"Existing file at -resultBundlePath"` failure mode), `-skipPackagePluginValidation`, `-skipMacroValidation`, opportunistic `xcbeautify` formatting, GitHub annotations, plus a new "Show available iOS simulators" diagnostic step. Also added an explicit `pod 'SyncProvider', :path => '../..', :testspecs => ['Tests']` to `example/ios/Podfile` (after `use_react_native!`) because `use_native_modules!` autolinking does not propagate `:testspecs` — without the opt-in, CocoaPods would never generate the test target — and added `installer.pods_project.recreate_user_schemes(false)` inside the existing `post_install` block to defensively share the generated test scheme.
- **scripts:** add `yarn test:ios` (`scripts/test-ios.sh`, executable) to mirror the CI iOS test invocation locally — same destination fallback loop and `.xcresult` cleanup as CI, so a green local run is a strong predictor of CI success.

## v0.1.0 - 2025-05-19

### Documentation

- **README rewrite.** Realigned `README.md` with the `react-native-background-location` information architecture: full badge set (NPM stable + beta + downloads + total downloads, CI / Pre-release / Release workflows, Codecov, GitHub Stars, Bundlephobia, License, Platform Android / iOS, TypeScript-Ready, New Architecture, Nitro Module), Table of Contents linking every section, expanded Features bullets describing the actual implemented surface (Room + Core Data persistence, `BGTaskScheduler` + `WorkManager` dispatch, `NWPathMonitor` + `ConnectivityManager` connectivity detection, 7 hooks, 15 typed events, `SyncError` discriminated codes, Nitro JSI bridge), per-platform Installation block (npm/yarn + iOS Background Modes + `BGTaskSchedulerPermittedIdentifiers` + pod install + Android `INTERNET` / `ACCESS_NETWORK_STATE` / `RECEIVE_BOOT_COMPLETED`), Quick Start sample exercising `configureSync` + `enableBackgroundSync` + `enqueue` + `useConnection`/`useSyncQueue`/`useSyncStatus`, Hooks table deep-linking every page in `website/docs/api-reference/hooks/`, API Reference signature tables (queue / sync / config / history / connectivity / background sync / event listeners / utilities), inline TypeScript blocks for every public type (`SyncItemInput`, `SyncItem`, `RetryPolicy`, `SyncOptions`, `SyncResult`, `SyncEvent`, `BackgroundSyncOptions`, `ConnectionState`, `SyncError`), inline enum tables for `SyncStrategy`, `SyncPriority`, `BackoffStrategy`, `HttpMethod`, `ConnectionStatus`, `ConnectionType`, `SyncEventType` (all 15), and `SyncErrorCode` (all 11), Platform Support table, and a curated Documentation section indexing every Docusaurus page. Dropped the pre-release banner — the v0.1 line is treated as opinionated GA. Preserved the unique "Why this library", "How it compares", "Ecosystem", "Performance notes", and "FAQ" sections.

### Chore

- **`package.json` metadata curated.** Refined `description` to align word-for-word with the README hero line (cross-platform React Native library for offline-first HTTP sync built on Nitro Modules / New Architecture). Expanded `keywords` to cover the full discovery surface (offline, queue, sync, http, background-sync, nitro-modules, etc.). Updated `homepage` to point at the Docusaurus site (`https://gabriel-sisjr.github.io/react-native-sync-provider/`).
- **`.github/FUNDING.yml` added** so the GitHub Sponsors button renders on the repo.
- **`context7.json` added** with a placeholder `public_key` to opt the package into the Context7 documentation index ahead of v0.1.0.
- **Repository labels automation added.** New `labels.json` defines the canonical issue/PR label set; `scripts/sync-labels.sh` applies it via `gh label`. Run once after fork to bring a new repository (or a contributor's fork) into alignment with the upstream label taxonomy.

### Fixed

Expand Down
Loading