Summary
react-native-nitro-sqlite works in Expo development builds through autolinking, but its optional native build configuration is currently manual:
- iOS FTS5/other SQLite flags require a consumer
Podfile post_install mutation.
- Android flags require
android/gradle.properties (nitroSqliteFlags).
- sqlite-vec uses the separate
NITRO_SQLITE_VEC=1 / nitroSqliteVec=true switches after the companion package is installed.
- iOS App Group database storage requires both
RNNitroSQLite_AppGroup in Info.plist and the Xcode App Groups entitlement.
- iOS system SQLite currently requires setting
NITRO_SQLITE_USE_PHONE_VERSION=1 while installing pods.
That prevents a complete managed Expo / EAS Build / Continuous Native Generation setup: generated ios and android projects should not need hand-edited Podfiles, Gradle properties, Info.plists, or entitlements.
Expo recommends library-owned config plugins for native setup. A built-in plugin would make the existing supported native capabilities reproducible across local expo prebuild, expo run:*, and EAS Build.
Proposed package surface
Ship a compiled plugin with the core package:
// app.config.ts
export default {
expo: {
plugins: [
[
'react-native-nitro-sqlite',
{
fts5: true,
sqliteVec: false,
ios: {
appGroup: 'group.com.example.shared',
useSystemSqlite: false,
},
sqliteFlags: {
ios: ['SQLITE_ENABLE_GEOPOLY=1'],
android: ['-DSQLITE_ENABLE_GEOPOLY=1'],
},
},
],
],
},
}
Suggested API principles:
fts5?: boolean defaults to false; the plugin maps true to SQLITE_ENABLE_FTS5=1 on both platforms. Keep it opt-in: FTS adds binary size/attack surface and is not required by every database consumer.
sqliteFlags?: { ios?: string[]; android?: string[] } is additive/advanced. Validate each entry (KEY=VALUE on iOS, -DKEY=VALUE on Android), de-duplicate it, and reject flags that contradict the library's fixed safety/ABI settings. Do not add a broad arbitrary-string escape hatch that can silently break a build.
ios?: { appGroup?: string; useSystemSqlite?: boolean }. appGroup writes the existing RNNitroSQLite_AppGroup Info.plist key and adds the exact identifier to the app target's com.apple.security.application-groups entitlement. It must preserve existing groups and fail clearly for malformed identifiers. useSystemSqlite should reproduce the current pod-install setting for the library pod only.
sqliteVec?: boolean belongs to the companion react-native-nitro-sqlite-vec package's plugin, not core. The core plugin may detect that the companion is installed and emit a targeted error / documentation link when sqliteVec: true is passed, but should not import or hard-depend on it. The companion plugin can delegate shared flag helpers from core and configure both native switches only when the companion package is resolvable.
The first version should intentionally not expose the podspec's performance_mode: it is hard-coded today and its threading semantics need a separate API/safety decision. Likewise, useSystemSqlite should be explicit and documented as a platform-version/feature trade-off, not enabled implicitly.
Native modifications
iOS
- Use
withInfoPlist for RNNitroSQLite_AppGroup.
- Use
withEntitlementsPlist (and, only if necessary, withXcodeProject) to merge the App Groups entitlement without removing app-owned entries.
- Use the narrowest safe CocoaPods/Podfile-properties mechanism to apply library-scoped C/C++ preprocessor definitions and
NITRO_SQLITE_USE_PHONE_VERSION=1. Do not mutate unrelated targets or overwrite an app's post_install hook.
Android
- Use
withGradleProperties to merge nitroSqliteFlags into the existing property without duplicate -D definitions.
- The companion plugin owns
nitroSqliteVec=true; it must verify the companion package is installed before enabling it.
- No manifest change is expected for core SQLite/FTS/vector configuration.
Acceptance criteria
- The package exposes
app.plugin.js and typed plugin options, with the plugin build included in published artifacts and compatible with app.config.js/ts/json configuration.
- Re-running prebuild is idempotent: no duplicate flags, plist keys, app groups, Podfile edits, or Gradle properties.
- Existing manual configuration remains supported and composes without overrides; conflicts produce actionable errors.
fts5: true produces a build where SELECT sqlite_compileoption_used('ENABLE_FTS5') is true on iOS and Android, and FTS table creation succeeds.
- The companion package's plugin reliably enables sqlite-vec on iOS and Android; a build without it leaves the base package vector-free.
ios.appGroup produces both the Info.plist value consumed by NitroSQLite and the matching app-target entitlement, while preserving pre-existing entitlements.
ios.useSystemSqlite produces a build linked with system SQLite and the docs state which bundled capabilities may differ.
- Unit tests cover option validation, platform transformations, merging and idempotency. An Expo example/test fixture runs clean prebuild for iOS and Android and checks generated plist/entitlements/Gradle outputs. CI should run that CNG fixture against the supported Expo SDK range.
- README documents the declarative setup plus the legacy manual setup, explicit rebuild requirement, and EAS Build behavior.
Prior art / context
Summary
react-native-nitro-sqliteworks in Expo development builds through autolinking, but its optional native build configuration is currently manual:Podfilepost_installmutation.android/gradle.properties(nitroSqliteFlags).NITRO_SQLITE_VEC=1/nitroSqliteVec=trueswitches after the companion package is installed.RNNitroSQLite_AppGroupinInfo.plistand the Xcode App Groups entitlement.NITRO_SQLITE_USE_PHONE_VERSION=1while installing pods.That prevents a complete managed Expo / EAS Build / Continuous Native Generation setup: generated
iosandandroidprojects should not need hand-edited Podfiles, Gradle properties, Info.plists, or entitlements.Expo recommends library-owned config plugins for native setup. A built-in plugin would make the existing supported native capabilities reproducible across local
expo prebuild,expo run:*, and EAS Build.Proposed package surface
Ship a compiled plugin with the core package:
Suggested API principles:
fts5?: booleandefaults tofalse; the plugin mapstruetoSQLITE_ENABLE_FTS5=1on both platforms. Keep it opt-in: FTS adds binary size/attack surface and is not required by every database consumer.sqliteFlags?: { ios?: string[]; android?: string[] }is additive/advanced. Validate each entry (KEY=VALUEon iOS,-DKEY=VALUEon Android), de-duplicate it, and reject flags that contradict the library's fixed safety/ABI settings. Do not add a broad arbitrary-string escape hatch that can silently break a build.ios?: { appGroup?: string; useSystemSqlite?: boolean }.appGroupwrites the existingRNNitroSQLite_AppGroupInfo.plist key and adds the exact identifier to the app target'scom.apple.security.application-groupsentitlement. It must preserve existing groups and fail clearly for malformed identifiers.useSystemSqliteshould reproduce the current pod-install setting for the library pod only.sqliteVec?: booleanbelongs to the companionreact-native-nitro-sqlite-vecpackage's plugin, not core. The core plugin may detect that the companion is installed and emit a targeted error / documentation link whensqliteVec: trueis passed, but should not import or hard-depend on it. The companion plugin can delegate shared flag helpers from core and configure both native switches only when the companion package is resolvable.The first version should intentionally not expose the podspec's
performance_mode: it is hard-coded today and its threading semantics need a separate API/safety decision. Likewise,useSystemSqliteshould be explicit and documented as a platform-version/feature trade-off, not enabled implicitly.Native modifications
iOS
withInfoPlistforRNNitroSQLite_AppGroup.withEntitlementsPlist(and, only if necessary,withXcodeProject) to merge the App Groups entitlement without removing app-owned entries.NITRO_SQLITE_USE_PHONE_VERSION=1. Do not mutate unrelated targets or overwrite an app'spost_installhook.Android
withGradlePropertiesto mergenitroSqliteFlagsinto the existing property without duplicate-Ddefinitions.nitroSqliteVec=true; it must verify the companion package is installed before enabling it.Acceptance criteria
app.plugin.jsand typed plugin options, with the plugin build included in published artifacts and compatible with app.config.js/ts/json configuration.fts5: trueproduces a build whereSELECT sqlite_compileoption_used('ENABLE_FTS5')is true on iOS and Android, and FTS table creation succeeds.ios.appGroupproduces both the Info.plist value consumed by NitroSQLite and the matching app-target entitlement, while preserving pre-existing entitlements.ios.useSystemSqliteproduces a build linked with system SQLite and the docs state which bundled capabilities may differ.Prior art / context