diff --git a/packages/react-native-nitro-sqlite/Package.swift b/packages/react-native-nitro-sqlite/Package.swift index a826b10c..fdb03336 100644 --- a/packages/react-native-nitro-sqlite/Package.swift +++ b/packages/react-native-nitro-sqlite/Package.swift @@ -14,9 +14,9 @@ let sqlite = SQLiteBuildOptions.resolve() addNitrogenTargets( to: package, - // SwiftPM cannot build Objective-C++ in a Swift target, so OnLoad.mm builds with the C++ sources. + // SwiftPM cannot build Objective-C++ in a Swift target, so HybridPlatformContext.mm builds with the C++ sources. swiftSources: [], - cxxSources: ["cpp", "ios/OnLoad.mm"], + cxxSources: ["cpp", "ios/HybridPlatformContext.mm"], cxxSettings: sqlite.defines.map { .define($0.name, to: $0.value) } ) diff --git a/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp index ec89e9b6..b652bb14 100644 --- a/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp +++ b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp @@ -1,45 +1,7 @@ -#include "HybridNitroSQLite.hpp" #include -#include #include #include -#include -#include -#include - -using namespace margelo::nitro::rnnitrosqlite; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { return facebook::jni::initialize(vm, [] { margelo::nitro::rnnitrosqlite::registerAllNatives(); }); } - -extern "C" JNIEXPORT void JNICALL Java_com_margelo_rnnitrosqlite_DocPathSetter_setDocPathInJNI(JNIEnv* env, jclass clazz, jstring doc_path, - jstring cache_path) { - const char* docPath = env->GetStringUTFChars(doc_path, nullptr); - if (docPath == nullptr) { - return; - } - - const char* cachePath = env->GetStringUTFChars(cache_path, nullptr); - if (cachePath == nullptr) { - env->ReleaseStringUTFChars(doc_path, docPath); - return; - } - - // SQLite caches this environment value during VFS initialization. Do not replace it on JS reload. - static std::once_flag tempDirectoryOnce; - static bool tempDirectoryConfigured = false; - std::call_once(tempDirectoryOnce, [&] { tempDirectoryConfigured = setenv("SQLITE_TMPDIR", cachePath, 1) == 0; }); - - if (tempDirectoryConfigured) { - HybridNitroSQLite::docPath = std::string(docPath); - } else { - jclass exception = env->FindClass("java/lang/IllegalStateException"); - if (exception != nullptr) { - env->ThrowNew(exception, "Could not configure SQLite temporary directory"); - } - } - - env->ReleaseStringUTFChars(cache_path, cachePath); - env->ReleaseStringUTFChars(doc_path, docPath); -} diff --git a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt deleted file mode 100644 index 58b3336a..00000000 --- a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.margelo.nitro.rnnitrosqlite - -import androidx.annotation.Keep -import com.facebook.proguard.annotations.DoNotStrip -import com.margelo.nitro.NitroModules -import com.margelo.rnnitrosqlite.DocPathSetter - -@Keep -@DoNotStrip -class HybridNitroSQLiteOnLoad : HybridNitroSQLiteOnLoadSpec() { - companion object : HybridNitroSQLiteOnLoadSpec.Companion { - @Keep - @DoNotStrip - override fun init() { - NitroModules.applicationContext?.let { context -> - DocPathSetter.setDocPath(context) - } - } - } -} diff --git a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt new file mode 100644 index 00000000..22bd859d --- /dev/null +++ b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt @@ -0,0 +1,25 @@ +package com.margelo.nitro.rnnitrosqlite + +import androidx.annotation.Keep +import com.facebook.proguard.annotations.DoNotStrip +import com.margelo.nitro.NitroModules + +/** Android directories for NitroSQLite, read from the application context. */ +@Keep +@DoNotStrip +class HybridPlatformContext : HybridPlatformContextSpec() { + companion object : HybridPlatformContextSpec.Companion { + override val databaseDirectory: String + get() = context.filesDir.absolutePath + + override val temporaryDirectory: String? + get() = context.cacheDir.absolutePath + + override val legacyDatabaseDirectory: String? + get() = null + + private val context + get() = NitroModules.applicationContext + ?: throw IllegalStateException("NitroSQLite needs the React Native application context to find its database directory") + } +} diff --git a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt deleted file mode 100644 index 399ba1f4..00000000 --- a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.margelo.rnnitrosqlite - -import com.facebook.react.bridge.ReactApplicationContext - -object DocPathSetter { - @JvmStatic - fun setDocPath(context: ReactApplicationContext) { - val path = context.filesDir.absolutePath - val cachePath = context.cacheDir.absolutePath - setDocPathInJNI(path, cachePath) - } - - private external fun setDocPathInJNI(docPath: String, cachePath: String) -} diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp index f4a316c2..ae537aad 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp @@ -7,11 +7,14 @@ #include "../NitroSQLiteMacros.hpp" #include "../NitroSQLiteOperations.hpp" #include "HybridPreparedStatement.hpp" +#include #include #include #include #include +#include #include +#include #include #include #include @@ -19,6 +22,24 @@ namespace margelo::nitro::rnnitrosqlite { +// SQLite caches SQLITE_TMPDIR when it initializes its VFS, so only the first root sets it. +static void configureTemporaryDirectory(const std::string& temporaryDirectory) { + static std::once_flag configureOnce; + static bool configured = false; + std::call_once(configureOnce, [&] { configured = setenv("SQLITE_TMPDIR", temporaryDirectory.c_str(), 1) == 0; }); + if (!configured) { + throw std::runtime_error("Could not configure SQLite temporary directory"); + } +} + +HybridNitroSQLite::HybridNitroSQLite(std::string databaseDirectory, const std::optional& temporaryDirectory, + const std::optional& legacyDatabaseDirectory) + : _databaseDirectory(std::move(databaseDirectory)), _legacyDatabaseDirectory(legacyDatabaseDirectory.value_or("")) { + if (temporaryDirectory) { + configureTemporaryDirectory(*temporaryDirectory); + } +} + // Copy any JS-backed ArrayBuffers on the JS thread so they can be safely // accessed from the connection's background worker. static std::optional copyArrayBufferParamsForBackground(const std::optional& params) { @@ -90,11 +111,11 @@ static Promise enqueueConnectionOperation(const SQLiteConnectionPtr& con return promise; } -const std::string getDocPath(const std::optional& location) { +const std::string getDocPath(const std::string& databaseDirectory, const std::optional& location) { if (location && location->find('\0') != std::string::npos) { throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database location contains a NUL byte"); } - std::string tempDocPath = std::string(HybridNitroSQLite::docPath); + std::string tempDocPath = databaseDirectory; if (location) { tempDocPath = tempDocPath + "/" + *location; } @@ -102,8 +123,8 @@ const std::string getDocPath(const std::optional& location) { return tempDocPath; } -const std::string getOldDocPath(const std::optional& location) { - std::string oldDocPath = HybridNitroSQLite::migrationDocPath; +const std::string getOldDocPath(const std::string& legacyDatabaseDirectory, const std::optional& location) { + std::string oldDocPath = legacyDatabaseDirectory; if (location) { oldDocPath = oldDocPath + "/" + *location; } @@ -111,13 +132,14 @@ const std::string getOldDocPath(const std::optional& location) { return oldDocPath; } -const std::string getMigratedDocPath(DatabaseConnections& connections, const std::string& dbName, +const std::string getMigratedDocPath(DatabaseConnections& connections, const std::string& databaseDirectory, + const std::string& legacyDatabaseDirectory, const std::string& dbName, const std::optional& location, bool readOnly = false) { - const auto currentDocPath = getDocPath(location); - if (HybridNitroSQLite::migrationDocPath.empty()) { + const auto currentDocPath = getDocPath(databaseDirectory, location); + if (legacyDatabaseDirectory.empty()) { return currentDocPath; } - const auto oldDocPath = getOldDocPath(location); + const auto oldDocPath = getOldDocPath(legacyDatabaseDirectory, location); std::string selectedPath; connections.withConnectionsLocked([&]() { const auto oldPath = std::filesystem::path(oldDocPath) / dbName; @@ -140,7 +162,8 @@ void HybridNitroSQLite::open(const std::string& dbName, const std::optional& connectionId) { validateDatabaseName(dbName); std::lock_guard lock(_connections.lifecycleMutex); - const auto currentDocPath = getDocPath(location); - if (migrationDocPath.empty()) { + const auto currentDocPath = getDocPath(_databaseDirectory, location); + if (_legacyDatabaseDirectory.empty()) { sqliteRemoveDb(_connections, dbName, currentDocPath, connectionId); return; } - const auto oldDocPath = getOldDocPath(location); + const auto oldDocPath = getOldDocPath(_legacyDatabaseDirectory, location); const auto preferredPath = _connections.physicalPathForKey(connectionId.value_or(dbName)); const auto currentPath = std::filesystem::path(currentDocPath) / dbName; std::error_code ec; @@ -199,7 +223,7 @@ void HybridNitroSQLite::attach(const std::string& mainDbName, const std::string& if (_connections.get(mainDbName)->readOnly) { throw NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase, "Cannot attach a database to a read-only connection"); } - const auto attachedDocPath = getMigratedDocPath(_connections, dbNameToAttach, location); + const auto attachedDocPath = getMigratedDocPath(_connections, _databaseDirectory, _legacyDatabaseDirectory, dbNameToAttach, location); sqliteAttachDb(_connections.get(mainDbName), attachedDocPath, dbNameToAttach, alias); }; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp index 236429a5..1dbbdcb5 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp @@ -14,17 +14,22 @@ namespace margelo::nitro::rnnitrosqlite { */ class HybridNitroSQLite : public HybridNitroSQLiteSpec { public: - HybridNitroSQLite() = default; - -public: - static std::string docPath; - // Directory databases were stored in by previous app versions, when the platform layer has - // relocated docPath (e.g. iOS with RNNitroSQLite_DatabaseLocation set to "ApplicationSupport"). - // When non-empty, databases found there are resolved as they are opened, attached, or dropped. - static std::string migrationDocPath; + /** Create a root that stores its databases in @p databaseDirectory. + * @param temporaryDirectory SQLite's temporary directory. SQLite reads it once per process, + * so the first root that passes one sets it. + * @param legacyDatabaseDirectory Directory that previous app versions stored databases in, + * for example Documents when iOS moves them to Application Support. Databases found there + * are moved as they are opened, attached, or dropped. + * @throws std::runtime_error If SQLite's temporary directory can't be configured. + */ + HybridNitroSQLite(std::string databaseDirectory, const std::optional& temporaryDirectory, + const std::optional& legacyDatabaseDirectory); private: DatabaseConnections _connections; + std::string _databaseDirectory; + // Empty when databases have never been stored anywhere else. + std::string _legacyDatabaseDirectory; public: // Methods @@ -99,7 +104,4 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { Promise loadFileAsync(const std::string& dbName, const std::string& location) override; }; -inline std::string HybridNitroSQLite::docPath = ""; -inline std::string HybridNitroSQLite::migrationDocPath = ""; - } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp new file mode 100644 index 00000000..7760707a --- /dev/null +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + +/** Apple platform directories for NitroSQLite, implemented in ios/HybridPlatformContext.mm. + * PlatformContext only has static members, so this class doesn't derive from its generated spec. + * Android implements PlatformContext in Kotlin instead. + */ +class HybridPlatformContext { +public: + /** Database directory selected by the RNNitroSQLite_AppGroup and RNNitroSQLite_DatabaseLocation Info.plist keys. + * @throws std::runtime_error If the app group container doesn't exist or the directory can't be created. + */ + static std::string getDatabaseDirectory(); + + /** Apple platforms keep SQLite's default temporary directory, so this is always empty. */ + static std::optional getTemporaryDirectory(); + + /** The Documents directory when RNNitroSQLite_DatabaseLocation moves databases to Application Support. */ + static std::optional getLegacyDatabaseDirectory(); +}; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm b/packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm new file mode 100644 index 00000000..824450ba --- /dev/null +++ b/packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm @@ -0,0 +1,107 @@ +#include "hybridObjects/HybridPlatformContext.hpp" +#import +#import +#include + +namespace margelo::nitro::rnnitrosqlite { + +namespace { + + [[noreturn]] void throwDirectoryError(NSString* message) { + throw std::runtime_error(message.UTF8String); + } + + NSString* appGroupIdentifier() { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_AppGroup"]; + } + + NSString* searchPathDirectory(NSSearchPathDirectory directory) { + return NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES).firstObject; + } + +#if TARGET_OS_OSX + NSString* macOSDatabaseDirectory() { + NSFileManager* fileManager = [NSFileManager defaultManager]; + NSError* error = nil; + NSURL* applicationSupportURL = [fileManager URLForDirectory:NSApplicationSupportDirectory + inDomain:NSUserDomainMask + appropriateForURL:nil + create:YES + error:&error]; + if (applicationSupportURL == nil) { + throwDirectoryError([NSString stringWithFormat:@"Could not find the Application Support directory: %@", error]); + } + + NSString* bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier] ?: [[NSProcessInfo processInfo] processName]; + NSURL* databaseURL = [applicationSupportURL URLByAppendingPathComponent:bundleIdentifier isDirectory:YES]; + if (![fileManager createDirectoryAtURL:databaseURL withIntermediateDirectories:YES attributes:nil error:&error]) { + throwDirectoryError([NSString stringWithFormat:@"Could not create the database directory: %@", error]); + } + return databaseURL.path; + } +#else + NSString* databaseLocation() { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_DatabaseLocation"]; + } +#endif + +} // namespace + +std::string HybridPlatformContext::getDatabaseDirectory() { + @autoreleasepool { + NSString* appGroupID = appGroupIdentifier(); + if (appGroupID != nil) { + NSURL* storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupID]; + if (storeURL == nil) { + NSLog(@"Invalid App Group ID provided (%@). Check the value of \"RNNitroSQLite_AppGroup\" in your Info.plist file", appGroupID); + throwDirectoryError(@"Error while initializing SQLite database (AppGroup)"); + } + NSLog(@"Configured with AppGroup ID: %@", appGroupID); + return storeURL.path.UTF8String; + } + +#if TARGET_OS_OSX + return macOSDatabaseDirectory().UTF8String; +#else + NSString* location = databaseLocation(); + if ([location isEqualToString:@"ApplicationSupport"]) { + // Library/Application Support is persistent, backed up, and never exposed to the user + // via the Files app, unlike the Documents directory when the app enables file sharing. + NSString* applicationSupport = searchPathDirectory(NSApplicationSupportDirectory); + NSFileManager* fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:applicationSupport]) { + [fileManager createDirectoryAtPath:applicationSupport withIntermediateDirectories:YES attributes:nil error:nil]; + } + return applicationSupport.UTF8String; + } + + if (location != nil && ![location isEqualToString:@"Documents"]) { + NSLog(@"Invalid RNNitroSQLite_DatabaseLocation value provided (%@). Supported values are \"Documents\" and \"ApplicationSupport\". " + @"Falling back to \"Documents\".", + location); + } + return searchPathDirectory(NSDocumentDirectory).UTF8String; +#endif + } +} + +std::optional HybridPlatformContext::getTemporaryDirectory() { + return std::nullopt; +} + +std::optional HybridPlatformContext::getLegacyDatabaseDirectory() { +#if TARGET_OS_OSX + return std::nullopt; +#else + @autoreleasepool { + // Databases created before RNNitroSQLite_DatabaseLocation moved them to Application Support + // still live in Documents. HybridNitroSQLite moves each one when it is opened. + if (appGroupIdentifier() != nil || ![databaseLocation() isEqualToString:@"ApplicationSupport"]) { + return std::nullopt; + } + return std::string(searchPathDirectory(NSDocumentDirectory).UTF8String); + } +#endif +} + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/ios/OnLoad.mm b/packages/react-native-nitro-sqlite/ios/OnLoad.mm deleted file mode 100644 index 58c39394..00000000 --- a/packages/react-native-nitro-sqlite/ios/OnLoad.mm +++ /dev/null @@ -1,99 +0,0 @@ -#import -#import -#import "hybridObjects/HybridNitroSQLite.hpp" - -#if TARGET_OS_OSX -static NSString *macOSDatabaseDirectory(void) { - NSFileManager *fileManager = [NSFileManager defaultManager]; - 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]; -} -#endif - -@interface OnLoad : NSObject -@end - -@implementation OnLoad - -using namespace margelo::nitro; -using namespace margelo::nitro::rnnitrosqlite; - -+ (void)load { - // Get appGroupID value from Info.plist using key "RNNitroSQLite_AppGroup". - NSString *appGroupID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_AppGroup"]; - NSString *documentPath; - - if (appGroupID != nil) { - // Get the app groups container storage url - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSURL *storeUrl = [fileManager containerURLForSecurityApplicationGroupIdentifier:appGroupID]; - - if (storeUrl == nil) { - 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]; - } - NSLog(@"Configured with AppGroup ID: %@", appGroupID); - - documentPath = [storeUrl path]; - } else { -#if TARGET_OS_OSX - documentPath = macOSDatabaseDirectory(); -#else - NSString *databaseLocation = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_DatabaseLocation"]; - - if ([databaseLocation isEqualToString:@"ApplicationSupport"]) { - // Library/Application Support is persistent, backed up, and never exposed to the user - // via the Files app (unlike the Documents directory, which becomes user-visible when - // the app enables file sharing). - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true); - documentPath = [paths objectAtIndex:0]; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - if (![fileManager fileExistsAtPath:documentPath]) { - [fileManager createDirectoryAtPath:documentPath withIntermediateDirectories:YES attributes:nil error:nil]; - } - - // Databases created before this option was enabled still live in Documents; each one is - // moved over when it is opened (see HybridNitroSQLite::open). - NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) objectAtIndex:0]; - HybridNitroSQLite::migrationDocPath = [documentsDirectory UTF8String]; - } else { - if (databaseLocation != nil && ![databaseLocation isEqualToString:@"Documents"]) { - NSLog(@"Invalid RNNitroSQLite_DatabaseLocation value provided (%@). Supported values are \"Documents\" and \"ApplicationSupport\". Falling back to \"Documents\".", databaseLocation); - } - // Get iOS app's document directory (to safely store database .sqlite3 file) - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true); - documentPath = [paths objectAtIndex:0]; - } -#endif - } - - HybridNitroSQLite::docPath = [documentPath UTF8String]; -} - -@end diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake index d004b400..a5e23273 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake @@ -15,7 +15,7 @@ target_sources(RNNitroSQLite PRIVATE "${CMAKE_CURRENT_LIST_DIR}/RNNitroSQLiteOnLoad.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridNitroSQLiteSpecClass.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridPreparedStatementSpecClass.cpp" - "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JHybridNitroSQLiteOnLoadSpec.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JHybridPlatformContextSpec.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryCommand.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryResult.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/FileLoadResult.cpp" diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp index f5e252d3..5dc62316 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp @@ -7,16 +7,16 @@ #include #include -#include +#include #include #include namespace margelo::nitro::rnnitrosqlite { void registerAllNatives() { - margelo::nitro::rnnitrosqlite::JHybridNitroSQLiteOnLoadSpec::CxxPart::registerNatives(); + margelo::nitro::rnnitrosqlite::JHybridPlatformContextSpec::CxxPart::registerNatives(); HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); - HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLiteOnLoad", JHybridNitroSQLiteOnLoadSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.PlatformContext", JHybridPlatformContextSpec::Class::get()); HybridClassRegistry::registerHybridClass("rnnitrosqlite.PreparedStatement", HybridPreparedStatementSpec::Class::get()); } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp index e0aaf001..abf341a0 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp @@ -31,10 +31,10 @@ namespace margelo::nitro::rnnitrosqlite { namespace { struct HybridNitroSQLiteSpecBindings final { - static std::shared_ptr constructor() { - static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>, + static std::shared_ptr constructor(const std::string& databaseDirectory, const std::optional& temporaryDirectory, const std::optional& legacyDatabaseDirectory) { + static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite, decltype(databaseDirectory), decltype(temporaryDirectory), decltype(legacyDatabaseDirectory)>, "NitroSQLite: ::margelo::nitro::rnnitrosqlite::HybridNitroSQLite must implement the declared public constructor."); - return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(); + return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(std::forward(databaseDirectory), std::forward(temporaryDirectory), std::forward(legacyDatabaseDirectory)); } }; } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp deleted file mode 100644 index b5c7f98e..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/// -/// JHybridNitroSQLiteOnLoadSpec.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/margelo/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#include - -namespace margelo::nitro::rnnitrosqlite { - - JHybridNitroSQLiteOnLoadSpec::~JHybridNitroSQLiteOnLoadSpec() = default; - - void JHybridNitroSQLiteOnLoadSpec::init() { - static const auto __method = JHybridNitroSQLiteOnLoadSpec::JavaPart::javaClassStatic()->getStaticMethod("init_cxx"); - __method(JHybridNitroSQLiteOnLoadSpec::JavaPart::javaClassStatic()); - } - - const std::shared_ptr& JHybridNitroSQLiteOnLoadSpec::Class::get() { - static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { - clazz.registerStaticHybridMethod("init", &JHybridNitroSQLiteOnLoadSpec::init); - }); - return hybridClass; - } - - std::shared_ptr JHybridNitroSQLiteOnLoadSpecJavaPart::getJHybridNitroSQLiteOnLoadSpec() { - auto hybridObject = JHybridObject::JavaPart::getJHybridObject(); - auto castHybridObject = std::dynamic_pointer_cast(hybridObject); - if (castHybridObject == nullptr) [[unlikely]] { - throw std::runtime_error("Failed to downcast JHybridObject to JHybridNitroSQLiteOnLoadSpec!"); - } - return castHybridObject; - } - - jni::local_ref JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid(jni::alias_ref jThis) { - return makeCxxInstance(jThis); - } - - jni::alias_ref JHybridNitroSQLiteOnLoadSpec::CxxPart::getClass() { - static const auto __field = CxxPart::javaClassStatic()->getStaticField("implementationClass_cxx"); - static const auto __class = jni::make_global(CxxPart::javaClassStatic()->getStaticFieldValue(__field)); - return __class; - } - - std::shared_ptr JHybridNitroSQLiteOnLoadSpec::CxxPart::createHybridObject(jni::alias_ref javaPart) { - auto castJavaPart = jni::dynamic_ref_cast(javaPart); - if (castJavaPart == nullptr) [[unlikely]] { - throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridNitroSQLiteOnLoadSpec::JavaPart!"); - } - return std::make_shared(castJavaPart); - } - - void JHybridNitroSQLiteOnLoadSpec::CxxPart::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid), - }); - } - - // Properties - - - // Methods - - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp new file mode 100644 index 00000000..3c47428c --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp @@ -0,0 +1,84 @@ +/// +/// JHybridPlatformContextSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + JHybridPlatformContextSpec::~JHybridPlatformContextSpec() = default; + + jni::local_ref JHybridPlatformContextSpec::getDatabaseDirectory() { + static const auto __method = JHybridPlatformContextSpec::JavaPart::javaClassStatic()->getStaticMethod()>("getDatabaseDirectory_cxx"); + auto __result = __method(JHybridPlatformContextSpec::JavaPart::javaClassStatic()); + return __result; + } + + jni::local_ref> JHybridPlatformContextSpec::getTemporaryDirectory() { + static const auto __method = JHybridPlatformContextSpec::JavaPart::javaClassStatic()->getStaticMethod>()>("getTemporaryDirectory_cxx"); + auto __result = __method(JHybridPlatformContextSpec::JavaPart::javaClassStatic()); + return __result; + } + + jni::local_ref> JHybridPlatformContextSpec::getLegacyDatabaseDirectory() { + static const auto __method = JHybridPlatformContextSpec::JavaPart::javaClassStatic()->getStaticMethod>()>("getLegacyDatabaseDirectory_cxx"); + auto __result = __method(JHybridPlatformContextSpec::JavaPart::javaClassStatic()); + return __result; + } + + const std::shared_ptr& JHybridPlatformContextSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerStaticHybridProperty("databaseDirectory", &JHybridPlatformContextSpec::getDatabaseDirectory); + clazz.registerStaticHybridProperty("temporaryDirectory", &JHybridPlatformContextSpec::getTemporaryDirectory); + clazz.registerStaticHybridProperty("legacyDatabaseDirectory", &JHybridPlatformContextSpec::getLegacyDatabaseDirectory); + }); + return hybridClass; + } + + std::shared_ptr JHybridPlatformContextSpecJavaPart::getJHybridPlatformContextSpec() { + auto hybridObject = JHybridObject::JavaPart::getJHybridObject(); + auto castHybridObject = std::dynamic_pointer_cast(hybridObject); + if (castHybridObject == nullptr) [[unlikely]] { + throw std::runtime_error("Failed to downcast JHybridObject to JHybridPlatformContextSpec!"); + } + return castHybridObject; + } + + jni::local_ref JHybridPlatformContextSpec::CxxPart::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + jni::alias_ref JHybridPlatformContextSpec::CxxPart::getClass() { + static const auto __field = CxxPart::javaClassStatic()->getStaticField("implementationClass_cxx"); + static const auto __class = jni::make_global(CxxPart::javaClassStatic()->getStaticFieldValue(__field)); + return __class; + } + + std::shared_ptr JHybridPlatformContextSpec::CxxPart::createHybridObject(jni::alias_ref javaPart) { + auto castJavaPart = jni::dynamic_ref_cast(javaPart); + if (castJavaPart == nullptr) [[unlikely]] { + throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridPlatformContextSpec::JavaPart!"); + } + return std::make_shared(castJavaPart); + } + + void JHybridPlatformContextSpec::CxxPart::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridPlatformContextSpec::CxxPart::initHybrid), + }); + } + + // Properties + + + // Methods + + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpec.hpp similarity index 56% rename from packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpec.hpp index 274882c4..16813a2b 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpec.hpp @@ -1,5 +1,5 @@ /// -/// JHybridNitroSQLiteOnLoadSpec.hpp +/// JHybridPlatformContextSpec.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -11,25 +11,29 @@ #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include namespace margelo::nitro::rnnitrosqlite { namespace jni = facebook::jni; - class JHybridNitroSQLiteOnLoadSpec final : public JHybridObject { + class JHybridPlatformContextSpec final : public JHybridObject { public: struct Class { using Base = JHybridObject::Class; - static constexpr const char* name = "NitroSQLiteOnLoad"; + static constexpr const char* name = "PlatformContext"; static const std::shared_ptr& get(); }; public: - using JavaPart = JHybridNitroSQLiteOnLoadSpecJavaPart; + using JavaPart = JHybridPlatformContextSpecJavaPart; struct CxxPart : public jni::HybridClass { - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec$CxxPart;"; + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec$CxxPart;"; static jni::local_ref initHybrid(jni::alias_ref jThis); static void registerNatives(); static jni::alias_ref getClass(); @@ -39,20 +43,20 @@ namespace margelo::nitro::rnnitrosqlite { }; public: - explicit JHybridNitroSQLiteOnLoadSpec(jni::alias_ref javaPart): + explicit JHybridPlatformContextSpec(jni::alias_ref javaPart): JHybridObject(javaPart), _javaPart(jni::static_ref_cast(JHybridObject::getJavaPart())) { #ifdef NITRO_DEBUG if (!jni::isSameObject(_javaPart->getClass(), CxxPart::getClass())) [[unlikely]] { - throw std::runtime_error("NitroSQLiteOnLoad requires its configured implementation when inheritance and multiple implementations are disabled."); + throw std::runtime_error("PlatformContext requires its configured implementation when inheritance and multiple implementations are disabled."); } #endif } // Defined in the owning library so RTTI has one identity across modules. - ~JHybridNitroSQLiteOnLoadSpec() override; + ~JHybridPlatformContextSpec() override; public: - inline jni::alias_ref getJavaPart() const noexcept { + inline jni::alias_ref getJavaPart() const noexcept { return _javaPart; } @@ -66,7 +70,9 @@ namespace margelo::nitro::rnnitrosqlite { public: // Constructor and static members - static void init(); + static jni::local_ref getDatabaseDirectory(); + static jni::local_ref> getTemporaryDirectory(); + static jni::local_ref> getLegacyDatabaseDirectory(); protected: const std::shared_ptr& getHybridClass() override { @@ -74,7 +80,7 @@ namespace margelo::nitro::rnnitrosqlite { } private: - jni::alias_ref _javaPart; + jni::alias_ref _javaPart; }; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpecJavaPart.hpp similarity index 52% rename from packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpecJavaPart.hpp index 4bb05911..d480a538 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpecJavaPart.hpp @@ -1,5 +1,5 @@ /// -/// JHybridNitroSQLiteOnLoadSpecJavaPart.hpp +/// JHybridPlatformContextSpecJavaPart.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -15,12 +15,12 @@ namespace margelo::nitro::rnnitrosqlite { namespace jni = facebook::jni; - class JHybridNitroSQLiteOnLoadSpec; + class JHybridPlatformContextSpec; - struct JHybridNitroSQLiteOnLoadSpecJavaPart : public jni::JavaClass { - using HybridType = JHybridNitroSQLiteOnLoadSpec; - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec;"; - std::shared_ptr getJHybridNitroSQLiteOnLoadSpec(); + struct JHybridPlatformContextSpecJavaPart : public jni::JavaClass { + using HybridType = JHybridPlatformContextSpec; + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec;"; + std::shared_ptr getJHybridPlatformContextSpec(); }; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec.kt similarity index 50% rename from packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt rename to packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec.kt index d1dd507c..c5d37e4d 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec.kt @@ -1,5 +1,5 @@ /// -/// HybridNitroSQLiteOnLoadSpec.kt +/// HybridPlatformContextSpec.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -11,12 +11,12 @@ import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import dalvik.annotation.optimization.FastNative -import com.margelo.nitro.rnnitrosqlite.HybridNitroSQLiteOnLoad +import com.margelo.nitro.rnnitrosqlite.HybridPlatformContext import com.margelo.nitro.core.HybridObject /** - * A Kotlin class representing the NitroSQLiteOnLoad HybridObject. - * Implement this abstract class to create Kotlin-based instances of NitroSQLiteOnLoad. + * A Kotlin class representing the PlatformContext HybridObject. + * Implement this abstract class to create Kotlin-based instances of PlatformContext. */ @DoNotStrip @Keep @@ -25,7 +25,7 @@ import com.margelo.nitro.core.HybridObject "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" ) -abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { +abstract class HybridPlatformContextSpec: HybridObject() { // Properties @@ -34,14 +34,14 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { // Default implementation of `HybridObject.toString()` override fun toString(): String { - return "[HybridObject NitroSQLiteOnLoad]" + return "[HybridObject PlatformContext]" } // C++ backing class @DoNotStrip @Keep - protected open class CxxPart(javaPart: HybridNitroSQLiteOnLoadSpec): HybridObject.CxxPart(javaPart) { - // C++ JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid(...) + protected open class CxxPart(javaPart: HybridPlatformContextSpec): HybridObject.CxxPart(javaPart) { + // C++ JHybridPlatformContextSpec::CxxPart::initHybrid(...) @FastNative external override fun initHybrid(): HybridData @@ -49,7 +49,7 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { @DoNotStrip @Keep @JvmField - val implementationClass_cxx: Class = HybridNitroSQLiteOnLoad::class.java + val implementationClass_cxx: Class = HybridPlatformContext::class.java } } override fun createCxxPart(): CxxPart { @@ -58,24 +58,45 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { interface Companion { // Static Properties + val databaseDirectory: String + val temporaryDirectory: String? + + val legacyDatabaseDirectory: String? // Static Methods - fun init(): Unit + } protected companion object Bridge { - protected const val TAG = "HybridNitroSQLiteOnLoadSpec" + protected const val TAG = "HybridPlatformContextSpec" private val implementationCompanion: Companion - get() = HybridNitroSQLiteOnLoad + get() = HybridPlatformContext + + // Static properties + @JvmStatic + @DoNotStrip + @Keep + private fun getDatabaseDirectory_cxx(): String { + val __result = HybridPlatformContext.databaseDirectory + return __result + } + + @JvmStatic + @DoNotStrip + @Keep + private fun getTemporaryDirectory_cxx(): String? { + val __result = HybridPlatformContext.temporaryDirectory + return __result + } - // Static methods @JvmStatic @DoNotStrip @Keep - private fun init_cxx(): Unit { - HybridNitroSQLiteOnLoad.init() + private fun getLegacyDatabaseDirectory_cxx(): String? { + val __result = HybridPlatformContext.legacyDatabaseDirectory + return __result } } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json index 79ad40ef..e7fe4069 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json @@ -17,12 +17,19 @@ "language": "c++" } }, - "NitroSQLiteOnLoad": { + "PlatformContext": { "android": { "implementation": { - "className": "HybridNitroSQLiteOnLoad" + "className": "HybridPlatformContext" }, "language": "kotlin" + }, + "ios": { + "implementation": { + "className": "HybridPlatformContext", + "include": "\"hybridObjects/HybridPlatformContext.hpp\"" + }, + "language": "c++" } }, "PreparedStatement": { diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp index 000a6130..1ec73701 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp @@ -9,6 +9,7 @@ #include #include +#include #include namespace margelo::nitro::rnnitrosqlite { @@ -17,6 +18,7 @@ namespace margelo::nitro::rnnitrosqlite { using namespace margelo::nitro::rnnitrosqlite; HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.PlatformContext", HybridPlatformContextSpec::Class::get()); HybridClassRegistry::registerHybridClass("rnnitrosqlite.PreparedStatement", HybridPreparedStatementSpec::Class::get()); } } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp index e0aaf001..abf341a0 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp @@ -31,10 +31,10 @@ namespace margelo::nitro::rnnitrosqlite { namespace { struct HybridNitroSQLiteSpecBindings final { - static std::shared_ptr constructor() { - static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>, + static std::shared_ptr constructor(const std::string& databaseDirectory, const std::optional& temporaryDirectory, const std::optional& legacyDatabaseDirectory) { + static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite, decltype(databaseDirectory), decltype(temporaryDirectory), decltype(legacyDatabaseDirectory)>, "NitroSQLite: ::margelo::nitro::rnnitrosqlite::HybridNitroSQLite must implement the declared public constructor."); - return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(); + return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(std::forward(databaseDirectory), std::forward(temporaryDirectory), std::forward(legacyDatabaseDirectory)); } }; } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp new file mode 100644 index 00000000..9b6400ae --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp @@ -0,0 +1,14 @@ +/// +/// HybridPlatformContextSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include + +namespace margelo::nitro::rnnitrosqlite { + + HybridPlatformContextSpec::~HybridPlatformContextSpec() = default; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp new file mode 100644 index 00000000..e198b508 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp @@ -0,0 +1,41 @@ +/// +/// HybridPlatformContextSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include "hybridObjects/HybridPlatformContext.hpp" + +namespace margelo::nitro::rnnitrosqlite { + + namespace { + struct HybridPlatformContextSpecBindings final { + static std::string getDatabaseDirectory() { + return ::margelo::nitro::rnnitrosqlite::HybridPlatformContext::getDatabaseDirectory(); + } + + static std::optional getTemporaryDirectory() { + return ::margelo::nitro::rnnitrosqlite::HybridPlatformContext::getTemporaryDirectory(); + } + + static std::optional getLegacyDatabaseDirectory() { + return ::margelo::nitro::rnnitrosqlite::HybridPlatformContext::getLegacyDatabaseDirectory(); + } + }; + } + + const std::shared_ptr& HybridPlatformContextSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerStaticHybridProperty("databaseDirectory", &HybridPlatformContextSpecBindings::getDatabaseDirectory); + clazz.registerStaticHybridProperty("temporaryDirectory", &HybridPlatformContextSpecBindings::getTemporaryDirectory); + clazz.registerStaticHybridProperty("legacyDatabaseDirectory", &HybridPlatformContextSpecBindings::getLegacyDatabaseDirectory); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp new file mode 100644 index 00000000..d527aab3 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp @@ -0,0 +1,61 @@ +/// +/// HybridPlatformContextSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + using namespace margelo::nitro; + + /** + * An abstract base class for `PlatformContext` + * Inherit this class to create instances of `HybridPlatformContextSpec` in C++. + * @example + * ```cpp + * class HybridPlatformContext : public HybridPlatformContextSpec { + * public: + * HybridPlatformContext(...) { ... } + * // ... + * }; + * ``` + */ + class HybridPlatformContextSpec : public virtual HybridObject { + public: + struct Class { + using Base = HybridObject::Class; + static constexpr const char* name = "PlatformContext"; + static const std::shared_ptr& get(); + }; + + public: + // Constructor + HybridPlatformContextSpec() = default; + + // Destructor + ~HybridPlatformContextSpec() override; + + public: + // Properties + + + public: + // Methods + + + protected: + // Hybrid Setup + const std::shared_ptr& getHybridClass() override { + return Class::get(); + } + }; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.cjs similarity index 70% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.cjs index 9e230f3e..82cd0f35 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.cjs @@ -1,5 +1,5 @@ /// -/// NitroSQLiteOnLoad.cjs +/// PlatformContext.cjs /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -10,9 +10,9 @@ const { NitroModules } = require('react-native-nitro-modules') let hybridClass module.exports = { - get NitroSQLiteOnLoad() { + get PlatformContext() { if (hybridClass === undefined) { - hybridClass = NitroModules.getHybridClass('rnnitrosqlite.NitroSQLiteOnLoad') + hybridClass = NitroModules.getHybridClass('rnnitrosqlite.PlatformContext') } return hybridClass }, diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.d.cts similarity index 59% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.d.cts index d91be463..28fba098 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.d.cts @@ -1,9 +1,9 @@ /// -/// NitroSQLiteOnLoad.d.cts +/// PlatformContext.d.cts /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -// The spec's `export declare class NitroSQLiteOnLoad` types this runtime export. +// The spec's `export declare class PlatformContext` types this runtime export. export {} diff --git a/packages/react-native-nitro-sqlite/src/OnLoad.android.ts b/packages/react-native-nitro-sqlite/src/OnLoad.android.ts deleted file mode 100644 index b4ebe523..00000000 --- a/packages/react-native-nitro-sqlite/src/OnLoad.android.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { NitroSQLiteOnLoad } from './specs/NitroSQLiteOnLoad.nitro' - -export const init = () => NitroSQLiteOnLoad.init() diff --git a/packages/react-native-nitro-sqlite/src/OnLoad.ts b/packages/react-native-nitro-sqlite/src/OnLoad.ts deleted file mode 100644 index a069caad..00000000 --- a/packages/react-native-nitro-sqlite/src/OnLoad.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Apple platforms initialize the database directory from OnLoad.mm. -export const init = () => {} diff --git a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts index efac7896..81281252 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts @@ -1,10 +1,18 @@ jest.mock('react-native-nitro-modules', () => ({ NitroModules: { getHybridClass: jest.fn((name: string) => - name === 'rnnitrosqlite.NitroSQLiteOnLoad' - ? { init: jest.fn() } + name === 'rnnitrosqlite.PlatformContext' + ? { + databaseDirectory: '/data/databases', + temporaryDirectory: '/data/cache', + legacyDatabaseDirectory: undefined, + } : class { open = jest.fn() + constructorArguments: unknown[] + constructor(...args: unknown[]) { + this.constructorArguments = args + } }, ), }, @@ -24,8 +32,6 @@ import { NitroSQLiteExceptionType as ExceptionTypeFromErrors, } from '../errors' import { HybridNitroSQLite } from '../nitro' -import { init as androidInit } from '../OnLoad.android' -import { init as iosInit } from '../OnLoad' describe('entrypoints', () => { it('shares the error class and category constants with the errors entry point', () => { @@ -40,20 +46,16 @@ describe('entrypoints', () => { expect(NitroSQLite.native).toBe(HybridNitroSQLite) expect(NitroSQLite.open).toBe(open) expect(NitroSQLite.open).not.toBe(HybridNitroSQLite.open) - expect(iosInit()).toBeUndefined() }) - it('initializes the Android native loader', () => { - androidInit() - + it('stores databases in the platform directories', () => { expect(NitroModules.getHybridClass).toHaveBeenCalledWith( - 'rnnitrosqlite.NitroSQLiteOnLoad', + 'rnnitrosqlite.PlatformContext', ) - const onLoad = jest - .mocked(NitroModules.getHybridClass) - .mock.results.map((result) => result.value as { init?: jest.Mock }) - .find((value) => 'init' in value) - expect(onLoad?.init).toHaveBeenCalledTimes(1) + expect( + (HybridNitroSQLite as unknown as { constructorArguments: unknown[] }) + .constructorArguments, + ).toEqual(['/data/databases', '/data/cache', undefined]) }) it('publishes built entry points so apps never compile the decorated specs', () => { diff --git a/packages/react-native-nitro-sqlite/src/index.ts b/packages/react-native-nitro-sqlite/src/index.ts index a8c97d47..1f4fa771 100644 --- a/packages/react-native-nitro-sqlite/src/index.ts +++ b/packages/react-native-nitro-sqlite/src/index.ts @@ -3,11 +3,8 @@ import { HybridNitroSQLite } from './nitro' import { open } from './operations/session' import { execute, executeAsync } from './operations/execute' import { prepare } from './operations/prepare' -import { init } from './OnLoad' import { executeBatch, executeBatchAsync } from './operations/executeBatch' -init() - /** Database entry point. Prefer {@link open} for a managed connection. * `native` exposes the Nitro object directly and bypasses the JavaScript queue. */ diff --git a/packages/react-native-nitro-sqlite/src/nitro.ts b/packages/react-native-nitro-sqlite/src/nitro.ts index 1cd966f9..91a5d13c 100644 --- a/packages/react-native-nitro-sqlite/src/nitro.ts +++ b/packages/react-native-nitro-sqlite/src/nitro.ts @@ -1,3 +1,8 @@ import { NitroSQLite } from './specs/NitroSQLite.nitro' +import { PlatformContext } from './specs/PlatformContext.nitro' -export const HybridNitroSQLite = new NitroSQLite() +export const HybridNitroSQLite = new NitroSQLite( + PlatformContext.databaseDirectory, + PlatformContext.temporaryDirectory, + PlatformContext.legacyDatabaseDirectory, +) diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts index 2597563d..ef843e18 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts @@ -32,8 +32,20 @@ export * from '#nitro/NitroSQLite' }, }) export declare class NitroSQLite extends HybridObject { - /** Create a root with its own default and independent connections. */ - constructor() + /** Create a root with its own default and independent connections. + * @param databaseDirectory Directory that database names and relative + * locations resolve against, usually `PlatformContext.databaseDirectory`. + * @param temporaryDirectory Directory for SQLite's temporary files. SQLite + * reads it once per process, so the first root that passes one sets it. + * @param legacyDatabaseDirectory Directory that databases are moved out of + * when they are opened, attached, or dropped. + * @throws If SQLite's temporary directory can't be configured. + */ + constructor( + databaseDirectory: string, + temporaryDirectory?: string, + legacyDatabaseDirectory?: string, + ) /** Open a name-based default connection, creating the database unless `readOnly` is true. * @param dbName Database file name and default connection key. diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts deleted file mode 100644 index 3cb3123d..00000000 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Android, type HybridObject } from 'react-native-nitro-modules' - -export * from '#nitro/NitroSQLiteOnLoad' - -/** Android startup hook that configures the native database directories. */ -@Android({ - language: 'kotlin', - implementation: { className: 'HybridNitroSQLiteOnLoad' }, -}) -export declare class NitroSQLiteOnLoad extends HybridObject { - /** Pass the app's files and cache directories from the application context to SQLite. */ - static init(): void -} diff --git a/packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts new file mode 100644 index 00000000..735f7b73 --- /dev/null +++ b/packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts @@ -0,0 +1,31 @@ +import { Android, iOS, type HybridObject } from 'react-native-nitro-modules' + +export * from '#nitro/PlatformContext' + +/** Platform directories that a `NitroSQLite` root stores its databases in. */ +@iOS({ + language: 'c++', + implementation: { + className: 'HybridPlatformContext', + include: '"hybridObjects/HybridPlatformContext.hpp"', + }, +}) +@Android({ + language: 'kotlin', + implementation: { className: 'HybridPlatformContext' }, +}) +export declare class PlatformContext extends HybridObject { + /** Directory that database names and relative locations resolve against. + * On Apple platforms, the `RNNitroSQLite_AppGroup` and + * `RNNitroSQLite_DatabaseLocation` Info.plist keys select it. + * @throws If the configured app group container doesn't exist or the + * directory can't be created. + */ + static readonly databaseDirectory: string + /** Directory for SQLite's temporary files, when the platform has no usable default. */ + static readonly temporaryDirectory?: string + /** Directory that databases are moved out of when they are opened, attached, or dropped. + * Set when the app stores databases somewhere other than earlier versions did. + */ + static readonly legacyDatabaseDirectory?: string +}