Skip to content
Open
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
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
> [!NOTE]
> Requires [Nitro modules](https://nitro.margelo.com/) and React Native `0.75` or later.

Nitro SQLite embeds SQLite and exposes a JSI API. Each operation is available in **sync** and **async** form; async runs off the JS thread to avoid blocking the UI.
Nitro SQLite embeds SQLite and exposes a JSI API on iOS, macOS, visionOS, and Android. Each operation is available in **sync** and **async** form; async runs off the JS thread to avoid blocking the UI.

---

Expand All @@ -44,6 +44,12 @@ npm install react-native-nitro-sqlite react-native-nitro-modules
npx pod-install
```

For a React Native macOS app, run CocoaPods from the `macos` directory:

```bash
cd macos && pod install
```

---

# API overview
Expand Down Expand Up @@ -184,7 +190,7 @@ const { rowsAffected, commands } = db.loadFile('/absolute/path/to/file.sql')

# Loading existing databases

Databases are created under the app documents directory (iOS) or files directory (Android). `location` is a directory path relative to that root, not an absolute file path. For example, `open({ name: 'myDb.sqlite', location: 'databases' })` opens `myDb.sqlite` under the `databases` directory. To use a database from another app-accessible location, copy or move it into this directory first. On iOS, files outside the app sandbox are inaccessible.
Databases are created under the app Documents directory (iOS and visionOS), Application Support directory (macOS), or files directory (Android). `location` is a directory path relative to that root, not an absolute file path. For example, `open({ name: 'myDb.sqlite', location: 'databases' })` opens `myDb.sqlite` under the `databases` directory. To use a database from another app-accessible location, copy or move it into this directory first. In sandboxed Apple apps, files outside the app sandbox are inaccessible.

Close a connection before deleting its database. A connection must not be used after `close()` or `delete()`.

Expand Down Expand Up @@ -222,10 +228,11 @@ Vector search is an opt-in companion package. It statically links sqlite-vec int
npm install react-native-nitro-sqlite-vec
```
2. Enable it for each native platform, then rebuild the app:
- **iOS:** run CocoaPods with `NITRO_SQLITE_VEC=1`, for example:
- **Apple platforms (iOS, macOS, visionOS):** run CocoaPods with `NITRO_SQLITE_VEC=1`, for example:
```bash
NITRO_SQLITE_VEC=1 npx pod-install
```
For React Native macOS, run `NITRO_SQLITE_VEC=1 pod install` from `macos/`.
- **Android:** add this to `android/gradle.properties`:
```properties
nitroSqliteVec=true
Expand Down Expand Up @@ -302,7 +309,7 @@ You can use this package as a TypeORM driver. Because of Metro and Node resoluti

# Configuration

## Configure bundled SQLite thread safety on iOS
## Configure bundled SQLite thread safety on Apple platforms

The bundled SQLite library compiles with `SQLITE_THREADSAFE=1` by default. This includes SQLite's mutex code and selects serialized mode, which lets SQLite serialize concurrent access to database connections and prepared statements. Configure it in your app's `package.json`:

Expand All @@ -325,7 +332,7 @@ With `SQLITE_THREADSAFE=0`, SQLite removes its mutex code and cannot be made thr

When `NITRO_SQLITE_USE_PHONE_VERSION=1`, the pod links the system SQLite library instead of compiling the bundled source. `NITRO_SQLITE_THREADSAFE` does not change how that system library was compiled.

## Configure SQLite performance mode on iOS
## Configure SQLite performance mode on Apple platforms

The bundled SQLite library enables NitroSQLite's performance compile flags by default. Disable them independently from thread safety in your app's `package.json`:

Expand All @@ -340,17 +347,19 @@ The bundled SQLite library enables NitroSQLite's performance compile flags by de

`performanceMode` accepts `true` or `false`. `NITRO_SQLITE_PERFORMANCE_MODE` overrides the package setting for one Pod installation and accepts `true`, `false`, `1`, or `0`. Disabling performance mode omits NitroSQLite's SQLite optimization flags but does not change `SQLITE_THREADSAFE`.

## Use system SQLite on iOS
## Use system SQLite on Apple platforms

To use the system SQLite instead of the bundled one:

```bash
NITRO_SQLITE_USE_PHONE_VERSION=1 npx pod-install
```

For React Native macOS, run the command from `macos/` with `pod install` instead of `npx pod-install`.

## Compile-time options (e.g. FTS5, Geopoly)

**iOS** — in your app’s `ios/Podfile`, in a `post_install` block:
**Apple platforms** — in your app’s `Podfile`, in a `post_install` block:

```ruby
installer.pods_project.targets.each do |target|
Expand All @@ -369,7 +378,7 @@ end
nitroSqliteFlags="-DSQLITE_ENABLE_FTS5=1"
```

## App groups (iOS)
## App groups (Apple platforms)

To put the database in an app group (e.g. for extensions), set `RNNitroSQLite_AppGroup` in your `Info.plist` to the app group ID and add the App Groups capability in Xcode.

Expand Down
3 changes: 2 additions & 1 deletion packages/react-native-nitro-sqlite-vec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ Install both this package and `react-native-nitro-sqlite`, then enable the nativ
npm install react-native-nitro-sqlite react-native-nitro-sqlite-vec
```

- **iOS:**
- **Apple platforms (iOS, macOS, visionOS):**
```bash
NITRO_SQLITE_VEC=1 npx pod-install
```
For React Native macOS, run `NITRO_SQLITE_VEC=1 pod install` from `macos/`.
- **Android:** add this to `android/gradle.properties` and rebuild:
```properties
nitroSqliteVec=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ require "json"

package = JSON.parse(File.read(File.join(__dir__, "package.json")))

# iOS opt-in (NITRO_SQLITE_VEC=1); compile sqlite-vec and static-link into the core's sqlite3.
# Apple-platform opt-in (NITRO_SQLITE_VEC=1); compile sqlite-vec and static-link into the core's sqlite3.
nitro_sqlite_vec = ENV['NITRO_SQLITE_VEC'] == '1'

# The core's bundled sqlite3.h (compiled with SQLITE_CORE to link it directly).
Expand All @@ -15,7 +15,11 @@ Pod::Spec.new do |s|
s.homepage = "https://github.com/margelo/react-native-nitro-sqlite"
s.license = "MIT"
s.authors = "Margelo"
s.platforms = { :ios => min_ios_version_supported, :visionos => "1.0" }
s.platforms = {
:ios => min_ios_version_supported,
:visionos => "1.0",
:osx => "10.13",
}
s.source = { :git => "https://github.com/margelo/react-native-nitro-sqlite.git", :tag => "#{s.version}" }

if nitro_sqlite_vec
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-nitro-sqlite-vec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"vector-search",
"nitro-modules",
"ios",
"macos",
"android"
],
"repository": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Android compiles these sources via the core's CMake, so autolink iOS only.
// CocoaPods autolinks this package on Apple platforms; Android compiles it via the core's CMake.
module.exports = {
dependency: {
platforms: {
ios: {},
macos: {},
android: null,
},
},
Expand Down
10 changes: 7 additions & 3 deletions packages/react-native-nitro-sqlite/RNNitroSQLite.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,21 @@ Pod::Spec.new do |s|
s.homepage = package["homepage"]
s.license = package["license"]
s.authors = package["author"]
s.platforms = { :ios => min_ios_version_supported, :visionos => "1.0" }
s.platforms = {
:ios => min_ios_version_supported,
:visionos => "1.0",
:osx => "10.13",
}
s.source = { :git => "https://github.com/margelo/react-native-nitro-sqlite.git", :tag => "#{s.version}" }

# Opt-in vector search (NITRO_SQLITE_VEC=1); the companion pod compiles the sources.
nitro_sqlite_vec = ENV['NITRO_SQLITE_VEC'] == '1'
nitro_sqlite_vec_cpp = File.expand_path(File.join(__dir__, "..", "react-native-nitro-sqlite-vec", "cpp"))

s.source_files = [
# Implementation (Swift)
# Apple platform implementation (Swift)
"ios/**/*.{swift}",
# Autolinking/Registration (Objective-C++)
# Apple platform autolinking/registration (Objective-C++)
"ios/**/*.{h,hpp,m,mm}",
# Implementation (C++ objects)
"cpp/**/*.{h,hpp,c,cpp}"
Expand Down
54 changes: 49 additions & 5 deletions packages/react-native-nitro-sqlite/ios/OnLoad.mm
Original file line number Diff line number Diff line change
@@ -1,7 +1,53 @@
#import <Foundation/Foundation.h>
#import <TargetConditionals.h>
#import "RNNitroSQLite-Swift-Cxx-Umbrella.hpp"
#import "HybridNitroSQLite.hpp"

static NSString *defaultDatabaseDirectory(void) {
NSFileManager *fileManager = [NSFileManager defaultManager];

#if TARGET_OS_OSX
NSError *error = nil;
NSURL *applicationSupportURL = [fileManager URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&error];
if (applicationSupportURL == nil) {
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
reason:[NSString stringWithFormat:@"Could not find the Application Support directory: %@", error]
userInfo:nil];
}

NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
if (bundleIdentifier == nil) {
bundleIdentifier = [[NSProcessInfo processInfo] processName];
}

NSURL *databaseURL = [applicationSupportURL URLByAppendingPathComponent:bundleIdentifier isDirectory:YES];
if (![fileManager createDirectoryAtURL:databaseURL withIntermediateDirectories:YES attributes:nil error:&error]) {
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
reason:[NSString stringWithFormat:@"Could not create the database directory: %@", error]
userInfo:nil];
}

return [databaseURL path];
#else
NSURL *documentsURL = [fileManager URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:nil];
if (documentsURL == nil) {
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
reason:@"Could not find the Documents directory"
userInfo:nil];
}

return [documentsURL path];
#endif
}

@interface OnLoad : NSObject
@end

Expand All @@ -11,7 +57,7 @@ @implementation OnLoad
using namespace margelo::nitro::rnnitrosqlite;

+ (void)load {
// Get appGroupID value from Info.plist using key "AppGroup"
// Get appGroupID value from Info.plist using key "RNNitroSQLite_AppGroup".
NSString *appGroupID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_AppGroup"];
NSString *documentPath;

Expand All @@ -21,7 +67,7 @@ + (void)load {
NSURL *storeUrl = [fileManager containerURLForSecurityApplicationGroupIdentifier:appGroupID];

if (storeUrl == nil) {
NSLog(@"Invalid AppGroup ID provided (%@). Check the value of \"AppGroup\" in your Info.plist file", appGroupID);
NSLog(@"Invalid App Group ID provided (%@). Check the value of \"RNNitroSQLite_AppGroup\" in your Info.plist file", appGroupID);
@throw [NSException exceptionWithName:@"SQLiteInitializationException"
reason:@"Error while initializing SQLite database (AppGroup)"
userInfo:nil];
Expand All @@ -30,9 +76,7 @@ + (void)load {

documentPath = [storeUrl path];
} else {
// Get iOS app's document directory (to safely store database .sqlite3 file)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true);
documentPath = [paths objectAtIndex:0];
documentPath = defaultDatabaseDirectory();
}

HybridNitroSQLite::docPath = [documentPath UTF8String];
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-nitro-sqlite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"sqlite",
"nitro-modules",
"ios",
"macos",
"android"
],
"repository": {
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-nitro-sqlite/react-native.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
* @type {import('@react-native-community/cli-types').IOSDependencyParams}
*/
ios: {},
macos: {},
/**
* @type {import('@react-native-community/cli-types').AndroidDependencyParams}
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-nitro-sqlite/src/OnLoad.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// NOOP on iOS
// Apple platforms initialize the database directory from OnLoad.mm.
export const init = () => {}