feat: add Swift Package Manager support and upgrade to Expo SDK 56#11
Merged
Conversation
…tooling to latest - expo-modules-core ~56.0.14, expo-module-scripts ~56.0.3 (Expo SDK 56) - @types/react ~19.2.0 - typescript ~5.9.2 (now required as host dep by expo-module-scripts 56) - eslint ^9.0.0 + flat config (replaces .eslintrc.js) - prettier ^3.0.0 (peer of eslint-config-universe) - @commitlint/cli + @commitlint/config-conventional 21.0.2 - semantic-release 25.0.3 - husky 9.1.7 - commitizen 4.3.1 - migrated tsconfig.json to expo-module-scripts 56 layout (rootDir, __rsc_tests__ exclude) - expo-module configure auto-fixed prettier formatting in src/
…t 19.2 - expo ~56.0.8, react 19.2.3, react-native 0.85.3 - typescript ~5.9.2, @babel/core ^7.29.7, @types/react ~19.2.0 - newArchEnabled: true - iOS deploymentTarget: 16.4 - adds NSLocalNetworkUsageDescription (required since iOS 14 for the local network permission prompt to appear) - regenerates metro.config.js and tsconfig.json for SDK 56 layout - removes webpack.config.js (Metro is the default web bundler since SDK 50)
… to iOS 14 - Drop Package.swift's broken `.package(url: expo/expo)` dependency. The expo/expo repo has no top-level Package.swift, so that line never resolved. Match the pattern used by other Expo-module SPM scaffolding (e.g. react-native-mrz-scanner): declare ExpoModulesCore by name only and let the consuming autolinking pipeline (RN CLI's SPM autolinking per RFC 0994, Expo's `et prebuild`, or a brownfield app's manifest) inject `.package(path: ".../node_modules/expo-modules-core")`. - Drop podspec iOS floor from 16.4 back to 14.0 (NWBrowser/local network permission is iOS 14+). Expo SDK 56's precompiled ExpoModulesCore xcframework requires 16.4, but the Expo cocoapods plugin auto-raises matching pods at install time, so consumers on older Expo SDKs aren't forced up unnecessarily. Avoids a breaking change. - Drop Package.swift platform floor to .v14 to match the podspec. - Update README to honestly describe the SPM scaffolding: drop the inaccurate "Add Package Dependencies in Xcode" instructions, link RFC 0994 as the rationale.
…e path This lets our Package.swift parse and resolve standalone whenever it is consumed as a local package alongside a standard Expo / React Native node_modules layout (the shape RFC 0994's autolinking generates). Previously the dependency was referenced by name only in the target's dependency list — which fails SPM manifest validation because every named package must appear in the package's own dependencies array. Verified by: - swift package describe / resolve: succeed when ../expo-modules-core is present. - xcodebuild via SPM scheme for iOS: gets past manifest resolution and into Swift compilation against a stub ExpoModulesCore package (compilation only fails on stub API surface, not on our manifest).
Drop spm.config.json from iOS 16 → iOS 14 so all three install paths (podspec, Package.swift, spm.config.json) declare the same floor — the actual API floor for NWBrowser. Without this, consumers using Expo's precompile pipeline got artificially restricted to iOS 16+ even though the library itself only needs iOS 14. Also: add Foundation to Package.swift linkerSettings for parity with spm.config.json, and clarify in the file-level comment that the .package(path: "../expo-modules-core") layout means this manifest does not resolve standalone via Xcode "Add Package Dependencies…" today. BREAKING CHANGE: minimum iOS deployment target is now 14.0 (was 13.4). The library calls NWBrowser, which is iOS 14+, so iOS 13 was never actually supported at runtime — this change just makes the unsupported floor explicit. Apps still targeting iOS 13 will see a "Specs satisfying the dependency were found, but they required a higher minimum deployment target" error from CocoaPods and need to bump their podfile platform to 14.0 or stay on 1.x of this library.
Bumping to 5.9 was cosmetic — the library's Swift uses no syntax newer than 5.4 and Expo 56 builds fine against either. Reverting to keep the diff scoped to changes that actually do something.
kuznetsov-sergei
approved these changes
Jun 1, 2026
- Package.swift: add prominent monorepo-layout warning near the expo-modules-core relative-path dependency so contributors don't hit silent resolution failures in hoisted Yarn/pnpm workspaces - Package.swift: drop redundant explicit Foundation linker setting (Foundation is implicitly linked for Swift targets) - spm.config.json: switch $schema URL to the canonical raw GitHub URL for expo/expo's spm.config.schema.json — the previous expo.dev URL returns 404 and gives no IDE validation - package.json: pin eslint to ~9.39.4 instead of ^9.0.0 to prevent unintended minor upgrades that could regress the flat config - example/ios/Podfile: add a header noting the file is generated by `expo prebuild` so future contributors know to regenerate, not hand-edit
github-actions Bot
pushed a commit
that referenced
this pull request
Jun 1, 2026
# [1.3.0](v1.2.0...v1.3.0) (2026-06-01) ### Features * add Swift Package Manager support and upgrade to Expo SDK 56 ([#11](#11)) ([65f99ef](65f99ef))
|
🎉 This PR is included in version 1.3.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
spm.config.jsonfor the Expo precompile pipeline (et prebuild→ XCFrameworks)Package.swiftaligned with RFC 0994:expo-modules-coreis referenced via the standardnode_moduleslayout, so the manifest will resolve once consumed by the future RN CLI SPM autolinkingios/PrivacyInfo.xcprivacy(required by Apple for SPM-distributed iOS frameworks)expo-modules-coreandexpo-module-scriptsto SDK 56, plus all dev tooling (eslint 9, prettier 3, typescript 5.9, semantic-release 25, husky 9, commitlint 21, etc.)Package.swift, andspm.config.json. iOS 14 is whenNWBrowserfirst exists, which is what this library calls — iOS 13 was never actually supported at runtimeNSLocalNetworkUsageDescriptionto the example'sInfo.plisteslint.config.js)Background: based on the App.js Conf 2026 talk on the React Native → SPM migration. Expo's
et prebuildpipeline and CocoaPods trunk going read-only on 2026-12-02 mean library maintainers should ship SPM configs now.Breaking change
Minimum iOS deployment target raised from 13.4 → 14.0. Apps still targeting iOS 13 will need to bump their Podfile platform to 14.0 or stay on 1.x of this library. The commit message includes a
BREAKING CHANGE:footer so semantic-release will cut a 2.0.0.Test plan
yarn install && yarn build && yarn lintfrom repo root all greenswift package describe/swift package resolvesucceed when checked out beside an Exponode_modulestree (the layout RFC 0994's autolinking generates)spm.config.jsonvalidates against Expo's officialspm.config.schema.jsonxcodebuildagainst the regeneratedexample/ios/workspace builds clean (Expo SDK 56 / RN 0.85 / iOS 16.4 default)EXPO_USE_PRECOMPILED_MODULES=1 pod installactivates the precompile pipeline and reports integratingReactNativeLocalNetworkPermissionwith the auto-raised deployment targettruefrom the native SwiftLocalNetworkAuthorizationbridge