Skip to content

feat(react-native): Expo module for on-device Moss (#432)#473

Open
samanyugoyal2010 wants to merge 2 commits into
usemoss:mainfrom
samanyugoyal2010:issue-432-react-native-expo
Open

feat(react-native): Expo module for on-device Moss (#432)#473
samanyugoyal2010 wants to merge 2 commits into
usemoss:mainfrom
samanyugoyal2010:issue-432-react-native-expo

Conversation

@samanyugoyal2010

@samanyugoyal2010 samanyugoyal2010 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds @moss-dev/moss-react-native under sdks/react-native/ — an Expo Modules package that exposes a MossClient SharedObject for on-device semantic search.
  • iOS: links Moss.xcframework (same binary as the Swift SDK, v0.6.2), downloaded + checksum-verified at pod install.
  • Android: clear stub that throws until native Android builds land (#411).
  • Includes an Expo config plugin, package README, and examples/react-native/ usage sketch. Updates ROADMAP / AGENTS / root README.

Closes #432

Notes

  • Requires a development build / expo prebuild (not Expo Go).
  • First release covers the cloud + local query loop (createIndex, loadIndex, query, addDocs, index CRUD). Session / Authenticator APIs from the Swift SDK are deferred.

Test plan

  • cd sdks/react-native && npm install && npm run build
  • Wire the package into an Expo app with plugins: ["@moss-dev/moss-react-native"], run npx expo prebuild + pod install, confirm Moss.xcframework downloads
  • On iOS simulator/device: create index → load → query with portal credentials
  • On Android: confirm constructing MossClient throws with the SDK: Kotlin / Android bindings #411 message
  • Confirm Expo Go is documented as unsupported

Made with Cursor

Review in cubic

Introduce @moss-dev/moss-react-native under sdks/react-native with an
Expo Modules SharedObject wrapping Moss.xcframework on iOS, an Android
stub pointing at usemoss#411, a config plugin, and a usage example.

Co-authored-by: Cursor <cursoragent@cursor.com>
Raise the iOS deployment target to 16.4, wire MossC module/search paths and
system frameworks, and exclude x86_64 simulator so prebuild + link succeed
on Apple Silicon.

Co-authored-by: Cursor <cursoragent@cursor.com>
@samanyugoyal2010

Copy link
Copy Markdown
Contributor Author

@cubic.dev

@cubic-dev-ai

cubic-dev-ai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

@cubic.dev

@samanyugoyal2010 I can't start this review because you've reached your trial's review limit. Trial plans have lower review limits than paid plans. Upgrade now to resume reviews.

To help optimise your usage, you can tune cubic to get the most out of your usage limits:

Learn more →

# System frameworks used by libmoss (see examples/c + Swift SDK)
s.frameworks = 'Security', 'SystemConfiguration', 'UIKit'

s.prepare_command = <<-CMD

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

BLOCKING ```ruby
s.prepare_command = <<-CMD
bash "#{dir}/scripts/download-moss-xcframework.sh"
CMD
s.vendored_frameworks = 'Frameworks/Moss.xcframework'

Expo/React Native autolinking installs this pod from `node_modules` as a local `:path` pod, and CocoaPods does not run `prepare_command` for local path pods. Since the npm package excludes `ios/Frameworks`, `Frameworks/Moss.xcframework` will be missing during normal `pod install`/build. Move the download to a hook that runs before CocoaPods resolves the local pod, such as the Expo config plugin or npm `postinstall`, or ship the xcframework in the package.

guard !closed, let handle else {
throw Self.mossError(code: -1, message: "MossClient already closed")
}
return handle

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

BLOCKING ```swift
private func borrow() throws -> OpaquePointer {
...
return handle
}

`borrow()` releases the lock before each async native method calls into `moss_client_*`, so `client.close()` can concurrently free the same handle while an operation is still using it. This is a use-after-free risk and may also race shared client state. Replace this with a `withHandle`/serial queue that holds ownership for the entire C call and makes `close()` wait for in-flight operations before calling `moss_client_free`.

const withMoss = (config) => {
config = withPodfileProperties(config, (cfg) => {
cfg.modResults['ios.deploymentTarget'] =
cfg.modResults['ios.deploymentTarget'] || '16.4';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CONSIDER ```js
cfg.modResults['ios.deploymentTarget'] =
cfg.modResults['ios.deploymentTarget'] || '16.4';

This only fills an empty deployment target. If an app already has a lower value, the plugin leaves it in place even though the podspec requires iOS 16.4, leading to a CocoaPods/build failure. Parse the existing value and set it to `max(existing, '16.4')`.

@github-actions

Copy link
Copy Markdown

Codex review

The PR adds a React Native/Expo SDK, but the iOS integration has blockers around installing the vendored binary and safely managing the native client handle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SDK: React Native and Expo module

2 participants