From 168c90358069afd4ee8bf16e9704d04815cc28f8 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Sat, 3 Oct 2026 01:05:07 +0530 Subject: [PATCH 01/10] chore: upgrade to rn v0.88 --- ...ring-op-sqlite-npm-15.2.5-936f5cf3a5.patch | 280 ---- ...ineering-op-sqlite-npm-18.2.5-mendix.patch | 325 +++++ android/gradle.properties | 4 +- .../mendixnative/config/AppPreferences.java | 4 +- .../mendixnative/fragment/ReactFragment.kt | 2 +- .../mendixnative/react/fs/NativeFsModule.kt | 29 +- .../react/splash/MendixSplashScreenModule.kt | 14 +- .../com/mendixnative/MendixNativePackage.kt | 6 +- ...nfigurationModule.kt => MxConfigModule.kt} | 10 +- eslint.config.mjs | 1 + example/Gemfile | 1 + example/Gemfile.lock | 1 + example/__tests__/file-system.harness.ts | 103 ++ example/android/app/build.gradle | 2 +- example/android/build.gradle | 6 +- example/android/gradle.properties | 7 +- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 48966 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- example/android/gradlew | 14 +- example/android/gradlew.bat | 3 +- .../project.pbxproj | 6 + .../ios/MendixNativeExample/AppDelegate.swift | 37 +- example/ios/MendixNativeExample/Info.plist | 17 + .../MendixNativeExample/PrivacyInfo.xcprivacy | 8 +- .../MendixNativeExample/SceneDelegate.swift | 37 + example/ios/Podfile.lock | 1279 +++++++++-------- example/package.json | 20 +- example/rn-harness.config.mjs | 4 +- ios/Modules/Encryption/EncryptedStorage.swift | 10 +- .../ErrorHandler/NativeErrorHandler.swift | 13 +- ios/Modules/Helper/DevHelper.swift | 11 +- .../Helper/LegacyWindowAppDelegate.swift | 8 + ios/Modules/Helper/ReactAppProvider.swift | 99 +- .../Helper/ReactHostHelper+Modules.swift | 15 + ios/Modules/Helper/ReactHostHelper.h | 8 +- ios/Modules/Helper/ReactHostHelper.mm | 52 +- .../Helper/TapGestureRecognizerHelper.swift | 1 + .../MendixSplashScreen.swift | 9 +- .../SessionCookieStore.swift | 10 +- .../NativeFsModule/NativeFsModule.swift | 44 +- ios/Modules/ReactNative.swift | 10 +- ios/TurboModules/MxConfiguration/MxConfig.h | 4 + .../{MxConfigurationModule.mm => MxConfig.mm} | 17 +- .../MxConfiguration/MxConfigurationModule.h | 4 - ios/TurboModules/MxCookie/MxCookie.mm | 4 +- ios/TurboModules/MxDownload/MxDownload.mm | 4 +- ios/TurboModules/MxEncryption/MxEncryption.mm | 4 +- ios/TurboModules/MxError/MxError.mm | 9 +- ios/TurboModules/MxFileSystem/MxFileSystem.mm | 13 +- ios/TurboModules/MxNavigation/MxNavigation.mm | 4 +- ios/TurboModules/MxOta/MxOta.mm | 4 +- ios/TurboModules/MxReload/MxReload.mm | 4 +- .../MxSplashScreen/MxSplashScreen.mm | 4 +- package.json | 19 +- src/dev-settings.ts | 12 - src/events.ts | 12 +- src/file-system/index.ts | 2 +- ...veMxConfiguration.ts => NativeMxConfig.ts} | 2 +- src/mx-configuration/index.ts | 4 +- src/ota/NativeMxOta.ts | 4 + src/reload-handler/NativeMxReload.ts | 3 + yarn.lock | 1127 ++++++++------- 62 files changed, 2095 insertions(+), 1677 deletions(-) delete mode 100644 .yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch create mode 100644 .yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch rename android/src/main/java/com/mendixnative/configuration/{MxConfigurationModule.kt => MxConfigModule.kt} (63%) create mode 100644 example/ios/MendixNativeExample/SceneDelegate.swift create mode 100644 ios/Modules/Helper/LegacyWindowAppDelegate.swift create mode 100644 ios/Modules/Helper/ReactHostHelper+Modules.swift create mode 100644 ios/TurboModules/MxConfiguration/MxConfig.h rename ios/TurboModules/MxConfiguration/{MxConfigurationModule.mm => MxConfig.mm} (63%) delete mode 100644 ios/TurboModules/MxConfiguration/MxConfigurationModule.h delete mode 100644 src/dev-settings.ts rename src/mx-configuration/{NativeMxConfiguration.ts => NativeMxConfig.ts} (90%) diff --git a/.yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch b/.yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch deleted file mode 100644 index 915c7b9..0000000 --- a/.yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch +++ /dev/null @@ -1,280 +0,0 @@ -diff --git a/android/build.gradle b/android/build.gradle -index 08631df..9ef3a95 100644 ---- a/android/build.gradle -+++ b/android/build.gradle -@@ -1,5 +1,4 @@ - import java.nio.file.Paths --import groovy.json.JsonSlurper - - buildscript { - ext.getExtOrDefault = {name -> -@@ -27,56 +26,16 @@ def getExtOrIntegerDefault(name) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["OPSQLite_" + name]).toInteger() - } - --def useSQLCipher = false -+def useSQLCipher = true - def useLibsql = false - def useCRSQLite = false --def performanceMode = false -+def performanceMode = true - def sqliteFlags = "" - def enableFTS5 = false - def useSqliteVec = false - def enableRtree = false - def tokenizers = [] - --// On the example app, the package.json is located at the root of the project --// On the user app, the package.json is located at the root of the node_modules directory --def isUserApp = rootDir.absolutePath.contains("node_modules") --def packageJsonFile -- --if (isUserApp) { -- // Start from the root + 1 level up (to avoid detecting the op-sqlite/package.json) and traverse upwards to find the first package.json -- File currentDir = new File("$rootDir/../") -- packageJsonFile = null -- -- // Try to find package.json by traversing upwards -- while (currentDir != null) { -- File potential = new File(currentDir, "package.json") -- if (potential.exists()) { -- packageJsonFile = potential -- break -- } -- currentDir = currentDir.parentFile -- } --} else { -- packageJsonFile = new File("$rootDir/../package.json") --} -- -- --def packageJson = new JsonSlurper().parseText(packageJsonFile.text) -- --def opsqliteConfig = packageJson["op-sqlite"] -- --if(opsqliteConfig) { -- println "[OP-SQLITE] Detected op-sqlite config from package.json at: " + packageJsonFile.absolutePath -- useSQLCipher = !!opsqliteConfig["sqlcipher"] -- useCRSQLite = !!opsqliteConfig["crsqlite"] -- useSqliteVec = !!opsqliteConfig["sqliteVec"] -- performanceMode = opsqliteConfig["performanceMode"] -- sqliteFlags = opsqliteConfig["sqliteFlags"] ? opsqliteConfig["sqliteFlags"] : "" -- enableFTS5 = !!opsqliteConfig["fts5"] -- useLibsql = !!opsqliteConfig["libsql"] -- enableRtree = !!opsqliteConfig["rtree"] -- tokenizers = opsqliteConfig["tokenizers"] ? opsqliteConfig["tokenizers"] : [] --} - - if(useSQLCipher) { - println "[OP-SQLITE] using sqlcipher." -diff --git a/android/cpp-adapter.cpp b/android/cpp-adapter.cpp -index 5912d7b..495880e 100644 ---- a/android/cpp-adapter.cpp -+++ b/android/cpp-adapter.cpp -@@ -19,8 +19,8 @@ struct OPSQLiteBridge : jni::JavaClass { - static void registerNatives() { - javaClassStatic()->registerNatives( - {makeNativeMethod("installNativeJsi", OPSQLiteBridge::installNativeJsi), -- makeNativeMethod("clearStateNativeJsi", -- OPSQLiteBridge::clearStateNativeJsi)}); -+ makeNativeMethod("clearStateNativeJsi", OPSQLiteBridge::clearStateNativeJsi), -+ makeNativeMethod("deleteAllDBsJsi", OPSQLiteBridge::deleteAllDBsJsi)}); - } - - private: -@@ -39,6 +39,10 @@ private: - static void clearStateNativeJsi(jni::alias_ref thiz) { - opsqlite::invalidate(); - } -+ -+ static bool deleteAllDBsJsi(jni::alias_ref thiz) { -+ return opsqlite::deleteAllDbs(); -+ } - }; - - JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) { -diff --git a/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt b/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt -index 44f86df..8c003db 100644 ---- a/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt -+++ b/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt -@@ -12,6 +12,7 @@ class OPSQLiteBridge { - docPath: String - ) - private external fun clearStateNativeJsi() -+ private external fun deleteAllDBsJsi(): Boolean - - fun install(context: ReactContext) { - val jsContextPointer = context.javaScriptContextHolder!!.get() -@@ -31,6 +32,10 @@ class OPSQLiteBridge { - clearStateNativeJsi() - } - -+ fun deleteAllDBs(): Boolean { -+ return deleteAllDBsJsi() -+ } -+ - companion object { - val instance = OPSQLiteBridge() - } -diff --git a/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt b/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt -index 8d341b7..33d3d7d 100644 ---- a/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt -+++ b/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt -@@ -12,7 +12,7 @@ import java.io.InputStream - import java.io.OutputStream - import com.facebook.react.util.RNLog; - --internal class OPSQLiteModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { -+class OPSQLiteModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { - override fun getName(): String { - return NAME - } -@@ -54,6 +54,18 @@ internal class OPSQLiteModule(context: ReactApplicationContext?) : ReactContextB - throw Exception("Do not call getDylibPath on Android") - } - -+ @ReactMethod(isBlockingSynchronousMethod = true) -+ fun closeAllConnections(): Boolean { -+ OPSQLiteBridge.instance.invalidate() -+ return true -+ } -+ -+ @ReactMethod(isBlockingSynchronousMethod = true) -+ fun deleteAllDBs(): Boolean { -+ return OPSQLiteBridge.instance.deleteAllDBs(); -+ } -+ -+ - @ReactMethod - fun moveAssetsDatabase(args: ReadableMap, promise: Promise) { - val filename = args.getString("filename")!! -diff --git a/cpp/DBHostObject.cpp b/cpp/DBHostObject.cpp -index 9682941..c0b9c21 100644 ---- a/cpp/DBHostObject.cpp -+++ b/cpp/DBHostObject.cpp -@@ -682,6 +682,10 @@ void DBHostObject::invalidate() { - #endif - } - -+void DBHostObject::drop() { -+ opsqlite_remove(db, db_name, std::string(base_path)); -+} -+ - DBHostObject::~DBHostObject() { invalidate(); } - - } // namespace opsqlite -diff --git a/cpp/DBHostObject.h b/cpp/DBHostObject.h -index 002b8c9..f3a2e1f 100644 ---- a/cpp/DBHostObject.h -+++ b/cpp/DBHostObject.h -@@ -68,6 +68,7 @@ public: - void on_commit(); - void on_rollback(); - void invalidate(); -+ void drop(); - ~DBHostObject() override; - - private: -diff --git a/cpp/OPSqlite.cpp b/cpp/OPSqlite.cpp -index e33579a..791fa70 100644 ---- a/cpp/OPSqlite.cpp -+++ b/cpp/OPSqlite.cpp -@@ -42,6 +42,13 @@ void invalidate() { - dbs.clear(); - } - -+bool deleteAllDbs() { -+ for(const auto &db : dbs) { -+ db->drop(); -+ } -+ return true; -+} -+ - void install(jsi::Runtime &rt, - const std::shared_ptr &_invoker, - const char *base_path, const char *crsqlite_path, -diff --git a/cpp/OPSqlite.hpp b/cpp/OPSqlite.hpp -index 91511ab..cc73dfe 100644 ---- a/cpp/OPSqlite.hpp -+++ b/cpp/OPSqlite.hpp -@@ -14,6 +14,7 @@ void install(jsi::Runtime &rt, - const char *base_path, const char *crsqlite_path, - const char *sqlite_vec_path); - void invalidate(); -+bool deleteAllDbs(); - void expoUpdatesWorkaround(const char *base_path); - - } // namespace opsqlite -diff --git a/op-sqlite.podspec b/op-sqlite.podspec -index e717811..147f516 100644 ---- a/op-sqlite.podspec -+++ b/op-sqlite.podspec -@@ -1,4 +1,3 @@ --require "json" - require_relative "./generate_tokenizers_header_file" - - log_message = lambda do |message| -@@ -38,11 +37,10 @@ end - - app_package = JSON.parse(File.read(package_json_path)) - --op_sqlite_config = app_package["op-sqlite"] --use_sqlcipher = false -+use_sqlcipher = true - use_crsqlite = false - use_libsql = false --performance_mode = false -+performance_mode = true - phone_version = false - sqlite_flags = "" - fts5 = false -@@ -50,36 +48,7 @@ rtree = false - use_sqlite_vec = false - tokenizers = [] - --if(op_sqlite_config != nil) -- use_sqlcipher = op_sqlite_config["sqlcipher"] == true -- use_crsqlite = op_sqlite_config["crsqlite"] == true -- use_libsql = op_sqlite_config["libsql"] == true -- performance_mode = op_sqlite_config["performanceMode"] || false -- phone_version = op_sqlite_config["iosSqlite"] == true -- sqlite_flags = op_sqlite_config["sqliteFlags"] || "" -- fts5 = op_sqlite_config["fts5"] == true -- rtree = op_sqlite_config["rtree"] == true -- use_sqlite_vec = op_sqlite_config["sqliteVec"] == true -- tokenizers = op_sqlite_config["tokenizers"] || [] --end -- --if phone_version then -- if use_sqlcipher then -- raise "SQLCipher is not supported with phone version. It cannot load extensions." -- end -- -- if use_crsqlite then -- raise "CRSQLite is not supported with phone version. It cannot load extensions." -- end - -- if rtree then -- raise "RTree is not supported with phone version. It cannot load extensions." -- end -- -- if use_sqlite_vec then -- raise "SQLite Vec is not supported with phone version. It cannot load extensions." -- end --end - - Pod::Spec.new do |s| - s.name = "op-sqlite" -@@ -158,12 +127,6 @@ Pod::Spec.new do |s| - xcconfig[:GCC_PREPROCESSOR_DEFINITIONS] += " SQLITE_ENABLE_RTREE=1" - end - -- if phone_version then -- log_message.call("[OP-SQLITE] using iOS embedded SQLite 📱") -- xcconfig[:GCC_PREPROCESSOR_DEFINITIONS] += " OP_SQLITE_USE_PHONE_VERSION=1" -- exclude_files += ["cpp/sqlite3.c", "cpp/sqlite3.h"] -- s.library = "sqlite3" -- end - - if performance_mode then - log_message.call("[OP-SQLITE] Performance mode enabled") diff --git a/.yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch b/.yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch new file mode 100644 index 0000000..99e5dec --- /dev/null +++ b/.yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch @@ -0,0 +1,325 @@ +diff --git a/android/build.gradle b/android/build.gradle +index 3049da4..17f793c 100644 +--- a/android/build.gradle ++++ b/android/build.gradle +@@ -52,10 +52,10 @@ def reactNativeArchitectures() { + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] + } + +-def useSQLCipher = false ++def useSQLCipher = true + def useLibsql = false + def useTurso = false +-def performanceMode = false ++def performanceMode = true + def sqliteFlags = "" + def enableFTS5 = false + def useSqliteVec = false +@@ -88,20 +88,6 @@ if (isUserApp) { + + def packageJson = new JsonSlurper().parseText(packageJsonFile.text) + +-def opsqliteConfig = packageJson["op-sqlite"] +- +-if(opsqliteConfig) { +- println "[OP-SQLITE] Detected op-sqlite config from package.json at: " + packageJsonFile.absolutePath +- useSQLCipher = !!opsqliteConfig["sqlcipher"] +- useSqliteVec = !!opsqliteConfig["sqliteVec"] +- performanceMode = opsqliteConfig["performanceMode"] +- sqliteFlags = opsqliteConfig["sqliteFlags"] ? opsqliteConfig["sqliteFlags"] : "" +- enableFTS5 = !!opsqliteConfig["fts5"] +- useLibsql = !!opsqliteConfig["libsql"] +- useTurso = !!opsqliteConfig["turso"] +- enableRtree = !!opsqliteConfig["rtree"] +- tokenizers = opsqliteConfig["tokenizers"] ? opsqliteConfig["tokenizers"] : [] +-} + + if(useLibsql && useTurso) { + throw new GradleException("[OP-SQLITE] Error: libsql and turso backends are mutually exclusive.") +diff --git a/android/cpp-adapter.cpp b/android/cpp-adapter.cpp +index 3f800c4..6fd9c44 100644 +--- a/android/cpp-adapter.cpp ++++ b/android/cpp-adapter.cpp +@@ -22,7 +22,9 @@ struct OPSQLiteBridge : jni::JavaClass { + javaClassStatic()->registerNatives( + {makeNativeMethod("installNativeJsi", OPSQLiteBridge::installNativeJsi), + makeNativeMethod("clearStateNativeJsi", +- OPSQLiteBridge::clearStateNativeJsi)}); ++ OPSQLiteBridge::clearStateNativeJsi), ++ makeNativeMethod("closeAllDBsJsi", OPSQLiteBridge::closeAllDBsJsi), ++ makeNativeMethod("deleteAllDBsJsi", OPSQLiteBridge::deleteAllDBsJsi)}); + } + + private: +@@ -60,6 +62,14 @@ private: + opsqlite::invalidate(*handle); + delete handle; + } ++ ++ static void closeAllDBsJsi(jni::alias_ref thiz) { ++ opsqlite::closeAllDbs(); ++ } ++ ++ static jboolean deleteAllDBsJsi(jni::alias_ref thiz) { ++ return opsqlite::deleteAllDbs(); ++ } + }; + + JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) { +diff --git a/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt b/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt +index 115ae37..4ad749d 100644 +--- a/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt ++++ b/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt +@@ -17,6 +17,8 @@ class OPSQLiteBridge { + docPath: String + ): Long + private external fun clearStateNativeJsi(handle: Long) ++ private external fun closeAllDBsJsi() ++ private external fun deleteAllDBsJsi(): Boolean + + fun install(context: ReactContext): Long { + val jsContextPointer = context.javaScriptContextHolder!!.get() +@@ -36,6 +38,14 @@ class OPSQLiteBridge { + clearStateNativeJsi(handle) + } + ++ fun closeAllDBs() { ++ closeAllDBsJsi() ++ } ++ ++ fun deleteAllDBs(): Boolean { ++ return deleteAllDBsJsi() ++ } ++ + companion object { + val instance = OPSQLiteBridge() + } +diff --git a/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt b/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt +index 3cbb7ef..c8aff94 100644 +--- a/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt ++++ b/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt +@@ -12,7 +12,7 @@ import java.io.InputStream + import java.io.OutputStream + import com.facebook.react.util.RNLog; + +-internal class OPSQLiteModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { ++class OPSQLiteModule(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) { + // Handle for THIS generation's liveness flag, returned by install() and + // handed back to invalidate(). OPSQLiteModule is recreated per bridge/ + // generation by OPSQLitePackage, unlike the OPSQLiteBridge singleton it +@@ -56,6 +56,17 @@ internal class OPSQLiteModule(context: ReactApplicationContext?) : ReactContextB + } + } + ++ @ReactMethod(isBlockingSynchronousMethod = true) ++ fun closeAllConnections(): Boolean { ++ OPSQLiteBridge.instance.closeAllDBs() ++ return true ++ } ++ ++ @ReactMethod(isBlockingSynchronousMethod = true) ++ fun deleteAllDBs(): Boolean { ++ return OPSQLiteBridge.instance.deleteAllDBs() ++ } ++ + @ReactMethod(isBlockingSynchronousMethod = true) + fun getDylibPath(bundleId: String, name: String): Boolean { + throw Exception("Do not call getDylibPath on Android") +diff --git a/cpp/OPDatabase.cpp b/cpp/OPDatabase.cpp +index 23da58e..54f31b9 100644 +--- a/cpp/OPDatabase.cpp ++++ b/cpp/OPDatabase.cpp +@@ -862,6 +862,32 @@ void OPDatabase::invalidate() { + #endif + } + ++void OPDatabase::drop() { ++ if (delete_db_name.empty()) { ++ // Remote-only databases have no local file; closing is all we can do. ++ invalidate(); ++ return; ++ } ++ ++ invalidated = true; ++ // Same sequence as the JS delete() host function: abort running work, drain ++ // the thread pool, then close the handle and remove the file. ++#if !defined(OP_SQLITE_USE_LIBSQL) && !defined(OP_SQLITE_USE_TURSO) ++ if (db != nullptr) { ++ sqlite3_interrupt(db); ++ } ++#endif ++ thread_pool->wait_finished(); ++ release_hooks(); ++#ifdef OP_SQLITE_USE_LIBSQL ++ opsqlite_libsql_remove(db, delete_db_name, base_path); ++#else ++ auto *closing_db = db; ++ db = nullptr; ++ opsqlite_remove(closing_db, delete_db_name, base_path); ++#endif ++} ++ + OPDatabase::~OPDatabase() { invalidate(); } + + } // namespace opsqlite +diff --git a/cpp/OPDatabase.hpp b/cpp/OPDatabase.hpp +index 9e387a6..8b28332 100644 +--- a/cpp/OPDatabase.hpp ++++ b/cpp/OPDatabase.hpp +@@ -77,6 +77,8 @@ public: + void on_commit(); + void on_rollback(); + void invalidate(); ++ // Closes the database and deletes its file, like the JS delete() function. ++ void drop(); + ~OPDatabase() override; + + private: +diff --git a/cpp/OPSqlite.cpp b/cpp/OPSqlite.cpp +index 7b914f7..66b0aa4 100644 +--- a/cpp/OPSqlite.cpp ++++ b/cpp/OPSqlite.cpp +@@ -10,8 +10,10 @@ + #include "OPLogs.h" + #include "OPMacros.hpp" + #include "OPUtils.hpp" ++#include + #include + #include ++#include + #include + #include + #include +@@ -26,6 +28,56 @@ std::string _sqlite_vec_path; + std::shared_ptr invoker; + std::shared_ptr> generation_alive; + ++// Weak references to every database handed out by open(), so the platform glue ++// can close or delete all of them (e.g. when the host app clears its data). ++// Weak so the registry never extends a database's lifetime past its JS object. ++std::mutex dbs_mutex; ++std::vector> dbs; ++ ++static void register_db(const std::shared_ptr &db) { ++ std::lock_guard lock(dbs_mutex); ++ dbs.erase(std::remove_if(dbs.begin(), dbs.end(), ++ [](const std::weak_ptr &weak_db) { ++ return weak_db.expired(); ++ }), ++ dbs.end()); ++ dbs.push_back(db); ++} ++ ++static std::vector> live_dbs() { ++ std::lock_guard lock(dbs_mutex); ++ std::vector> result; ++ for (const auto &weak_db : dbs) { ++ if (auto db = weak_db.lock()) { ++ result.push_back(db); ++ } ++ } ++ dbs.clear(); ++ for (const auto &db : result) { ++ dbs.push_back(db); ++ } ++ return result; ++} ++ ++void closeAllDbs() { ++ for (const auto &db : live_dbs()) { ++ db->invalidate(); ++ } ++} ++ ++bool deleteAllDbs() { ++ bool all_deleted = true; ++ for (const auto &db : live_dbs()) { ++ try { ++ db->drop(); ++ } catch (const std::exception &e) { ++ LOGE("[op-sqlite] deleteAllDbs failed for a database: %s", e.what()); ++ all_deleted = false; ++ } ++ } ++ return all_deleted; ++} ++ + // Each platform module calls its own invalidate() lifecycle hook when React + // Native tears down the JS context (CodePush/Hot Reload, or any other + // runtime teardown) -- OPSQLiteModule.invalidate() on Android, which reaches +@@ -99,6 +151,7 @@ install(jsi::Runtime &rt, const std::shared_ptr &invoker, + std::shared_ptr db = std::make_shared( + rt, js_db, path, name, path, readOnly, failOnCreate, encryption_key); + js_db.setNativeState(rt, db); ++ register_db(db); + return js_db; + }); + +@@ -154,6 +207,7 @@ install(jsi::Runtime &rt, const std::shared_ptr &invoker, + #endif + + js_db.setNativeState(rt, db); ++ register_db(db); + return js_db; + }); + +@@ -216,6 +270,7 @@ install(jsi::Runtime &rt, const std::shared_ptr &invoker, + #endif + + js_db.setNativeState(rt, db); ++ register_db(db); + return js_db; + }); + #endif +diff --git a/cpp/OPSqlite.hpp b/cpp/OPSqlite.hpp +index 8e81903..245c7bb 100644 +--- a/cpp/OPSqlite.hpp ++++ b/cpp/OPSqlite.hpp +@@ -20,5 +20,10 @@ install(jsi::Runtime &rt, const std::shared_ptr &invoker, + const char *base_path, const char *sqlite_vec_path); + void invalidate(const std::shared_ptr> &generation_alive); + void expoUpdatesWorkaround(const char *base_path); ++// Close every database opened through open() that is still alive. ++void closeAllDbs(); ++// Close and delete the file of every database opened through open() that is ++// still alive. Returns false if any of them could not be deleted. ++bool deleteAllDbs(); + + } // namespace opsqlite +diff --git a/op-sqlite.podspec b/op-sqlite.podspec +index 905d8e9..40b6cc4 100644 +--- a/op-sqlite.podspec ++++ b/op-sqlite.podspec +@@ -38,11 +38,10 @@ end + + app_package = JSON.parse(File.read(package_json_path)) + +-op_sqlite_config = app_package["op-sqlite"] +-use_sqlcipher = false ++use_sqlcipher = true + use_libsql = false + use_turso = false +-performance_mode = false ++performance_mode = true + phone_version = false + sqlite_flags = "" + fts5 = false +@@ -50,18 +49,6 @@ rtree = false + use_sqlite_vec = false + tokenizers = [] + +-if(op_sqlite_config != nil) +- use_sqlcipher = op_sqlite_config["sqlcipher"] == true +- use_libsql = op_sqlite_config["libsql"] == true +- use_turso = op_sqlite_config["turso"] == true +- performance_mode = op_sqlite_config["performanceMode"] || false +- phone_version = op_sqlite_config["iosSqlite"] == true +- sqlite_flags = op_sqlite_config["sqliteFlags"] || "" +- fts5 = op_sqlite_config["fts5"] == true +- rtree = op_sqlite_config["rtree"] == true +- use_sqlite_vec = op_sqlite_config["sqliteVec"] == true +- tokenizers = op_sqlite_config["tokenizers"] || [] +-end + + if phone_version then + if use_sqlcipher then diff --git a/android/gradle.properties b/android/gradle.properties index 25d5a2f..8691e28 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ -MendixNative_kotlinVersion=2.0.21 +MendixNative_kotlinVersion=2.2.0 MendixNative_minSdkVersion=29 MendixNative_targetSdkVersion=36 -MendixNative_compileSdkVersion=36 +MendixNative_compileSdkVersion=37 MendixNative_ndkVersion=27.3.13750724 diff --git a/android/src/main/java/com/mendix/mendixnative/config/AppPreferences.java b/android/src/main/java/com/mendix/mendixnative/config/AppPreferences.java index b3f0989..662fe0b 100644 --- a/android/src/main/java/com/mendix/mendixnative/config/AppPreferences.java +++ b/android/src/main/java/com/mendix/mendixnative/config/AppPreferences.java @@ -2,7 +2,6 @@ import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; import com.facebook.react.modules.debug.interfaces.DeveloperSettings; import com.facebook.react.packagerconnection.PackagerConnectionSettings; @@ -38,7 +37,8 @@ final public class AppPreferences { private final SharedPreferences preferences; public AppPreferences(Context applicationContext) { - preferences = PreferenceManager.getDefaultSharedPreferences(applicationContext); + // Same file PreferenceManager.getDefaultSharedPreferences() uses, which React Native's dev settings also read. + preferences = applicationContext.getSharedPreferences(applicationContext.getPackageName() + "_preferences", Context.MODE_PRIVATE); } public String getAppUrl() { diff --git a/android/src/main/java/com/mendix/mendixnative/fragment/ReactFragment.kt b/android/src/main/java/com/mendix/mendixnative/fragment/ReactFragment.kt index d18a2a3..978bcc1 100644 --- a/android/src/main/java/com/mendix/mendixnative/fragment/ReactFragment.kt +++ b/android/src/main/java/com/mendix/mendixnative/fragment/ReactFragment.kt @@ -25,7 +25,7 @@ open class ReactFragment : com.facebook.react.ReactFragment() { return view } - @Suppress("DEPRECATION") + @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) reactDelegate.onActivityResult(requestCode, resultCode, data, true) diff --git a/android/src/main/java/com/mendix/mendixnative/react/fs/NativeFsModule.kt b/android/src/main/java/com/mendix/mendixnative/react/fs/NativeFsModule.kt index 96a8f29..9fe5000 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/fs/NativeFsModule.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/fs/NativeFsModule.kt @@ -24,6 +24,8 @@ class NativeFsModule(private val reactContext: ReactApplicationContext) { private val fileBackend: FileBackend = FileBackend(reactContext) private val filesDir: String = reactContext.filesDir.absolutePath private val cacheDir: String = reactContext.cacheDir.absolutePath + private val allowedRoots: List = + listOf(reactContext.filesDir.canonicalPath, reactContext.cacheDir.canonicalPath) fun setEncryptionEnabled(encryptionEnabled: Boolean) { this.fileBackend.setEncryptionEnabled(encryptionEnabled) @@ -87,6 +89,7 @@ class NativeFsModule(private val reactContext: ReactApplicationContext) { if (!fileBackend.exists(fromPath)) { promise.reject(ERROR_READ_FAILED, "File does not exist") + return } try { @@ -104,10 +107,11 @@ class NativeFsModule(private val reactContext: ReactApplicationContext) { fun remove(filePath: String, promise: Promise) { try { - if (fileBackend.isDirectory(filePath)) { - fileBackend.deleteDirectory(filePath) + val path = ensureWhiteListedPath(filePath) + if (fileBackend.isDirectory(path)) { + fileBackend.deleteDirectory(path) } else { - fileBackend.deleteFile(ensureWhiteListedPath(filePath)) + fileBackend.deleteFile(path) } promise.resolve(null) } catch (e: PathNotAccessibleException) { @@ -165,9 +169,12 @@ class NativeFsModule(private val reactContext: ReactApplicationContext) { fun readAsText(filePath: String, promise: Promise) { try { - promise.resolve(String(fileBackend.read(filePath), StandardCharsets.UTF_8)) + promise.resolve(String(fileBackend.read(ensureWhiteListedPath(filePath)), StandardCharsets.UTF_8)) } catch (e: IOException) { promise.reject("no text", e) + } catch (e: PathNotAccessibleException) { + e.printStackTrace() + promise.reject(INVALID_PATH, e) } } @@ -214,7 +221,7 @@ class NativeFsModule(private val reactContext: ReactApplicationContext) { ) } catch (e: FileNotFoundException) { e.printStackTrace() - promise.resolve("null") + promise.resolve(null) } catch (e: JsonParseException) { e.printStackTrace() promise.reject(ERROR_SERIALIZATION_FAILED, "Failed to deserialize JSON", e) @@ -252,7 +259,17 @@ class NativeFsModule(private val reactContext: ReactApplicationContext) { @Throws(PathNotAccessibleException::class) private fun ensureWhiteListedPath(path: String): String { - if (!(path.startsWith(filesDir) || path.startsWith(cacheDir))) { + // Canonicalize first so "../" can't escape a root, and require a "/" boundary so a + // sibling like "Evil" doesn't match "". + val canonical = try { + File(path).canonicalPath + } catch (e: IOException) { + throw PathNotAccessibleException(path) + } + val isAllowed = path.startsWith("/") && allowedRoots.any { root -> + canonical == root || canonical.startsWith("$root/") + } + if (!isAllowed) { throw PathNotAccessibleException(path) } return path diff --git a/android/src/main/java/com/mendix/mendixnative/react/splash/MendixSplashScreenModule.kt b/android/src/main/java/com/mendix/mendixnative/react/splash/MendixSplashScreenModule.kt index 1298a7c..cd3f4ce 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/splash/MendixSplashScreenModule.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/splash/MendixSplashScreenModule.kt @@ -3,15 +3,21 @@ package com.mendix.mendixnative.react.splash import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.WritableMap import com.facebook.react.bridge.WritableNativeMap +import com.mendix.mendixnative.react.runOnUiThread class MendixSplashScreenModule(val reactContext: ReactApplicationContext) { - fun show(presenter: MendixSplashScreenPresenter?) = reactContext.currentActivity?.let { - presenter?.show(it) + // Called from the native modules thread; presenters touch views, so hop to the UI thread. + fun show(presenter: MendixSplashScreenPresenter?) { + runOnUiThread { + reactContext.currentActivity?.let { presenter?.show(it) } + } } - fun hide(presenter: MendixSplashScreenPresenter?) = reactContext.currentActivity?.let { - presenter?.hide(it) + fun hide(presenter: MendixSplashScreenPresenter?) { + runOnUiThread { + reactContext.currentActivity?.let { presenter?.hide(it) } + } } fun getConstants(): WritableMap { diff --git a/android/src/main/java/com/mendixnative/MendixNativePackage.kt b/android/src/main/java/com/mendixnative/MendixNativePackage.kt index 9560089..70a55bd 100644 --- a/android/src/main/java/com/mendixnative/MendixNativePackage.kt +++ b/android/src/main/java/com/mendixnative/MendixNativePackage.kt @@ -6,7 +6,7 @@ import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.model.ReactModuleInfo import com.facebook.react.module.model.ReactModuleInfoProvider import com.mendix.mendixnative.react.splash.MendixSplashScreenPresenter -import com.mendixnative.configuration.MxConfigurationModule +import com.mendixnative.configuration.MxConfigModule import com.mendixnative.cookie.MxCookieModule import com.mendixnative.download.MxDownloadModule import com.mendixnative.encryption.MxEncryptionModule @@ -34,7 +34,7 @@ class MendixNativePackage : BaseReactPackage() { MxOtaModule.NAME -> MxOtaModule(reactContext) MxDownloadModule.NAME -> MxDownloadModule(reactContext) MxReloadModule.NAME -> MxReloadModule(reactContext) - MxConfigurationModule.NAME -> MxConfigurationModule(reactContext) + MxConfigModule.NAME -> MxConfigModule(reactContext) MxCookieModule.NAME -> MxCookieModule(reactContext) MxErrorModule.NAME -> MxErrorModule(reactContext) MxNavigationModule.NAME -> MxNavigationModule(reactContext) @@ -52,7 +52,7 @@ class MendixNativePackage : BaseReactPackage() { MxOtaModule.NAME, MxDownloadModule.NAME, MxReloadModule.NAME, - MxConfigurationModule.NAME, + MxConfigModule.NAME, MxCookieModule.NAME, MxErrorModule.NAME, MxNavigationModule.NAME diff --git a/android/src/main/java/com/mendixnative/configuration/MxConfigurationModule.kt b/android/src/main/java/com/mendixnative/configuration/MxConfigModule.kt similarity index 63% rename from android/src/main/java/com/mendixnative/configuration/MxConfigurationModule.kt rename to android/src/main/java/com/mendixnative/configuration/MxConfigModule.kt index 351e215..3e8b2ca 100644 --- a/android/src/main/java/com/mendixnative/configuration/MxConfigurationModule.kt +++ b/android/src/main/java/com/mendixnative/configuration/MxConfigModule.kt @@ -3,11 +3,11 @@ package com.mendixnative.configuration import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.annotations.ReactModule import com.mendix.mendixnative.react.MxConfiguration -import com.mendixnative.NativeMxConfigurationSpec +import com.mendixnative.NativeMxConfigSpec -@ReactModule(name = MxConfigurationModule.NAME) -class MxConfigurationModule(reactContext: ReactApplicationContext) : - NativeMxConfigurationSpec(reactContext) { +@ReactModule(name = MxConfigModule.NAME) +class MxConfigModule(reactContext: ReactApplicationContext) : + NativeMxConfigSpec(reactContext) { private val configuration = MxConfiguration(reactContext) @@ -18,6 +18,6 @@ class MxConfigurationModule(reactContext: ReactApplicationContext) : } companion object { - const val NAME = "MxConfiguration" + const val NAME = "MxConfig" } } diff --git a/eslint.config.mjs b/eslint.config.mjs index 16b00bb..4359c2e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -21,6 +21,7 @@ export default defineConfig([ rules: { 'react/react-in-jsx-scope': 'off', 'prettier/prettier': 'error', + '@react-native/no-deep-imports': 'error', }, }, { diff --git a/example/Gemfile b/example/Gemfile index 24519fd..fa80d50 100644 --- a/example/Gemfile +++ b/example/Gemfile @@ -9,3 +9,4 @@ gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' gem 'xcodeproj', '< 1.26.0' gem 'concurrent-ruby', '< 1.3.4' +gem 'nkf' diff --git a/example/Gemfile.lock b/example/Gemfile.lock index 75055b4..9b8a018 100644 --- a/example/Gemfile.lock +++ b/example/Gemfile.lock @@ -111,6 +111,7 @@ DEPENDENCIES activesupport (>= 6.1.7.5, != 7.1.0) cocoapods (>= 1.13, != 1.15.1, != 1.15.0) concurrent-ruby (< 1.3.4) + nkf xcodeproj (< 1.26.0) RUBY VERSION diff --git a/example/__tests__/file-system.harness.ts b/example/__tests__/file-system.harness.ts index ca8b769..ddc6e04 100644 --- a/example/__tests__/file-system.harness.ts +++ b/example/__tests__/file-system.harness.ts @@ -1,8 +1,16 @@ import { describe, test, expect } from 'react-native-harness'; import { NativeFileSystem } from 'mendix-native'; +// React Native's Blob exposes its native reference, which the DOM Blob type lacks. +type RNBlob = { + data: Parameters[0]; + close(): void; +}; + describe('NativeFileSystem', () => { const testFile = 'test-file.txt'; + const notWhiteListedMessage = + 'Path needs to be an absolute path to the apps accessible space.'; describe('Constants', () => { test('should have constants defined', () => { @@ -38,6 +46,26 @@ describe('NativeFileSystem', () => { } }); + test('should throw for paths escaping the documents directory', async () => { + const documentDirectory = NativeFileSystem.DocumentDirectoryPath; + const escapingPaths = [ + `${documentDirectory}/../escape.txt`, + `${documentDirectory}Evil/escape.txt`, + ]; + for (const path of escapingPaths) { + await expect(NativeFileSystem.fileExists(path)).rejects.toThrow( + notWhiteListedMessage + ); + } + }); + + test('should allow normalized paths inside the documents directory', async () => { + const exists = await NativeFileSystem.fileExists( + `${NativeFileSystem.DocumentDirectoryPath}/sub/../non-existent-file.txt` + ); + expect(exists).toBe(false); + }); + test('should return true for created file', async () => { // Create a test file first using writeJson const testPath = @@ -122,6 +150,14 @@ describe('NativeFileSystem', () => { // Cleanup await NativeFileSystem.remove(filePath); }); + + test('should resolve null for non-existent file', async () => { + const readData = await NativeFileSystem.readJson( + NativeFileSystem.relativeToDocumentsAbsolutePath('non-existent.json') + ); + // iOS resolves undefined, Android resolves null. + expect(readData == null).toBe(true); + }); }); describe('remove', () => { @@ -143,6 +179,15 @@ describe('NativeFileSystem', () => { // Should not throw error await expect(NativeFileSystem.remove(filePath)).resolves.not.toThrow(); }); + + test('should throw for non white listed path', async () => { + try { + await NativeFileSystem.remove(testFile); + expect(true).toBe(false); // This should not be reached + } catch (error: any) { + expect(error.message).contains(notWhiteListedMessage); + } + }); }); describe('move', () => { @@ -187,6 +232,64 @@ describe('NativeFileSystem', () => { // Cleanup await NativeFileSystem.remove(destPath); }); + + test('should reject and not create destination for non-existent source', async () => { + const sourcePath = NativeFileSystem.relativeToDocumentsAbsolutePath( + 'missing-source.json' + ); + const destPath = + NativeFileSystem.relativeToDocumentsAbsolutePath('missing-dest.json'); + + await expect( + NativeFileSystem.move(sourcePath, destPath) + ).rejects.toBeDefined(); + expect(await NativeFileSystem.fileExists(destPath)).toBe(false); + }); + }); + + describe('save and read', () => { + test('should round-trip blob content through the blob manager', async () => { + const filePath = + NativeFileSystem.relativeToDocumentsAbsolutePath('test-blob.txt'); + // Keep a reference so the blob isn't released before save resolves. + const blob = new Blob(['hello mendix']) as unknown as RNBlob; + + await NativeFileSystem.save(blob.data, filePath); + const readBlob = await NativeFileSystem.read(filePath); + const dataUrl = await NativeFileSystem.readAsDataURL(filePath); + + expect(typeof readBlob.blobId).toBe('string'); + expect(dataUrl).toContain(btoa('hello mendix')); + + // Cleanup + blob.close(); + await NativeFileSystem.remove(filePath); + }); + }); + + describe('readAsText', () => { + test('should throw for non white listed path', async () => { + try { + await NativeFileSystem.readAsText(testFile); + expect(true).toBe(false); // This should not be reached + } catch (error: any) { + expect(error.message).contains(notWhiteListedMessage); + } + }); + + test('should read file content as UTF-8 text', async () => { + const filePath = + NativeFileSystem.relativeToDocumentsAbsolutePath('test-text.json'); + const testData = { greeting: 'héllo' }; + + await NativeFileSystem.writeJson(testData, filePath); + const text = await NativeFileSystem.readAsText(filePath); + + expect(JSON.parse(text)).toEqual(testData); + + // Cleanup + await NativeFileSystem.remove(filePath); + }); }); describe('list', () => { diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 6e3ab92..b2e9da8 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -102,7 +102,7 @@ android { // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds - proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" } } diff --git a/example/android/build.gradle b/example/android/build.gradle index e40705d..2ea1de2 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,11 +1,11 @@ buildscript { ext { - buildToolsVersion = "36.0.0" + buildToolsVersion = "37.0.0" minSdkVersion = 29 - compileSdkVersion = 36 + compileSdkVersion = 37 targetSdkVersion = 36 ndkVersion = "27.3.13750724" - kotlinVersion = "2.0.21" + kotlinVersion = "2.2.0" } repositories { google() diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 9afe615..53da105 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -41,4 +41,9 @@ hermesEnabled=true # Use this property to enable edge-to-edge display support. # This allows your app to draw behind system bars for an immersive UI. # Note: Only works with ReactActivity and should not be used with custom Activity. -edgeToEdgeEnabled=false +edgeToEdgeEnabled=true + +# Opt out of built-in kotlin and new DSL behavior that ships with AGP 9. +# Starting from AGP 10.x these opt outs will be removed. +android.builtInKotlin=false +android.newDsl=false diff --git a/example/android/gradle/wrapper/gradle-wrapper.jar b/example/android/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..d997cfc60f4cff0e7451d19d49a82fa986695d07 100644 GIT binary patch delta 40682 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Ðt5p(LLtXn?pxm3OZHd|13r);5)1uCW40m{;j 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 A;{X5v delta 35496 zcmXVXRajhI(` z*w5aMC@gKw}sbFj6xXo|NAzsKa|n3$(g<(TLveor>2vd(dA?ce-n8kQMX7-x`S zgh4)mn5FC$>C(00QZBG96^X~$G_(gEW;koQ!If8A7*e02J!RL7JhhNUm;RwN*c>q{XFRL^X)64H>wTCg9oT5^kvyxHK zI`pVXt>0nl(~5*II}kO2b^sOZ0B1UtZdsh_S&GVjWNt7p8aZdg7#%~C-qcsDmf^Om zVLgr85{q?va)HMQBo+#b4vTi8&q=PH!h1hfKp1B@cXJ-!y7GLs%*LPBNu_zvw}Lu+ z(q)@6o=Te{V+|$=)L@lWE&q;0@--SO&uhgesB4i-D%%G2Wb?n4Dg+Q#8AA#^yA{&G6mLiXXH_V<;)_kd~uoN?s=maW9-`syiw8$U;9&K=dc3mE5;AByknn z74IM(cLL|Im7PG1OqxnVn?=Va;!rHn?9&F!{-$DvU>5z%`i?$y>ByVn^r!R$hj9J# z^AA8!#YvN|nqX3lQQD2~YOS9GUmq)pb){!Cf=3lQn?{C812Pr>y6T%sgyvyisJe=0 zQI?l0dTjz0|HY~s15>5UKWIui_mhJ1i~7ZC6~qbJw5X6Unk2x;fQAkmSj2>x)*a;q zlx)YCXZ1!DO=!Ms${=E| z&G>?21%PAc56PKi%^CCHYWL1E)O1E&oNbLDvQNQ&Kz7+_Jwr!e&n*c2P2NWE<#Bp;E(Sw;dPHFA)R7{GU~RTtUOyRn8(6UuofsC`=F4R6zRz1T<;o@a zdJDT5zsjrKAB?88o-#b1{eh!b8dyEeCDHfc>e?y@2($0_Z&H#VX_~RnOs2b z06_Eqerj2TUkve5+1XEN#Llq=yza^>E!eiPKs|1-bf6!Dj!LR5YrN%zSnAhj=tvS< z!IFo-(Q)OR`vdD1(l!>8L$|*dS)MVTT*X{ok2()xWhn64$zT z9!@;bt7#U%OV}wR)}q#3J>U-}Tcss7)US9PY4grx=vH~$M=5MkloZ^V0aSAg4o|Rh zoa%(@?vOgOL90b29})uH+dHlhoabQ+tBCnIB$wMw)@R%i4#~@8G+HTcm_NnB9wxi3 zE8*iR0XWO?xoMSnv26VB&7Og$hPqrRjc5tujVGJG#?i``$}<==!=0miZa3K;4x$Rx z+|}-&SwB#?c@4Nt*>e()6U`N-u~U1c9n8g#=KyBYoDKl{Q_-$>j()CZ7h_H?2XU3 z&{L7|yb1BP5zLoPW1=?+$Z62@T@QhKYhz3*QHItOGT{NEUse@|#-*<|$gP$Y|S60%$vkpv4k%q#~MzyL_2U;^VLP1tE{;Z5=35=CLLwG^W z=IgKh_72@F5aRJj45U;&pA#hvTB;C>Cj}P}S^1p?|4|r|{xP9+v)P>J&}Mn*1Y#|H)Ch#oh z)o~QUUR#C+&V{}KC%mMUzs%i=akhRhZy{L0=->C0%bP#U;u%)9AkH^7#>@uSXOrU5 zEkDtp{1jeyTI}IdIM*G{0qnw?$B}1fVL7^TPks;U3rV^-388QJ1s5gq9cPwrn)bkO zCYKp9Q?7HfQ-jW!N3NW2e~5996i-AB8;Z#bf@jvd0qQ^qIAxckZ(n zemF8&Zc(a&rj6}ii8U8Df)5P;E2hX@Hhf074pEJb8iv&dZ6PJF-6`v}U=CxN;RVaobGq+B(UY0e`W^(KX z%BMK<7W&@=845jry8Dfu<|;U(wBz@)JrUvnxR%rU<9FG0>6+Uy&(rhw5amPWH4DTe zhGcc|-pNW?f$X3J&juY_94Z#CyfS*=26A^Fi?U#fPFy=c&>~R`g;roIpx@pZ)8x8~ zor5a2ucT>H!!73Z)bWKMx0whNVpt@nOUpt>Ey?VEhO!c zd-he|bXN-q$&g5@U`!FIt2(m}JdO}7TbJuO>Y}P_5Mql_g%-f}<_#6)10%Br^WR(j zUP)&OxqMt`UaT{y6yx5}1^H_wQCzy+~$XD&h~(pb3xU?&8t=`s-otE6x0PizHgKc8dz@ z>%C4D)-lGDq$l9B_;IGJ1AoZZ*^2{z0#t3{;9x31Bz-@XF#$*;v1SR_?@}38hw-PW zY>=LSs|?q1aRjkIv6GJ7Oz+Ev7(3pU?)7&ejS}O6{Q`h z4L9E2pQ5tMUn80;yr`9$cOc-|Df!&IWAR*LLzpaY-QN`y>bY`mwZURav;tpDLMn zHL|=ARtn#vUa0!RL$ zI|^zt?`hsf6UN+6(ClUi6I-COrXoM4q4$SXOWl>9T5JUrj-Oq&;(#u)gCzw>xH!Y9 z^LZ)~T#xpnP?CXUT8ztyc@Xy<;FEhX0ER@S#KGMsZBEudBY>X*kA{RkazWPxG%QQf zcZ3!$hvV2QI-n7Q*^N~`GvAf;g5UsS%%yD%HAI9hRBJ^2e%hj@E&Xx%`KlYFKj_DgCimnMr!kCoM`b!cmwM` zOI~B7|AsX1!jk1jj4ZF^?_5bJ@-0!~PsDDkz}&OZzlnLW=U~)Z5L>od3_~D3UBR5vB(LPmyGkbP%tN>l-oP`}jE>RwL;x$k1(8CyV@9vEm2DtQN z1Yre&Bb`bF^R>a6x}_6$*y=U8v*T?gmzdidh%rv>k%sL!vT?)YM))54Ih?l?9{Z?7 zNv=X)g+%D->~qV@oM@0KwmoXNu+vW!mS(=L`AGc>A?rjRrIp={#QW}2nJ8n-SN{V) zpd2L(cd*(gbWH{0V|YfT^Yp&aEAU6n7I`BDGg#X~Z0$v0+AnWoazXoFgMqJX^*K_L zuiMU*BvN;R+_{4bDKd@OU;TKw6cwrK{EV<#vO9iM<5*WMV?VMuC=LAV8-WPuzD0MG z#68yc={R0Tb#i2tZX$dY5z+9-jO7R5kuwD@k6h&0BkEH_F!t*>mD@`d@4~~UHnVuV})?WcO1&%fk37DfBwz=$ugW?-d{?qGbZ{LXfb6K68wY|l{PuIG*G zUuRN;&Q-%D;TZhmx|@Jsbd7jhT%EoMx05CcAz7Wezr)er#y!UlJyTVDxFnCxYXFAE zw&-n95m~uikA;`lK{8o63sIqw8RNmu`bxoW?}}DAl*QuxTJ4YeoT^~AMbghp6ce$E zdVd49!1NoF@wb;FPtWO$8QMCU#07jS;m`V%$EEkc5(G9{1$5P*y>g)#wID%-j7hbi zPRa9Y>f&?C?YuP9mZNZsK2ZS#YBLznKze=smT!J(|KaB238&{+x7lkDR~PD%i?| zy_YvA-oxWuzr3+UZZ#hGg{*&a3q`?=y88<5F+Zxbn8QjMW2NZu{toPac(>*XetUj{ z`$YkOpufDZ5MDNN^LT_bHsX$-S#gcubye@)3||*-Kc##If7a^-iIRDEg00d7`qof= z49cq9T8Sbu7Mf6FJy2;Z!tT4we|Cwl0fhyiq+i?iSg&IZ$^3j`vCL?Z^_iELB)x+P^MqF< z_m^^ij3;ef0D;i*qdPwrV7Jbv@UThZDxpO`0Di?cWP%wgE{M`dnC}i#cvm^Iio*`1 z5YY9?eu8k!*UB~xRP=-s$Hn~;D9>*fpNKP{9q|}xZlzV1`5!9O|v(Vl< zcj=z)4wfeIMYgGPr?cPIRjz~z$0eyeeF+9hV%ZI`=(??(5&WzVGyw+|SJy5plAA7E< z6A8=B`Zh;g{c$?NKqor8ULnyzk_+o+aLm+0XTol|+UnZ9xb8X+SLmg!W*#|m;;y7| zR4cpBevf{=J!~gQb@WG^#YR2yqWz3uQp95w#=ZuSDM)7=n;1N6l0}1cm zaS+^(Q+~m(w^DPAD<58J8@xNg-)B3)_zb!*fm5~>3i!LcANM+d1y*5scn`q7@PQ9u z`FzOm*T54@B>5`9IGPAOBE99?YR})SDhDjhXF@cOpCr5-ND1rv_E_` zurqTxTNbB??)S~;^Nx!@L#|IpZBxQGLqqLx4mW){C1f>XRsC+3A~`xR8aZ|VWSc0O z#WK$*DSrd!t#e$cqMj?hGi4uM8g|!{bO30;YNe5xy;@SX4|j`WMu2ef+iX8P(wII% zW(q0f@L0{#3R(UsK@Gzt8{ZD|qOe@;C{!)TlQsCOt6-X%n3&Ptru1a$-9iv6xf$u& zntXNvom))G9oKg2w$W#I$lM@OMz^WiE&!WIgsqKFy2SOj?`!Ftf^Jh|Y@Fj4x<(b3?BF|tenkBw z>}Qn!;I%R7TjAorjF*M~AIE^FRRAA$1VEH!`J9g`LW@jvJ_{B7h|{GMFQ&~a8O`Up zyfE9{`crM^7#zG6dS`g2ULN}PhnNZvjSNJh{Gt(<4eG}~e2KxhU$>i$%;==WP z5XH+ag#I3_%WCJ`Qzhj<%!Pq{zf>ox-!^F&HGy}3Ft!A!pH9KGu^lWIBmg$Zd8C{4 z+ZJT?eP>4VN&5MM{wGmPmg0BP%L}svl^D5AK98Iyc#Z*0_IY(xf#oNuHVV6kvGFGd}$E;5YKPg)g zErHAYbHKTn5Ul%P(Y9HV8Zj_j4p%;!0z&dc=|wA&27U{>gzyU5^@{%#Qc#zo$JHkH zoAp+h#V}4X9v%JImZ{~{()e&YJh9MnU2>k#;lXsWak? zRRz4A-#=Uer_IGEiRU)^XgM9 z4ENT$oTA5=yAb6W55#jM-05$@Jd4~584xD#=l|NFzsM22TxU|X5i9IIC-H#27AK$7VYIY9(&}2%9;y05|@+4*%f=|ZPQop#}Bxp^2sahB3p3og{p*;<9`AnK=q3G z%LD14!`p*~#fIE&iGXmE>YXFyK@!LlQn5xXC!-Nt?6=l&<+q1739a^KWu3KGbib+I zF2NM1T=^|yX|Sv4f|4vrkmSxcLQ*5Xc+WCpv|E|RzF%cE^dRp{>cITCzs*|ulQ<`+ zJo*9d?6h*Od?6+~#1aGjEiip$)Y11E{7e)QD716BRVX-`lPZ^(9Od>=jx5v8cU8!em1twPR>*R%EO*%FtS6^DT2+HwRD1sC z=in_K6QlmCaM1s0zy*w7!75|_tQ?%Kx~6%Xrfw}}V!g&0=c~FhbUj*RF_pTVK7EUW z?}X!&R2)oUN1>1S)gSTwe~?ja%smGN!X>)8PL8yVbU9wK)O@H#LjjPIkxtlp#7qVe zspmJGe^e+v`N;2pGNP8BOmvDt=cr7f6gP~gw3Zjrt1uIeZP_tm4i3~PC23=G?CA5( z>uDl*CMx1;s<|DHNlKE|UDI#C!bJ+P3XY&%l}J=(8eP=n(X@34(?9h82n-SfdC32e z5~B#J;Eu;9AeFs?rR#(v8PW@Jcj4cq7H#;86rEI>7Rnej!*%JRaIX67@q&F3G3+FV|TYT{SMF4e1n zI8D!m9fWyAPW5k>uEMBbA)C^zvLA%x8nEccioi6XDU8*a`&AdgM&sh)QbFd zu?K-KSPgP>S%OO}pMHOjS>Rhyz+~^+PPPR4)ccOi?D~1fb32tO;WLdJbzh3Iq1wPw z=ku_-)bpZp2+f~)gqS!gfhV*309By4r~kz-Ze%39^k214{8#NQ%$i`lQREayTpX>r zX19)ilGCrW&*9TcKQITr%KtvUFxOd%J-EQ*k|gc7yb7g;#|A%s5KeM-pqu$D1I^9$ zu{_A)<7oIN-RJgv_-zdNH=Xs4-OzN6RtaG)Jr_9GpGvGFzh<0XFQLLg(d|Y3=>&Vf zi1w0@5-h~j-WRl!9Y=y!*CNGLYWN_NwveB^;_lns`q`y=I>NnG7I`*4eyt%$lG2ci`C;@fMkOnh`Wy?oDccBco>w z&;Te37z%tr<8;CoLz5th%9Y}-Ya5{=v5 z(gzC<{ZrsakA07;rv%|&fN1+tL!WNjj`b|ejJ!EHgoRmCOv6xLw%RSztfi6$#JrPy za-1st`JE#=_S6!#47l_R*h40MIdBly+IIgLHR(+x!1$h+d%9K?b(L}VOJO#r$9i1% zzBAb|%XrD7w-#`T1^PVg&kzX53xot(K)?s~!Z^gpyQ~>s!nUfY&jwT=Q}D7~+graR zOLP(gH84zhD^M1lf^&3Gy0@HbE}j?HW481ggPn~s41wCXFVzHayqC@ zDUcj_uU)SpL4Vp^H{oGDJtLBZI-?ziN6|l6@e@NX#+U3u1mK-(m>Ct$zK%%mVyMhS z3d_j6qh-|u;^^u13`TF&Gaga-_JJ`rTOFo2CDJnqO7&`x$B4A2f|X(d832ho4m!=H zF8W$TW94+f+y%J4II<&B#~Smvg_ftuNsA zY0z&+oh$nSx&)@U+CW^*g%qt2C92{@5AyZgtjWG%ld$|tumvTXKi|9;J-9R~6PDE2 zYTS|EY>IpqQ_oP{oektyj7|G4`Ddgi!N;^J{BMOhaVX1-GF}+w1sV}En+t!P&)XY0 zQsJ57jwWz7?K7r~-Mamr0l*YMDH+j4&G=2C>~m2m-I_JU9{%cGNHealOrVJ}Nt>nG z7^#9Cnz_@wqN40n-`3~XNU+1E7Awej%95N0uM?5pYB`o20Lha;fI!3V&-tWSQPg%S zisYO4d%eG>&GI~qwlffM@r^zljWYTP^G> zTF)tGUrYmCee?ODSu}EYIkPJBP7+2P$q?4vzr8bs97752t0Vgi29tL-#MlpzlKIfK zdl1kB#pZ}c4;p^H28xC3M8VuwA$g1MGuAX5&K5K9V^m|GuHg6JTL+qK;4I4Z zytZ%PJMSba-zQ+O5{vIC-Zw=y!7H0B9{w+sssXlMpFCfa9{8=()x~)oXpf2YOn%in? z(-GnUY11tKo=jCpguRF%%*Dd^X{4Pc0MW=h686wLk+|O5`)$TvefxT~2=mXdG)*Om z-ei@Zz^Km_E7&S)AHmMBro1SN8T+Hrp{>p&B=Lvxks#(0T=8Plr(Pvy!qGCur6fiM zW$U0^aMmI<7o1Ms7Oy~H^ns+embVL7H#PoZ)plteV{&Xjy9_pOr7=QdS$WX|!xQbH z3rXpJN8YC}S2Jp*a$I(vlcIy-ru#)g%sm%@iqRhBg3htMJi^XOy=;JyI1Dr3Nt#-p z3;`689x)HxL)OK+9#CL{H8IS~pv;c&@k9Y$cHJlP{)9azI4&xZViy&FytWE}f$qkf zEXSmI7MSmSi+&6YRMErB9s~wvZ_1?^#YuA!xrsNOUoeDGaQ{Hu0r>yK6JD-d7bDhC z+#(6cJfZ9fx#vg1vH&u_r;2ARF|b!hK$B7aaxH?P_9)zZDslZ;Q98d{!hcqOL5gft zE0<@W91`F;igMGxC9Fmf+cZ_~W?UsTY`$A;Joaa^;ElgjnnEyl( zp8aNNS8SKYPeZ+tT1VZC)-5?_HJa|`Aq@Pb&}*#3i1W){wL+JEy6_hU+2z^Ha_e+( zvkWDi98w(i4497M3g>vYA-0Y}XVpCJAwJ`lHZv`Dc16Gt?I02!gXY5x6-Mr@Oz z7$(XVHld)SfJ8Dd{gnMN2wb{1FaB`-br7q$T+a^;GEjYZ^^POe_$X~tG{sDRToKNa zhpey%>|?USyoH~)%Ym+dqIo_l2u9C+3mF7UuGhtx`;ccJT7U3k|Ivxzk$P;4J{|)= z3##6s@0w35m`y!;=#3@6?u_H1B#q0^AWX>#B@EoqATFI0dcOQNdP4Q0z?m@apygB$ zv29los5VW;syd*vo%`k8Hxis55!r{H2tLNxEk8n$XZH=Iaw#D&FlmnXx$FjiNooQP z_&{{czjYKV-5H>r@jzy@7bWsNY`>~h3ha-5y~q+gm&PcU_&i+lMWfPuk)d_l&^O>4 z;8?qGeXdQrLH7h{Pul4fBlBCM)D>u3d_Zdb50kLavye+zZ0`ID0BN6lg>mZHzaD8+ z;MddPlCH=vD)w?Xz0ZjkFG#B2eW3V?BaemY8`{)q(IP{o<6^nnx03k`>Sdv4;=y=@ z8!K}BL4ORViM%x7C!ZzK-3>Xh8O3RP0@n>~sI=`zNFU!2{u`A}**&89|G~@l|5>)f z0{q~(aarhBoRCSN{R+_D-u;vUMTHGg5&0PO8J-6Z2flZovrS=0F@Zf1NBmCI7X_b! z_P>dpm#)>-we2CxaUwhYGB=jxgO9ekr>8d(=i>|oNsMm#=h7YWPgYIEo)ZhNee5 zOCM+`um|XZn%dk?`+5uDh?qf#WE+F^LDYKq?wo|$zmTE6lb!hb97_kW1e)}Y3w8A4 zb1~@)#_4EQj+GyFfX-i+2X)7yUeh1~&b`1g4fl<;`lzv?k${Fc?+7h^i8nq;b z9ITuDiiBd;%uWAD9w~IADnlhXWZi3?w8GoYB*FOit-LSP2tlX9D~TTRO18-Dt=HV& z5Fibw!s;9P$_ITY+I2Q~ft#NJm*DyRtlhj-QklCggOWdA-8O!K7n3b5|5FgIlR>Ly zAS-9Ovs4PIVPL|7NS4}!~7lW;r>a!$6st#Vv@2gRt~;905Zq&@T-tB6ZYG)Wjd5J>u%xm_n$+I zJ2OXuZ6P5{_ctoHu4DF9FM@<^7bxN_#KrN#xA3-WKmYj}8cukr1f!_@3IKr&H_vMH zgyuL8PXWArI=i5Nzb0wmA2K{pjpvudD>iS()-Pv33a2XlFJ~k>`L^c_!VYZUIu@p3o%L-?zLw}kmZAL(kg>hsQ~Vp0E2&-Y&up@~)?>JJ z7IY&AM9-jVG0zsbCuVrx89fzSJ_5>K{!ch~qEy0p z|3}-h{?E)n1Sx@)6_i%LV)%W-k{45zwtj-SfTxHW7$S#PFBjVv*JzTy>oicxqB?bN zw3W)M_#5{Yki(bnvNaq)rr~ZE;C)1D!Fk!`#UT(2zPNxnGtu8V{PSmV`hhjxMwS~D zU5pE@MNDIl!``eMg=k+wHcEh&JJ=n&Nnk;*IgOc?(t}db# zfLhvG&mwRY^Ck+Ton6jDZLlIfOgn6lo&lAc9kP-ky+Uytmi8vEy}TPHPp~|I#385Q zQH1xGTtIWh7^&v8&LA=ZtnGWsmbXfzucv8BAta4n-meB<=f<3Tq4Pf)w$?~D zOrAX1|NP-yw5(3m+ZBzVf)yY$P6kg9ZQX@Yf*?E!6!<-54$xz~O8?&uLYLJ9@$ zWAoeP{@OCu0WSToLtGNYVwl$Xs*y1=sS9H}#vWZn&q&c-O1DOUaess3Gy^0VfN}Ng z=Xt?+9CgXzue2atX9C};PFm?6oZ@MUij!WC#$x7OF7a_9^TRfs?e!|< zxwHr_-bJRazb{im-+S4A5 zQky3?T*aU!TGCAn(=10dp!CrC`3h3)wvjDLsDf3qkEnxaV#)Rszf8AJJHERaM`8F& zj?~64iG8yuwI@GI$WArri$#zMQc1XF_umXuwTk^2GWM9xT{-nrFCH((1$z8V%6*(! z=x4=NkX}w=^X^yXS|8S^+Ui=aQmSHzU3_=iZ$1=EZrppV%IX>FS=D8;NE$IYC|`?(0;`>ZK(#$wi;0RyofYC2F?TPIl#A=DAU z)rHCKm17~9sxL-NT@|BTYw7fjr7=ig$<`GA1^HCTycB2xf~d7JgS`}#OOkJ^*P7vz zw+6TI*ZzL2Ec@2_`m>YahO4)%r{R_06B&*cY*Rte750BMmnAWi5%VuLr2oYR5rm!? zYmAt9sezaXRb&IJIL>O~yfIs!EV#F7@cR)p+eWN=vTuWGrIKDy*b?0FG{l$T&(>4Q+6YVYpy*$-L4adFGGeb z2C%%*H9*q!juy=})8^JDI^R`2_Nrz+TV2tXLvKMBxE}Bvs-39wKfx6wnn^;MQW;ar z4Q(aLkh8xCF36b~V!(_!x7FLax7=Z)G?f z*Gg-U{w?iilHD}VC0YR6QS|4Ol-3jPzYB1C9Akz^mfD)a-$BIv^$0%Z3nf(j74G97vxZSt zvspx9QWbK1;g5fNl9ek!LUhj#7@_Y*AGwaD0F{z|vON5Fo)fmU-@d@(E)b|b^|c46 zn7LU2Iaq_Yjf>bEz7ElhjuEo57IcCDIxnc-zU+Wih?zaC(E2Q-54ALrPlHl3q)8#u z9;WRRg)xvq@%jB0+(u1?Il$gkd5meArt>1t)$-||YjAWcCY={omeJJnTI7IDX2kF! z@}CDb4LC0xH{Tcv==S@W4wO+rO2U`^McrSC)JBrKAHD91No8HmiBI%4g(l1l&76cP zivpbR_eM&&6xSwTdsv`f_e{z`%hzueOURvt)3=wkttFUwa)AR^k9rjRHSuW-4u zhjzfh5qWH=GFsx{bU=+MJTTm3Si8h1Jk+MucKivQtzhd@MQ~U7aK@rP)QOF!D@Xuk zvTTwr>nk>XGGe$;4H$Qva%Azi{=Ttb6 zL1vHf4I|rX;MbK*clMnj5E*q2jhxlAphTw`*|5EAnh<7q`tx$i^I=!p$g`t6N3Lf9 zdCilYSZ&NoQYF$B@~vE#`+;duMqN)$Sr7S}lag}%@2+653f>?}jplWueEe!onC-l3 zLEld#h9h!hwL}Z!z*_dMZ-$l2-0+?3N>T6_rDl9$(qnWgZW7Y5t+Y9cij=cRYL!-w zeMW#$PzyCGo8xjI`SGY~1!bFcuqX03z5u-o25rHVV!adGd2^!B`3DvtxW>^Tv1Ls`S(ytIai`cId#e~W*_ga zQG^f2toC%EHs4qFCLC>qJT%%X#8_h$*4J&F>v0Jy`R!{xb)d*o7nCf6MU8FOP6BxGn zrwhFgNs_PSjXXOv|K5*E@{P_1#R`vCr1e$?0_r(Oga&UpJI+tPAv>5DNQfW=26ce; zb)NIsB&pG-m4a0uf=WvEca?dW3qE(;;^0erH!YJV)Vmme$vwEhpCU(%K{`^OR*soX z-2s06;U2VuH||;GiSNSX^+-Y@&vtOr{8(^wx+lQ*KsTc9FNra~%o47>(;5W3w4kZ9?vPxK)1yAgl<=Rm%qkBi|< zx_a}xJnBq}bC?ckMUh9*`KbAWMp3cqYiBT~SCBuAnEL{AA1$@ZiLN27`Tba(VB@Q3H(R5rO5IAEcUzB zUWEn_7gIG7gaL(Zk5kiOH%OM>c>n5x?@X+SPjOR5mt0bApBf5J(j09qr@-k(Pq)&j zzPnK70C=d7sV-$gSQvCNR$m+jGiZ9|{AfQBL^{OFu)P`Xz;PYMG~kYjWCw?Gc(Tl>*3+xpE>x)qZiKj0P3^A^rocgr_Z1D=g$nyZ^acY*y zk%_Sn33`$Ibu~H0%Z!^^4)`<)7!=_Cw)u%6KW&D4ZX=RqyJKUyy+ge=wB$X9Uy>}8 zdWt^bU4}A6ZRjj6A2}1^=`eo}o;*>Hm*O;bAdOSdYq3_=7<_g`>F=s4G1S()2>KL> z*BkxQ@5(s*(Z<;7O(a1V+{X=>M@iq^n?+-3HZ4UrV8qj1_0^6*>DLl~QYEbh*$CP@ zB?xnObJ?S+IFze&Y(7rWB}_*%Be#|VZiGQiTq~tTs@6xR)?-f$q3n-0&PYOlNLp&+ z6EzuR*_tqQpdV#IS%=%~jd2Uerw(+wfJ##{JabwnRe3gEO}hY&LuYaRe(7rBr=LNT z#25i0Hqw^wCxKuo&4~Jj@wuI7m!CX^y9y^YzekT>`{~h=nY2Exc`IcQXYH*H6$nyw zG8&6$K+!^0Y~-8W_=T6TC)N_fGj>xU*e6tUz8LTo`3tWu* zN`+^uBG1L&fd{lX*z*%!n69uTZ2Q5Tz{|eEXGZHIJp==GOmnB>uS;?gD9`HZ_{OHt z9&AF|8PA;CM$BZ*g^4}zZozVavnU>JG-Cqjg)L|A(Xn`<({>zK4GwEj!!L8t_uLie zAB654x|IIv4_|2%T@Ur(hree=Xd!Vyzo5>1jJD2@0BYil61TH#MEZ2L!d;rSx<4%B zR5w>=yX1mpWcT&Ey4LH@!Cv1#m}OrW=}enxaCjvVrVwXex6x*5bH|#QBzUZ#C7aIC zp}K!&x)0uS@Ug+NE0O(_ILmpXf9X8rDn0dOA4vtzcO2 z$F9LztUPyvSb?-yQKaL_Q7;mE^XJ0gPvtZymdoOhiuVM*dv4VSI>EgGPSTPY3WgS2 zl?)oXIwgLR?!?(TI`kUm&-Rmo)=xL6!fAQZ+`L%Q)0S5{&eduF{Ba?z{iv1MJw}Hw zUCY>IOo>!SK28JalS}~MPX$tVZ!o@eFv}v?T3P^>#5hR_=bI2v=1-d9v_K> z9xGhwnxej$2s5(mEebIS3x?N3-n}CPF>*(R3?_t6{iqlaTg8#98&vC@Pv;xp>yc11 zi11_@f?=vC0q&Ce()2uy+lXRy%Q1yz7@{YG$$6^I?xgj-#=X`9D6)HEOS>LP{eL-u zszH%9bjsQ#f)%o z$^vWeSEp&G=0O?yKV$+_l4Xa-d)c|>pJJ5nw|9D3>XUH^Wpci}MNlKI1FU5ee6EPV zvPNPSc;G`udP%q8AdxT~sPIAACvXAHFJ1IE`3I@wWo7fxc@2w(SHr}I<6c9$LIn3O z<=U?76<^=*hs)CW?j0XHq@%!7#Ot!*OdGU!+^4cMpIWCGF1#uWz2pmM3Q^2W3W{pj z*_M~%4rGaDe5GoGHRX^@AMuS}l;s7%Ut7Nuj!~Q^wz39ksI?~L7djww0X&R3{5}#W z7La2dXZ3kQ0Nm~h#vD)rPwhh$#_|?63XcVZQ;t@bhv|k=n^@7m({?dTI_9=AZOWQD zM9Uo>SX%QWLkrKlR@sC1(mv~y-{(n(xPHbIehIRrvAd8s8g$pW_=bor)oDWr-VTe4 z69o$tcEwKs9F`J#d!Z|*7C4_r%hQJ z>Sk#(2YbWvYw#t?iY~c6j$QG0ZeWh0CB(`iGB*vZSw!-M3sC5D zzm*Vg?D0oee0Uw6ZRNmP;|Xsub1G}33+jN~3jq-jAM+zC=_6cTAm;?w26jKcUM{Eh zzQq2Ls&9T4N$Zt*C9}ouv1L0B6@Ax%Xd~#wj#tzl^Ge00MdD*_ zkpb>-S$qX$zu&i8+JBc@A_1g+)H9~r zLi4eK7E`%ztCkC&{XYP@Kt;cQE>Lm;|IAfYG5r>y_}@@V2M8Dhunc7h00RIj5|aUo zGn1ELD1Si|Jwq$qexO)UP*h}9C<)t*;zLDZf>Pk22Gd#-pPK3J?RM#YWp=lQ82KUo z3uA&t6Muj|%6PYEjN*eYGjq?JbMLu#=G*trUjf|5iom<$<96eX-j~*h0$bnIt%1I- zTcIDho=n^@F#OOa#ua%aW8%x9j16l@)+kQ>SbyIfNH3;!J#q|RMuwZ^p#H-Lc7KDp zs_{!dNIj2%cqol~86|MsfJnK4!|0e)%(WPA)Hmu4!=|zRR)Y{Ib;49xwCj2#uo^1I zbd^;059L^zo(vrGpnphKQoyvp!cKE{yW4uv z+kb0s@3fk|Zl~Gq?H@dA3RGLa6`dq=_DDe6vOG6%lg9$N+S*Hj`M*g|QrELd6;KhF z-kNYLIFE7(Gq@m7Oxap}$lf$u{KHk}C{D;P;F3Vuq2##=xu4`nV5N4}$=X?{g3Gv4 z!W`zga5jv<7BK!x`_nV0xQc6;(M9gmtYx2$R>KXBlJJx&FjxC$@g>~Kl*<)pC>C)J zw*~S~`LXlM92EG23C_-Ulaq!L%Dms@Xcbd@0v5ku=G8~cR;!<|aDwaAo4lMr|A0I1 zfr%`~>lAW708mQ@2tjif3E2Sv0I~v;0cBHvrCAAl8|9UMZ*r8mn`dMz!bEwp6+-;88iwj9#m=9gqf-}m18-hF)Y%=-^NN<_<~UZ&fxymIS* z%FC;|wa8vQ8LbLdMS7}gt0G3CKNiLg8rf8TL|+$+>r4xcRBwH6N{hzz`u!=bzh6()uQz{g zw|=#2v7}6PrkR&$`?UJFmh7$H+=G%4j;%{1d}}$~2Q{ z8V+iPvMh<2PMdVZ*e-~dlSidlRKYZ7Dkzy|GnIjC$cUK6gklOrlX|AUYikIE=8#vV zQ|MGC_xK%|PGfRpjIOP1lhE3LHlI#cX&(8C(b{CHVshckPWVUyVpJ4R$7|b73u%!` z3+O|zN)L>ykiW=k7Mx5=n4J25rCInGQ>8yN(X6YhcetsR0xH!|9c*QB5;N)r&H61` zrVmCulgS2#;6MIiAqp~$hX-rR=q#0%(%DSqllNs>4wf>8<&mR$0f<-u_DWh+Mk^>- z&`W+trgNEO;Y%RmrZtxM=YiI_v1BZ>W`cO5Ug@SrYEr3znk}_%(NcPUGUKLJL7;)w zSwuUugzlyd)*9^P+*NmpmRhLLCOAM{f672`WMX<+p?2_<();6@2&z;XT3K1*+!CCW zGU8_1A~b(K)8dmOVv5r#nA~PLyd{oMkee=`Rbpp5lW$z0N8&NKbRwZ8qamaWAf)w_ zOko(+Z_(SS(hk}M>ud3UxUs)0xi@L-Pj2oP4iB$kc*sSx#|4;+@vB#%ZrIHt9>{`L zpwCFa|Dw>E(Qie`ijo;3G&NV&Y0yXy^$KqKPAG!~Ez>2ig_i2gCZK|C1O4!)S)mCj z2qfc_aM4}@TYRZP{RqlSvoSrRPzoz83c-YB>49`cPXvUa723ytG~FbV&BWsMp;#K( z?*N4A)H6N{(3kg!0iV(1%k=5KjTf~0{CZt)oiEUm7!bP+iGh7uJgZmNDRdc5i0bJ` zDwfwzc`0YOf<7$xys{9-=IM>8ls14E{1<3fOAB6@78Pl?5XhlomO=0u`iM$b(?=)k z(sY98IE~8mF(_|;jKT&j-3M`Hx(-?0vTC|%z+x4S5-Nsl*ZOhX$LSNoN&a;bA#BU^ zZxFy#2wZB8e>}I%Mm%mMa}c?SZdU0=`gbO;zch^Hv$v{rJ$+KtqR=F+^B|v6>00_U z)AA1rhJ{UfkCC#%xij0H-vW+xkIJT(0>$?qG`LfjGofE zMRNO3CM70*WsH=NYP^El^6OB~=jqNe`W$_sK&5D3rY|9zp}pwP4`j^nM(7UGU1juT z`U>hq(p)aCCwcF2(^u&p0rxeg+7Hy1_2|rK8E}3t{57EsbnEz?%52Vic*$f8cJ8MK zRJxBIWRe1Z0fmk*1wQb&#vTZm&qp#1i2yiRoj;_~Fg*;d1OhuRYS>+)&^PcSp=D59 z({6fHa8pA^Q5w?O?sVS0EB$RHv-LOWaRL1;WL_g#B<+rqECC-Vszq>|esS!#>6lR2 zlT6G0d3>3kMmEc{EBvA{1qsjep9C+(TzrR~Rp}Xj`Yx#X&r4V5_1RFjM4{)P(pWO8 zAK2UjFN5;h-1L2VLFnoS!k62oQs)l^$bX?pHIj|_G|tpi%5(l%ZeOC81-GxDK$zSL zW=&pSMfO^Vx**Cq+^Hp&7V#H#(@(7u_cNsGJVs!*K=?(WKQ#GiEMT^#QX=4frP6Dn zbe2VbjARClXnK=A;HK9_Lv2onE`{E;!NO*j2fG%|0}pI|KX2uOx3J--VU_0U3>Chmr4p3*2;EX!t$|K{HJ{1#`3}qi&W&PjMgH zid#~%bjs|=cP^t%)x?4@wzJyJGAk-O*(DSTMW1^z-Z3c~jI|f+MpfWxOdmQq9GPbz zA%rFriD$WZCYKi)=VAbvD^#u&xtbdkK4prWC}M>%K-4e>2vQhBgRMV1v8~L1 zr|Buneo-#x`Ha!xM#gASQA(>aW5jUckj8i%g=BmM6_p&BlNa(Ll@~Cki|PF-Jq^zp z?FT0oe^GGV?B{A16pL{~DTIQX&B5Y&4v74aZcX%O2Hac^|Km!=Okq#QF4Nt-3=W2c zvnJ);(bBYx&k+!q8%`frI?)jHYH>4v;9Czw^t`oJGR?JE^`Q{@64`hr1{e2Ptw){0 zL6ujDfIB@86*csG|qKq=31AhsEVCm3Q)P zG5H=q9KsRzh@{uRm|v<&kjP(uezYFYBU#Z#aW{NlB%8%0wK6eBS!e1hM;P_b3HR@b zp~e+OpAq>JqqZmhuh= zba?)$C6L>a=?n%_nJ+J%V+#A?K0uV^M7QZ|A4X`GG~1|?nI~SQ@|BFCYWE2lK7lbx zZWi&9Kj|8kui%fM5sAh`gV~+6TE^)U?t}Ose@vL=S{SKb;p>qUFu!KntiH<4pRkGq zrYlBn!ZanPwI01I6=RxzKgG4oDCwK{W}#pVRnsy?V`p<)TfR}?Tg__}#vo;DZ#hTd zPr(C=Z^PR4bXx1xTVlPsC~1eRWMvv9DQ?-8PMxeu(*Qr8;X72moiPhJy0)zgtW;Qx zKOoyQkP+TDyA;ixO>X`?-zk)UlIqO%N0IqK!N0RfRID%Ymj%s#!9vYLkKb3{6zgqE zW^^+_U;=VRO%6n+Fv)$D?-4kdd7S<>lML*2ugZ7xeWHhYT)aIX8Y$$0nd8mZq@_{0 zj)<&oa1OTEvUT&u*5+*r4^MzJZ>#uW3vvXIm&N)m>_@D%N3Asr?lEian}`JcKqQ_` z$M%_5w~dhqRM@V6C80&cZNqrqi$TCtQj1$xY;hy97wW2Soe~}T{}w;tf>VB*>9nZ> zZsAgyF>|C&7)-^URw^X&)JpD^%!ZZ~o>uuOe#Y_&^CAZ|q-b!>-|q0U{9Tn~{vM24 z7mw^!_<2|}u{Vlg-pwyqc^^|qSq!~?3jKtULKE^sYaOG1$Ejl!w`P+WBvEvuro<%F0^BfeWQY!hjf3D%0ZA4;<`3rik5B{ZpSO`K4-sj*(?P zELN9qjN@818Rm4XsRB}YWWqFXvo1Vn|jmZ^0tb;iZ_Gu^x?x76w@sM)u%ajP$X zmMkofFP*-{i_(kh6bVz46FC+IeFCo~^izV@!n7o{NUdldq;)6;`F>d3-Ye1u@u{%H z71g*q7HK280BI9by$`+zzN5bVS}X$~Gy9L$YM*9iFki+ni$M_7F>^UZ!58lsw90(3 zv@dIYVo{{?arBs$FtGMP7Z}Wa)>R~bgzvhoKgoClakOL7!T_`cq1x&U1>gpRC z^{fgd)H*iynj;bp!g#f&8MzKiQA~}gL@cTMBEsGJQNT7?)*(|S!Ia2VCC7sCi4&KU$l-cEu9L>m4 zWsc_N=!|eEM~lm=b5wswezj(p&UuJdGld4JeESGBgxhO!w04MEYC}tE3cuIm-^TJ# zc}I@64pCQ*F0}rJMrcQP*RGC#A=+&}LYm_dstJc}<&jQ%x!#$hSb5D6G777gVl^#R zw-;8jSlKUD!sP=1EWi8+T{TPxN9fvc&^|)fhXaS{h8*28M7Ismp%MB_IOqs??L+k0 zhvv+4;{EGPkAZYh&e7pR{3Wkko)coytPvUpu0S1s89e?h)*s2y zV~5BKG#Scy!Yl8|(Nj74UeGak{2uH-Z|>KL{h19pdU3e`tOV$fEYM1a{bKX&i5&e{ zAngazPfR4AK(dd4dS&Mr*p>(A=eN@w0RPeib`Db62)z~_qW?Y`02&~J3Z(WbIeOy| zRR~(*y};YdK%REcC7@h?Ce%l~juCn@>~-xa|LqX{E=O!?)h7Yj)%6;srpVv<#g$Xd+28w7|~34*}j@uRSl zR?O_X;*`jgeB}X}1V)Zoyf63K!4%tvS?w618^QSymz8I8JpC|#dvZK`%-YmeWNQ!4 z$?@Fqa^()1CFps0UXIV$K6v~EuPKUGwpA)Z8rgnv-qhyygI;?$AdXyI9ua!t>Dv!; zjaaBVM4etZU_;PR9>IDz=rnm)YQIMKg!SWW`xodG;dc0C%kc^@gQyuKeS}wqJ-m8| z&pm3rt`V;faPxM554R3;8_qgLl_Intk^?wiC*-Gqhc^v##}vCW%oPWyh|mm##m^cK zZyDmwVGctEvEX$St?d{K_IL$)VJI1&!mj_`u;5J!i&_b~5m zAK?VR1GR@a4NDC3{yjr{*$7_|Zb#&e@RcCxs2Sp`14I0OQNV{g4)b+_KCK1A9{zZa zZwN1!?+}hX-RrEhbS`Y?;TsEkDrAxeX`0t*tCUU41i~OQ%(vwDwxHtSPY?5F!$Fr9 zub<2D7jt~q2;U7qvM*P1{Pju&Jl#KYVU8a(-Al&L!*DKfI=!{WaJ;bI?Ue~r6nRm5Q9zyHP>N28V;%jYA&xM zB&1Xe#1_|jT{YtfJzh*G|LPp2d6?nY13V=-l!Xs^4G9+z3I*#L7a2zghJVBD3g>@4dm=_(T3Umz9 z6}NOT&83Cpm%8ou+KGoR~! zoNdlNJVVaS=5w3#BJ@%NNI}gfDcph}#WWwL#yiGjiCb`{wZjn39XP4Y-J};54 z5l{3nJ@~JVHkrN6Dw1dm*=PsZNk`8UBPR`@^SKH=&&}v{?j)5^PU$P;rh8}_-AmKy zIhsK)&`efo7MD}G^fmHG4^xG7lq#iv$7!~09-U(I(Hz?%^4hBDRNHczYip*{Y+Goa zt&is0l61Q5qvW$)M`zf6KvlMPXo1~E3+*y3vd^Fo*~@9M-A{gdEmhmkrX}_jRAX(AoBP=p6fdv>YS%3dcfP=?KtQD#w`= zbhOcG$7VX$k)Q_0K3d}#pz|D`rnQcHsnJqSlPlDjE+gAl(BAL7 za0)1h4#6P`sEC3hGSB&vtZA3c_4iB9J>TQJzVrRh`SyPN;KKkGid6#JFS~5bl1r+) z^w1_F9#IXntk;a{j%mgHF)M7)c*2Mpx^2*8k8b-zJw|Agos8Mlfo?r& z8}-$_5r0hY^_wii=vsP0xN8xuO)Sao?@mUeG+_7W{sp`w9x>yFkuc*C8r^IpY|=&J zOBxn6Eb)hp&DEEx5CU4el}v<;Rc6!>m}Vs+jgf>Njv9ZBeF?p{*GM$B#BE29M&~S0 zP#`dIqrO>hjOy`7;yU+V63COnc6Jaz5XtjQ6~5nHe{o*b}jg%hBI)c!12epNx@lUZF=DuR*V90HYa2oR*!;-_N}&K#1yQd$QcQ` z*X4)IUQJdyWUHaa$bz+4SA=$)OLx3mH=}>agmD(dL61<%l;%sA^AKch=Mz%o5vX7T zC0#EMLP8lA3wz$6~=H_%!RgG!N(!p4ZN?VIi?3jLF|NgR z1deez@Kwy_fg31}Q7aNLNYT`Mcc@iPlC~RhQxOIJ>*V!HP9I9Es&E!6s#JWFVWg8` zXS;y!h>{fCOpzg#UfjaVzlB>V;^~BxwXkGN3UI7$#~pm=-zM1QFFo zt`*sv;>Cj)W+@Mmw^^;HCA)vSjf4?iW9YJ8Jxu46ook8rCNpr7oqi-+>oNxCEK%@S zo`aHw(;LFFH!NNK<&uF92rL}MNeyZ6nhzm4sA=Dl$rmjhTZrXT@jKJ zZl%u8i|06GyYX{U8;V*sjr@X}f!+8ex!7zaqv5K!5OAwaLs2KxCV`KgjUe@qy{ANr!&tCeYmh<28&H0^xXi)JgIY%zr zRy;sPzLv!qxpQq#!s<)6nt$M$WH_19;l&#qg#-8_*=*Sjaq2)+{E13BXI8=@#~cE; z>BQyr=^+(8U;nhTe7)LUxw@5f#9CBUFC_l+7CWwi=vV?BgVbh8z z;}Gbkvx>_D^=K_#Q7$SpF-c6OYC@*vTr;}FIo)jT{qqW+sN_vkM-?&>8q*zzou96W z8M2?AYtN0Vg1&z|-Evl7S)Mdnf5e<0EtoV{i`gVw%wYvfM&$|RH(hH*98UnAd0nN4 z#&*-`QIa)J)M}ze)KM9s4v6}$WUu2DegXg*Z6Np=0RY=@s*Ej0DCzJGs-i0qGi`n? z+6)ME*~ENSOM)Gv&FGW8u2?AB3qh@R<%sq*$+%<2jMIO&gp6LoO8+IYNX>h1B#>WKlS=gx_NTQE!IQ zTTD`ViAjG-FE;=#T3?1q^x|GgTrKVQ5S>vQ+_1q{uoD$^J29nxCo26rG0j)F6Eg-e z>pt*b392zWy{~Ww=_Kjy>uQHFH`rP`fGH`=8%ABQwsR2mlAWKz38hW+FNLLpST=yl z6i(fS#dRq(Z$ks^si0qFFojh^XbqkQm_H7(gtbxSLc@Q;}avSIgCH(CYoZf)pnvcG| z&~bl-SM(oz)u#nipZWm4ERg=VUSJy*@z>V`9-)u~G_wC291x$@S-NcyJIKv+EK;~_ z2zPe$AAFkZ^9-Org?s!yWeE4OVFTnwKVI)BFY?@u=X}bO*jq1G1p|r{r*ME%806?a zkd?SApbkr|KGmoBGe_Z1ubiK=lFoqwGK_!S!416Q(cmy1CkqF$r}U{oJTr)AQ`i?! zQ+VE|29$oZalndvJg~bynDt2MEPatY8p10n>@WTOA-A&gYG>)|(&IM|O^JX~(4>|Z zxh@Pg72P5Nd{x@L}mkDGs)$A1{AM zmka%6!bN_Gwqa2a^z6d>!Jx0OGw3c8p7w$=p|%$`c~YXd+|$`UD8{EmDP>JcOxXsT z2Q-cPn=Ax``wb>Lya%f z0X!h-W7PC9-HT@>eHr^DeGLaBeUsV;rXN!6B}z3`lXM)FFQ%1ZmZa5Usic1=i#3wQ zM6Y;NoFXm~S4n!cxK`5Z#STet7DJLgB=$+VPdqOU0OCdQlH?DFx0t%Faoy-1Css&W zB${12T(?S|Df73v?vy-J=KEa(l4r{NpzA@&Gi834>k-K_W&SbO6Ow1j{8O%1B+r!j z{jN78&y@MMUGGYsDf92SK9GMrQ|3Q(7fPNf@$M3L1@n>;Pk?zkf#*h467UL~NdVjd zH`b$op8SRM&h+3)0^u8=;w}Q!kD!SaC?=5giU`Ju7{jjcTDj_l| ziCFECv3wTm&9%+7rWaDry&r)Ps9dC76VRd3B(Rj4$d8N+HTkzjW*Hg(II+3Zdht6S z6c;OFP+;;}_N1?668UGXYYOr*hS~3H{3wmtuX@sFRO%Q0yDYS&(p`T;r(~^+n3y{G zb-Bok+cGu0rxKO#3oI=EHTVzLF9k}=^-Bj1suh$m;a~)#qZmTXK?P$)H7ziBz^{aL zZp!>K1E>`gSG9uSEI1sD^E%7jJW3qE#LCsx3no{eG1Yj+%oET@OMQ#dCs0cV2&x2= zN@@WB0OtV!08mQ<1Qe49MHQ3lj4yu)cpJxcenS8RxPlInqGaf>*OX|1I7l59DM7Xz zUbZPhM?@WgC0kws3vwl3m)TuNqFpO#EB8vOwhN@KZhYr3tIMy&+WQ6lz=-MVSg zv}w{aZDTiW(<@Ey!%_Y>07#Go<+RnO53@7#X6DU%|NGw?zV@w8-Xx;!A}4?7@`VeB zcRkrUqNUI1W~MdKn$EVyTGLj3+{kIJVVUu~mC-S7>p5L>bWDzEPCPxPr_VTrywjS< zYB@)bwT_R*^V)da;63z_-S=ijc0ktNRau`c8r#n>=-3s{=x1A>3Xl+_3|oH%JFP!xn{ zhUhx|d^%TfjI&a&o^)Dwoc)@q$y4sHUTm1IZkt-JGYi4aoRvO<3wM7GEV&$;*WYKD zhPzkLqv6}=ds_`_O&-$Ru^z|K^CLMdZ$Bo;6K+2iq!qMEAwM+=+VlU=+fU63t)|8x z1!;K$`Djg$0@T1?cLYhHW&E`c?$qR}&0Du_6*OA&f@O#9NlIrLRwo};?n&1UyNsGW z?YCLHx!m?KOxd@iy4!!3(;P=obGW@~FFCj;NO#g*Yz0+Nu=-d(wZb9#dBbrXX|P9v zw3*rz+C=vVYLTJ^*T{ADS-BkW1`IoX3JYq`^W*MB66*vtRZf(WJca`!6ji95Vi3(? zgb%|Bjp6na^Y0y`4(jCdV6W!6U3zR=liT}gyFxqIeaj4|->`q7gk?_zX=h2xE@-V~ z0O^)+a$#`n;oIz@-Ml^_XvKUT{dAuozu^q@ z-O}c4Q8SkAsHWwrY0Gpq!&EhM0%9ed4BhEa2hNY9qi0mtQnQAcQT6j$+RaU<+h*k^ zIs())FO*CE_EUc!T#>cxyat=@4lf48i5fRtEES{ydQhQ$dPvZg?+`(L8WglC{FaE6 z;WVVsK1vGmI>r;a1kGTO4$wh1-yuZxlIAO0&4F<&HUEFL-C-OFw6n(t+ZS6TNJr=> ztHK13Ge!dR4#o-eZLeXBUdwW!rZ&DGiVeG(4OZB^%};+P6gtV6YoBiuQ_C|oxJ)oL zaQqmbbV|^^w?+^jui1RnSuCkFR^h&ypfyMzMs}h?e|_cLBxq+1l)SYQ0sG;Hd*a)7 zb_ECyTrWi&JzcO3ccODY=nIV3Z;a|3B%=sCm|LR7OhbHIjWf%BsJ#bFW6)`Z#^{Wo zwbj}Un&W>37hC9B-cNaEhxy8v@MbAw(s+d(FgI@*5|S5RU;tnEL@z_prGi2ZokcVi z#xt4=o&A^^9OUiJ(*$es1jN%h%h7}MU7Q~rdJ5thsV_DJOZ5inUG#32{qBm^RX6S} z7`Y5*h3{49A_JvyPGS(LMP`iegXvuBVf}n*%_4uq&Iarc&<`r~{q#ee%27ACV?p|1 zI><5nBN$?+n7H4DaNpw9Wks;bd+Enmm-h*ZFYTcvR(^n2K7%ykS`}Sahij_(ZcNS0?1?e&~Y(IU34Tu`bg-t(NBIjoXtps*@MjR_waCOemL3)mN*hD`m>gta% ztc`!PEW=bQTPpz6tOg`x?rt;N%oHl6nlgE9LLJl2>gtHDo2skj5!&F9bA~(C(Ps8p zX4bItsyn8+_|erZ)r*J6Gz7wMA-_c(w=FDmCsah^1fNwRi+GtVI?D4PE0wDT)o>8J zHZv0vL57#8nhn*;VG4uE9dq4rC(&7Ezz!zEa>+Ya>~=CCmB>b_ zK0CqQv9j=$ffK6D2i_jcmaH|xfKm$%%%iDkToTu<7LBQnu1lw=hU>7k&l&(ADDHo! zP;t&-?Qp?#jl7OpOdscUe)^dO>3v>0npEfodJ$zt34ACKY7ogI2@%B#!J=JHHEG-clmYG&;dv-$Ct=~r0%SCLm1X*~cnC;as5&=`Sx0O>ABuW-PAhF%4+ELlKvXdkgPe&%SU zl7b2FH&JamT2=-=?iKSD!zF8UT0wof5Nr0d#*@aYAn) zo8@>vSa7TI!tV*XquNdLXMbOzFR@=jbDpghC`0QH6#63lAu30i0B2_fb%v9*O;@?h z{49n0{4xCryY^4vm0Ab->CXVSb4Z>r_+N02`g8g!|2)O3ked_;x5f6V}j^zOTogje_`v=^0$;XzTzQM(kH5#OEaySJPJsTkl6<9)j*QvXIcszCl9$fLr=b60oM zV@m~=sk@y=4-d+~T8`}xfmKbn^g>=0ZeLJ$;eG;;5Os_TfYjG9jxv8PAbbE{e-#x6 zgdereZC;gr(E!*pUXR*_pgY40w3*)xie)0G2t_PkkZ_l*%&QWvSP3VIRh7qBc~8G+ zg8Hs?^l-B3qNT|s4qPo-6wxf!%wLxDi#q^Oq$bXEX6cazLS3+aZVo%G6YCWb5*t7P zcs%uLj*;#ufbc=QrBr`2SNT@%yVPcg6mh4xi!Fi2WfSn3F62;j9d&fOXB0aIMJrH& z=}mAxkH+P2K(ti|XwjyAu?1T>x_cNk1}d^c<;08!&5{N0g2W)&MMM!{5rt{6|2fM( za|B7nDu5ToU{J(GM+0=~M6SR&<)ddMykRaD#Wt~>_t=3wq%wb6rYsQ@J4;ibrnTWE zV_xiHncZ;as64~Py_2N^PwYW~hspcqy#x_jIsKX9|64_blaO;qZ3HX7e|2-wA9EH)#O8iIs}*u?rGIF_ za-2UX_OTs@=Kp_n<$t@8U+hQDs}xRnhq(o(ZwwdJWnI5-AA94VIHZUJ;_YCv+0y8o z=BUQptvdo@SfMxRMd(C`3JQqhU@}`i+>Tg5k>cFGNuV5PtmXz;ngzs3psrkSCRDfN zYBd}Xk8$x`qjay1=*Kyt@mBNXo%Vo83yRzxsURS@Wb04YUIC8;j5AVHYM92El2AI3|7!eaOP?B zwm{yCc6}sua*CR6(CXCC6tzUI)7t2D3dOF|`l}K?4YYwamKKSJu%sUCvS_48cONg( zmdm6}Q+$7Dk{*Z_X2Idn(~8QuifN zq9J_jIeyVACU3nS9g4h6ZxeKhRPU$BpBnPShMRgL)AaDr4ceDVipUi0pQH~#3JCCC zsTLbvBsL!LyiCXIQ0r{M_@-1U8EHyQ(IZgy5`}-G^8CA_H|QiQ_$d01r;@MG%IHn+ zbJP&^Y@Z~rc(wY7kwr%=mz{_}C;ADPNQg7|jlkaZu<;?P!_(12XJM@O!phHLbQ0Eo z9e(*H%y|oP4V0!#*{JoHXU}~u_9}U=Hf5(Nci;w@sf0H=Mel4}MV|^Jd?7De>|Cm= z{#k!&iidojmii(+ISFgi2U_auuCUp^5)XNcbfHM!gY_4&eu|#907NUtl+F_T0ZAirZ{p&qksfw!^X0boDa% zJTG0WgYIuY^2$qP;G$S6+qkP79nasO>#5X!s97x1CmDA$jJu2Y_%#8@d?s~(cZPrI z<3;+7Y5JT5&gU=DO1{+Z9-qAR`AIqvi{GFxvgDUi?3pS0a>zGDe^jKeB)pB@1^)U7 zt*rR#^~qabkEhB`dISF_Z@qgcf|K5ui52NDukz0fB2+=V_DTz_mhDP19drO&y4&u2G1Q7CqJU^(p#WAOsj{`g{Du%HRKpA3&){|56r> zpKAIyDf-{DGc!1g;GcT1H?!5Z5Fzr!IslZJOI(XZQZkf>qDA2;od|3f1uTF0!Ddlk z+Df|W%JK3+u~W?=fRm=hilS(&=&=3(n;Xm}JnT-9@QQ>_imXLYuvZg)b}In#W%j7p z$Y@7g@&6RZg}A#YHaClVP8CJ$n%G(t_sZYyqDUlsjbS){e^K1u;Lm_{{J4sHtP28Y2Q_bSYlsGyQ4f#X9_%(5? zS-b<+ufPsG7>Kf|A~5HP<5$7nJBN4~+YNSY7LUTBAOz9aEKcDwF0X$$(kwD1OGl=} z=uGv_uTX&Dej()LFL>pR$P9&OlunBgVaWC|_%=`HWuIH_pQk6qX7st;fd0Ga1=;78 z`!CYRWS?8^f1Iw$KDXTG=;c1Q+<%2WEBoAX|Eu&h+2@w~Z=wL?KDX!#k7(q+Y`Gs3 z-LlUu_tWATsb?uJnt&nxw*#w>QJqMVN2JjglBMd%^KDQ|2M8I^b004L#lL18> zlTV&Ce-Y?HDMGmk78KW8TUb`W50x4d)5L_NQDY58zD>7>?ZRHlUNFYU58+p+(VFBm{Q>$NJ|{2!V7hNJ5KVI4%h+2BB@* zp=`Kheh6i&MWI;@Y@0$2!va$W@>rU#^lkH1{eY}kLrP%wBKn*Ozai@`X&4n4IZ7Og ze+9&zKuG41%pi^NF^nL~Gj3oD%;l>Wd26v+M_F-~ zYN&mTV)8W1F%u;0GuJ_!ziMS3`X)A1KR* z-1vNDVCIGYbA1vNRf1LSYK3>9z+{y--OI$QQ}|Zl*x;UO5E$bptD4N`VuZglnBdXi zzj<8a8%P)5|HM@82d2M5U0KXvwyVi?HIv2fm_9}N8*Z+)ar<1jf;(Mdp)1UGM1*o4BCmfOhpf@3_ByLfoa7dS#aDmKFF5N13d^#7};eeNEkc%=u0TD!X(J^H`&8LxaKoLaarog-OHPc!9ENLyJM{Tp3keFgWbp`~*}H z)?3g1yZ(%U*Xz%^;6tYaEp6Cg(72*6zzCXT>tb|#*rvWq?ts)IZ63ct_w_eWgDvpB z0Z>Z^2yr0v!TT@%u$ScDfR zrzVR=Rjj3cjDj)fWv?wQe{s`x1Vh%7^+H|psv`>PlDAqy7RrzPKs0Ylj}Cz?{5kHD zSZatc3_s*+yx?%RURbI;6jq>Nh+(uYf`e8J=hO2&ZQCoTU^AKRV>_^&!W{P-3%oVM zaQqOcL1!4cYP)vuF~dMQb1#lKj_HWu4TgBXPYuJQYWv&8km~(7e?~B><2X(*oY-@{ zmzRcwc!@qSMwx77~HffT%{;WVXnF!^2*Z|O+jZH9>B@hZcqJ*7VTp6)w1tHLB1 z1}(?)MI0$rLIUS0;Z^atECLmzzb6FE#PKdBl;L{}$M%UdWEi4$AS4ew$#8O?ZRr(G z4syuHkcGi8a#*gRf54y--xkHAAdZU|jp2PnV^(S3q+UC;7s@e_qZG#+N=oo0o$G1>e-r7$dvw09V+G$(lhoq7L}=qb+OaPSD&;$TuUtG(4;py( zh)8|Nord(*e|cqhn<_f)!lLVAcZrtz>ZgT{+@PB-at?#UC-tM@BT9dUI-UN&5J`Z| zY!@+ezJoVIjBR2t_q>a7(_HA_R2KjdJ4$g!)7ve&Q^b1Tf+{(Vd6vIW*>~09ef+&hY&p1LG>l&m%tgUqlUAX=)EV9!3JfWLB4n1z)!ums&0UuuVLUH zP)i30*5f6tngaj;P6m?!i!+lhrzL-FPZL29$7i9?QjgLW5Tq({h<$)kp@8K5wX06&y*ws)tcJ#3Sk*`5Dyc6Vm?*Y6)c z0bm}s34FS`%4R-@d0Mz&YEfJf3ng(zENGRgtWZXZS#^FmfMZpQ9Op|k5qDr#Lm@cal&eoZ3 z;95AJnN81Tl0{Y*Kl*?W@aMFeUSQ8y3O=WAR?Ah6$5smx3rX7^T+YK?E7;c@)mFfKAQm$4Z;C(MwtxVjrv;kc4QqwQq$`z*7Oaf$&z(}1c za*>*BrzO#$u3+?pK<}EY%H}$O?pXXtfFT(6gBNb&R$gQ`clLMB4s(CI*|V1iuXcSf zDu5qu^+6Ae5$JbH#rJ3U;I06I6}&G%!15jlFkpG206_?G@1X!;806j~0s{s!cdnH# z6uVwKz9}E{aeacopmbet6<{b9cPr+g;U*rAb!y{BovE#gw&$>BN87Z2+af@}b>1|J zj2lFF{g6L#+UGY~2UdT?TE>o8gAhhux3w30h7ArGoe@uLj~{9bp`)AHk2GF@G2=fH zPwa%J@oeL3gE>5x7hgEOAl?%62)_?aE7-Q*wgKA?*cO}LwAgyILGEaxBz&gsDnR)O*hg5l@`!SHyRdGggQ-L(xH=? zI5TMr2<{4s`%1+X1yNK`m{uzCgXi#rf0W1jW|AgpQxE6lL5Kjg|fw-2=$ckjjni@`P2~P7mSGa#k*x&)Re4puFGnQ zW{0_MkT05VZra$?98U1zz$rHvgD0wG^*G-nE1V&q>8VIcml6t(jObD(!}Z7^NA4cw z@vN!oE>tosJSGiG5k-GeQ<3h0V?1uUP)(*Xx<;C&%ngPm9kx!^l$A)&)ckga`2{V< z>3m01)*@m|8r5-4P0A^ThK||eX|r{*y3L^gwaBV$KFUy6Uuv&>91RBMymD4LWggy%&73p`}yA%=N6mlC@OrfUaug`u{-p`$>5)D#uo?!_9c6@WSd zq`285>0C7(ei!Bec}BcwKu|btWN0qR+2%-AO|GkwlF!`sEDvNw;^d!*puI#YE`+Jb zac4M9iD6yYA{2i|oQp~2X5>I`JH-^iIuDw#o?(H(ODrb&E|JAySF1 zvdGJ}-db*i%1zi_R0mt#lqkJQdb?wCY~$QHXaAY~%=ejRo^xjB_dB!SZ|@OowuPDJ zv0!zj&{&N1?FeiKg9>#_vmcdkqW`R48ge~VDe0$C<~Z3hx;c{0=n}e1*%MkNLZ1z% z-7FP`25qbs)k-_{i0Q=WT|4ePSRwGu8R13<`l-y0QF4FmeZI>6D2bPE)vo?0gOkyN zyL@xs-DtnI_Oge0lVx<`#Sz8#Kyj{S0>SeJ&;GW(t2o1O0Gmeet(krre#`dEM20~S_ z*^#SRQ^|a|Y{)$)Bw43lx2QDeQNYuD+zF?WJTLWie!RfL#iyOY2@OoMR5g1GFi&Hk zd_PdX?Wg4uMkS%RX7iI3uixOYN-@F$7!_ZfmO= zr7d#s-r0`_@c5oDMs=&7=|AdzL7L$!XZLsS z4%>tG>6P2S%uFe#Ml&#t+6S2 zUwQI=n5)oUHNQ>N1nxcK-p(~xm&@!+*t%D>yxMW&?w3b~83Up6gI5L?6Aw(#Y+f2Q z;gc8lr0JNYCh82Io|F@m#a=jgl^OnIn553BEN%Y-7p$8#)5l#2YoP^BT7|FiqgS8lEy zi`}`&hGpq2xu$l$>aX~M;+eE_)2g!tm3mP4v)|wt)J|o{r#48DRlC-49b7RvK{d6` zAQZNXj)NholLLSQ3X)(DD6HNZ{4u-L5d|ga!Vn#lCpw>l2cN7RO8zEc4qOUZm@G$NSq$33SxHUi z;nItEa6WGfR<%T_2AU$Ef`|nE7>VSBg0_+oC|+a>%CbflUh$0Fpn@`+djK#)4fS?43>ZSE8t|aZ>wDqsD(oR?gAX`wHVw~;ic-;Zf&nZP)ks}2 z?_3N+Yf+E}6@UzAILNEX7M%Ccg(-6se{=u<5(*^J z5wNL69im04BCzarC;%`-!R0Ijb`mQy3t|4Z9Rsav y#(}b@+JzTQ6GHT>TdhFZ%?JQYQ2J4M2t+AYfOOmRRdDbMY5W2JI>od1qyGT+r>T|z diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 48b43d3..c82ad3f 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/example/android/gradlew b/example/android/gradlew index f5feea6..739907d 100755 --- a/example/android/gradlew +++ b/example/android/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -115,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -173,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -206,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/example/android/gradlew.bat b/example/android/gradlew.bat index 9d21a21..c4bdd3a 100644 --- a/example/android/gradlew.bat +++ b/example/android/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/example/ios/MendixNativeExample.xcodeproj/project.pbxproj b/example/ios/MendixNativeExample.xcodeproj/project.pbxproj index 8d0597b..5601230 100644 --- a/example/ios/MendixNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/MendixNativeExample.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 1499ABBDB7935B67C3951198 /* libPods-MendixNativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 24A5FB93E78C6A91516539F4 /* libPods-MendixNativeExample.a */; }; 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; + 761780EF2CA45674006654EF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EE2CA45674006654EF /* SceneDelegate.swift */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; E7824D7967CD7EE7C8E76686 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; /* End PBXBuildFile section */ @@ -22,6 +23,7 @@ 24A5FB93E78C6A91516539F4 /* libPods-MendixNativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MendixNativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 503B3921D3702B3C7DF3D941 /* Pods-MendixNativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MendixNativeExample.release.xcconfig"; path = "Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample.release.xcconfig"; sourceTree = ""; }; 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = MendixNativeExample/AppDelegate.swift; sourceTree = ""; }; + 761780EE2CA45674006654EF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SceneDelegate.swift; path = MendixNativeExample/SceneDelegate.swift; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = MendixNativeExample/LaunchScreen.storyboard; sourceTree = ""; }; 9EF6D8952E93D80B00BFE8AE /* MendixNativeExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MendixNativeExample-Bridging-Header.h"; sourceTree = ""; }; DC6440C7A3C29FAC4633A591 /* Pods-MendixNativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MendixNativeExample.debug.xcconfig"; path = "Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample.debug.xcconfig"; sourceTree = ""; }; @@ -45,6 +47,7 @@ children = ( 13B07FB51A68108700A75B9A /* Images.xcassets */, 761780EC2CA45674006654EE /* AppDelegate.swift */, + 761780EE2CA45674006654EF /* SceneDelegate.swift */, 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */, @@ -249,6 +252,7 @@ buildActionMask = 2147483647; files = ( 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */, + 761780EF2CA45674006654EF /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -389,6 +393,7 @@ "$(inherited)", " ", ); + PODFILE_DIR = "$(SRCROOT)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -467,6 +472,7 @@ "$(inherited)", " ", ); + PODFILE_DIR = "$(SRCROOT)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ENABLE_EXPLICIT_MODULES = NO; diff --git a/example/ios/MendixNativeExample/AppDelegate.swift b/example/ios/MendixNativeExample/AppDelegate.swift index d86af0f..0392210 100644 --- a/example/ios/MendixNativeExample/AppDelegate.swift +++ b/example/ios/MendixNativeExample/AppDelegate.swift @@ -1,41 +1,10 @@ import UIKit -import React import MendixNative @main -class AppDelegate: ReactAppProvider { +class AppDelegate: LegacyWindowAppDelegate { - override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - setUpProvider() - guard let bundleUrl = bundleURL() else { - let message = "No script URL provided. Make sure the metro packager is running or you have embedded a JS bundle in your application bundle." - fatalError(message) - } - let mendixApp = MendixApp.init( - identifier: nil, - bundleUrl: bundleUrl, - runtimeUrl: URL(string: "http://localhost:8081")!, - warningsFilter: .none, - isDeveloperApp: true, - clearDataAtLaunch: false, - splashScreenPresenter: nil, - reactLoading: nil, - enableThreeFingerGestures: false - ) - - AppPreferences.devModeEnabled = true - AppPreferences.remoteDebuggingEnabled = true - - ReactNative.shared.setup(mendixApp, launchOptions: nil) - ReactNative.shared.start() - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } - - func bundleURL() -> URL? { - #if DEBUG - RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") - #else - Bundle.main.url(forResource: "main", withExtension: "jsbundle") - #endif + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { + return true } } diff --git a/example/ios/MendixNativeExample/Info.plist b/example/ios/MendixNativeExample/Info.plist index d934e25..d7851ed 100644 --- a/example/ios/MendixNativeExample/Info.plist +++ b/example/ios/MendixNativeExample/Info.plist @@ -35,6 +35,23 @@ RCTNewArchEnabled + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/example/ios/MendixNativeExample/PrivacyInfo.xcprivacy b/example/ios/MendixNativeExample/PrivacyInfo.xcprivacy index 41b8317..fc90547 100644 --- a/example/ios/MendixNativeExample/PrivacyInfo.xcprivacy +++ b/example/ios/MendixNativeExample/PrivacyInfo.xcprivacy @@ -14,18 +14,18 @@ NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPICategorySystemBootTime NSPrivacyAccessedAPITypeReasons - CA92.1 + 35F9.1 NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPICategoryUserDefaults NSPrivacyAccessedAPITypeReasons - 35F9.1 + CA92.1 diff --git a/example/ios/MendixNativeExample/SceneDelegate.swift b/example/ios/MendixNativeExample/SceneDelegate.swift new file mode 100644 index 0000000..ff1d849 --- /dev/null +++ b/example/ios/MendixNativeExample/SceneDelegate.swift @@ -0,0 +1,37 @@ +import UIKit +import React +import MendixNative + +class SceneDelegate: ReactAppProvider { + + override func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + super.scene(scene, willConnectTo: session, options: connectionOptions) + + setUpProvider() + guard let bundleUrl = bundleURL() else { + let message = "No script URL provided. Make sure the metro packager is running or you have embedded a JS bundle in your application bundle." + fatalError(message) + } + let mendixApp = MendixApp.init( + identifier: nil, + bundleUrl: bundleUrl, + runtimeUrl: URL(string: "http://localhost:8081")!, + warningsFilter: .none, + isDeveloperApp: true, + clearDataAtLaunch: false, + splashScreenPresenter: nil, + reactLoading: nil, + enableThreeFingerGestures: false + ) + ReactNative.shared.setup(mendixApp, launchOptions: ReactAppProvider.launchOptions(from: connectionOptions)) + ReactNative.shared.start() + } + + func bundleURL() -> URL? { + #if DEBUG + RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") + #else + Bundle.main.url(forResource: "main", withExtension: "jsbundle") + #endif + } +} diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index a7708a9..e8f8031 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,14 +1,27 @@ PODS: - - FBLazyVector (0.84.1) - - hermes-engine (250829098.0.9): - - hermes-engine/Pre-built (= 250829098.0.9) - - hermes-engine/Pre-built (250829098.0.9) - - MendixNative (0.6.1): + - boost (1.84.0): + - ReactNativeDependencies + - DoubleConversion (1.1.6): + - ReactNativeDependencies + - fast_float (8.0.0): + - ReactNativeDependencies + - FBLazyVector (0.88.0-rc.3): + - React-Core-prebuilt + - fmt (12.1.0): + - ReactNativeDependencies + - glog (0.3.5): + - ReactNativeDependencies + - hermes-engine (260318099.0.4): + - hermes-engine/Pre-built (= 260318099.0.4) + - hermes-engine/Pre-built (260318099.0.4) + - MendixNative (0.6.2): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -22,19 +35,20 @@ PODS: - React-utils - ReactAppDependencyProvider - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - RNCAsyncStorage - SSZipArchive - Yoga - - op-sqlite (15.2.5): + - op-sqlite (18.2.5): - hermes-engine - OpenSSL-Universal - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -47,339 +61,131 @@ PODS: - React-rendererdebug - React-utils - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - OpenSSL-Universal (3.6.0000) - - RCTDeprecation (0.84.1) - - RCTRequired (0.84.1) - - RCTSwiftUI (0.84.1) - - RCTSwiftUIWrapper (0.84.1): - - RCTSwiftUI - - RCTTypeSafety (0.84.1): - - FBLazyVector (= 0.84.1) - - RCTRequired (= 0.84.1) - - React-Core (= 0.84.1) - - React (0.84.1): - - React-Core (= 0.84.1) - - React-Core/DevSupport (= 0.84.1) - - React-Core/RCTWebSocket (= 0.84.1) - - React-RCTActionSheet (= 0.84.1) - - React-RCTAnimation (= 0.84.1) - - React-RCTBlob (= 0.84.1) - - React-RCTImage (= 0.84.1) - - React-RCTLinking (= 0.84.1) - - React-RCTNetwork (= 0.84.1) - - React-RCTSettings (= 0.84.1) - - React-RCTText (= 0.84.1) - - React-RCTVibration (= 0.84.1) - - React-callinvoker (0.84.1) - - React-Core (0.84.1): - - hermes-engine - - RCTDeprecation - - React-Core-prebuilt - - React-Core/Default (= 0.84.1) - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils + - RCT-Folly (2024.11.18.00): + - RCT-Folly/Default (= 2024.11.18.00) - ReactNativeDependencies - - Yoga - - React-Core-prebuilt (0.84.1): + - RCT-Folly/Default (2024.11.18.00): - ReactNativeDependencies - - React-Core/CoreModulesHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - RCTDeprecation (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/Default (0.84.1): - - hermes-engine - - RCTDeprecation + - RCTRequired (0.88.0-rc.3): - React-Core-prebuilt - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/DevSupport (0.84.1): - - hermes-engine - - RCTDeprecation + - RCTSwiftUI (0.88.0-rc.3) + - RCTSwiftUIWrapper (0.88.0-rc.3): + - RCTSwiftUI + - RCTTypeSafety (0.88.0-rc.3): + - FBLazyVector (= 0.88.0-rc.3) + - RCTRequired (= 0.88.0-rc.3) + - React-Core (= 0.88.0-rc.3) + - React (0.88.0-rc.3): + - React-Core (= 0.88.0-rc.3) + - React-Core/DevSupport (= 0.88.0-rc.3) + - React-Core/RCTWebSocket (= 0.88.0-rc.3) + - React-RCTActionSheet (= 0.88.0-rc.3) + - React-RCTAnimation (= 0.88.0-rc.3) + - React-RCTBlob (= 0.88.0-rc.3) + - React-RCTImage (= 0.88.0-rc.3) + - React-RCTLinking (= 0.88.0-rc.3) + - React-RCTNetwork (= 0.88.0-rc.3) + - React-RCTSettings (= 0.88.0-rc.3) + - React-RCTText (= 0.88.0-rc.3) + - React-RCTVibration (= 0.88.0-rc.3) + - React-bridging (0.88.0-rc.3): + - React-callinvoker - React-Core-prebuilt - - React-Core/Default (= 0.84.1) - - React-Core/RCTWebSocket (= 0.84.1) - - React-cxxreact - - React-featureflags - - React-hermes - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils + - React-timing - ReactNativeDependencies - - Yoga - - React-Core/RCTActionSheetHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-callinvoker (0.88.0-rc.3): + - React-callinvoker/callinvokerUmbrella (= 0.88.0-rc.3) + - React-cxxstableapi + - React-callinvoker/callinvokerUmbrella (0.88.0-rc.3): + - React-cxxstableapi + - React-Core (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils + - React-Core/Default (= 0.88.0-rc.3) + - React-Core-prebuilt (0.88.0-rc.3): - ReactNativeDependencies - - Yoga - - React-Core/RCTAnimationHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/CoreModulesHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTBlobHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/Default (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTImageHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/DevSupport (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTLinkingHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/RCTActionSheetHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTNetworkHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/RCTAnimationHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTSettingsHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/RCTBlobHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTTextHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/RCTImageHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTVibrationHeaders (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/RCTLinkingHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-Core/RCTWebSocket (0.84.1): - - hermes-engine - - RCTDeprecation + - React-Core/RCTNetworkHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/Default (= 0.84.1) - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-CoreModules (0.84.1): - - RCTTypeSafety (= 0.84.1) + - React-Core/RCTSettingsHeaders (0.88.0-rc.3): + - React-Core-prebuilt + - React-Core/RCTTextHeaders (0.88.0-rc.3): + - React-Core-prebuilt + - React-Core/RCTVibrationHeaders (0.88.0-rc.3): - React-Core-prebuilt - - React-Core/CoreModulesHeaders (= 0.84.1) + - React-Core/RCTWebSocket (0.88.0-rc.3): + - React-Core-prebuilt + - React-CoreModules (0.88.0-rc.3): + - RCTTypeSafety (= 0.88.0-rc.3) + - React-Core-prebuilt + - React-Core/CoreModulesHeaders (= 0.88.0-rc.3) - React-debug - - React-jsi (= 0.84.1) + - React-featureflags + - React-jsi (= 0.88.0-rc.3) - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing - React-NativeModulesApple + - React-networking - React-RCTBlob - React-RCTFBReactNativeSpec - - React-RCTImage (= 0.84.1) + - React-RCTImage (= 0.88.0-rc.3) - React-runtimeexecutor - React-utils - ReactCommon - ReactNativeDependencies - - React-cxxreact (0.84.1): + - React-cxxreact (0.88.0-rc.3): - hermes-engine - - React-callinvoker (= 0.84.1) + - React-callinvoker (= 0.88.0-rc.3) - React-Core-prebuilt - - React-debug (= 0.84.1) - - React-jsi (= 0.84.1) + - React-debug (= 0.88.0-rc.3) + - React-jserrorhandler (= 0.88.0-rc.3) + - React-jsi (= 0.88.0-rc.3) - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing - - React-logger (= 0.84.1) - - React-perflogger (= 0.84.1) + - React-logger (= 0.88.0-rc.3) + - React-perflogger (= 0.88.0-rc.3) - React-runtimeexecutor - - React-timing (= 0.84.1) + - React-timing (= 0.88.0-rc.3) - React-utils - ReactNativeDependencies - - React-debug (0.84.1) - - React-defaultsnativemodule (0.84.1): + - React-cxxstableapi (0.88.0-rc.3) + - React-debug (0.88.0-rc.3): + - React-cxxstableapi + - React-debug/debugUmbrella (= 0.88.0-rc.3) + - React-debug/redbox (= 0.88.0-rc.3) + - React-debug/debugUmbrella (0.88.0-rc.3): + - React-cxxstableapi + - React-debug/redbox (0.88.0-rc.3): + - React-cxxstableapi + - React-defaultsnativemodule (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-cxxstableapi - React-domnativemodule + - React-Fabric/animated - React-featureflags - React-featureflagsnativemodule - React-idlecallbacksnativemodule @@ -387,13 +193,18 @@ PODS: - React-jsi - React-jsiexecutor - React-microtasksnativemodule + - React-mutationobservernativemodule - React-RCTFBReactNativeSpec + - React-resizeobservernativemodule + - React-viewtransitionnativemodule - React-webperformancenativemodule - ReactNativeDependencies - Yoga - - React-domnativemodule (0.84.1): + - React-domnativemodule (0.88.0-rc.3): - hermes-engine + - React-bridging - React-Core-prebuilt + - React-cxxstableapi - React-Fabric - React-Fabric/bridging - React-FabricComponents @@ -405,33 +216,35 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-Fabric (0.84.1): + - React-Fabric (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact - - React-debug - - React-Fabric/animated (= 0.84.1) - - React-Fabric/animationbackend (= 0.84.1) - - React-Fabric/animations (= 0.84.1) - - React-Fabric/attributedstring (= 0.84.1) - - React-Fabric/bridging (= 0.84.1) - - React-Fabric/componentregistry (= 0.84.1) - - React-Fabric/componentregistrynative (= 0.84.1) - - React-Fabric/components (= 0.84.1) - - React-Fabric/consistency (= 0.84.1) - - React-Fabric/core (= 0.84.1) - - React-Fabric/dom (= 0.84.1) - - React-Fabric/imagemanager (= 0.84.1) - - React-Fabric/leakchecker (= 0.84.1) - - React-Fabric/mounting (= 0.84.1) - - React-Fabric/observers (= 0.84.1) - - React-Fabric/scheduler (= 0.84.1) - - React-Fabric/telemetry (= 0.84.1) - - React-Fabric/templateprocessor (= 0.84.1) - - React-Fabric/uimanager (= 0.84.1) + - React-cxxstableapi + - React-debug + - React-Fabric/animated (= 0.88.0-rc.3) + - React-Fabric/animationbackend (= 0.88.0-rc.3) + - React-Fabric/animations (= 0.88.0-rc.3) + - React-Fabric/attributedstring (= 0.88.0-rc.3) + - React-Fabric/bridging (= 0.88.0-rc.3) + - React-Fabric/componentregistry (= 0.88.0-rc.3) + - React-Fabric/componentregistrynative (= 0.88.0-rc.3) + - React-Fabric/components (= 0.88.0-rc.3) + - React-Fabric/consistency (= 0.88.0-rc.3) + - React-Fabric/core (= 0.88.0-rc.3) + - React-Fabric/dom (= 0.88.0-rc.3) + - React-Fabric/imagemanager (= 0.88.0-rc.3) + - React-Fabric/leakchecker (= 0.88.0-rc.3) + - React-Fabric/mounting (= 0.88.0-rc.3) + - React-Fabric/observers (= 0.88.0-rc.3) + - React-Fabric/scheduler (= 0.88.0-rc.3) + - React-Fabric/telemetry (= 0.88.0-rc.3) + - React-Fabric/uimanager (= 0.88.0-rc.3) + - React-Fabric/viewtransition (= 0.88.0-rc.3) - React-featureflags - React-graphics - React-jsi @@ -443,14 +256,17 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/animated (0.84.1): + - React-Fabric/animated (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug + - React-Fabric/animationbackend - React-featureflags - React-graphics - React-jsi @@ -462,13 +278,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/animationbackend (0.84.1): + - React-Fabric/animationbackend (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -481,13 +299,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/animations (0.84.1): + - React-Fabric/animations (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -500,13 +320,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/attributedstring (0.84.1): + - React-Fabric/attributedstring (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -519,13 +341,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/bridging (0.84.1): + - React-Fabric/bridging (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -538,13 +362,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/componentregistry (0.84.1): + - React-Fabric/componentregistry (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -557,13 +383,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/componentregistrynative (0.84.1): + - React-Fabric/componentregistrynative (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -576,18 +404,21 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/components (0.84.1): + - React-Fabric/components (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - - React-Fabric/components/legacyviewmanagerinterop (= 0.84.1) - - React-Fabric/components/root (= 0.84.1) - - React-Fabric/components/scrollview (= 0.84.1) - - React-Fabric/components/view (= 0.84.1) + - React-Fabric/components/legacyviewmanagerinterop (= 0.88.0-rc.3) + - React-Fabric/components/root (= 0.88.0-rc.3) + - React-Fabric/components/scrollview (= 0.88.0-rc.3) + - React-Fabric/components/view (= 0.88.0-rc.3) + - React-Fabric/components/viewUmbrella (= 0.88.0-rc.3) - React-featureflags - React-graphics - React-jsi @@ -599,13 +430,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/components/legacyviewmanagerinterop (0.84.1): + - React-Fabric/components/legacyviewmanagerinterop (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -618,13 +451,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/components/root (0.84.1): + - React-Fabric/components/root (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -637,13 +472,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/components/scrollview (0.84.1): + - React-Fabric/components/scrollview (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -656,13 +493,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/components/view (0.84.1): + - React-Fabric/components/view (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -677,13 +516,15 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-Fabric/consistency (0.84.1): + - React-Fabric/components/viewUmbrella (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -696,13 +537,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/core (0.84.1): + - React-Fabric/consistency (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -715,13 +558,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/dom (0.84.1): + - React-Fabric/core (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -734,13 +579,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/imagemanager (0.84.1): + - React-Fabric/dom (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -753,13 +600,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/leakchecker (0.84.1): + - React-Fabric/imagemanager (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -772,13 +621,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/mounting (0.84.1): + - React-Fabric/leakchecker (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -791,20 +642,21 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/observers (0.84.1): + - React-Fabric/mounting (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - - React-Fabric/observers/events (= 0.84.1) - - React-Fabric/observers/intersection (= 0.84.1) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor + - React-jsinspectortracing - React-logger - React-rendererdebug - React-runtimeexecutor @@ -812,14 +664,20 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/observers/events (0.84.1): + - React-Fabric/observers (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug + - React-Fabric/observers/events (= 0.88.0-rc.3) + - React-Fabric/observers/intersection (= 0.88.0-rc.3) + - React-Fabric/observers/mutation (= 0.88.0-rc.3) + - React-Fabric/observers/resize (= 0.88.0-rc.3) - React-featureflags - React-graphics - React-jsi @@ -831,13 +689,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/observers/intersection (0.84.1): + - React-Fabric/observers/events (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -850,35 +710,36 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/scheduler (0.84.1): + - React-Fabric/observers/intersection (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - - React-Fabric/observers/events - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - - React-performancecdpmetrics - - React-performancetimeline - React-rendererdebug - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/telemetry (0.84.1): + - React-Fabric/observers/mutation (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -891,13 +752,15 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/templateprocessor (0.84.1): + - React-Fabric/observers/resize (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-graphics @@ -910,35 +773,64 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/uimanager (0.84.1): + - React-Fabric/scheduler (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi + - React-debug + - React-Fabric/animationbackend + - React-Fabric/observers/events + - React-Fabric/viewtransition + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-performancecdpmetrics + - React-performancetimeline + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - ReactNativeDependencies + - React-Fabric/telemetry (0.88.0-rc.3): + - hermes-engine + - RCTRequired + - RCTTypeSafety + - React-bridging + - React-Core + - React-Core-prebuilt + - React-cxxreact + - React-cxxstableapi - React-debug - - React-Fabric/uimanager/consistency (= 0.84.1) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - - React-rendererconsistency - React-rendererdebug - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-Fabric/uimanager/consistency (0.84.1): + - React-Fabric/uimanager (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug + - React-Fabric/uimanager/consistency (= 0.88.0-rc.3) - React-featureflags - React-graphics - React-jsi @@ -951,71 +843,61 @@ PODS: - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-FabricComponents (0.84.1): + - React-Fabric/uimanager/consistency (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - - React-Fabric - - React-FabricComponents/components (= 0.84.1) - - React-FabricComponents/textlayoutmanager (= 0.84.1) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - - React-RCTFBReactNativeSpec + - React-rendererconsistency - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - Yoga - - React-FabricComponents/components (0.84.1): + - React-Fabric/viewtransition (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - - React-Fabric - - React-FabricComponents/components/inputaccessory (= 0.84.1) - - React-FabricComponents/components/iostextinput (= 0.84.1) - - React-FabricComponents/components/modal (= 0.84.1) - - React-FabricComponents/components/rncore (= 0.84.1) - - React-FabricComponents/components/safeareaview (= 0.84.1) - - React-FabricComponents/components/scrollview (= 0.84.1) - - React-FabricComponents/components/switch (= 0.84.1) - - React-FabricComponents/components/text (= 0.84.1) - - React-FabricComponents/components/textinput (= 0.84.1) - - React-FabricComponents/components/unimplementedview (= 0.84.1) - - React-FabricComponents/components/virtualview (= 0.84.1) - - React-FabricComponents/components/virtualviewexperimental (= 0.84.1) - React-featureflags - React-graphics - React-jsi - React-jsiexecutor - React-logger - - React-RCTFBReactNativeSpec - React-rendererdebug + - React-runtimeexecutor - React-runtimescheduler - React-utils - ReactCommon/turbomodule/core - ReactNativeDependencies - - Yoga - - React-FabricComponents/components/inputaccessory (0.84.1): + - React-FabricComponents (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric + - React-FabricComponents/components (= 0.88.0-rc.3) + - React-FabricComponents/textlayoutmanager (= 0.88.0-rc.3) - React-featureflags - React-graphics - React-jsi @@ -1028,15 +910,26 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/iostextinput (0.84.1): + - React-FabricComponents/components (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.88.0-rc.3) + - React-FabricComponents/components/iostextinput (= 0.88.0-rc.3) + - React-FabricComponents/components/modal (= 0.88.0-rc.3) + - React-FabricComponents/components/rncore (= 0.88.0-rc.3) + - React-FabricComponents/components/safeareaview (= 0.88.0-rc.3) + - React-FabricComponents/components/switch (= 0.88.0-rc.3) + - React-FabricComponents/components/text (= 0.88.0-rc.3) + - React-FabricComponents/components/textinput (= 0.88.0-rc.3) + - React-FabricComponents/components/unimplementedview (= 0.88.0-rc.3) + - React-FabricComponents/components/virtualview (= 0.88.0-rc.3) - React-featureflags - React-graphics - React-jsi @@ -1049,13 +942,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/modal (0.84.1): + - React-FabricComponents/components/inputaccessory (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1070,13 +964,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/rncore (0.84.1): + - React-FabricComponents/components/iostextinput (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1091,13 +986,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/safeareaview (0.84.1): + - React-FabricComponents/components/modal (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1112,13 +1008,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/scrollview (0.84.1): + - React-FabricComponents/components/rncore (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1133,13 +1030,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/switch (0.84.1): + - React-FabricComponents/components/safeareaview (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1154,13 +1052,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/text (0.84.1): + - React-FabricComponents/components/switch (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1175,13 +1074,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/textinput (0.84.1): + - React-FabricComponents/components/text (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1196,13 +1096,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/unimplementedview (0.84.1): + - React-FabricComponents/components/textinput (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1217,13 +1118,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/virtualview (0.84.1): + - React-FabricComponents/components/unimplementedview (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1238,13 +1140,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/components/virtualviewexperimental (0.84.1): + - React-FabricComponents/components/virtualview (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1259,13 +1162,14 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricComponents/textlayoutmanager (0.84.1): + - React-FabricComponents/textlayoutmanager (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety - React-Core - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1280,59 +1184,72 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-FabricImage (0.84.1): + - React-FabricImage (0.88.0-rc.3): - hermes-engine - - RCTRequired (= 0.84.1) - - RCTTypeSafety (= 0.84.1) + - RCTRequired (= 0.88.0-rc.3) + - RCTTypeSafety (= 0.88.0-rc.3) - React-Core-prebuilt + - React-cxxstableapi - React-Fabric - React-featureflags - React-graphics - React-ImageManager - React-jsi - - React-jsiexecutor (= 0.84.1) + - React-jsiexecutor (= 0.88.0-rc.3) - React-logger - React-rendererdebug - React-utils - ReactCommon - ReactNativeDependencies - Yoga - - React-featureflags (0.84.1): + - React-featureflags (0.88.0-rc.3): - React-Core-prebuilt + - React-cxxstableapi + - React-featureflags/featureflagsUmbrella (= 0.88.0-rc.3) - ReactNativeDependencies - - React-featureflagsnativemodule (0.84.1): + - React-featureflags/featureflagsUmbrella (0.88.0-rc.3): + - React-Core-prebuilt + - React-cxxstableapi + - ReactNativeDependencies + - React-featureflagsnativemodule (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-cxxstableapi - React-featureflags - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-graphics (0.84.1): + - React-graphics (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-featureflags - React-jsi - React-jsiexecutor + - React-rendererdebug - React-utils - ReactNativeDependencies - - React-hermes (0.84.1): + - React-hermes (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - - React-cxxreact (= 0.84.1) + - React-cxxreact (= 0.88.0-rc.3) + - React-cxxstableapi - React-jsi - - React-jsiexecutor (= 0.84.1) + - React-jsiexecutor (= 0.88.0-rc.3) - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing - React-jsitooling - React-oscompat - - React-perflogger (= 0.84.1) + - React-perflogger (= 0.88.0-rc.3) - React-runtimeexecutor - ReactNativeDependencies - - React-idlecallbacksnativemodule (0.84.1): + - React-idlecallbacksnativemodule (0.88.0-rc.3): - hermes-engine + - React-bridging - React-Core-prebuilt + - React-cxxstableapi - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec @@ -1340,19 +1257,22 @@ PODS: - React-runtimescheduler - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-ImageManager (0.84.1): + - React-ImageManager (0.88.0-rc.3): - React-Core-prebuilt - React-Core/Default + - React-cxxstableapi - React-debug - React-Fabric - React-graphics - React-rendererdebug - React-utils - ReactNativeDependencies - - React-intersectionobservernativemodule (0.84.1): + - React-intersectionobservernativemodule (0.88.0-rc.3): - hermes-engine + - React-bridging - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-Fabric - React-Fabric/bridging - React-graphics @@ -1364,23 +1284,24 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - React-jserrorhandler (0.84.1): + - React-jserrorhandler (0.88.0-rc.3): - hermes-engine + - React-bridging - React-Core-prebuilt - - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags - React-jsi - - ReactCommon/turbomodule/bridging - ReactNativeDependencies - - React-jsi (0.84.1): + - React-jsi (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - ReactNativeDependencies - - React-jsiexecutor (0.84.1): + - React-jsiexecutor (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-jserrorhandler - React-jsi @@ -1392,7 +1313,7 @@ PODS: - React-runtimeexecutor - React-utils - ReactNativeDependencies - - React-jsinspector (0.84.1): + - React-jsinspector (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - React-featureflags @@ -1401,56 +1322,87 @@ PODS: - React-jsinspectornetwork - React-jsinspectortracing - React-oscompat - - React-perflogger (= 0.84.1) + - React-perflogger (= 0.88.0-rc.3) - React-runtimeexecutor - React-utils - ReactNativeDependencies - - React-jsinspectorcdp (0.84.1): + - React-jsinspectorcdp (0.88.0-rc.3): - React-Core-prebuilt + - React-cxxstableapi - ReactNativeDependencies - - React-jsinspectornetwork (0.84.1): + - React-jsinspectornetwork (0.88.0-rc.3): - React-Core-prebuilt + - React-cxxstableapi - React-jsinspectorcdp - ReactNativeDependencies - - React-jsinspectortracing (0.84.1): + - React-jsinspectortracing (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-cxxstableapi - React-jsi - React-jsinspectornetwork - React-oscompat - React-timing + - React-utils - ReactNativeDependencies - - React-jsitooling (0.84.1): + - React-jsitooling (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - - React-cxxreact (= 0.84.1) + - React-cxxreact (= 0.88.0-rc.3) + - React-cxxstableapi - React-debug - - React-jsi (= 0.84.1) + - React-jsi (= 0.88.0-rc.3) - React-jsinspector - React-jsinspectorcdp - React-jsinspectortracing - React-runtimeexecutor - React-utils - ReactNativeDependencies - - React-jsitracing (0.84.1): + - React-jsitracing (0.88.0-rc.3): - React-jsi - - React-logger (0.84.1): + - React-logger (0.88.0-rc.3): - React-Core-prebuilt - ReactNativeDependencies - - React-Mapbuffer (0.84.1): + - React-Mapbuffer (0.88.0-rc.3): - React-Core-prebuilt + - React-cxxstableapi - React-debug + - React-Mapbuffer/mapbufferUmbrella (= 0.88.0-rc.3) - ReactNativeDependencies - - React-microtasksnativemodule (0.84.1): + - React-Mapbuffer/mapbufferUmbrella (0.88.0-rc.3): + - React-Core-prebuilt + - React-cxxstableapi + - React-debug + - ReactNativeDependencies + - React-microtasksnativemodule (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-cxxstableapi - React-jsi - React-jsiexecutor - React-RCTFBReactNativeSpec - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-NativeModulesApple (0.84.1): + - React-mutationobservernativemodule (0.88.0-rc.3): - hermes-engine + - React-bridging + - React-Core-prebuilt + - React-cxxreact + - React-cxxstableapi + - React-Fabric + - React-Fabric/bridging + - React-Fabric/observers/mutation + - React-featureflags + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - ReactCommon/turbomodule/core + - ReactNativeDependencies + - Yoga + - React-NativeModulesApple (0.88.0-rc.3): + - hermes-engine + - React-bridging - React-callinvoker - React-Core - React-Core-prebuilt @@ -1461,39 +1413,51 @@ PODS: - React-jsinspector - React-jsinspectorcdp - React-runtimeexecutor - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - - React-networking (0.84.1): + - React-networking (0.88.0-rc.3): - React-Core-prebuilt + - React-cxxstableapi - React-jsinspectornetwork - React-jsinspectortracing - React-performancetimeline - React-timing - ReactNativeDependencies - - React-oscompat (0.84.1) - - React-perflogger (0.84.1): + - React-oscompat (0.88.0-rc.3): + - React-cxxstableapi + - React-perflogger (0.88.0-rc.3): - React-Core-prebuilt - ReactNativeDependencies - - React-performancecdpmetrics (0.84.1): + - React-performancecdpmetrics (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-cxxstableapi - React-jsi - React-performancetimeline - React-runtimeexecutor - React-timing - ReactNativeDependencies - - React-performancetimeline (0.84.1): + - React-performancetimeline (0.88.0-rc.3): - React-Core-prebuilt + - React-cxxstableapi - React-featureflags - React-jsinspector - React-jsinspectortracing - React-perflogger - React-timing - ReactNativeDependencies - - React-RCTActionSheet (0.84.1): - - React-Core/RCTActionSheetHeaders (= 0.84.1) - - React-RCTAnimation (0.84.1): + - React-RCTActionSheet (0.88.0-rc.3): + - React-Core/RCTActionSheetHeaders (= 0.88.0-rc.3) + - React-RCTAnimatedModuleProvider (0.88.0-rc.3): + - hermes-engine + - React-Core + - React-Core-prebuilt + - React-Fabric/animated + - React-featureflags + - ReactCommon + - ReactNativeDependencies + - Yoga + - React-RCTAnimation (0.88.0-rc.3): - RCTTypeSafety - React-Core-prebuilt - React-Core/RCTAnimationHeaders @@ -1504,7 +1468,7 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon - ReactNativeDependencies - - React-RCTAppDelegate (0.84.1): + - React-RCTAppDelegate (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety @@ -1519,9 +1483,11 @@ PODS: - React-hermes - React-jsitooling - React-NativeModulesApple + - React-RCTAnimatedModuleProvider - React-RCTFabric - React-RCTFBReactNativeSpec - React-RCTImage + - React-RCTLinking - React-RCTNetwork - React-RCTRuntime - React-rendererdebug @@ -1532,7 +1498,7 @@ PODS: - React-utils - ReactCommon - ReactNativeDependencies - - React-RCTBlob (0.84.1): + - React-RCTBlob (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - React-Core/RCTBlobHeaders @@ -1545,54 +1511,28 @@ PODS: - React-RCTNetwork - ReactCommon - ReactNativeDependencies - - React-RCTFabric (0.84.1): - - hermes-engine - - RCTSwiftUIWrapper - - React-Core + - React-RCTFabric (0.88.0-rc.3): - React-Core-prebuilt - - React-debug - - React-Fabric - - React-FabricComponents - - React-FabricImage - - React-featureflags - - React-graphics - - React-ImageManager - - React-jsi - - React-jsinspector - - React-jsinspectorcdp - - React-jsinspectortracing - - React-networking - - React-performancecdpmetrics - - React-performancetimeline - - React-RCTAnimation - - React-RCTFBReactNativeSpec - - React-RCTImage - - React-RCTText - - React-rendererconsistency - - React-renderercss - - React-rendererdebug - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - ReactNativeDependencies - - Yoga - - React-RCTFBReactNativeSpec (0.84.1): + - React-RCTFBReactNativeSpec (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-jsi - React-NativeModulesApple - - React-RCTFBReactNativeSpec/components (= 0.84.1) + - React-RCTFBReactNativeSpec/components (= 0.88.0-rc.3) - ReactCommon - ReactNativeDependencies - - React-RCTFBReactNativeSpec/components (0.84.1): + - React-RCTFBReactNativeSpec/components (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1604,7 +1544,7 @@ PODS: - ReactCommon - ReactNativeDependencies - Yoga - - React-RCTImage (0.84.1): + - React-RCTImage (0.88.0-rc.3): - RCTTypeSafety - React-Core-prebuilt - React-Core/RCTImageHeaders @@ -1614,14 +1554,14 @@ PODS: - React-RCTNetwork - ReactCommon - ReactNativeDependencies - - React-RCTLinking (0.84.1): - - React-Core/RCTLinkingHeaders (= 0.84.1) - - React-jsi (= 0.84.1) + - React-RCTLinking (0.88.0-rc.3): + - React-Core/RCTLinkingHeaders (= 0.88.0-rc.3) + - React-jsi (= 0.88.0-rc.3) - React-NativeModulesApple - React-RCTFBReactNativeSpec - ReactCommon - - ReactCommon/turbomodule/core (= 0.84.1) - - React-RCTNetwork (0.84.1): + - ReactCommon/turbomodule/core (= 0.88.0-rc.3) + - React-RCTNetwork (0.88.0-rc.3): - RCTTypeSafety - React-Core-prebuilt - React-Core/RCTNetworkHeaders @@ -1635,23 +1575,9 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon - ReactNativeDependencies - - React-RCTRuntime (0.84.1): - - hermes-engine - - React-Core + - React-RCTRuntime (0.88.0-rc.3): - React-Core-prebuilt - - React-debug - - React-jsi - - React-jsinspector - - React-jsinspectorcdp - - React-jsinspectortracing - - React-jsitooling - - React-RuntimeApple - - React-RuntimeCore - - React-runtimeexecutor - - React-RuntimeHermes - - React-utils - - ReactNativeDependencies - - React-RCTSettings (0.84.1): + - React-RCTSettings (0.88.0-rc.3): - RCTTypeSafety - React-Core-prebuilt - React-Core/RCTSettingsHeaders @@ -1660,10 +1586,10 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon - ReactNativeDependencies - - React-RCTText (0.84.1): - - React-Core/RCTTextHeaders (= 0.84.1) + - React-RCTText (0.88.0-rc.3): + - React-Core/RCTTextHeaders (= 0.88.0-rc.3) - Yoga - - React-RCTVibration (0.84.1): + - React-RCTVibration (0.88.0-rc.3): - React-Core-prebuilt - React-Core/RCTVibrationHeaders - React-jsi @@ -1671,21 +1597,40 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon - ReactNativeDependencies - - React-rendererconsistency (0.84.1) - - React-renderercss (0.84.1): + - React-rendererconsistency (0.88.0-rc.3) + - React-renderercss (0.88.0-rc.3): - React-debug - React-utils - - React-rendererdebug (0.84.1): + - React-rendererdebug (0.88.0-rc.3): - React-Core-prebuilt - React-debug - ReactNativeDependencies - - React-RuntimeApple (0.84.1): + - React-resizeobservernativemodule (0.88.0-rc.3): + - hermes-engine + - React-bridging + - React-Core-prebuilt + - React-cxxreact + - React-cxxstableapi + - React-Fabric + - React-Fabric/bridging + - React-Fabric/observers/resize + - React-graphics + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - React-runtimescheduler + - ReactCommon/turbomodule/core + - ReactNativeDependencies + - Yoga + - React-RuntimeApple (0.88.0-rc.3): - hermes-engine - React-callinvoker - React-Core-prebuilt - React-Core/Default - React-CoreModules - React-cxxreact + - React-cxxstableapi - React-featureflags - React-jserrorhandler - React-jsi @@ -1702,10 +1647,11 @@ PODS: - React-runtimescheduler - React-utils - ReactNativeDependencies - - React-RuntimeCore (0.84.1): + - React-RuntimeCore (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-Fabric - React-featureflags - React-jserrorhandler @@ -1718,16 +1664,17 @@ PODS: - React-runtimescheduler - React-utils - ReactNativeDependencies - - React-runtimeexecutor (0.84.1): + - React-runtimeexecutor (0.88.0-rc.3): - React-Core-prebuilt - React-debug - React-featureflags - - React-jsi (= 0.84.1) + - React-jsi (= 0.88.0-rc.3) - React-utils - ReactNativeDependencies - - React-RuntimeHermes (0.84.1): + - React-RuntimeHermes (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-cxxstableapi - React-featureflags - React-hermes - React-jsi @@ -1740,13 +1687,15 @@ PODS: - React-runtimeexecutor - React-utils - ReactNativeDependencies - - React-runtimescheduler (0.84.1): + - React-runtimescheduler (0.88.0-rc.3): - hermes-engine - React-callinvoker - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-debug - React-featureflags + - React-jserrorhandler - React-jsi - React-jsinspectortracing - React-performancetimeline @@ -1756,18 +1705,37 @@ PODS: - React-timing - React-utils - ReactNativeDependencies - - React-timing (0.84.1): + - React-timing (0.88.0-rc.3): + - React-cxxstableapi + - React-debug + - React-timing/timingUmbrella (= 0.88.0-rc.3) + - React-timing/timingUmbrella (0.88.0-rc.3): + - React-cxxstableapi - React-debug - - React-utils (0.84.1): + - React-utils (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt - React-debug - - React-jsi (= 0.84.1) + - React-jsi (= 0.88.0-rc.3) - ReactNativeDependencies - - React-webperformancenativemodule (0.84.1): + - React-viewtransitionnativemodule (0.88.0-rc.3): - hermes-engine - React-Core-prebuilt + - React-Fabric + - React-Fabric/bridging + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - ReactCommon/turbomodule/core + - ReactNativeDependencies + - Yoga + - React-webperformancenativemodule (0.88.0-rc.3): + - hermes-engine + - React-bridging + - React-Core-prebuilt - React-cxxreact + - React-cxxstableapi - React-jsi - React-jsiexecutor - React-performancetimeline @@ -1775,12 +1743,13 @@ PODS: - React-runtimeexecutor - ReactCommon/turbomodule/core - ReactNativeDependencies - - ReactAppDependencyProvider (0.84.1): + - ReactAppDependencyProvider (0.88.0-rc.3): - ReactCodegen - - ReactCodegen (0.84.1): + - ReactCodegen (0.88.0-rc.3): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt - React-debug @@ -1794,52 +1763,43 @@ PODS: - React-RCTAppDelegate - React-rendererdebug - React-utils - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - - ReactCommon (0.84.1): + - ReactCommon (0.88.0-rc.3): - React-Core-prebuilt - - ReactCommon/turbomodule (= 0.84.1) + - ReactCommon/turbomodule (= 0.88.0-rc.3) - ReactNativeDependencies - - ReactCommon/turbomodule (0.84.1): + - ReactCommon/turbomodule (0.88.0-rc.3): - hermes-engine - - React-callinvoker (= 0.84.1) + - React-callinvoker (= 0.88.0-rc.3) - React-Core-prebuilt - - React-cxxreact (= 0.84.1) - - React-jsi (= 0.84.1) - - React-logger (= 0.84.1) - - React-perflogger (= 0.84.1) - - ReactCommon/turbomodule/bridging (= 0.84.1) - - ReactCommon/turbomodule/core (= 0.84.1) + - React-jsi (= 0.88.0-rc.3) + - React-logger (= 0.88.0-rc.3) + - React-perflogger (= 0.88.0-rc.3) + - ReactCommon/turbomodule/core (= 0.88.0-rc.3) - ReactNativeDependencies - - ReactCommon/turbomodule/bridging (0.84.1): + - ReactCommon/turbomodule/core (0.88.0-rc.3): - hermes-engine - - React-callinvoker (= 0.84.1) + - React-bridging + - React-callinvoker (= 0.88.0-rc.3) - React-Core-prebuilt - - React-cxxreact (= 0.84.1) - - React-jsi (= 0.84.1) - - React-logger (= 0.84.1) - - React-perflogger (= 0.84.1) + - React-cxxreact (= 0.88.0-rc.3) + - React-debug (= 0.88.0-rc.3) + - React-featureflags (= 0.88.0-rc.3) + - React-jsi (= 0.88.0-rc.3) + - React-logger (= 0.88.0-rc.3) + - React-perflogger (= 0.88.0-rc.3) + - React-utils (= 0.88.0-rc.3) - ReactNativeDependencies - - ReactCommon/turbomodule/core (0.84.1): - - hermes-engine - - React-callinvoker (= 0.84.1) - - React-Core-prebuilt - - React-cxxreact (= 0.84.1) - - React-debug (= 0.84.1) - - React-featureflags (= 0.84.1) - - React-jsi (= 0.84.1) - - React-logger (= 0.84.1) - - React-perflogger (= 0.84.1) - - React-utils (= 0.84.1) - - ReactNativeDependencies - - ReactNativeDependencies (0.84.1) + - ReactNativeDependencies (0.88.0-rc.3) - RNCAsyncStorage (2.2.0): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1852,16 +1812,17 @@ PODS: - React-rendererdebug - React-utils - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - RNGestureHandler (2.31.2): + - RNGestureHandler (2.33.0): - hermes-engine - RCTRequired - RCTTypeSafety + - React-bridging - React-Core - React-Core-prebuilt + - React-cxxstableapi - React-debug - React-Fabric - React-featureflags @@ -1874,30 +1835,40 @@ PODS: - React-rendererdebug - React-utils - ReactCodegen - - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga + - SocketRocket (0.7.1): + - ReactNativeDependencies - SSZipArchive (2.4.3) - - Yoga (0.0.0) + - Yoga (0.0.0): + - React-Core-prebuilt DEPENDENCIES: - - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - boost (from `build/rndeps-facades/boost`) + - DoubleConversion (from `build/rndeps-facades/DoubleConversion`) + - fast_float (from `build/rndeps-facades/fast_float`) + - FBLazyVector (from `build/rncore-facades/FBLazyVector`) + - fmt (from `build/rndeps-facades/fmt`) + - glog (from `build/rndeps-facades/glog`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - MendixNative (from `../..`) - "op-sqlite (from `../node_modules/@op-engineering/op-sqlite`)" - - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - - RCTRequired (from `../node_modules/react-native/Libraries/Required`) + - RCT-Folly (from `build/rndeps-facades/RCT-Folly`) + - RCTDeprecation (from `build/rncore-facades/RCTDeprecation`) + - RCTRequired (from `build/rncore-facades/RCTRequired`) - RCTSwiftUI (from `../node_modules/react-native/ReactApple/RCTSwiftUI`) - RCTSwiftUIWrapper (from `../node_modules/react-native/ReactApple/RCTSwiftUIWrapper`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - React (from `../node_modules/react-native/`) + - React-bridging (from `../node_modules/react-native/ReactCommon/react/bridging`) - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - - React-Core (from `../node_modules/react-native/`) + - React-Core (from `build/rncore-facades/React-Core`) - React-Core-prebuilt (from `../node_modules/react-native/React-Core-prebuilt.podspec`) - - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `build/rncore-facades/React-Core`) - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-cxxstableapi (from `../node_modules/react-native/ReactCommon/react/cxxstableapi`) - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) @@ -1923,6 +1894,7 @@ DEPENDENCIES: - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - React-mutationobservernativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/mutationobserver`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-networking (from `../node_modules/react-native/ReactCommon/react/networking`) - React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`) @@ -1930,21 +1902,23 @@ DEPENDENCIES: - React-performancecdpmetrics (from `../node_modules/react-native/ReactCommon/react/performance/cdpmetrics`) - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimatedModuleProvider (from `../node_modules/react-native/ReactApple/RCTAnimatedModuleProvider`) - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) - - React-RCTFabric (from `../node_modules/react-native/React`) + - React-RCTFabric (from `build/rncore-facades/React-RCTFabric`) - React-RCTFBReactNativeSpec (from `../node_modules/react-native/React`) - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) - - React-RCTRuntime (from `../node_modules/react-native/React/Runtime`) + - React-RCTRuntime (from `build/rncore-facades/React-RCTRuntime`) - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) - React-renderercss (from `../node_modules/react-native/ReactCommon/react/renderer/css`) - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-resizeobservernativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/resizeobserver`) - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) @@ -1952,6 +1926,7 @@ DEPENDENCIES: - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-timing (from `../node_modules/react-native/ReactCommon/react/timing`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - React-viewtransitionnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/viewtransition`) - React-webperformancenativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/webperformance`) - ReactAppDependencyProvider (from `build/generated/ios/ReactAppDependencyProvider`) - ReactCodegen (from `build/generated/ios/ReactCodegen`) @@ -1959,7 +1934,8 @@ DEPENDENCIES: - ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`) - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + - SocketRocket (from `build/rndeps-facades/SocketRocket`) + - Yoga (from `build/rncore-facades/Yoga`) SPEC REPOS: trunk: @@ -1967,19 +1943,31 @@ SPEC REPOS: - SSZipArchive EXTERNAL SOURCES: + boost: + :path: build/rndeps-facades/boost + DoubleConversion: + :path: build/rndeps-facades/DoubleConversion + fast_float: + :path: build/rndeps-facades/fast_float FBLazyVector: - :path: "../node_modules/react-native/Libraries/FBLazyVector" + :path: build/rncore-facades/FBLazyVector + fmt: + :path: build/rndeps-facades/fmt + glog: + :path: build/rndeps-facades/glog hermes-engine: :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" - :tag: hermes-v250829098.0.9 + :tag: hermes-v260318099.0.2 MendixNative: :path: "../.." op-sqlite: :path: "../node_modules/@op-engineering/op-sqlite" + RCT-Folly: + :path: build/rndeps-facades/RCT-Folly RCTDeprecation: - :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + :path: build/rncore-facades/RCTDeprecation RCTRequired: - :path: "../node_modules/react-native/Libraries/Required" + :path: build/rncore-facades/RCTRequired RCTSwiftUI: :path: "../node_modules/react-native/ReactApple/RCTSwiftUI" RCTSwiftUIWrapper: @@ -1988,16 +1976,20 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/TypeSafety" React: :path: "../node_modules/react-native/" + React-bridging: + :path: "../node_modules/react-native/ReactCommon/react/bridging" React-callinvoker: :path: "../node_modules/react-native/ReactCommon/callinvoker" React-Core: - :path: "../node_modules/react-native/" + :path: build/rncore-facades/React-Core React-Core-prebuilt: :podspec: "../node_modules/react-native/React-Core-prebuilt.podspec" React-CoreModules: :path: "../node_modules/react-native/React/CoreModules" React-cxxreact: :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-cxxstableapi: + :path: "../node_modules/react-native/ReactCommon/react/cxxstableapi" React-debug: :path: "../node_modules/react-native/ReactCommon/react/debug" React-defaultsnativemodule: @@ -2048,6 +2040,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" React-microtasksnativemodule: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + React-mutationobservernativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/mutationobserver" React-NativeModulesApple: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-networking: @@ -2062,6 +2056,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" React-RCTActionSheet: :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimatedModuleProvider: + :path: "../node_modules/react-native/ReactApple/RCTAnimatedModuleProvider" React-RCTAnimation: :path: "../node_modules/react-native/Libraries/NativeAnimation" React-RCTAppDelegate: @@ -2069,7 +2065,7 @@ EXTERNAL SOURCES: React-RCTBlob: :path: "../node_modules/react-native/Libraries/Blob" React-RCTFabric: - :path: "../node_modules/react-native/React" + :path: build/rncore-facades/React-RCTFabric React-RCTFBReactNativeSpec: :path: "../node_modules/react-native/React" React-RCTImage: @@ -2079,7 +2075,7 @@ EXTERNAL SOURCES: React-RCTNetwork: :path: "../node_modules/react-native/Libraries/Network" React-RCTRuntime: - :path: "../node_modules/react-native/React/Runtime" + :path: build/rncore-facades/React-RCTRuntime React-RCTSettings: :path: "../node_modules/react-native/Libraries/Settings" React-RCTText: @@ -2092,6 +2088,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/renderer/css" React-rendererdebug: :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" + React-resizeobservernativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/resizeobserver" React-RuntimeApple: :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" React-RuntimeCore: @@ -2106,6 +2104,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/timing" React-utils: :path: "../node_modules/react-native/ReactCommon/react/utils" + React-viewtransitionnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/viewtransition" React-webperformancenativemodule: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/webperformance" ReactAppDependencyProvider: @@ -2120,89 +2120,104 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-async-storage/async-storage" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" + SocketRocket: + :path: build/rndeps-facades/SocketRocket Yoga: - :path: "../node_modules/react-native/ReactCommon/yoga" + :path: build/rncore-facades/Yoga SPEC CHECKSUMS: - FBLazyVector: e97c19a5a442429d1988f182a1940fb08df514da - hermes-engine: a7179a4cd45fa3f8143712e52bd3c2d20b5274a0 - MendixNative: 455c4ad23d8a7c632c223d3c899edfa0ed95b5dd - op-sqlite: e9ef65bcf95a97863874cee87841425bb71c8396 + boost: 8502bfdc46e2804408af2e163049ece181009af4 + DoubleConversion: 501a575c40c0b50c89685762dd3e415e6bb26fb0 + fast_float: 7c925d1cebf8328d4018d061f49377e9f887e3b4 + FBLazyVector: ef9b6a95cc4517abbb071142b8cfddd77811c031 + fmt: ba0886e864ebb21d14c98b2e12e164b8002f5b93 + glog: 3cf7cb46f743c4bc758ae3e6d9c15bd1b4cfd6d4 + hermes-engine: a1158910bb7e300b9e3d2f1e2d433f817ec1a4b5 + MendixNative: 978e728a9a8766e743e073f344756648959df3c3 + op-sqlite: 35c49f420ecc7c3890ce85f00b97cd80e51ca043 OpenSSL-Universal: 9110d21982bb7e8b22a962b6db56a8aa805afde7 - RCTDeprecation: af44b104091a34482596cd9bd7e8d90c4e9b4bd7 - RCTRequired: bb77b070f75f53398ce43c0aaaa58337cebe2bf6 - RCTSwiftUI: afc0a0a635860da1040a0b894bfd529da06d7810 - RCTSwiftUIWrapper: 3197c020094f3b2151bb2d1223f7276787be8166 - RCTTypeSafety: d13e192a37f151ce354641184bf4239844a3be17 - React: 1ba7d364ade7d883a1ec055bfc3606f35fdee17b - React-callinvoker: bc2a26f8d84fb01f003fc6de6c9337b64715f95b - React-Core: 7840d3a80b43a95c5e80ef75146bd70925ebab0f - React-Core-prebuilt: a666604237ac1fb51754ee37234701cf197d851b - React-CoreModules: 2eb010400b63b89e53a324ffb3c112e4c7c3ce42 - React-cxxreact: a558e92199d26f145afa9e62c4233cf8e7950efe - React-debug: 755200a6e7f5e6e0a40ff8d215493d43cce285fc - React-defaultsnativemodule: bb85b1bdd9b4b82650cfa92998567fcfdb030145 - React-domnativemodule: ffdba8ba4323387e821d8298be2013516036df87 - React-Fabric: 8705ba7f14acf5b1df474d1af4b0191c69ac4690 - React-FabricComponents: 5a1b5007fe8c5d5f043e45c335ebef2af0717fb2 - React-FabricImage: e96eea6bb65b501cf5db3ce4ad057a97dea1dd69 - React-featureflags: 410f6c383eb94019f63f105374d738169df291ae - React-featureflagsnativemodule: 5d6d7931ec5d4576639661c0f79169a0ae383023 - React-graphics: b9b69adbe79d6944838aa304c849d78f977e9f21 - React-hermes: 666c66bbc856b46dfa4b132f1c9efaa37ad419a1 - React-idlecallbacksnativemodule: 785d307b9236ec9fb4ec0bcf99b34e8539d2d76e - React-ImageManager: daeef8b1c19803c71a9233f21f7f235cd3ec294e - React-intersectionobservernativemodule: c17189d2350205012682aefe566f7ebaa4f980e3 - React-jserrorhandler: 431377b3d1783127bc394986fe8d932bcb8982fe - React-jsi: 33db13b95bb53827b03d9fb0f567d12b63dfc8ef - React-jsiexecutor: 49de4d48a7c4f283eaa865f7a4f3919f2c39be1c - React-jsinspector: 3ec7dd478806a0eb4ec6ab394e51a395e8f895ba - React-jsinspectorcdp: bcb79a666959b1a3e8aac3ff8209d05c719aaa2a - React-jsinspectornetwork: be3b81a6342b56c74dd0bdd58bf3f62f978c1472 - React-jsinspectortracing: 293251deadf7c255da593bf1d9d337a645abdfdc - React-jsitooling: 6f729cdb85ff0c8294709ec1903e1f0c59662331 - React-jsitracing: be95d903cc9440ab89a704c999dd7db6675dc47f - React-logger: b5521614afb8690420146dfc61a1447bb5d65419 - React-Mapbuffer: f4ee8c62e0ef8359d139124f35a471518a172cd3 - React-microtasksnativemodule: d1956f0eec54c619b63a379520fb4c618a55ccb9 - React-NativeModulesApple: 5ba0903927f6b8d335a091700e9fda143980f819 - React-networking: 3a4b7f9ed2b2d1c0441beacb79674323a24bcca6 - React-oscompat: ff26abf0ae3e3fdbe47b44224571e3fc7226a573 - React-perflogger: a86b2146936f2ffa80188425c6e8892729e2ad01 - React-performancecdpmetrics: 65b699c3e52c0a1d978d9cdf15e60c62e335b900 - React-performancetimeline: b44f82caa563e46068d02d9cf5b0d2b84bdc7a6a - React-RCTActionSheet: fc1d5d419856868e7f8c13c14591ed63dadef43a - React-RCTAnimation: 2a1e7eeb55b71e8524db296fa31e46eeaa2d0da4 - React-RCTAppDelegate: 317c1102a2d0bcc07567d8de58d9147102080b0e - React-RCTBlob: c82bbf96b2d1389550c05fb9739d4e85d471052e - React-RCTFabric: d82ad8120ba70fe63207e261b9e33d9b6077e2de - React-RCTFBReactNativeSpec: 4d33b5f3b339e9fa902168e8a1d62c458dda16e9 - React-RCTImage: f959463e53ea731ab267e371eea1b92fccf27634 - React-RCTLinking: 2a857113b8059ac4f0a8ae89f8aa312837b955d0 - React-RCTNetwork: dc026bf25f6457249349be8cf8bd5fdf84cdfb14 - React-RCTRuntime: b0630731fd864064066301e1e31406fea606d5f9 - React-RCTSettings: e159e19475df2e92fd3b4ddcfe29f6cc12cf0ee4 - React-RCTText: 7356cc84c2ed79635931891c176f72e0289dc75d - React-RCTVibration: 77621175b67b22e655ce4b29d1cda8498f2033e7 - React-rendererconsistency: e91aba4bb482dac127ad955dba6333a8af629c5b - React-renderercss: 7cc41efaecf557d7b70edaa08fad5ace79f714f6 - React-rendererdebug: 0f004cbed7b4c27327423be47209770830bf3c6d - React-RuntimeApple: 6f4ff8e2d8b05cb3ceabf57e494c04da8751f009 - React-RuntimeCore: 25be9c7025eabb524cd00dbb6ce56d6b122e3d92 - React-runtimeexecutor: 84d394b9f0a8fc7dab8a98bf88a43228bb04dac2 - React-RuntimeHermes: 2bed5b2d2419945cc5c2f6d627a1b46ce3a0f66a - React-runtimescheduler: 23b092dbcd3088f9c947551c23366dd00254caf3 - React-timing: 2ab9ccd4b41aa171090c16f664f6c5bfb2fd0ddc - React-utils: 8d888b379f0808bfabaea03d85f9e8dd9b8548da - React-webperformancenativemodule: c10016db7f1bb1153060d4aa9f7dbde2c88c845d - ReactAppDependencyProvider: e96e93b493d8d86eeaee3e590ba0be53f6abe46f - ReactCodegen: 797de5178718324c6eba3327b07f9a423fbd5787 - ReactCommon: 07572bf9e687c8a52fbe4a3641e9e3a1a477c78e - ReactNativeDependencies: 9ed9fcba1a22047730c895521de699bacbb90312 - RNCAsyncStorage: 3a4f5e2777dae1688b781a487923a08569e27fe4 - RNGestureHandler: b4f6de20b30325ee40b693f558ad02213201ce91 + RCT-Folly: 82921e585c0400eda46fac1068297aa9dfb035e4 + RCTDeprecation: 5c034047b1d03c50321e4d7cb0a5d3e0d43f9af0 + RCTRequired: cd4fe49ee5ac84c0f62e483f93206a456f0bceee + RCTSwiftUI: 52082a46da2b839a2779026752375ea59a04110c + RCTSwiftUIWrapper: d5b8645274e112a316aea9d163428826b87a8913 + RCTTypeSafety: ee3d9baad6286c2ef45ef379409908d790d8804f + React: 8481ff37bcd808e18b85af345ce2657c36b710e6 + React-bridging: 1aefed44104d9f96331be33c3dd98d90c0cb659b + React-callinvoker: ac6c2fc9b50d76a288e691f11c291117774bda06 + React-Core: 6853ddd4abd39ec72c3c8607d300c9834d9e81c4 + React-Core-prebuilt: efbd0e6abf3ed16dfb9266e287e54055410853fa + React-CoreModules: 68fe06622841f65486b0a2766e9121221acbbfd1 + React-cxxreact: 44f1f66e0253215f4b66157cde67a2c0b23bf22e + React-cxxstableapi: 57f354ce04cee8c512be47564d504ea0a5ea4c88 + React-debug: b15be93fef4cfc9bf2626466c1debfb622a47ce5 + React-defaultsnativemodule: c3c1b3d858e87595052a485c3ed5a31cb3e4adfe + React-domnativemodule: 336b709eddd02fbe246cede4fb7da69b1e41770a + React-Fabric: 0f1597b153f76ed8cc36fdb702f7cbf13ff2efc6 + React-FabricComponents: 998508427c3eba5e863272778a5cee273589ca58 + React-FabricImage: 8e1d78cdb6a80588e901b7c059e89488e788f4ea + React-featureflags: 09128a24814d12cbe664ed3c61d6eb172e5401ff + React-featureflagsnativemodule: 41bd0f142db8eb3158ce0f703d83a67774f65efd + React-graphics: c897611bd82c592a45f79998c33d07a8147d87e5 + React-hermes: 29071fbc6965fe36fcb975cdac0e75a0289df5ed + React-idlecallbacksnativemodule: 0791c6168b6d56a263c285600e151de12e5fb23e + React-ImageManager: 774627401d7a4d0f1cd7bf90d6bf2c610ec74731 + React-intersectionobservernativemodule: 565a8e14f37ee6f3a35769b493208b605630f550 + React-jserrorhandler: b755866f88c0794c9c1d0c8a6d07b02b05811b3e + React-jsi: e01cc5236728a086d41ae03bdfe0c13c23a9c2d7 + React-jsiexecutor: a4443846bf69cf1f829e128b251619ea418522da + React-jsinspector: ba0583f41e4dc47583589f5cc6d7256a65a04365 + React-jsinspectorcdp: d8d7ebe9d7abc0230b7613a8eeb98d45148e3cd4 + React-jsinspectornetwork: e9a6d50516512a4f8afb003f47e66fc02ca36e14 + React-jsinspectortracing: 4bca3eea80bbc83a83f3510f3023496492d97c5c + React-jsitooling: a8ad633a5cf6c5090a144d56dc3ab9ce9b7f3a87 + React-jsitracing: 2f653042940aad792cb80f0243cc6274e1f2267b + React-logger: e4d2983ed19fcb983733acd66178927527a7cfad + React-Mapbuffer: d5a910808e159d5780a384937f2f289cd929f210 + React-microtasksnativemodule: 9bdc748bc7766ae29e1f04a30993bdb95f4c0fb7 + React-mutationobservernativemodule: 13aac2d70ba3905b08008656a790b18f7befb7c7 + React-NativeModulesApple: 999002af8ab66eaac2081c63c22ecd6c87cc0b03 + React-networking: aa69f8768a1948016b29b73a755add782790a1f2 + React-oscompat: e37c189485c22d908ac597c698e1af4cd0138dc2 + React-perflogger: 6ea87fd1a41c5b9aae156974677a3b326cf18010 + React-performancecdpmetrics: 9daab7ed2b1d20e560a3faf2d0c49f8376ea860a + React-performancetimeline: c66a0922af954d80a6658c54d47ea77db6b0cdae + React-RCTActionSheet: 31d73e87210e1d2ce32ef5bb18977749307ed037 + React-RCTAnimatedModuleProvider: a56c58011516b048cf986cd80acb955be7ad1695 + React-RCTAnimation: 401bececd892b386b352e425482af4805648f704 + React-RCTAppDelegate: f86ddf49e2d27cece224b4abc26249f3a090424d + React-RCTBlob: 24b8aa9bd86662e0c82e3bcd16bce8c920c252e8 + React-RCTFabric: 2f77c38c8d1685549c4013bc96b5ebf2fe72db1e + React-RCTFBReactNativeSpec: b833c2103f6e06a10c7cf6eddb73ad306d87b8cc + React-RCTImage: a6dcd8c9afb08deccacc589e3a0339a25abfb33e + React-RCTLinking: 38d3bf388b32f61d4f3688360d329e31a1663a9c + React-RCTNetwork: 97e8fc197cb5320a4fe9cb2903006990bf26ff59 + React-RCTRuntime: b8549e10404bfee61eb233a0cf2477f886a3c7ba + React-RCTSettings: 12daed63338921949bd284ff2e7fc844ae5a1b42 + React-RCTText: dcdf3c1375d50ec75c0da86ddc505672db66d68d + React-RCTVibration: 1240f0f3a3c520a7432552f7c7b3aeb078dc31c2 + React-rendererconsistency: be9375ecf17c8314d8362742bfb5cd85c17d93d7 + React-renderercss: ad2db79c4c625fd2593e2259d3279ce6c4000d93 + React-rendererdebug: 8115b1932811b1c9a775f8480f4188cfca35ae6a + React-resizeobservernativemodule: 4c783c449ebd7fbbc579afab1043fd3c3df10d64 + React-RuntimeApple: ef1e910bb7b73dd511fc0a6f17dc14dd4dfde8a7 + React-RuntimeCore: cdbc5df5657d609685c56ab33af11ad98f7cd511 + React-runtimeexecutor: 39700afb1d262a1bb989e1462d6cf8681bb9ad14 + React-RuntimeHermes: daa379749073b0fe28b2dcf7d9c898c3f424e4ca + React-runtimescheduler: 9fab6de66403268257eb02c61c3a1740335f5c76 + React-timing: 1fad79368ce7222e59640f97c205d16b1557f916 + React-utils: ee7a1e77c52943c17130b1bb0bbe0226dc73d612 + React-viewtransitionnativemodule: 46f16d7424211818474442e89885d4679228d1fd + React-webperformancenativemodule: 05b19df261de4ba2dfcc7ab9080a0c0c056f1a0b + ReactAppDependencyProvider: 7a86900b342815446f0d353a877f2b777597c365 + ReactCodegen: fd1482b53f6ef90c9558bba383ff12213c7e6da6 + ReactCommon: 4273431f94620e485114031bab040602f60016ff + ReactNativeDependencies: 6241d10de6f9bb4b93bd318ab3b59fd98cd5539a + RNCAsyncStorage: 9aad1f18e1b3d98690ae696b01bd984054108916 + RNGestureHandler: c30d0805eccd9b0f143c252ae769131096337322 + SocketRocket: 37aec555668fb852ec12e3c0de59a86ca58f0871 SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef - Yoga: c0b3f2c7e8d3e327e450223a2414ca3fa296b9a2 + Yoga: d1c536142c5ff8ec8cd856ab2a7c227a1d875c8e PODFILE CHECKSUM: 115c3d28fbc33ec0a408f3aba951d5d16e47a401 diff --git a/example/package.json b/example/package.json index eafae15..67ffd01 100644 --- a/example/package.json +++ b/example/package.json @@ -22,25 +22,25 @@ "harness:ios:with:build": "yarn app:package:ios && yarn app:install:ios && yarn harness:ios" }, "dependencies": { - "@op-engineering/op-sqlite": "15.2.5", + "@op-engineering/op-sqlite": "18.2.5", "@react-native-async-storage/async-storage": "2.2.0", - "react": "19.2.3", - "react-native": "0.84.1", - "react-native-gesture-handler": "2.31.2" + "react": "19.3.0", + "react-native": "0.88.0-rc.3", + "react-native-gesture-handler": "2.33.0" }, "devDependencies": { "@babel/core": "7.29.0", "@babel/preset-env": "7.29.0", "@babel/runtime": "^7.28.6", - "@react-native-community/cli": "20.1.3", - "@react-native-community/cli-platform-android": "20.1.3", - "@react-native-community/cli-platform-ios": "20.1.3", + "@react-native-community/cli": "20.2.0", + "@react-native-community/cli-platform-android": "20.2.0", + "@react-native-community/cli-platform-ios": "20.2.0", "@react-native-harness/jest": "1.1.0", "@react-native-harness/platform-android": "1.1.0", "@react-native-harness/platform-apple": "1.1.0", - "@react-native/babel-preset": "0.84.1", - "@react-native/metro-config": "0.84.1", - "@react-native/typescript-config": "0.84.1", + "@react-native/babel-preset": "0.88.0-rc.3", + "@react-native/metro-config": "0.88.0-rc.3", + "@react-native/typescript-config": "0.88.0-rc.3", "@types/react": "19.2.14", "react-native-builder-bob": "0.40.18", "react-native-harness": "1.1.0", diff --git a/example/rn-harness.config.mjs b/example/rn-harness.config.mjs index 3190d96..5495e15 100644 --- a/example/rn-harness.config.mjs +++ b/example/rn-harness.config.mjs @@ -20,12 +20,12 @@ const config = { runners: [ androidPlatform({ name: 'android', - device: androidEmulator('Pixel_API_35'), + device: androidEmulator('Pixel_10'), bundleId: 'mendixnative.example', }), applePlatform({ name: 'ios', - device: appleSimulator('iPhone 17', '26.2'), + device: appleSimulator('iPhone 17e', '26.5'), bundleId: 'mendixnative.example', }), ], diff --git a/ios/Modules/Encryption/EncryptedStorage.swift b/ios/Modules/Encryption/EncryptedStorage.swift index c0c1bf7..f3c6cc1 100644 --- a/ios/Modules/Encryption/EncryptedStorage.swift +++ b/ios/Modules/Encryption/EncryptedStorage.swift @@ -1,5 +1,6 @@ import Foundation +import LocalAuthentication @objcMembers public class EncryptedStorage: NSObject { @@ -34,7 +35,7 @@ import Foundation kSecAttrAccount: key, kSecReturnData: kCFBooleanTrue as Any, kSecMatchLimit: kSecMatchLimitOne, - kSecUseAuthenticationUI: kSecUseAuthenticationUIFail + kSecUseAuthenticationContext: EncryptedStorage.nonInteractiveContext() ] as CFDictionary var dataRef: CFTypeRef? let status = SecItemCopyMatching(query, &dataRef) @@ -54,6 +55,13 @@ import Foundation } } + // Fails with errSecInteractionNotAllowed instead of showing an authentication prompt. + private static func nonInteractiveContext() -> LAContext { + let context = LAContext() + context.interactionNotAllowed = true + return context + } + public func removeItem(key: String, promise: Promise) { let query = [ diff --git a/ios/Modules/ErrorHandler/NativeErrorHandler.swift b/ios/Modules/ErrorHandler/NativeErrorHandler.swift index 7b5886a..1701333 100644 --- a/ios/Modules/ErrorHandler/NativeErrorHandler.swift +++ b/ios/Modules/ErrorHandler/NativeErrorHandler.swift @@ -3,7 +3,18 @@ import React @objcMembers public class NativeErrorHandler: NSObject { + private let exceptionsManager: RCTExceptionsManager? + + public init(exceptionsManager: RCTExceptionsManager?) { + self.exceptionsManager = exceptionsManager + super.init() + } + + public override convenience init() { + self.init(exceptionsManager: nil) + } + public func handle(message: String, stackTrace: [[String: Any]]) { - DevHelper.getModule(type: RCTExceptionsManager.self)?.reportFatalException(message, stack: stackTrace, exceptionId: -1) + exceptionsManager?.reportFatalException(message, stack: stackTrace, exceptionId: -1) } } diff --git a/ios/Modules/Helper/DevHelper.swift b/ios/Modules/Helper/DevHelper.swift index b18f8e8..460a5da 100644 --- a/ios/Modules/Helper/DevHelper.swift +++ b/ios/Modules/Helper/DevHelper.swift @@ -6,18 +6,19 @@ public class DevHelper { AppPreferences.remoteDebuggingEnabled = enabled } + @MainActor public static func setShakeToShowDevMenuEnabled(enabled: Bool) { getModule(type: RCTDevSettings.self)?.isShakeToShowDevMenuEnabled = enabled - - // This event can be triggered to facilitate communication with the DevSettings JS module. Please refer to dev-settings.ts for further details. - // ReactHostHelper().emitEvent("mendixSetShakeToShowDevMenu", payload: enabled) } + @MainActor public static func hideDevLoadingView() { getModule(type: RCTDevLoadingView.self)?.hide() } - public static func getModule(type: T.Type) -> T? { - return ReactHostHelper().module(for: T.self) as? T + // Private so only main-thread callers in this file can use it. TurboModules must use their injected moduleRegistry. + @MainActor + private static func getModule(type: T.Type) -> T? { + return ReactHostHelper.module(for: T.self) as? T } } diff --git a/ios/Modules/Helper/LegacyWindowAppDelegate.swift b/ios/Modules/Helper/LegacyWindowAppDelegate.swift new file mode 100644 index 0000000..b50773b --- /dev/null +++ b/ios/Modules/Helper/LegacyWindowAppDelegate.swift @@ -0,0 +1,8 @@ +import UIKit + +open class LegacyWindowAppDelegate: UIResponder, UIApplicationDelegate { + @objc open var window: UIWindow? { + get { ReactAppProvider.shared()?.window } + set { ReactAppProvider.shared()?.window = newValue } + } +} diff --git a/ios/Modules/Helper/ReactAppProvider.swift b/ios/Modules/Helper/ReactAppProvider.swift index 4c222f2..459097e 100644 --- a/ios/Modules/Helper/ReactAppProvider.swift +++ b/ios/Modules/Helper/ReactAppProvider.swift @@ -3,18 +3,19 @@ import React import React_RCTAppDelegate import ReactAppDependencyProvider -@objcMembers -open class ReactAppProvider: UIResponder, UIApplicationDelegate { +open class ReactAppProvider: UIResponder, UIWindowSceneDelegate { public static let defaultName = "App" public var window: UIWindow? - public var reactNativeFactory: RCTReactNativeFactory? + // @objc members are used by ReactHostHelper.mm. + @objc public var reactNativeFactory: RCTReactNativeFactory? public var reactNativeDelegate: ReactNativeDelegate? public var moduleName: String = defaultName var reactRootViewName: String = defaultName - + + private static weak var currentProvider: ReactAppProvider? private var reactRootViewController: UIViewController? public var hasStartedReact: Bool { @@ -27,16 +28,89 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { ) { self.moduleName = moduleName self.reactRootViewName = reactRootViewName + guard reactNativeFactory == nil else { + return + } let delegate = ReactNativeDelegate() let factory = RCTReactNativeFactory(delegate: delegate) delegate.dependencyProvider = RCTAppDependencyProvider() reactNativeDelegate = delegate reactNativeFactory = factory - window = UIWindow(frame: UIScreen.main.bounds) } - - open func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - return true + + open func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = scene as? UIWindowScene else { + return + } + ReactAppProvider.currentProvider = self + window = UIWindow(windowScene: windowScene) + + if let reactRootViewController = reactRootViewController { + changeRoot(to: reactRootViewController) + } + } + + open func sceneDidDisconnect(_ scene: UIScene) { + if ReactAppProvider.currentProvider === self { + ReactAppProvider.currentProvider = nil + } + } + + open func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { + forwardURLContextsToReact(URLContexts) + } + + public func handleURLContexts( + _ URLContexts: Set, + whenReactInactive: ([AnyHashable: Any]) -> Void + ) { + if ReactAppProvider.isReactAppActive() { + forwardURLContextsToReact(URLContexts) + } else if let context = URLContexts.first { + whenReactInactive(ReactAppProvider.launchOptions(fromURLContext: context)) + } + } + + open func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + RCTLinkingManager.application( + UIApplication.shared, + continue: userActivity, + restorationHandler: { _ in } + ) + } + + public static func launchOptions(from connectionOptions: UIScene.ConnectionOptions) -> [AnyHashable: Any] { + var launchOptions: [AnyHashable: Any] = [:] + if let context = connectionOptions.urlContexts.first { + launchOptions.merge(ReactAppProvider.launchOptions(fromURLContext: context)) { _, new in new } + } + if let userActivity = connectionOptions.userActivities.first { + launchOptions[UIApplication.LaunchOptionsKey.userActivityDictionary] = [ + UIApplication.LaunchOptionsKey.userActivityType: userActivity.activityType, + "UIApplicationLaunchOptionsUserActivityKey": userActivity + ] as [AnyHashable: Any] + } + return launchOptions + } + + public static func launchOptions(fromURLContext context: UIOpenURLContext) -> [AnyHashable: Any] { + var launchOptions: [AnyHashable: Any] = [ + UIApplication.LaunchOptionsKey.url: context.url + ] + launchOptions[UIApplication.LaunchOptionsKey.sourceApplication] = context.options.sourceApplication + launchOptions[UIApplication.LaunchOptionsKey.annotation] = context.options.annotation + return launchOptions + } + + private func forwardURLContextsToReact(_ URLContexts: Set) { + URLContexts.forEach { context in + var options: [UIApplication.OpenURLOptionsKey: Any] = [ + .openInPlace: context.options.openInPlace + ] + options[.sourceApplication] = context.options.sourceApplication + options[.annotation] = context.options.annotation + RCTLinkingManager.application(UIApplication.shared, open: context.url, options: options) + } } public func setReactViewController(_ controller: UIViewController) { @@ -62,7 +136,7 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { return nil } view.autoresizingMask = [.flexibleWidth, .flexibleHeight] - view.frame = window?.rootViewController?.view.frame ?? .zero + view.frame = window?.bounds ?? .zero return view } @@ -94,8 +168,8 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { public func stopReactApp() { } - public static func shared() -> ReactAppProvider? { - return UIApplication.shared.delegate as? ReactAppProvider + @objc public static func shared() -> ReactAppProvider? { + return currentProvider } public func changeRoot(to controller: UIViewController) { @@ -107,8 +181,9 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { return window?.rootViewController?.view } + @MainActor public static func isReactAppActive() -> Bool { - return ReactHostHelper().isReactAppActive() + return ReactHostHelper.isReactAppActive() } } diff --git a/ios/Modules/Helper/ReactHostHelper+Modules.swift b/ios/Modules/Helper/ReactHostHelper+Modules.swift new file mode 100644 index 0000000..29fc370 --- /dev/null +++ b/ios/Modules/Helper/ReactHostHelper+Modules.swift @@ -0,0 +1,15 @@ +import Foundation +import React + +// Main actor only. Don't hop here with main.sync: the main thread can be blocked waiting on the +// JS thread, so a JS-thread caller would deadlock. TurboModules use their injected moduleRegistry instead. +@MainActor +extension ReactHostHelper { + static func module(for type: AnyClass) -> Any? { + currentModuleRegistry()?.module(for: type) + } + + static func isReactAppActive() -> Bool { + currentModuleRegistry() != nil + } +} diff --git a/ios/Modules/Helper/ReactHostHelper.h b/ios/Modules/Helper/ReactHostHelper.h index d381d70..0c78e5b 100644 --- a/ios/Modules/Helper/ReactHostHelper.h +++ b/ios/Modules/Helper/ReactHostHelper.h @@ -6,14 +6,16 @@ // #import +#import NS_ASSUME_NONNULL_BEGIN +// RCTHost.h includes C++ headers, so Swift cannot reach the host directly. +// This exposes only its module registry, which is plain Objective-C. @interface ReactHostHelper : NSObject -- (nullable id) moduleForClass: (Class) clazz; -- (BOOL) isReactAppActive; -- (void) emitEvent: (nonnull NSString*) eventName payload: (nullable id) payload; +// Imported into Swift as @MainActor. ++ (nullable RCTModuleRegistry *) currentModuleRegistry NS_SWIFT_UI_ACTOR; @end diff --git a/ios/Modules/Helper/ReactHostHelper.mm b/ios/Modules/Helper/ReactHostHelper.mm index 0800bcc..3acbbff 100644 --- a/ios/Modules/Helper/ReactHostHelper.mm +++ b/ios/Modules/Helper/ReactHostHelper.mm @@ -7,6 +7,7 @@ #import "ReactHostHelper.h" #import +// RCTReloadListener and RCTDefaultReactNativeFactoryDelegate are referenced by MendixNative-Swift.h. #import #import "RCTDefaultReactNativeFactoryDelegate.h" #import "RCTReactNativeFactory.h" @@ -16,54 +17,9 @@ @implementation ReactHostHelper -- (nullable id) moduleForClass: (Class) clazz { - if ([NSThread isMainThread]) { - return [self getModuleForClass: clazz]; - } else { - __block id result; - dispatch_sync(dispatch_get_main_queue(), ^{ - result = [self getModuleForClass: clazz]; - }); - return result; - } -} - -- (nullable id) getModuleForClass: (Class) clazz { - RCTHost *reactHost = [self currentHost]; - RCTModuleRegistry *moduleRegistry = [reactHost moduleRegistry]; - id nativeModule = [moduleRegistry moduleForClass: clazz]; - return nativeModule; -} - -- (RCTHost *) currentHost { - ReactAppProvider *reactAppProvider = (ReactAppProvider *) [[UIApplication sharedApplication] delegate]; - RCTReactNativeFactory *reactNativeFactory = [reactAppProvider reactNativeFactory]; - RCTRootViewFactory *rootViewFactory = [reactNativeFactory rootViewFactory]; - RCTHost *reactHost = [rootViewFactory reactHost]; - return reactHost; -} - -- (BOOL)isReactAppActive { - if ([NSThread isMainThread]) { - return [self currentHost] != nil; - } else { - __block bool result; - dispatch_sync(dispatch_get_main_queue(), ^{ - result = [self currentHost] != nil; - }); - return result; - } -} - -- (void)emitEvent:(nonnull NSString *)eventName payload:(nullable id)payload { - RCTHost *reactHost = [self currentHost]; - - NSMutableArray *args = [NSMutableArray arrayWithObject:eventName]; - if (payload != nil) { - [args addObject:payload]; - } - - [reactHost callFunctionOnJSModule:@"RCTDeviceEventEmitter" method:@"emit" args:args]; ++ (nullable RCTModuleRegistry *) currentModuleRegistry { + RCTHost *reactHost = [[[[ReactAppProvider shared] reactNativeFactory] rootViewFactory] reactHost]; + return [reactHost moduleRegistry]; } @end diff --git a/ios/Modules/Helper/TapGestureRecognizerHelper.swift b/ios/Modules/Helper/TapGestureRecognizerHelper.swift index 58dfa50..b76286b 100644 --- a/ios/Modules/Helper/TapGestureRecognizerHelper.swift +++ b/ios/Modules/Helper/TapGestureRecognizerHelper.swift @@ -3,6 +3,7 @@ import UIKit typealias TapAction = ((_ gestureRecognizer: UITapGestureRecognizer) -> Void) +@MainActor class TapGestureRecognizerHelper { private let window: UIWindow private var numberOfTouchesRequired: Int diff --git a/ios/Modules/MendixSplashScreen/MendixSplashScreen.swift b/ios/Modules/MendixSplashScreen/MendixSplashScreen.swift index c4326e2..ae22625 100644 --- a/ios/Modules/MendixSplashScreen/MendixSplashScreen.swift +++ b/ios/Modules/MendixSplashScreen/MendixSplashScreen.swift @@ -7,11 +7,16 @@ import Foundation @objcMembers public class MendixSplashScreen: NSObject { + // Called from the TurboModule's method queue; presenters touch UIKit, so hop to main. public func show() { - ReactNative.shared.showSplashScreen() + DispatchQueue.main.async { + ReactNative.shared.showSplashScreen() + } } public func hide() { - ReactNative.shared.hideSplashScreen() + DispatchQueue.main.async { + ReactNative.shared.hideSplashScreen() + } } } diff --git a/ios/Modules/NativeCookieModule/SessionCookieStore.swift b/ios/Modules/NativeCookieModule/SessionCookieStore.swift index ea2dd2d..4d8cb78 100644 --- a/ios/Modules/NativeCookieModule/SessionCookieStore.swift +++ b/ios/Modules/NativeCookieModule/SessionCookieStore.swift @@ -1,4 +1,5 @@ import Foundation +import LocalAuthentication public class SessionCookieStore { @@ -57,12 +58,19 @@ public class SessionCookieStore { } } + // Fails with errSecInteractionNotAllowed instead of showing an authentication prompt. + private static func nonInteractiveContext() -> LAContext { + let context = LAContext() + context.interactionNotAllowed = true + return context + } + private static func get(key: String) -> [HTTPCookie]? { let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrAccount: key, kSecReturnData: true, - kSecUseAuthenticationUI: kSecUseAuthenticationUIFail + kSecUseAuthenticationContext: nonInteractiveContext() ] var item: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &item) diff --git a/ios/Modules/NativeFsModule/NativeFsModule.swift b/ios/Modules/NativeFsModule/NativeFsModule.swift index 0d47252..2304b34 100644 --- a/ios/Modules/NativeFsModule/NativeFsModule.swift +++ b/ios/Modules/NativeFsModule/NativeFsModule.swift @@ -16,6 +16,17 @@ public class NativeFsModule: NSObject { private static let NativeFsErrorDomain = "com.mendix.mendixnative.nativefsmodule" + private let blobManager: RCTBlobManager? + + public init(blobManager: RCTBlobManager?) { + self.blobManager = blobManager + super.init() + } + + public override convenience init() { + self.init(blobManager: nil) + } + public static func setEncryptionEnabled(_ enabled: Bool) { encryptionEnabled = enabled } @@ -25,7 +36,7 @@ public class NativeFsModule: NSObject { } private func getBlobManager() -> RCTBlobManager? { - guard let blobManager: RCTBlobManager = DevHelper.getModule(type: RCTBlobManager.self) else { + guard let blobManager else { NSLog("NativeFsModule: Failed to get RCTBlobManager") return nil } @@ -98,15 +109,25 @@ public class NativeFsModule: NSObject { try fileManager.removeItem(atPath: filepath) } + private static func standardizedPath(_ path: String) -> String { + return URL(fileURLWithPath: path).standardizedFileURL.path + } + static func ensureWhiteListedPath(_ paths: [String]) throws { let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? "" let cachesPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first ?? "" let tempPath = (NSTemporaryDirectory() as NSString).standardizingPath + let allowedRoots = [documentsPath, cachesPath, tempPath].filter { !$0.isEmpty }.map(standardizedPath) + for path in paths { - if !path.hasPrefix(documentsPath) && - !path.hasPrefix(cachesPath) && - !path.hasPrefix(tempPath) { + // Standardize first so "../" can't escape a root, and require a "/" boundary so a + // sibling like "Evil" doesn't match "". + let standardized = standardizedPath(path) + let isAllowed = path.hasPrefix("/") && allowedRoots.contains { root in + standardized == root || standardized.hasPrefix(root + "/") + } + if !isAllowed { throw NSError( domain: NativeFsErrorDomain, code: 999, @@ -222,6 +243,21 @@ public class NativeFsModule: NSObject { resolve(dataURL) } + public func readAsText(_ filePath: String, + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock) { + + guard isWhiteListedPath(filePath, reject: reject) else { return } + + guard let data = NativeFsModule.readData(filePath), + let text = String(data: data, encoding: .utf8) else { + reject(NativeFsModule.ERROR_READ_FAILED, NativeFsModule.formatError("Failed to read file as text"), nil) + return + } + + resolve(text) + } + public func fileExists(_ filepath: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { diff --git a/ios/Modules/ReactNative.swift b/ios/Modules/ReactNative.swift index a2d8232..ea77849 100644 --- a/ios/Modules/ReactNative.swift +++ b/ios/Modules/ReactNative.swift @@ -33,6 +33,7 @@ open class ReactNative: NSObject, RCTReloadListener { } // MARK: - Lifecycle Methods + @MainActor public func start() { guard let mendixApp = self.mendixApp else { fatalError("MendixApp not passed before starting the app") @@ -64,6 +65,7 @@ open class ReactNative: NSObject, RCTReloadListener { } } + @MainActor public func stop() { hideSplashScreen() delegate?.onAppClosed() @@ -71,10 +73,12 @@ open class ReactNative: NSObject, RCTReloadListener { } // MARK: - Splash Screen Methods + @MainActor public func showSplashScreen() { mendixApp?.splashScreenPresenter?.show(ReactAppProvider.shared()?.rootView) } + @MainActor public func hideSplashScreen() { mendixApp?.splashScreenPresenter?.hide() DevHelper.hideDevLoadingView() @@ -93,10 +97,13 @@ open class ReactNative: NSObject, RCTReloadListener { // MARK: - RCTReloadListener @objc public func didReceiveReloadCommand() { - showSplashScreen() + // Reload listeners run on the thread that triggered the reload (e.g. RCTExceptionsManager + // off the main thread), so hop to main. + DispatchQueue.main.async { self.showSplashScreen() } } // MARK: - Debugging Methods + @MainActor public func remoteDebugging(_ enable: Bool) { showSplashScreen() bundleUrl = AppUrl.forBundle( @@ -108,6 +115,7 @@ open class ReactNative: NSObject, RCTReloadListener { DevHelper.setDebugMode(enabled: enable) } + @MainActor public func setRemoteDebuggingPackagerPort(_ port: Int) { AppPreferences.remoteDebuggingPackagerPort = port remoteDebugging(true) diff --git a/ios/TurboModules/MxConfiguration/MxConfig.h b/ios/TurboModules/MxConfiguration/MxConfig.h new file mode 100644 index 0000000..4a91410 --- /dev/null +++ b/ios/TurboModules/MxConfiguration/MxConfig.h @@ -0,0 +1,4 @@ +#import + +@interface MxConfig : NativeMxConfigSpecBase +@end diff --git a/ios/TurboModules/MxConfiguration/MxConfigurationModule.mm b/ios/TurboModules/MxConfiguration/MxConfig.mm similarity index 63% rename from ios/TurboModules/MxConfiguration/MxConfigurationModule.mm rename to ios/TurboModules/MxConfiguration/MxConfig.mm index 4fe5121..e128033 100644 --- a/ios/TurboModules/MxConfiguration/MxConfigurationModule.mm +++ b/ios/TurboModules/MxConfiguration/MxConfig.mm @@ -1,25 +1,27 @@ -#import "MxConfigurationModule.h" +#import "MxConfig.h" #import "RCTAppDelegate.h" #import #import "MendixNative-Swift.h" -@implementation MxConfigurationModule +@implementation MxConfig -RCT_EXPORT_MODULE(MxConfiguration) ++ (NSString *)moduleName { + return @"MxConfig"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params { - return std::make_shared(params); + return std::make_shared(params); } -- (nonnull facebook::react::ModuleConstants)constantsToExport { +- (nonnull facebook::react::ModuleConstants)constantsToExport { return [self getConstants]; } -- (nonnull facebook::react::ModuleConstants)getConstants { +- (nonnull facebook::react::ModuleConstants)getConstants { MxConfigProxy *config = [MxConfigProxy prepare]; - return facebook::react::typedConstants({ + return facebook::react::typedConstants({ .RUNTIME_URL = config.runtimeUrl, .APP_NAME = config.appName ?: [[NSNull alloc] init], .FILES_DIRECTORY_NAME = config.filesDirectoryName, @@ -28,7 +30,6 @@ @implementation MxConfigurationModule .OTA_MANIFEST_PATH = config.otaManifestPath, .NATIVE_DEPENDENCIES = config.nativeDependencies, .IS_DEVELOPER_APP = config.isDeveloperApp, - .CODE_PUSH_KEY= NULL, .NATIVE_BINARY_VERSION = [config.nativeBinaryVersion doubleValue], .APP_SESSION_ID = config.appSessionId }); diff --git a/ios/TurboModules/MxConfiguration/MxConfigurationModule.h b/ios/TurboModules/MxConfiguration/MxConfigurationModule.h deleted file mode 100644 index c07ad52..0000000 --- a/ios/TurboModules/MxConfiguration/MxConfigurationModule.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MxConfigurationModule : NativeMxConfigurationSpecBase -@end diff --git a/ios/TurboModules/MxCookie/MxCookie.mm b/ios/TurboModules/MxCookie/MxCookie.mm index 96808d7..753508c 100644 --- a/ios/TurboModules/MxCookie/MxCookie.mm +++ b/ios/TurboModules/MxCookie/MxCookie.mm @@ -5,7 +5,9 @@ @implementation MxCookie -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxCookie"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/TurboModules/MxDownload/MxDownload.mm b/ios/TurboModules/MxDownload/MxDownload.mm index 100f7fd..8647893 100644 --- a/ios/TurboModules/MxDownload/MxDownload.mm +++ b/ios/TurboModules/MxDownload/MxDownload.mm @@ -5,7 +5,9 @@ @implementation MxDownload -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxDownload"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/TurboModules/MxEncryption/MxEncryption.mm b/ios/TurboModules/MxEncryption/MxEncryption.mm index 1476dec..6f029e6 100644 --- a/ios/TurboModules/MxEncryption/MxEncryption.mm +++ b/ios/TurboModules/MxEncryption/MxEncryption.mm @@ -5,7 +5,9 @@ @implementation MxEncryption -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxEncryption"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/TurboModules/MxError/MxError.mm b/ios/TurboModules/MxError/MxError.mm index 8f400a1..26e4144 100644 --- a/ios/TurboModules/MxError/MxError.mm +++ b/ios/TurboModules/MxError/MxError.mm @@ -5,7 +5,12 @@ @implementation MxError -RCT_EXPORT_MODULE() +// Injected by React Native. Lookups here don't need the main thread, unlike DevHelper.getModule. +@synthesize moduleRegistry = _moduleRegistry; + ++ (NSString *)moduleName { + return @"MxError"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params @@ -15,7 +20,7 @@ @implementation MxError - (void)handle:(nonnull NSString *)message stackTrace:(nonnull NSArray *)stackTrace { - [[[NativeErrorHandler alloc] init] handleWithMessage:message stackTrace:stackTrace]; + [[[NativeErrorHandler alloc] initWithExceptionsManager:[_moduleRegistry moduleForName:"ExceptionsManager"]] handleWithMessage:message stackTrace:stackTrace]; } @end diff --git a/ios/TurboModules/MxFileSystem/MxFileSystem.mm b/ios/TurboModules/MxFileSystem/MxFileSystem.mm index c31fb5a..8bd6c1d 100644 --- a/ios/TurboModules/MxFileSystem/MxFileSystem.mm +++ b/ios/TurboModules/MxFileSystem/MxFileSystem.mm @@ -5,7 +5,12 @@ @implementation MxFileSystem -RCT_EXPORT_MODULE() +// Injected by React Native. Lookups here don't need the main thread, unlike DevHelper.getModule. +@synthesize moduleRegistry = _moduleRegistry; + ++ (NSString *)moduleName { + return @"MxFileSystem"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params @@ -30,13 +35,13 @@ - (void)save:(nonnull NSDictionary *)blob filePath:(nonnull NSString *)filePath resolve:(nonnull RCTPromiseResolveBlock)resolve reject:(nonnull RCTPromiseRejectBlock)reject { - [[[NativeFsModule alloc] init] save:blob filepath:filePath resolve:resolve reject:reject]; + [[[NativeFsModule alloc] initWithBlobManager:[_moduleRegistry moduleForName:"BlobModule"]] save:blob filepath:filePath resolve:resolve reject:reject]; } - (void)read:(nonnull NSString *)filePath resolve:(nonnull RCTPromiseResolveBlock)resolve reject:(nonnull RCTPromiseRejectBlock)reject { - [[[NativeFsModule alloc] init] read:filePath resolve:resolve reject:reject]; + [[[NativeFsModule alloc] initWithBlobManager:[_moduleRegistry moduleForName:"BlobModule"]] read:filePath resolve:resolve reject:reject]; } - (void)move:(nonnull NSString *)filePath @@ -67,7 +72,7 @@ - (void)readAsDataURL:(nonnull NSString *)filePath - (void)readAsText:(nonnull NSString *)filePath resolve:(nonnull RCTPromiseResolveBlock)resolve reject:(nonnull RCTPromiseRejectBlock)reject { - reject(@"NOT_SUPPORTED", @"Read as text is not supported on iOS", nil); + [[[NativeFsModule alloc] init] readAsText:filePath resolve:resolve reject:reject]; } - (void)fileExists:(nonnull NSString *)filePath diff --git a/ios/TurboModules/MxNavigation/MxNavigation.mm b/ios/TurboModules/MxNavigation/MxNavigation.mm index 3f7af41..5e2c3a2 100644 --- a/ios/TurboModules/MxNavigation/MxNavigation.mm +++ b/ios/TurboModules/MxNavigation/MxNavigation.mm @@ -5,7 +5,9 @@ @implementation MxNavigation -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxNavigation"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/TurboModules/MxOta/MxOta.mm b/ios/TurboModules/MxOta/MxOta.mm index 8c35834..5906604 100644 --- a/ios/TurboModules/MxOta/MxOta.mm +++ b/ios/TurboModules/MxOta/MxOta.mm @@ -5,7 +5,9 @@ @implementation MxOta -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxOta"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/TurboModules/MxReload/MxReload.mm b/ios/TurboModules/MxReload/MxReload.mm index f3f0358..83a1bf8 100644 --- a/ios/TurboModules/MxReload/MxReload.mm +++ b/ios/TurboModules/MxReload/MxReload.mm @@ -5,7 +5,9 @@ @implementation MxReload -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxReload"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/TurboModules/MxSplashScreen/MxSplashScreen.mm b/ios/TurboModules/MxSplashScreen/MxSplashScreen.mm index 7808289..1bd20cf 100644 --- a/ios/TurboModules/MxSplashScreen/MxSplashScreen.mm +++ b/ios/TurboModules/MxSplashScreen/MxSplashScreen.mm @@ -5,7 +5,9 @@ @implementation MxSplashScreen -RCT_EXPORT_MODULE() ++ (NSString *)moduleName { + return @"MxSplashScreen"; +} - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/package.json b/package.json index d4a2a53..9031074 100644 --- a/package.json +++ b/package.json @@ -64,11 +64,12 @@ "@eslint/compat": "1.4.1", "@eslint/eslintrc": "3.3.5", "@eslint/js": "9.39.4", - "@op-engineering/op-sqlite": "15.2.5", + "@op-engineering/op-sqlite": "18.2.5", "@react-native-async-storage/async-storage": "2.2.0", - "@react-native-community/cli": "20.1.3", - "@react-native/babel-preset": "0.84.1", - "@react-native/eslint-config": "0.84.1", + "@react-native-community/cli": "20.2.0", + "@react-native/babel-preset": "0.88.0-rc.3", + "@react-native/eslint-config": "0.88.0-rc.3", + "@react-native/jest-preset": "0.88.0-rc.3", "@release-it/conventional-changelog": "10.0.5", "@types/jest": "29.5.14", "@types/react": "19.2.14", @@ -80,10 +81,10 @@ "jest": "29.7.0", "lefthook": "2.1.3", "prettier": "3.4.2", - "react": "19.2.3", - "react-native": "0.84.1", + "react": "19.3.0", + "react-native": "0.88.0-rc.3", "react-native-builder-bob": "0.40.18", - "react-native-gesture-handler": "2.31.2", + "react-native-gesture-handler": "2.33.0", "release-it": "19.2.4", "turbo": "2.8.21", "typescript": "5.9.3" @@ -100,7 +101,7 @@ ], "packageManager": "yarn@4.12.0", "jest": { - "preset": "react-native", + "preset": "@react-native/jest-preset", "modulePathIgnorePatterns": [ "/example/node_modules", "/lib/" @@ -176,6 +177,6 @@ "version": "0.55.1" }, "resolutions": { - "@op-engineering/op-sqlite@15.2.5": "patch:@op-engineering/op-sqlite@npm%3A15.2.5#./.yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch" + "@op-engineering/op-sqlite@18.2.5": "patch:@op-engineering/op-sqlite@npm%3A18.2.5#./.yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch" } } diff --git a/src/dev-settings.ts b/src/dev-settings.ts deleted file mode 100644 index c699e3a..0000000 --- a/src/dev-settings.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Listen for native-to-JS calls to control the shake gesture. -// If the native layer cannot update RCTDevSettings directly, -// enable a listener and use RCTHost.callFunctionOnJSModule to emit the event. -// This pattern can also apply to other methods. -// if (__DEV__ && Platform.OS === 'ios') { -// DeviceEventEmitter.addListener( -// 'mendixSetShakeToShowDevMenu', -// (enabled: boolean) => { -// NativeDevSettings?.setIsShakeToShowDevMenuEnabled?.(enabled); -// } -// ); -// } diff --git a/src/events.ts b/src/events.ts index b7c10d1..9336f1e 100644 --- a/src/events.ts +++ b/src/events.ts @@ -1,5 +1,9 @@ -import NativeMxReload from './reload-handler/NativeMxReload'; -import NativeMxOta from './ota/NativeMxOta'; +import NativeMxReload, { + type OnReloadWithState, +} from './reload-handler/NativeMxReload'; +import NativeMxOta, { type OnDownloadProgress } from './ota/NativeMxOta'; -export const onReloadWithStateEvent = NativeMxReload.onReloadWithState; -export const onDownloadProgressEvent = NativeMxOta.onDownloadProgress; +export const onReloadWithStateEvent: OnReloadWithState = + NativeMxReload.onReloadWithState; +export const onDownloadProgressEvent: OnDownloadProgress = + NativeMxOta.onDownloadProgress; diff --git a/src/file-system/index.ts b/src/file-system/index.ts index e9704b9..954c0d3 100644 --- a/src/file-system/index.ts +++ b/src/file-system/index.ts @@ -17,7 +17,7 @@ const initFs = () => { read: NativeMxFileSystem.read, list: NativeMxFileSystem.list, readAsDataURL: NativeMxFileSystem.readAsDataURL, - readAsText: NativeMxFileSystem.readAsText, //Android only + readAsText: NativeMxFileSystem.readAsText, fileExists: NativeMxFileSystem.fileExists, move: NativeMxFileSystem.move, remove: NativeMxFileSystem.remove, diff --git a/src/mx-configuration/NativeMxConfiguration.ts b/src/mx-configuration/NativeMxConfig.ts similarity index 90% rename from src/mx-configuration/NativeMxConfiguration.ts rename to src/mx-configuration/NativeMxConfig.ts index 2b50057..5b3cde1 100644 --- a/src/mx-configuration/NativeMxConfiguration.ts +++ b/src/mx-configuration/NativeMxConfig.ts @@ -26,6 +26,6 @@ export interface Spec extends TurboModule { readonly getConstants: () => Configuration; } -export default TurboModuleRegistry.getEnforcing('MxConfiguration'); +export default TurboModuleRegistry.getEnforcing('MxConfig'); export type { Configuration }; diff --git a/src/mx-configuration/index.ts b/src/mx-configuration/index.ts index a55f886..589235d 100644 --- a/src/mx-configuration/index.ts +++ b/src/mx-configuration/index.ts @@ -1,3 +1,3 @@ -import NativeMxConfiguration from './NativeMxConfiguration'; +import NativeMxConfig from './NativeMxConfig'; -export const MxConfiguration = NativeMxConfiguration.getConstants(); +export const MxConfiguration = NativeMxConfig.getConstants(); diff --git a/src/ota/NativeMxOta.ts b/src/ota/NativeMxOta.ts index eb89732..b3ae628 100644 --- a/src/ota/NativeMxOta.ts +++ b/src/ota/NativeMxOta.ts @@ -26,6 +26,9 @@ export interface Spec extends TurboModule { readonly onDownloadProgress: CodegenTypes.EventEmitter; } +// Codegen requires EventEmitter inline in Spec, so derive the alias from it. +type OnDownloadProgress = Spec['onDownloadProgress']; + export default TurboModuleRegistry.getEnforcing('MxOta'); export type { @@ -33,4 +36,5 @@ export type { OtaDeployConfig, OtaDownloadResponse, DownloadProgress, + OnDownloadProgress, }; diff --git a/src/reload-handler/NativeMxReload.ts b/src/reload-handler/NativeMxReload.ts index 673d08b..7244872 100644 --- a/src/reload-handler/NativeMxReload.ts +++ b/src/reload-handler/NativeMxReload.ts @@ -7,4 +7,7 @@ export interface Spec extends TurboModule { readonly onReloadWithState: CodegenTypes.EventEmitter; } +// Codegen requires EventEmitter inline in Spec, so derive the alias from it. +export type OnReloadWithState = Spec['onReloadWithState']; + export default TurboModuleRegistry.getEnforcing('MxReload'); diff --git a/yarn.lock b/yarn.lock index 36bfc46..4c4668b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -290,7 +290,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.4, @babel/parser@npm:^7.25.3, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.4, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.0 resolution: "@babel/parser@npm:7.29.0" dependencies: @@ -1491,7 +1491,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": +"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": version: 7.29.0 resolution: "@babel/traverse@npm:7.29.0" dependencies: @@ -2762,23 +2762,31 @@ __metadata: languageName: node linkType: hard -"@op-engineering/op-sqlite@npm:15.2.5": - version: 15.2.5 - resolution: "@op-engineering/op-sqlite@npm:15.2.5" +"@op-engineering/op-sqlite@npm:18.2.5": + version: 18.2.5 + resolution: "@op-engineering/op-sqlite@npm:18.2.5" peerDependencies: + "@sqlite.org/sqlite-wasm": "*" react: "*" react-native: "*" - checksum: 10/e37163e99b5959fdb93076a929f1b2b40db8bb981c996a6342262105a3f387a2cf01d95bd4944cfe4c59424603054fbeeda3179184619b417cd6094a3759b037 + peerDependenciesMeta: + "@sqlite.org/sqlite-wasm": + optional: true + checksum: 10/1bd63684631d506da0ac1ad75ce08b56c4798b0353e25e36ab7e8612a15197846cc26e84a11ee92e5b073483af0b322cd9423f843ea1e91075dd242f13ecaaa8 languageName: node linkType: hard -"@op-engineering/op-sqlite@patch:@op-engineering/op-sqlite@npm%3A15.2.5#./.yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch::locator=mendix-native%40workspace%3A.": - version: 15.2.5 - resolution: "@op-engineering/op-sqlite@patch:@op-engineering/op-sqlite@npm%3A15.2.5#./.yarn/patches/@op-engineering-op-sqlite-npm-15.2.5-936f5cf3a5.patch::version=15.2.5&hash=1ffd55&locator=mendix-native%40workspace%3A." +"@op-engineering/op-sqlite@patch:@op-engineering/op-sqlite@npm%3A18.2.5#./.yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch::locator=mendix-native%40workspace%3A.": + version: 18.2.5 + resolution: "@op-engineering/op-sqlite@patch:@op-engineering/op-sqlite@npm%3A18.2.5#./.yarn/patches/@op-engineering-op-sqlite-npm-18.2.5-mendix.patch::version=18.2.5&hash=96efc9&locator=mendix-native%40workspace%3A." peerDependencies: + "@sqlite.org/sqlite-wasm": "*" react: "*" react-native: "*" - checksum: 10/2d549579379d04b046d629e9c8df72d72c1a96813cb7999f8d618af4564c254f26013220f7ba3ddf25143f50cdaafb283b2bab85c52f44a19c23d8532a958045 + peerDependenciesMeta: + "@sqlite.org/sqlite-wasm": + optional: true + checksum: 10/124d697074ea31ae61a914e6c2ba0f7c597ec4e249982185f266893db8c3ca378cbc9c3eed71334b46699f30fe544ec02826e0ba0dba2f70ef9d676a0722c5d1 languageName: node linkType: hard @@ -2814,65 +2822,65 @@ __metadata: languageName: node linkType: hard -"@react-native-community/cli-clean@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-clean@npm:20.1.3" +"@react-native-community/cli-clean@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-clean@npm:20.2.0" dependencies: - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-tools": "npm:20.2.0" execa: "npm:^5.0.0" fast-glob: "npm:^3.3.2" picocolors: "npm:^1.1.1" - checksum: 10/f36c41aa7321f87c27e0411a6b21eaa5381f2c223d45d0a271ef261710893d65a4f862ea61f4ba0a42b592962731dc1b7aea8bb4670e861c2b9e999ce6ac93c0 + checksum: 10/61329f866422f6addef06d9848a3ae0fccb9cc37c863be928ed26dcdc814b8228d765a7ff2e2b1a9c544c8b243446181200eaa178d839d218730eaab3df03a2d languageName: node linkType: hard -"@react-native-community/cli-config-android@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-config-android@npm:20.1.3" +"@react-native-community/cli-config-android@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-config-android@npm:20.2.0" dependencies: - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-tools": "npm:20.2.0" fast-glob: "npm:^3.3.2" fast-xml-parser: "npm:^5.3.6" picocolors: "npm:^1.1.1" - checksum: 10/1e3ab058f916b8fc7ede9f7505d12332eb240225626d22657bde523afaba06a92938f4589b8c9d56ec63ed9abe18eb8cd06bd908ec3434722090ff6ff77dac21 + checksum: 10/42f518a0245087f136712c61ab4e17f28c826758751a6b4ff75da47cfed37d3debd45e80667dde6f0401ccb7d0bb4606119dbf78d85c0f48fd282b41cdfd5bd3 languageName: node linkType: hard -"@react-native-community/cli-config-apple@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-config-apple@npm:20.1.3" +"@react-native-community/cli-config-apple@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-config-apple@npm:20.2.0" dependencies: - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-tools": "npm:20.2.0" execa: "npm:^5.0.0" fast-glob: "npm:^3.3.2" picocolors: "npm:^1.1.1" - checksum: 10/d9e2bfeb4747ccc48f12e0906d9c7647972ce63c457e5327f48dc3a805dc06562f5ec1928a02cba58949087d46ac310f8bf771991646d2d4382b5f611f69dc6f + checksum: 10/2aee28a6e56590f6b04c240808e58c25d482366e76c7bf53ca65b3e29d5a3f52672208cb339bc3700fa42a6cb7c79548ba49df5f6007dd4d1fad59ce2f0524b1 languageName: node linkType: hard -"@react-native-community/cli-config@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-config@npm:20.1.3" +"@react-native-community/cli-config@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-config@npm:20.2.0" dependencies: - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-tools": "npm:20.2.0" cosmiconfig: "npm:^9.0.0" deepmerge: "npm:^4.3.0" fast-glob: "npm:^3.3.2" joi: "npm:^17.2.1" picocolors: "npm:^1.1.1" - checksum: 10/6ff96ef8bd8a93aadc210d370542b61175b0f43c23f7635dd4c8a985f91a76eac8f5692d50a555983a17f1843bdd68e15bac81cc449413dd51d24378fe8fb3d6 + checksum: 10/348034a3d80796e0d9065a50e0d2ec2d08322ad4c1bdf8dd84627497af846365b8325495f0f66f7a7b73a084b6e0d69547e59afbc63fa375d5026488271ddb3e languageName: node linkType: hard -"@react-native-community/cli-doctor@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-doctor@npm:20.1.3" +"@react-native-community/cli-doctor@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-doctor@npm:20.2.0" dependencies: - "@react-native-community/cli-config": "npm:20.1.3" - "@react-native-community/cli-platform-android": "npm:20.1.3" - "@react-native-community/cli-platform-apple": "npm:20.1.3" - "@react-native-community/cli-platform-ios": "npm:20.1.3" - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-config": "npm:20.2.0" + "@react-native-community/cli-platform-android": "npm:20.2.0" + "@react-native-community/cli-platform-apple": "npm:20.2.0" + "@react-native-community/cli-platform-ios": "npm:20.2.0" + "@react-native-community/cli-tools": "npm:20.2.0" command-exists: "npm:^1.2.8" deepmerge: "npm:^4.3.0" envinfo: "npm:^7.13.0" @@ -2883,50 +2891,50 @@ __metadata: semver: "npm:^7.5.2" wcwidth: "npm:^1.0.1" yaml: "npm:^2.2.1" - checksum: 10/fa17643871f47b36b69baeb874507f9c456ebf751aa55bbd6d5f25c2d39fa5b774be848b817ff15a1b8a04ba91632cdc218bb2f2c5b8a9e6f88eb50545803f05 + checksum: 10/9892749c8ac8e8a2510b2cec609df25a37bc03ad33281e1a4c98197591ac425242af8ffbe8d28af5ffc7dc7fe9de40f52847af3abad8c7fa9ebc7b6d665ded5a languageName: node linkType: hard -"@react-native-community/cli-platform-android@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-platform-android@npm:20.1.3" +"@react-native-community/cli-platform-android@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-platform-android@npm:20.2.0" dependencies: - "@react-native-community/cli-config-android": "npm:20.1.3" - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-config-android": "npm:20.2.0" + "@react-native-community/cli-tools": "npm:20.2.0" execa: "npm:^5.0.0" logkitty: "npm:^0.7.1" picocolors: "npm:^1.1.1" - checksum: 10/5f67a914e871feb0920ba1121853a6c3e47af3195569929915f09a236d8aabb2a3a3e5d3e62d7eb2f36d6f1c6a27e4c8f4a132a8617d802b3336e30d88f0789e + checksum: 10/f72b6dedb2f7c1aed1c902815adba70a779769a1dc4effad6a024919eeb955ed3d3660eb88449e66f574c9f1720e33cf6c58a16aaae4482904bcff07ef30c84c languageName: node linkType: hard -"@react-native-community/cli-platform-apple@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-platform-apple@npm:20.1.3" +"@react-native-community/cli-platform-apple@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-platform-apple@npm:20.2.0" dependencies: - "@react-native-community/cli-config-apple": "npm:20.1.3" - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-config-apple": "npm:20.2.0" + "@react-native-community/cli-tools": "npm:20.2.0" execa: "npm:^5.0.0" fast-xml-parser: "npm:^5.3.6" picocolors: "npm:^1.1.1" - checksum: 10/47e11e7398be608bbb58b436dc229286c5d49306fc9b0959582004ff4adab7fad51d167ec4a1b3aa02cec015e2631bea9c3f214b8e121f48b188a6fcdfbbd82b + checksum: 10/2c7abb0c98a59cd6660ef17d02c9c6002ed36fc754e8297fa3bb2381d5e6767ddb2c8d59175e3072205b4b3a965409fc69471aa2b820180b2ba9df9bd36ba6b2 languageName: node linkType: hard -"@react-native-community/cli-platform-ios@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-platform-ios@npm:20.1.3" +"@react-native-community/cli-platform-ios@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-platform-ios@npm:20.2.0" dependencies: - "@react-native-community/cli-platform-apple": "npm:20.1.3" - checksum: 10/9a43f6158a3f3cf3b1a432881a5e3218623ca31fdc0d6872d7731ff20de95c414d5c364081e3082afc149cd8129b051471702caaea707715869681fd43d0e528 + "@react-native-community/cli-platform-apple": "npm:20.2.0" + checksum: 10/5ccec2a92842043bdabfa3464226571dc1c9bf8e73dac2adbd3dea98a1d9f6e75d2dcb5b4fee9ea48c2acf6921013ba70f9b751a7255715f59ce9e0d66e1a4fc languageName: node linkType: hard -"@react-native-community/cli-server-api@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-server-api@npm:20.1.3" +"@react-native-community/cli-server-api@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-server-api@npm:20.2.0" dependencies: - "@react-native-community/cli-tools": "npm:20.1.3" + "@react-native-community/cli-tools": "npm:20.2.0" body-parser: "npm:^2.2.2" compression: "npm:^1.7.1" connect: "npm:^3.6.5" @@ -2935,15 +2943,14 @@ __metadata: open: "npm:^6.2.0" pretty-format: "npm:^29.7.0" serve-static: "npm:^1.13.1" - strict-url-sanitise: "npm:0.0.1" ws: "npm:^6.2.3" - checksum: 10/2e65e2cd1b2f78d3b38e46510d456f2d82b61ab9b58af37d1f7d674716416575c8dd56907acb87cfb3b81c10833db092d2dd6f6c36f7df1d16845f39b8322635 + checksum: 10/c135195b5e60d4a5e42ed9caa374c18fe76108825d5c20f4171b6b35229b03f22231201642aabfcf3d0e4fc43e7183b6348faec7f0306ed363599e26e409d1f5 languageName: node linkType: hard -"@react-native-community/cli-tools@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-tools@npm:20.1.3" +"@react-native-community/cli-tools@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-tools@npm:20.2.0" dependencies: "@vscode/sudo-prompt": "npm:^9.0.0" appdirsjs: "npm:^1.2.4" @@ -2955,29 +2962,29 @@ __metadata: picocolors: "npm:^1.1.1" prompts: "npm:^2.4.2" semver: "npm:^7.5.2" - checksum: 10/7bcf1b23ee4e655fe7bf24b5ce917f5c40d65eaf64bd6f0ce55bd1315a77df16b0e9dc1fc517eb56ab7f64717fc33a2c247b15989223165f908a8604ab898059 + checksum: 10/ef7b00deaccf6a716b7659463bccefb0b19012ffff2679c25d79a79b746456fd773511914f90e8e19612092953d40322c706c2c59501786f202ef052b31a72a1 languageName: node linkType: hard -"@react-native-community/cli-types@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli-types@npm:20.1.3" +"@react-native-community/cli-types@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli-types@npm:20.2.0" dependencies: joi: "npm:^17.2.1" - checksum: 10/23184e526378139386962a645ed4248f7c3563aa0b345f01449f3e0d53c78b1a16331911e040db998c5a0a74315dd0395310439aec910925fbd7398ca01eed14 + checksum: 10/218fb539c8fb33bf18afe67500ca0a2d929e4e9b4ad33041101bf5f718abf8814249fae704fa60c9838dd2cfa8b3f97cf71dd35c5440055a6edffced67f50042 languageName: node linkType: hard -"@react-native-community/cli@npm:20.1.3": - version: 20.1.3 - resolution: "@react-native-community/cli@npm:20.1.3" +"@react-native-community/cli@npm:20.2.0": + version: 20.2.0 + resolution: "@react-native-community/cli@npm:20.2.0" dependencies: - "@react-native-community/cli-clean": "npm:20.1.3" - "@react-native-community/cli-config": "npm:20.1.3" - "@react-native-community/cli-doctor": "npm:20.1.3" - "@react-native-community/cli-server-api": "npm:20.1.3" - "@react-native-community/cli-tools": "npm:20.1.3" - "@react-native-community/cli-types": "npm:20.1.3" + "@react-native-community/cli-clean": "npm:20.2.0" + "@react-native-community/cli-config": "npm:20.2.0" + "@react-native-community/cli-doctor": "npm:20.2.0" + "@react-native-community/cli-server-api": "npm:20.2.0" + "@react-native-community/cli-tools": "npm:20.2.0" + "@react-native-community/cli-types": "npm:20.2.0" commander: "npm:^9.4.1" deepmerge: "npm:^4.3.0" execa: "npm:^5.0.0" @@ -2989,7 +2996,7 @@ __metadata: semver: "npm:^7.5.2" bin: rnc-cli: build/bin.js - checksum: 10/d750e7899754eb225986f49fc041e6811cec6b75fb0e7fd6b6feee8010e754ba15e01d908fe5b9b3b29afec3d598058d1f816c5651c748e33dc2d363350fdd1f + checksum: 10/7521195d01cbbb34028d41da4ec6c5f7df05eda4feaa10b61a093658c49141ceead48eb90c8f81f4199f860915d2ff41a1d6c81e996b834dfb27c724cbc60c5a languageName: node linkType: hard @@ -3183,20 +3190,10 @@ __metadata: languageName: node linkType: hard -"@react-native/assets-registry@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/assets-registry@npm:0.84.1" - checksum: 10/1f31c649090c3d569115dfa5f1620a6e124e6e88f8eeb857f3db406b61663d3820b4c669edbc62049ce5de460f5dc224d28560f590e9759c4ee055618a8aa8dc - languageName: node - linkType: hard - -"@react-native/babel-plugin-codegen@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/babel-plugin-codegen@npm:0.84.1" - dependencies: - "@babel/traverse": "npm:^7.25.3" - "@react-native/codegen": "npm:0.84.1" - checksum: 10/59f2571e2855755f3fbc99a05e9956a150d8f10343219d88641160bfae956e8d8703a9e9c6c3df0ee758bdb6672bf512aac0f04034b3ea4cf91769a86e076ccc +"@react-native/asset-utils@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/asset-utils@npm:0.88.0-rc.3" + checksum: 10/d75d3966766a8f46ec835497192a2fcf3639e36b1e5f7be8ec82332f829437b2f240b9dd4f620c0a4d83ccdecb11c7743436d383e604b2bd0ce0f5a001b81faa languageName: node linkType: hard @@ -3210,9 +3207,19 @@ __metadata: languageName: node linkType: hard -"@react-native/babel-preset@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/babel-preset@npm:0.84.1" +"@react-native/babel-plugin-codegen@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/babel-plugin-codegen@npm:0.88.0-rc.3" + dependencies: + "@babel/traverse": "npm:^7.29.0" + "@react-native/codegen": "npm:0.88.0-rc.3" + checksum: 10/393657e9204518ad98ac4c797a9c9adae3f2184e67f47982d36a3e187a00337376fa1112b9304645de33b5cb0ce5bcc9d756c4d41e506331af295e370ae3cc5e + languageName: node + linkType: hard + +"@react-native/babel-preset@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/babel-preset@npm:0.85.3" dependencies: "@babel/core": "npm:^7.25.2" "@babel/plugin-proposal-export-default-from": "npm:^7.24.7" @@ -3243,19 +3250,19 @@ __metadata: "@babel/plugin-transform-runtime": "npm:^7.24.7" "@babel/plugin-transform-typescript": "npm:^7.25.2" "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" - "@react-native/babel-plugin-codegen": "npm:0.84.1" - babel-plugin-syntax-hermes-parser: "npm:0.32.0" + "@react-native/babel-plugin-codegen": "npm:0.85.3" + babel-plugin-syntax-hermes-parser: "npm:0.33.3" babel-plugin-transform-flow-enums: "npm:^0.0.2" react-refresh: "npm:^0.14.0" peerDependencies: "@babel/core": "*" - checksum: 10/9d362f7fa72a6b2abb9adb67cdc5dca1fe9f8a38bfd66cef01e5d99ef6b715df8842446d74859151829d883aad7ffcc46faa7cdf4b67aef9a787270a7600974c + checksum: 10/0750392facf3e1e1439accb030d04a9dc3e0242a25b5a3938f31f2a4db1cfbc7e527c11e2673c21d52d993c54e6438044db623dabf1d0a40ded065b748677220 languageName: node linkType: hard -"@react-native/babel-preset@npm:0.85.3": - version: 0.85.3 - resolution: "@react-native/babel-preset@npm:0.85.3" +"@react-native/babel-preset@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/babel-preset@npm:0.88.0-rc.3" dependencies: "@babel/core": "npm:^7.25.2" "@babel/plugin-proposal-export-default-from": "npm:^7.24.7" @@ -3286,152 +3293,158 @@ __metadata: "@babel/plugin-transform-runtime": "npm:^7.24.7" "@babel/plugin-transform-typescript": "npm:^7.25.2" "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" - "@react-native/babel-plugin-codegen": "npm:0.85.3" - babel-plugin-syntax-hermes-parser: "npm:0.33.3" + "@react-native/babel-plugin-codegen": "npm:0.88.0-rc.3" babel-plugin-transform-flow-enums: "npm:^0.0.2" + flow-parser: "npm:0.327.0" react-refresh: "npm:^0.14.0" peerDependencies: "@babel/core": "*" - checksum: 10/0750392facf3e1e1439accb030d04a9dc3e0242a25b5a3938f31f2a4db1cfbc7e527c11e2673c21d52d993c54e6438044db623dabf1d0a40ded065b748677220 + checksum: 10/1b388ea77952849cc0da241ee9683507737bc35012550b067cde666ba5f21fe1dfff4651976be0f784688edcd70d58fbbf9e3e6c7a93c228fa6a64bf879b7f68 languageName: node linkType: hard -"@react-native/codegen@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/codegen@npm:0.84.1" +"@react-native/codegen@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/codegen@npm:0.85.3" dependencies: "@babel/core": "npm:^7.25.2" - "@babel/parser": "npm:^7.25.3" - hermes-parser: "npm:0.32.0" + "@babel/parser": "npm:^7.29.0" + hermes-parser: "npm:0.33.3" invariant: "npm:^2.2.4" nullthrows: "npm:^1.1.1" tinyglobby: "npm:^0.2.15" yargs: "npm:^17.6.2" peerDependencies: "@babel/core": "*" - checksum: 10/2fa65f813c56afd4deafce8adcfaa31c5b87fb5b4ee66b625dd1171c745c6114ac192b3dd7f028e71c5ccaae752a9096b12d70d980d99bd71806b043e9234078 + checksum: 10/71986731526148205e43d624b4d02348a55da03d05c302cad3a314c7f216bad4703abc8280dfb77c17c787bce1e1c980f1ea516b404a238ae858b1307717a1c9 languageName: node linkType: hard -"@react-native/codegen@npm:0.85.3": - version: 0.85.3 - resolution: "@react-native/codegen@npm:0.85.3" +"@react-native/codegen@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/codegen@npm:0.88.0-rc.3" dependencies: "@babel/core": "npm:^7.25.2" "@babel/parser": "npm:^7.29.0" - hermes-parser: "npm:0.33.3" + flow-parser: "npm:0.327.0" invariant: "npm:^2.2.4" nullthrows: "npm:^1.1.1" tinyglobby: "npm:^0.2.15" yargs: "npm:^17.6.2" peerDependencies: "@babel/core": "*" - checksum: 10/71986731526148205e43d624b4d02348a55da03d05c302cad3a314c7f216bad4703abc8280dfb77c17c787bce1e1c980f1ea516b404a238ae858b1307717a1c9 + checksum: 10/1fae18360a90a84fe6f79fa64967458488965fe6ffb44450726e2fb41ea1ad1c235057cd29a1c4d4d6b23c689a8479d0f92c861b90dacd24205d04c267d629d1 languageName: node linkType: hard -"@react-native/community-cli-plugin@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/community-cli-plugin@npm:0.84.1" +"@react-native/community-cli-plugin@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/community-cli-plugin@npm:0.88.0-rc.3" dependencies: - "@react-native/dev-middleware": "npm:0.84.1" + "@react-native/asset-utils": "npm:0.88.0-rc.3" + "@react-native/dev-middleware": "npm:0.88.0-rc.3" + commander: "npm:^12.0.0" debug: "npm:^4.4.0" invariant: "npm:^2.2.4" - metro: "npm:^0.83.3" - metro-config: "npm:^0.83.3" - metro-core: "npm:^0.83.3" + metro: "npm:^0.87.1" semver: "npm:^7.1.3" peerDependencies: "@react-native-community/cli": "*" - "@react-native/metro-config": "*" + "@react-native/metro-config": 0.88.0-rc.3 peerDependenciesMeta: "@react-native-community/cli": optional: true "@react-native/metro-config": optional: true - checksum: 10/561bcb26af1c391144b71ca0fa3024896d8a74f52dcef856c1bc0b59aaa13560e244ae791039e25ab665c51f913556fc854d69ed0fffc3ed27a099cf3476b2c5 + checksum: 10/34b16f4e09acce65231b9cb0b1453386e382900ffaf84a96461fd90262b13f68625c9865549bc764b493f237debd52afcb947faf96d1a680a159bde269024eed languageName: node linkType: hard -"@react-native/debugger-frontend@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/debugger-frontend@npm:0.84.1" - checksum: 10/841386dcbb6964b3e256777ddb0bab26c2c1efa34059ba2bf5533ba2e257130eaefe68a5c557a220aa7c742045c27b158df63aaed7313dfecba48c6c31ae5451 +"@react-native/debugger-frontend@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/debugger-frontend@npm:0.88.0-rc.3" + checksum: 10/0d1fa91ef3c6868ac703bc181cc60f644f3fc8752d624c9c659e076349bf22c1cbcbe8e8013d08ba8a0c950f12bdb380c2f423f8635a162184629279a10131f4 languageName: node linkType: hard -"@react-native/debugger-shell@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/debugger-shell@npm:0.84.1" +"@react-native/debugger-shell@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/debugger-shell@npm:0.88.0-rc.3" dependencies: cross-spawn: "npm:^7.0.6" debug: "npm:^4.4.0" fb-dotslash: "npm:0.5.8" - checksum: 10/0ce7acd2161b3911089d75907182fb4357cb1069b19fd0d9d0262632a7eb3aeb3aac4c911b682e90f74a6de5cc1c158366182ded9b4f5d727f113227d304f656 + checksum: 10/aa55a7f4a6e4668b649786591298677bcc41d433f4f7131be83673093004200236133a137ffbb5a5d03bd7eba2200c650b094bab7504e425155d600bc3b1f86d languageName: node linkType: hard -"@react-native/dev-middleware@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/dev-middleware@npm:0.84.1" +"@react-native/dev-middleware@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/dev-middleware@npm:0.88.0-rc.3" dependencies: "@isaacs/ttlcache": "npm:^1.4.1" - "@react-native/debugger-frontend": "npm:0.84.1" - "@react-native/debugger-shell": "npm:0.84.1" - chrome-launcher: "npm:^0.15.2" - chromium-edge-launcher: "npm:^0.2.0" + "@react-native/debugger-frontend": "npm:0.88.0-rc.3" + "@react-native/debugger-shell": "npm:0.88.0-rc.3" connect: "npm:^3.6.5" debug: "npm:^4.4.0" invariant: "npm:^2.2.4" nullthrows: "npm:^1.1.1" - open: "npm:^7.0.3" + open: "npm:^8.4.2" serve-static: "npm:^1.16.2" ws: "npm:^7.5.10" - checksum: 10/7c6e588e6f6a36d57d318487437bcafc8a3c5d3959512e75f7133e92e71ddc4cc6af4e359b0098cf6151f28c01b8136077b801d7539231b2b95b56fbb4dd0f74 + checksum: 10/8dc8df6d356c3937e6e2b91d75c3725769dc0fb864d9b755efd29c4898e3e16aeb49c84d2551253814d4693ff00ad1c9db116f6524816c2cafe90972c3272778 languageName: node linkType: hard -"@react-native/eslint-config@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/eslint-config@npm:0.84.1" +"@react-native/eslint-config@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/eslint-config@npm:0.88.0-rc.3" dependencies: "@babel/core": "npm:^7.25.2" "@babel/eslint-parser": "npm:^7.25.1" - "@react-native/eslint-plugin": "npm:0.84.1" - "@typescript-eslint/eslint-plugin": "npm:^8.36.0" - "@typescript-eslint/parser": "npm:^8.36.0" + "@react-native/eslint-plugin": "npm:0.88.0-rc.3" + "@typescript-eslint/eslint-plugin": "npm:^8.59.2" + "@typescript-eslint/parser": "npm:^8.59.2" eslint-config-prettier: "npm:^8.5.0" eslint-plugin-eslint-comments: "npm:^3.2.0" eslint-plugin-ft-flow: "npm:^2.0.1" eslint-plugin-jest: "npm:^29.0.1" - eslint-plugin-react: "npm:^7.30.1" + eslint-plugin-react: "npm:^7.37.5" eslint-plugin-react-hooks: "npm:^7.0.1" eslint-plugin-react-native: "npm:^5.0.0" peerDependencies: eslint: ^8.0.0 || ^9.0.0 prettier: ">=2" - checksum: 10/37b6e632d43fbc9ffd7f126c90aecc9d3acb018f060a8006853275386ec4d79e6176514b59a22833a6abe9839f0b95670e86da63a5964437ef63d8abb4d90e1b + checksum: 10/117c40f70801367e97832f497ddafb0f39b91aed127b994d6c8d8f1c6659c400a9d15530051c5d4770805e970c99c3d68156d5144c2557037a5e05e76a02b32d languageName: node linkType: hard -"@react-native/eslint-plugin@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/eslint-plugin@npm:0.84.1" - checksum: 10/6dabbdbc9a42a197fd9194f5eeff2f7a413753fa27fb005187416a1cac016b11186409b8029d92d11603f0b5c67aff075bda542e47737819d71a6b54e35741ee +"@react-native/eslint-plugin@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/eslint-plugin@npm:0.88.0-rc.3" + checksum: 10/a51f6282cfa2a69439a6a15492be2b520339426df0e2041adf297269071abd086274915994e3e48a7860aac5685c3ae849b3927a4068445c590009e62f213ed1 languageName: node linkType: hard -"@react-native/gradle-plugin@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/gradle-plugin@npm:0.84.1" - checksum: 10/9edf358cb865b287eb04c34a218a8fc31740cff01a8d53bc83fe181c6bcbecc6337b3623b4f9f3490fa1d3a309a6e8ba863a900c7e6bdc88d76717af9175c50e +"@react-native/gradle-plugin@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/gradle-plugin@npm:0.88.0-rc.3" + checksum: 10/a401036fa3ad84f043a6d010b8532504ff6ca7d470f931f4a1f3009164366d5699e6c045f4245b4a45779c41edefa06bcbe87e6e501d2030c4a27f261743a272 languageName: node linkType: hard -"@react-native/js-polyfills@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/js-polyfills@npm:0.84.1" - checksum: 10/7074e66d54f302864b580d2bf2c048cdb4c37fc4f6fd9dee0faeb4084d524c2f1e7fa60014a54bdcaaa51d75955fbac6a9274e25b806783eee7edf5bce2fb074 +"@react-native/jest-preset@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/jest-preset@npm:0.88.0-rc.3" + dependencies: + "@jest/create-cache-key-function": "npm:^29.7.0" + "@react-native/js-polyfills": "npm:0.88.0-rc.3" + babel-jest: "npm:^29.7.0" + jest-environment-node: "npm:^29.7.0" + regenerator-runtime: "npm:^0.13.2" + peerDependencies: + react: ^19.2.3 + checksum: 10/82ac14781e775344b5dea4a0874e926d0c9959f910c8faee2e51e21253b64984ec110881e5f18f1a274e2e8412b72c086a5841c074c7f17fcbe317dbb91fc134 languageName: node linkType: hard @@ -3442,17 +3455,10 @@ __metadata: languageName: node linkType: hard -"@react-native/metro-babel-transformer@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/metro-babel-transformer@npm:0.84.1" - dependencies: - "@babel/core": "npm:^7.25.2" - "@react-native/babel-preset": "npm:0.84.1" - hermes-parser: "npm:0.32.0" - nullthrows: "npm:^1.1.1" - peerDependencies: - "@babel/core": "*" - checksum: 10/0fc5988b37eb0ef083ab354b5c04a722a44009dd08fa40a7574a630e2f47c19ee34b2da7ee0bd9fab9434515ce4d39ef853fc4d7dc7bab575d71e52d12292e89 +"@react-native/js-polyfills@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/js-polyfills@npm:0.88.0-rc.3" + checksum: 10/163fc552b4452390f488bafbb319b94d60048a7ef8fea81b70bac18cc5d8bc6c3413fabcfe8a284c586047282ae2ef5cad8f3242f39de0ab712ba769e9a3b9c5 languageName: node linkType: hard @@ -3470,6 +3476,20 @@ __metadata: languageName: node linkType: hard +"@react-native/metro-babel-transformer@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/metro-babel-transformer@npm:0.88.0-rc.3" + dependencies: + "@babel/core": "npm:^7.25.2" + "@react-native/babel-preset": "npm:0.88.0-rc.3" + flow-parser: "npm:0.327.0" + nullthrows: "npm:^1.1.1" + peerDependencies: + "@babel/core": "*" + checksum: 10/243f3491404bc92232f01967b23b82f5e77e90e6bed620e53b043dd7a94b06a1e1dc983b5c606a817658850499b82b578838965ce148e6460624e8c18694a776 + languageName: node + linkType: hard + "@react-native/metro-config@npm:*": version: 0.85.3 resolution: "@react-native/metro-config@npm:0.85.3" @@ -3482,46 +3502,46 @@ __metadata: languageName: node linkType: hard -"@react-native/metro-config@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/metro-config@npm:0.84.1" +"@react-native/metro-config@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/metro-config@npm:0.88.0-rc.3" dependencies: - "@react-native/js-polyfills": "npm:0.84.1" - "@react-native/metro-babel-transformer": "npm:0.84.1" - metro-config: "npm:^0.83.3" - metro-runtime: "npm:^0.83.3" - checksum: 10/0637fe16d5e1fa7fcfd729dbfa3842b9ead126c1eb6ebe8ff4bcdc959f92a71bc5e0e9bdeb103a33fb04bb3a53dd3ee219736508acee89963aea6fb9db2901c2 + "@react-native/js-polyfills": "npm:0.88.0-rc.3" + "@react-native/metro-babel-transformer": "npm:0.88.0-rc.3" + metro-config: "npm:^0.87.1" + metro-runtime: "npm:^0.87.1" + checksum: 10/ca24be9e47ac3d59effd5898d74b5779c06a3d6b71888da0be804c856f7f1a1d242f3c7d6e23e85cd84e74c2721edec1b6fe6d0ad17b7a17f858663c0214f61d languageName: node linkType: hard -"@react-native/normalize-colors@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/normalize-colors@npm:0.84.1" - checksum: 10/5c65d26dbfab87d19ae9253cfce4eeb284c6f7663d94e8708a535082da65de8150677cac7953146d691922705fe84ea8abf9205e37096f2d9055bd9e9cca6bf1 +"@react-native/normalize-colors@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/normalize-colors@npm:0.88.0-rc.3" + checksum: 10/2c63e4523acaf60fa13cd86f87579b63503accc6591aba9856b143a3e1fabc69829772a9403d0d6760606670a231b9a1e242118081ddd78f5e71556ce4db05be languageName: node linkType: hard -"@react-native/typescript-config@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/typescript-config@npm:0.84.1" - checksum: 10/6616765f8cf7702818ef251168522aeb68fb9baddcfc8235cd00731d0b4158131bf3fb12680b725c851002832c6fa604bee66b059bb15d35362b437b39615fa0 +"@react-native/typescript-config@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/typescript-config@npm:0.88.0-rc.3" + checksum: 10/39182cd7ad216ee644af22a29623a68e6986bc664d267961020b85a84249bfef32478f1c0edd1bf723d77be8bddc6500d29c8a816b0b08174dfe0626da0ec3d5 languageName: node linkType: hard -"@react-native/virtualized-lists@npm:0.84.1": - version: 0.84.1 - resolution: "@react-native/virtualized-lists@npm:0.84.1" +"@react-native/virtualized-lists@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "@react-native/virtualized-lists@npm:0.88.0-rc.3" dependencies: invariant: "npm:^2.2.4" nullthrows: "npm:^1.1.1" peerDependencies: "@types/react": ^19.2.0 react: "*" - react-native: "*" + react-native: 0.88.0-rc.3 peerDependenciesMeta: "@types/react": optional: true - checksum: 10/7d28ec774884569fe761a8a28d9667220056c38e8e0775ee44bb8d5d661254810f69bf569fc0efff4fa1b1213764b6e08fc4aedb5661478e6d1f6b7194561d72 + checksum: 10/83e6df384a4a8d73ebc259bf0f5b874a9d6f94f15a9f42d99894b39b4be0a562cd9613dbeb3da355d19871ad1def5d4c97e50a44f052b4a3ef9ea41de8e3322c languageName: node linkType: hard @@ -3870,39 +3890,39 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^8.36.0": - version: 8.56.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.56.1" +"@typescript-eslint/eslint-plugin@npm:^8.59.2": + version: 8.71.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.71.0" dependencies: "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/type-utils": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.71.0" + "@typescript-eslint/type-utils": "npm:8.71.0" + "@typescript-eslint/utils": "npm:8.71.0" + "@typescript-eslint/visitor-keys": "npm:8.71.0" ignore: "npm:^7.0.5" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.4.0" + ts-api-utils: "npm:^2.5.0" peerDependencies: - "@typescript-eslint/parser": ^8.56.1 + "@typescript-eslint/parser": ^8.71.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10/669d19cff91fcad5fe34dba97cc8c0c2df3160ae14646759fb23dfd6ffbb861d00d8d081e74d1060d544bfba0ea4d05588c5b73ae104907af26cc18189c0d139 + typescript: ">=4.8.4 <6.1.0" + checksum: 10/3b4c24bd7ceb5fd01d073e111f1108cada55c07d723cc81231c84a5767dae8b6abc8d734810a28c7987c5b7fd69b168ec743482a1715945e9aaceb2ef8e23b39 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^8.36.0": - version: 8.56.1 - resolution: "@typescript-eslint/parser@npm:8.56.1" +"@typescript-eslint/parser@npm:^8.59.2": + version: 8.71.0 + resolution: "@typescript-eslint/parser@npm:8.71.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.56.1" - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/visitor-keys": "npm:8.56.1" + "@typescript-eslint/scope-manager": "npm:8.71.0" + "@typescript-eslint/types": "npm:8.71.0" + "@typescript-eslint/typescript-estree": "npm:8.71.0" + "@typescript-eslint/visitor-keys": "npm:8.71.0" debug: "npm:^4.4.3" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10/280b041a69153caf9e721b307781830483dd39d881b02d993156635bd8600e30e6a816aaead8bdd662ae5149b8870aef7b3823d3b98ec974d924c23a786fb6d9 + typescript: ">=4.8.4 <6.1.0" + checksum: 10/198b78dd5f9ccd14f8f4f90467c5c9ab9cae1769ec32d8e9fb3008269bdf62373a8913951c2fe66ed3b981e16a95947736aa5a18f37ffa3612845c6f31f29187 languageName: node linkType: hard @@ -3919,6 +3939,19 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/project-service@npm:8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/project-service@npm:8.71.0" + dependencies: + "@typescript-eslint/tsconfig-utils": "npm:^8.71.0" + "@typescript-eslint/types": "npm:^8.71.0" + debug: "npm:^4.4.3" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10/7cf26e65414b08e4a503635d40104b8c495059861428648b78715af780415b455454aec02f444027dfe3afb4e8850b6f65f6c2f03f6d41811e13056d06443234 + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:8.56.1": version: 8.56.1 resolution: "@typescript-eslint/scope-manager@npm:8.56.1" @@ -3929,6 +3962,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/scope-manager@npm:8.71.0" + dependencies: + "@typescript-eslint/types": "npm:8.71.0" + "@typescript-eslint/visitor-keys": "npm:8.71.0" + checksum: 10/671d2dd893cfd657f20190caf570b6aa9bb39d2b0ba19ac1937180c2981b00af76edbbfab24f445c71f2abba87a762e3e49a22a5ade318a8c6f30e006966c648 + languageName: node + linkType: hard + "@typescript-eslint/tsconfig-utils@npm:8.56.1, @typescript-eslint/tsconfig-utils@npm:^8.56.1": version: 8.56.1 resolution: "@typescript-eslint/tsconfig-utils@npm:8.56.1" @@ -3938,19 +3981,28 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.56.1": - version: 8.56.1 - resolution: "@typescript-eslint/type-utils@npm:8.56.1" +"@typescript-eslint/tsconfig-utils@npm:8.71.0, @typescript-eslint/tsconfig-utils@npm:^8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.71.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10/1881f383fd3e34e4a9a63d315a26ebbe4faa8528d225539035fd32ee37f5055e80bf6f28fe423e4d62e3ea5e4e5b2319253583e95d41f0c66ac95943e752b588 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/type-utils@npm:8.71.0" dependencies: - "@typescript-eslint/types": "npm:8.56.1" - "@typescript-eslint/typescript-estree": "npm:8.56.1" - "@typescript-eslint/utils": "npm:8.56.1" + "@typescript-eslint/types": "npm:8.71.0" + "@typescript-eslint/typescript-estree": "npm:8.71.0" + "@typescript-eslint/utils": "npm:8.71.0" debug: "npm:^4.4.3" - ts-api-utils: "npm:^2.4.0" + ts-api-utils: "npm:^2.5.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10/2b07c674c26d797d05c05779ac5c89761b6b96680ecaf01440957727d12c6d06a2e48f0b139e45752eb4b53bf13c03940628656c519d362082b716d6a0ece6d9 + typescript: ">=4.8.4 <6.1.0" + checksum: 10/3d7fa4164e1b1e83dc83b23a0cba6570f615cac8d82155429c27fcf26aa745c107aa7fc91264050512c0cbdf5cf8b491abf9528e5d4bbed13731c75a75778ee8 languageName: node linkType: hard @@ -3961,6 +4013,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:8.71.0, @typescript-eslint/types@npm:^8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/types@npm:8.71.0" + checksum: 10/24c72ad99a5f3edb0021f87cd1366f63a73ecdd537b3c89d8189c52b999499a498913eed17c46edacca1e3990fd761e28293d2cf3cfde0a1f637d1879f1cb10f + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:8.56.1": version: 8.56.1 resolution: "@typescript-eslint/typescript-estree@npm:8.56.1" @@ -3980,7 +4039,41 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.56.1, @typescript-eslint/utils@npm:^8.0.0": +"@typescript-eslint/typescript-estree@npm:8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.71.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.71.0" + "@typescript-eslint/tsconfig-utils": "npm:8.71.0" + "@typescript-eslint/types": "npm:8.71.0" + "@typescript-eslint/visitor-keys": "npm:8.71.0" + debug: "npm:^4.4.3" + minimatch: "npm:^10.2.2" + semver: "npm:^7.7.3" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.5.0" + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + checksum: 10/6d1022ba1ca4da2083078f3c654e4e3faacf43bcd91f7f2a62320a45c20613e67deaf4de04c4b4656446bf7289d4f1152f966afcf9fcbbaa12357dff3bc039b4 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/utils@npm:8.71.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.9.1" + "@typescript-eslint/scope-manager": "npm:8.71.0" + "@typescript-eslint/types": "npm:8.71.0" + "@typescript-eslint/typescript-estree": "npm:8.71.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + checksum: 10/ace4ff09bb7a3592dc83c2a56de48a6e8631615fba2060eb38b721c40e8e0b532869547f33c718ee761039df970e607126d873716bf23e4b2a877e4185e56e4d + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:^8.0.0": version: 8.56.1 resolution: "@typescript-eslint/utils@npm:8.56.1" dependencies: @@ -4005,6 +4098,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.71.0": + version: 8.71.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.71.0" + dependencies: + "@typescript-eslint/types": "npm:8.71.0" + eslint-visitor-keys: "npm:^5.0.0" + checksum: 10/48ced48cf4d051fd9a3e1a6c10ebbca593ba5619553657e1100e17a60081bcee2a7bb9b11431b95f52478572bdd2e5be0f044678a570d9ce50b45c9bbdf5ea7e + languageName: node + linkType: hard + "@vitest/expect@npm:4.0.16": version: 4.0.16 resolution: "@vitest/expect@npm:4.0.16" @@ -4059,15 +4162,6 @@ __metadata: languageName: node linkType: hard -"abort-controller@npm:^3.0.0": - version: 3.0.0 - resolution: "abort-controller@npm:3.0.0" - dependencies: - event-target-shim: "npm:^5.0.0" - checksum: 10/ed84af329f1828327798229578b4fe03a4dd2596ba304083ebd2252666bdc1d7647d66d0b18704477e1f8aa315f055944aa6e859afebd341f12d0a53c37b4b40 - languageName: node - linkType: hard - "accepts@npm:^2.0.0": version: 2.0.0 resolution: "accepts@npm:2.0.0" @@ -4558,15 +4652,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-syntax-hermes-parser@npm:0.32.0": - version: 0.32.0 - resolution: "babel-plugin-syntax-hermes-parser@npm:0.32.0" - dependencies: - hermes-parser: "npm:0.32.0" - checksum: 10/ec76abeefabf940e2d571db3b47d022a9be7602286133291e8e047d4855af6a8afc079e4631bc9a56209d751fad54b5199932a55753b1e2b56a719d20e2d5065 - languageName: node - linkType: hard - "babel-plugin-syntax-hermes-parser@npm:0.33.3": version: 0.33.3 resolution: "babel-plugin-syntax-hermes-parser@npm:0.33.3" @@ -4962,34 +5047,6 @@ __metadata: languageName: node linkType: hard -"chrome-launcher@npm:^0.15.2": - version: 0.15.2 - resolution: "chrome-launcher@npm:0.15.2" - dependencies: - "@types/node": "npm:*" - escape-string-regexp: "npm:^4.0.0" - is-wsl: "npm:^2.2.0" - lighthouse-logger: "npm:^1.0.0" - bin: - print-chrome-path: bin/print-chrome-path.js - checksum: 10/6faa189950790e63356113a08c4dbb25d9ef7d1ffc778f9fcf5967895ea8968aa3e711f6e7a55dadb42aa7a329d77721abf929a589b87e9e19e6e8c084b87e0d - languageName: node - linkType: hard - -"chromium-edge-launcher@npm:^0.2.0": - version: 0.2.0 - resolution: "chromium-edge-launcher@npm:0.2.0" - dependencies: - "@types/node": "npm:*" - escape-string-regexp: "npm:^4.0.0" - is-wsl: "npm:^2.2.0" - lighthouse-logger: "npm:^1.0.0" - mkdirp: "npm:^1.0.4" - rimraf: "npm:^3.0.2" - checksum: 10/9c58094cb6f149f8b9aae6937c5e60fee3cdf7e43a6902d8d70d2bc18878a0479f1637a5b44f6fbec5c84aa52972fc3ccba61b9984a584f3d98700e247d4ad94 - languageName: node - linkType: hard - "ci-info@npm:^2.0.0": version: 2.0.0 resolution: "ci-info@npm:2.0.0" @@ -5534,7 +5591,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.6.9": +"debug@npm:2.6.9": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -5632,6 +5689,13 @@ __metadata: languageName: node linkType: hard +"define-lazy-prop@npm:^2.0.0": + version: 2.0.0 + resolution: "define-lazy-prop@npm:2.0.0" + checksum: 10/0115fdb065e0490918ba271d7339c42453d209d4cb619dfe635870d906731eff3e1ade8028bb461ea27ce8264ec5e22c6980612d332895977e89c1bbc80fcee2 + languageName: node + linkType: hard + "define-lazy-prop@npm:^3.0.0": version: 3.0.0 resolution: "define-lazy-prop@npm:3.0.0" @@ -6224,7 +6288,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react@npm:^7.30.1": +"eslint-plugin-react@npm:^7.37.5": version: 7.37.5 resolution: "eslint-plugin-react@npm:7.37.5" dependencies: @@ -6423,13 +6487,6 @@ __metadata: languageName: node linkType: hard -"event-target-shim@npm:^5.0.0": - version: 5.0.1 - resolution: "event-target-shim@npm:5.0.1" - checksum: 10/49ff46c3a7facbad3decb31f597063e761785d7fdb3920d4989d7b08c97a61c2f51183e2f3a03130c9088df88d4b489b1b79ab632219901f184f85158508f4c8 - languageName: node - linkType: hard - "event-target-shim@npm:^6.0.2": version: 6.0.2 resolution: "event-target-shim@npm:6.0.2" @@ -6721,6 +6778,38 @@ __metadata: languageName: node linkType: hard +"flow-estree@npm:0.327.0": + version: 0.327.0 + resolution: "flow-estree@npm:0.327.0" + checksum: 10/55dc4dc88f67b16a63beff317b10e9771e67e55be638bb0147cc71348e58366188f3586caf604a6cfffe2ff9269f8346cd5989ddf0284f1a4def568f023c8a6e + languageName: node + linkType: hard + +"flow-estree@npm:0.331.0": + version: 0.331.0 + resolution: "flow-estree@npm:0.331.0" + checksum: 10/ab19ede3a0a9aa3b03140df7e9a7732ed28f987b7b556a874968bc3d1bf7a952be3545e73117875a2f47bae319a758365b692d2fa25feae5ba1cfe4cc5663635 + languageName: node + linkType: hard + +"flow-parser@npm:0.327.0": + version: 0.327.0 + resolution: "flow-parser@npm:0.327.0" + dependencies: + flow-estree: "npm:0.327.0" + checksum: 10/9ffef49ac5e4888dd7f47873c41fe9261adaf62789107aa54068f70388bd1b86afe9bf6cc4652fd4c67d9e2337c5891bc0b98d3dbfe1175f4a8485c32f3d01df + languageName: node + linkType: hard + +"flow-parser@npm:0.331.0": + version: 0.331.0 + resolution: "flow-parser@npm:0.331.0" + dependencies: + flow-estree: "npm:0.331.0" + checksum: 10/3ac27e2ad45e3fea263e7f915fafc7d6857001f5bb962ff411eb6856b29a922e601ebc803339c8139a6f2f36f342f86907bfd1cb48955d50cc3171b4d55ba0fa + languageName: node + linkType: hard + "for-each@npm:^0.3.3, for-each@npm:^0.3.5": version: 0.3.5 resolution: "for-each@npm:0.3.5" @@ -7193,10 +7282,10 @@ __metadata: languageName: node linkType: hard -"hermes-compiler@npm:250829098.0.9": - version: 250829098.0.9 - resolution: "hermes-compiler@npm:250829098.0.9" - checksum: 10/15e1a0565e93f12a01e543d0d6f1a3a4cfb8037c44f89d930abd97c42e37c2b69f230b03e699c97402e6db33b7a9eb2d168c8c4a12966ef3b584e56cc565430a +"hermes-compiler@npm:260318099.0.4": + version: 260318099.0.4 + resolution: "hermes-compiler@npm:260318099.0.4" + checksum: 10/c035dc2c245e01356b3c0b54a44d8170c4372c702066dea42281c2fb9e7ff6b5d6828ca1f76d638061ad193ba2f12ee389b9edd53c2926a1dfc6bb6e11c14f6d languageName: node linkType: hard @@ -7214,13 +7303,6 @@ __metadata: languageName: node linkType: hard -"hermes-estree@npm:0.32.0": - version: 0.32.0 - resolution: "hermes-estree@npm:0.32.0" - checksum: 10/65a30a86a5a560152a2de1842c7bc7ecdadebd62e9cdd7d1809a824de7bc19e8d6a42907d3caff91d9f823862405d4b200447aa0bc25ba16072937e93d0acbd5 - languageName: node - linkType: hard - "hermes-estree@npm:0.33.3": version: 0.33.3 resolution: "hermes-estree@npm:0.33.3" @@ -7244,15 +7326,6 @@ __metadata: languageName: node linkType: hard -"hermes-parser@npm:0.32.0": - version: 0.32.0 - resolution: "hermes-parser@npm:0.32.0" - dependencies: - hermes-estree: "npm:0.32.0" - checksum: 10/496210490cb45e97df14796d94aec6c817c4cefa20f1dbe3ba1df323cc58c930033cfec93f3ecfad6b90e09166fc9ffc4f665843d25b4862523aa70dacbae81f - languageName: node - linkType: hard - "hermes-parser@npm:0.33.3": version: 0.33.3 resolution: "hermes-parser@npm:0.33.3" @@ -7625,7 +7698,7 @@ __metadata: languageName: node linkType: hard -"is-docker@npm:^2.0.0": +"is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": version: 2.2.1 resolution: "is-docker@npm:2.2.1" bin: @@ -7980,7 +8053,7 @@ __metadata: languageName: node linkType: hard -"is-wsl@npm:^2.1.1, is-wsl@npm:^2.2.0": +"is-wsl@npm:^2.2.0": version: 2.2.0 resolution: "is-wsl@npm:2.2.0" dependencies: @@ -8918,16 +8991,6 @@ __metadata: languageName: node linkType: hard -"lighthouse-logger@npm:^1.0.0": - version: 1.4.2 - resolution: "lighthouse-logger@npm:1.4.2" - dependencies: - debug: "npm:^2.6.9" - marky: "npm:^1.2.2" - checksum: 10/ffcedbf6878cc8b3289649ad60f42e3def7212b79eac6a21be2408724a2a7f65f9cfc3fbef6c0618ae4f476834949e1a56235e02ffa6b4e5019d2643d9d5977c - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -9176,13 +9239,6 @@ __metadata: languageName: node linkType: hard -"marky@npm:^1.2.2": - version: 1.3.0 - resolution: "marky@npm:1.3.0" - checksum: 10/c90687e18dbcfbe501e4161c3dbddfe0dcc715ad7643b5b06f17cebcb3c8cc8c12f34ddc3a2a1c0432b74b207a6ebaac6466a240794e0e04b0afb287cfed4933 - languageName: node - linkType: hard - "math-intrinsics@npm:^1.1.0": version: 1.1.0 resolution: "math-intrinsics@npm:1.1.0" @@ -9211,22 +9267,22 @@ __metadata: "@babel/core": "npm:7.29.0" "@babel/preset-env": "npm:7.29.0" "@babel/runtime": "npm:^7.28.6" - "@op-engineering/op-sqlite": "npm:15.2.5" + "@op-engineering/op-sqlite": "npm:18.2.5" "@react-native-async-storage/async-storage": "npm:2.2.0" - "@react-native-community/cli": "npm:20.1.3" - "@react-native-community/cli-platform-android": "npm:20.1.3" - "@react-native-community/cli-platform-ios": "npm:20.1.3" + "@react-native-community/cli": "npm:20.2.0" + "@react-native-community/cli-platform-android": "npm:20.2.0" + "@react-native-community/cli-platform-ios": "npm:20.2.0" "@react-native-harness/jest": "npm:1.1.0" "@react-native-harness/platform-android": "npm:1.1.0" "@react-native-harness/platform-apple": "npm:1.1.0" - "@react-native/babel-preset": "npm:0.84.1" - "@react-native/metro-config": "npm:0.84.1" - "@react-native/typescript-config": "npm:0.84.1" + "@react-native/babel-preset": "npm:0.88.0-rc.3" + "@react-native/metro-config": "npm:0.88.0-rc.3" + "@react-native/typescript-config": "npm:0.88.0-rc.3" "@types/react": "npm:19.2.14" - react: "npm:19.2.3" - react-native: "npm:0.84.1" + react: "npm:19.3.0" + react-native: "npm:0.88.0-rc.3" react-native-builder-bob: "npm:0.40.18" - react-native-gesture-handler: "npm:2.31.2" + react-native-gesture-handler: "npm:2.33.0" react-native-harness: "npm:1.1.0" react-native-monorepo-config: "npm:0.3.3" languageName: unknown @@ -9240,11 +9296,12 @@ __metadata: "@eslint/compat": "npm:1.4.1" "@eslint/eslintrc": "npm:3.3.5" "@eslint/js": "npm:9.39.4" - "@op-engineering/op-sqlite": "npm:15.2.5" + "@op-engineering/op-sqlite": "npm:18.2.5" "@react-native-async-storage/async-storage": "npm:2.2.0" - "@react-native-community/cli": "npm:20.1.3" - "@react-native/babel-preset": "npm:0.84.1" - "@react-native/eslint-config": "npm:0.84.1" + "@react-native-community/cli": "npm:20.2.0" + "@react-native/babel-preset": "npm:0.88.0-rc.3" + "@react-native/eslint-config": "npm:0.88.0-rc.3" + "@react-native/jest-preset": "npm:0.88.0-rc.3" "@release-it/conventional-changelog": "npm:10.0.5" "@types/jest": "npm:29.5.14" "@types/react": "npm:19.2.14" @@ -9256,10 +9313,10 @@ __metadata: jest: "npm:29.7.0" lefthook: "npm:2.1.3" prettier: "npm:3.4.2" - react: "npm:19.2.3" - react-native: "npm:0.84.1" + react: "npm:19.3.0" + react-native: "npm:0.88.0-rc.3" react-native-builder-bob: "npm:0.40.18" - react-native-gesture-handler: "npm:2.31.2" + react-native-gesture-handler: "npm:2.33.0" release-it: "npm:19.2.4" turbo: "npm:2.8.21" typescript: "npm:5.9.3" @@ -9316,18 +9373,6 @@ __metadata: languageName: node linkType: hard -"metro-babel-transformer@npm:0.83.5": - version: 0.83.5 - resolution: "metro-babel-transformer@npm:0.83.5" - dependencies: - "@babel/core": "npm:^7.25.2" - flow-enums-runtime: "npm:^0.0.6" - hermes-parser: "npm:0.33.3" - nullthrows: "npm:^1.1.1" - checksum: 10/2a7664a55a5c3f276c884288978bf2fb4d5f5a5137f3769d5fdfd79d6a2f0027475b0d8a19ff1d8b3d39b91f4bb7c54dbd191f7d671d776ccd4a84183f69aee2 - languageName: node - linkType: hard - "metro-babel-transformer@npm:0.84.4": version: 0.84.4 resolution: "metro-babel-transformer@npm:0.84.4" @@ -9341,12 +9386,16 @@ __metadata: languageName: node linkType: hard -"metro-cache-key@npm:0.83.5": - version: 0.83.5 - resolution: "metro-cache-key@npm:0.83.5" +"metro-babel-transformer@npm:0.87.1": + version: 0.87.1 + resolution: "metro-babel-transformer@npm:0.87.1" dependencies: + "@babel/core": "npm:^7.25.2" flow-enums-runtime: "npm:^0.0.6" - checksum: 10/704d0d8e06e8477d20c700cd5f729356aaa704999d4b80882b85aa21ccf7da13959dcd0760f9a456931466bf77dffe688f2a11f468aae5c074f74667957c6608 + flow-parser: "npm:0.331.0" + metro-cache-key: "npm:0.87.1" + nullthrows: "npm:^1.1.1" + checksum: 10/daa69a2ed9e800815dbe9d035fcd26d64ff4a4fda37f4649675c9e43bebf90d66a486e52600f5b95aca667feb31b1374132a93e546540e964ea9aec0c01f0c9a languageName: node linkType: hard @@ -9359,15 +9408,12 @@ __metadata: languageName: node linkType: hard -"metro-cache@npm:0.83.5": - version: 0.83.5 - resolution: "metro-cache@npm:0.83.5" +"metro-cache-key@npm:0.87.1": + version: 0.87.1 + resolution: "metro-cache-key@npm:0.87.1" dependencies: - exponential-backoff: "npm:^3.1.1" flow-enums-runtime: "npm:^0.0.6" - https-proxy-agent: "npm:^7.0.5" - metro-core: "npm:0.83.5" - checksum: 10/f2b3b9e85e46f262b0adeb36dcbd2e14692199ba834757013bc7fca200f66573ca1d3925090597326764f4efe57da3a1416b8b611cf83b6c965541a3c51af4f2 + checksum: 10/a972a3efaa64dd642dcbe33f86ef75266cc94a433776dcecc784ed9cb9ba51651074073b666b92e45ce208003ce610af4174f05547181caa8c7ecf5a62c8395f languageName: node linkType: hard @@ -9383,19 +9429,15 @@ __metadata: languageName: node linkType: hard -"metro-config@npm:0.83.5, metro-config@npm:^0.83.3": - version: 0.83.5 - resolution: "metro-config@npm:0.83.5" +"metro-cache@npm:0.87.1": + version: 0.87.1 + resolution: "metro-cache@npm:0.87.1" dependencies: - connect: "npm:^3.6.5" + exponential-backoff: "npm:^3.1.1" flow-enums-runtime: "npm:^0.0.6" - jest-validate: "npm:^29.7.0" - metro: "npm:0.83.5" - metro-cache: "npm:0.83.5" - metro-core: "npm:0.83.5" - metro-runtime: "npm:0.83.5" - yaml: "npm:^2.6.1" - checksum: 10/d085f7cd50b7c8557bd5b105fb23551ac3915ef162b62443fb9c44d9e25d450e37a729177c1267063167b5445e779c136b9a123c2c968d9ddfe6f979fb3f9ae2 + https-proxy-agent: "npm:^7.0.5" + metro-core: "npm:0.87.1" + checksum: 10/b7868281ba75c07f66d16e3b293362933ce5117b662a53bbd8e54c3c05ab2c191cf25a84865a0a464ce378f501fc6ecb688f486d71033f75061a1d80b62651ce languageName: node linkType: hard @@ -9415,14 +9457,18 @@ __metadata: languageName: node linkType: hard -"metro-core@npm:0.83.5, metro-core@npm:^0.83.3": - version: 0.83.5 - resolution: "metro-core@npm:0.83.5" +"metro-config@npm:0.87.1, metro-config@npm:^0.87.1": + version: 0.87.1 + resolution: "metro-config@npm:0.87.1" dependencies: + connect: "npm:^3.6.5" flow-enums-runtime: "npm:^0.0.6" - lodash.throttle: "npm:^4.1.1" - metro-resolver: "npm:0.83.5" - checksum: 10/a65e83fc73f2cc42f9ea72f9d6c976b2272c9c3477f17c6a1288497995a5572d2a89c2ebf29b8ff45195bde29b2ae90fa58b7238dfcfe07928289f58049c2842 + jest-validate: "npm:^29.7.0" + metro: "npm:0.87.1" + metro-cache: "npm:0.87.1" + metro-core: "npm:0.87.1" + metro-runtime: "npm:0.87.1" + checksum: 10/85956ed66948b4b942262ea2993719af403a3654b70741b535b35ba3ff620c390c4a9e8d38cbf4175fb83ea4e0ccd01eae2d04eac8c31b84c990e72bf7b4a3e9 languageName: node linkType: hard @@ -9437,20 +9483,14 @@ __metadata: languageName: node linkType: hard -"metro-file-map@npm:0.83.5": - version: 0.83.5 - resolution: "metro-file-map@npm:0.83.5" +"metro-core@npm:0.87.1": + version: 0.87.1 + resolution: "metro-core@npm:0.87.1" dependencies: - debug: "npm:^4.4.0" - fb-watchman: "npm:^2.0.0" flow-enums-runtime: "npm:^0.0.6" - graceful-fs: "npm:^4.2.4" - invariant: "npm:^2.2.4" - jest-worker: "npm:^29.7.0" - micromatch: "npm:^4.0.4" - nullthrows: "npm:^1.1.1" - walker: "npm:^1.0.7" - checksum: 10/0cce73c75bbf9b248628285554ddd73fce6f4e86ee4776c9f6b65fcf2cfd1f75b15e3f4cf2dc44ad91e5c78fc61a6eb7d3daaee09b61af2b55d82558a2b0423c + lodash.throttle: "npm:^4.1.1" + metro-resolver: "npm:0.87.1" + checksum: 10/df1ccdb89784ef3ad35dbd790bf82ead750c79515f17d776f14f6642b2f4ac2cb996791bf27669626c2d231a553724056e92e45f9c43b76fa7fa7550ab67af27 languageName: node linkType: hard @@ -9471,13 +9511,19 @@ __metadata: languageName: node linkType: hard -"metro-minify-terser@npm:0.83.5": - version: 0.83.5 - resolution: "metro-minify-terser@npm:0.83.5" +"metro-file-map@npm:0.87.1": + version: 0.87.1 + resolution: "metro-file-map@npm:0.87.1" dependencies: + debug: "npm:^4.4.0" + fb-watchman: "npm:^2.0.0" flow-enums-runtime: "npm:^0.0.6" - terser: "npm:^5.15.0" - checksum: 10/b9e257b5a74343a271e89603479775ed76b9c5e7b28015bafbce2afb4d7507acf36e897fc78c2ee571ad89951ba0ca708188ecb33fff0b947d1cee0ea8fd7837 + graceful-fs: "npm:^4.2.4" + invariant: "npm:^2.2.4" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + nullthrows: "npm:^1.1.1" + checksum: 10/e4de94eff66bd92bfcb88f0ec40e9cdef603a1c8d831f0277051c7387da36382a4f98c5797b8b04e09e4aed47d757c1b8e22e6a892ef8672f953c14864451cbe languageName: node linkType: hard @@ -9491,12 +9537,13 @@ __metadata: languageName: node linkType: hard -"metro-resolver@npm:0.83.5": - version: 0.83.5 - resolution: "metro-resolver@npm:0.83.5" +"metro-minify-terser@npm:0.87.1": + version: 0.87.1 + resolution: "metro-minify-terser@npm:0.87.1" dependencies: flow-enums-runtime: "npm:^0.0.6" - checksum: 10/0ad900735aa3446d8e5b341ff921b990895bb26517be96530b2a7c21504a617fa079299447b5ea4e3014894c94bcab7da54d37cbdc00bcc0c54f5c645c1d42cd + terser: "npm:^5.15.0" + checksum: 10/9998b826818e1280d99c1df044f62517acab0e291eaa6621f806a81f5c061ff2094425c3e0f62b1b1d13d52c15dbf45b909e09f6b814601ebb8c6ba39bb1cc99 languageName: node linkType: hard @@ -9509,13 +9556,12 @@ __metadata: languageName: node linkType: hard -"metro-runtime@npm:0.83.5, metro-runtime@npm:^0.83.3": - version: 0.83.5 - resolution: "metro-runtime@npm:0.83.5" +"metro-resolver@npm:0.87.1": + version: 0.87.1 + resolution: "metro-resolver@npm:0.87.1" dependencies: - "@babel/runtime": "npm:^7.25.0" flow-enums-runtime: "npm:^0.0.6" - checksum: 10/95a5f670fb2b230eea86e29833d0353c0fc845905fdae65c2f8a63c272ea095bf94976db7e28908bc6213ca22dffc21438eb18360321d92d8fb5aeb12a8d7520 + checksum: 10/d99d1ec97da3ca6d57cc3f3ca780b3595cbf38c21877a03408b55f2b4175ac1b37af80a61be4ba45bab0686baa25897ede277fcb01c1b75c2ba8399249a49a7b languageName: node linkType: hard @@ -9529,20 +9575,13 @@ __metadata: languageName: node linkType: hard -"metro-source-map@npm:0.83.5, metro-source-map@npm:^0.83.3": - version: 0.83.5 - resolution: "metro-source-map@npm:0.83.5" +"metro-runtime@npm:0.87.1, metro-runtime@npm:^0.87.1": + version: 0.87.1 + resolution: "metro-runtime@npm:0.87.1" dependencies: - "@babel/traverse": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" + "@babel/runtime": "npm:^7.25.0" flow-enums-runtime: "npm:^0.0.6" - invariant: "npm:^2.2.4" - metro-symbolicate: "npm:0.83.5" - nullthrows: "npm:^1.1.1" - ob1: "npm:0.83.5" - source-map: "npm:^0.5.6" - vlq: "npm:^1.0.0" - checksum: 10/55e9562f95e1056b48bd4b705a8ff01998c0bb9da2166638141ce7404f8800caa5c7ba077ead999809245400e38bbff1e175c2feefd044ac78a69f9a69c73d3d + checksum: 10/4341e98cffdcce68b83f39ea8b676f17aa59cfa73ab1e0f53f7b2bdd40a72b80998cacf1a3a7b4511d9ab10c67d69c2aa127bab929a3557caf9cb96c2249599c languageName: node linkType: hard @@ -9563,19 +9602,20 @@ __metadata: languageName: node linkType: hard -"metro-symbolicate@npm:0.83.5": - version: 0.83.5 - resolution: "metro-symbolicate@npm:0.83.5" +"metro-source-map@npm:0.87.1, metro-source-map@npm:^0.87.1": + version: 0.87.1 + resolution: "metro-source-map@npm:0.87.1" dependencies: + "@babel/traverse": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" flow-enums-runtime: "npm:^0.0.6" invariant: "npm:^2.2.4" - metro-source-map: "npm:0.83.5" + metro-symbolicate: "npm:0.87.1" nullthrows: "npm:^1.1.1" + ob1: "npm:0.87.1" source-map: "npm:^0.5.6" vlq: "npm:^1.0.0" - bin: - metro-symbolicate: src/index.js - checksum: 10/56cab184eff91d13f6122342f6564dd1b9bba97a32017c21ca1b0dade69a9020a53ef6971668a02ac0d4c457a05941162f3e6052a5854d124a30a63ee611d59b + checksum: 10/8c4b145c55f4dc59a0fd8f9b9d889d012865ed16b0721cf4ec520e6df6ce86f273967c7fed321e74beac19cbbcf40e2b532a1613cc962b766a443bae915182e9 languageName: node linkType: hard @@ -9595,17 +9635,19 @@ __metadata: languageName: node linkType: hard -"metro-transform-plugins@npm:0.83.5": - version: 0.83.5 - resolution: "metro-transform-plugins@npm:0.83.5" +"metro-symbolicate@npm:0.87.1": + version: 0.87.1 + resolution: "metro-symbolicate@npm:0.87.1" dependencies: - "@babel/core": "npm:^7.25.2" - "@babel/generator": "npm:^7.29.1" - "@babel/template": "npm:^7.28.6" - "@babel/traverse": "npm:^7.29.0" flow-enums-runtime: "npm:^0.0.6" + invariant: "npm:^2.2.4" + metro-source-map: "npm:0.87.1" nullthrows: "npm:^1.1.1" - checksum: 10/227da814239803d8c8288a403fe166e4d99b4d070426c57dc4a02e82c117cf9398b40a82b5e1060f1ebdb65a882dab840dbbea7d3f09a97ef3d3e4f6297fc2af + source-map: "npm:^0.5.6" + vlq: "npm:^1.0.0" + bin: + metro-symbolicate: src/index.js + checksum: 10/c364fbe3945dddf6f0d455bfac7e80af83991f7b38e1813fe34c2a111c2ff2432875bc6d3bcb1be7db042cfd6e669673f54960bd74a89880e8533259ac053529 languageName: node linkType: hard @@ -9623,24 +9665,17 @@ __metadata: languageName: node linkType: hard -"metro-transform-worker@npm:0.83.5": - version: 0.83.5 - resolution: "metro-transform-worker@npm:0.83.5" +"metro-transform-plugins@npm:0.87.1": + version: 0.87.1 + resolution: "metro-transform-plugins@npm:0.87.1" dependencies: "@babel/core": "npm:^7.25.2" "@babel/generator": "npm:^7.29.1" - "@babel/parser": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.29.0" flow-enums-runtime: "npm:^0.0.6" - metro: "npm:0.83.5" - metro-babel-transformer: "npm:0.83.5" - metro-cache: "npm:0.83.5" - metro-cache-key: "npm:0.83.5" - metro-minify-terser: "npm:0.83.5" - metro-source-map: "npm:0.83.5" - metro-transform-plugins: "npm:0.83.5" nullthrows: "npm:^1.1.1" - checksum: 10/6f3201cde7af9cb063ce0dd40b695dbcc658856e8db1d03d3b0c6854dab692477c33885c7891cb2f829ca6c682e7842f9a1801ac4c62db711183d2f7dd33a10d + checksum: 10/ff381fd4853e1be6373b6ec6dc873176f9ad000818d102166b656f6ab923d72935a47c3696c5eec46b602414c2da4f52fd4099e4a8c51e852e99ec1777942d59 languageName: node linkType: hard @@ -9665,9 +9700,30 @@ __metadata: languageName: node linkType: hard -"metro@npm:0.83.5, metro@npm:^0.83.3": - version: 0.83.5 - resolution: "metro@npm:0.83.5" +"metro-transform-worker@npm:0.87.1": + version: 0.87.1 + resolution: "metro-transform-worker@npm:0.87.1" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/generator": "npm:^7.29.1" + "@babel/parser": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + flow-enums-runtime: "npm:^0.0.6" + metro: "npm:0.87.1" + metro-babel-transformer: "npm:0.87.1" + metro-cache: "npm:0.87.1" + metro-cache-key: "npm:0.87.1" + metro-minify-terser: "npm:0.87.1" + metro-source-map: "npm:0.87.1" + metro-transform-plugins: "npm:0.87.1" + nullthrows: "npm:^1.1.1" + checksum: 10/814004de07b3ee963c78c639f0ff2f3aed6709de55028cefe991952cc2daaff115cc2c28c392d075b1ba81f2745f3a18f575e9844df134a69d751fdb18464d0b + languageName: node + linkType: hard + +"metro@npm:0.84.4": + version: 0.84.4 + resolution: "metro@npm:0.84.4" dependencies: "@babel/code-frame": "npm:^7.29.0" "@babel/core": "npm:^7.25.2" @@ -9677,31 +9733,30 @@ __metadata: "@babel/traverse": "npm:^7.29.0" "@babel/types": "npm:^7.29.0" accepts: "npm:^2.0.0" - chalk: "npm:^4.0.0" ci-info: "npm:^2.0.0" connect: "npm:^3.6.5" debug: "npm:^4.4.0" error-stack-parser: "npm:^2.0.6" flow-enums-runtime: "npm:^0.0.6" graceful-fs: "npm:^4.2.4" - hermes-parser: "npm:0.33.3" + hermes-parser: "npm:0.35.0" image-size: "npm:^1.0.2" invariant: "npm:^2.2.4" jest-worker: "npm:^29.7.0" jsc-safe-url: "npm:^0.2.2" lodash.throttle: "npm:^4.1.1" - metro-babel-transformer: "npm:0.83.5" - metro-cache: "npm:0.83.5" - metro-cache-key: "npm:0.83.5" - metro-config: "npm:0.83.5" - metro-core: "npm:0.83.5" - metro-file-map: "npm:0.83.5" - metro-resolver: "npm:0.83.5" - metro-runtime: "npm:0.83.5" - metro-source-map: "npm:0.83.5" - metro-symbolicate: "npm:0.83.5" - metro-transform-plugins: "npm:0.83.5" - metro-transform-worker: "npm:0.83.5" + metro-babel-transformer: "npm:0.84.4" + metro-cache: "npm:0.84.4" + metro-cache-key: "npm:0.84.4" + metro-config: "npm:0.84.4" + metro-core: "npm:0.84.4" + metro-file-map: "npm:0.84.4" + metro-resolver: "npm:0.84.4" + metro-runtime: "npm:0.84.4" + metro-source-map: "npm:0.84.4" + metro-symbolicate: "npm:0.84.4" + metro-transform-plugins: "npm:0.84.4" + metro-transform-worker: "npm:0.84.4" mime-types: "npm:^3.0.1" nullthrows: "npm:^1.1.1" serialize-error: "npm:^2.1.0" @@ -9711,13 +9766,13 @@ __metadata: yargs: "npm:^17.6.2" bin: metro: src/cli.js - checksum: 10/3c4643121335cf157696531829448b2c86ec653d5a7a11aa9cd005a1b9ad7a3f87f5e6ba8b997fc87e7b9f679a212d74db16739b4526a42425c6fb83e86283dc + checksum: 10/22369963a965398add8e79939852b6a8906565d81bcb2a764255526fc8548417aed2976e315ec44cc432e104ea03afc616879449a0a9e4c292cfe0e9f252649d languageName: node linkType: hard -"metro@npm:0.84.4": - version: 0.84.4 - resolution: "metro@npm:0.84.4" +"metro@npm:0.87.1, metro@npm:^0.87.1": + version: 0.87.1 + resolution: "metro@npm:0.87.1" dependencies: "@babel/code-frame": "npm:^7.29.0" "@babel/core": "npm:^7.25.2" @@ -9727,30 +9782,28 @@ __metadata: "@babel/traverse": "npm:^7.29.0" "@babel/types": "npm:^7.29.0" accepts: "npm:^2.0.0" - ci-info: "npm:^2.0.0" connect: "npm:^3.6.5" debug: "npm:^4.4.0" error-stack-parser: "npm:^2.0.6" flow-enums-runtime: "npm:^0.0.6" + flow-parser: "npm:0.331.0" graceful-fs: "npm:^4.2.4" - hermes-parser: "npm:0.35.0" - image-size: "npm:^1.0.2" invariant: "npm:^2.2.4" jest-worker: "npm:^29.7.0" jsc-safe-url: "npm:^0.2.2" lodash.throttle: "npm:^4.1.1" - metro-babel-transformer: "npm:0.84.4" - metro-cache: "npm:0.84.4" - metro-cache-key: "npm:0.84.4" - metro-config: "npm:0.84.4" - metro-core: "npm:0.84.4" - metro-file-map: "npm:0.84.4" - metro-resolver: "npm:0.84.4" - metro-runtime: "npm:0.84.4" - metro-source-map: "npm:0.84.4" - metro-symbolicate: "npm:0.84.4" - metro-transform-plugins: "npm:0.84.4" - metro-transform-worker: "npm:0.84.4" + metro-babel-transformer: "npm:0.87.1" + metro-cache: "npm:0.87.1" + metro-cache-key: "npm:0.87.1" + metro-config: "npm:0.87.1" + metro-core: "npm:0.87.1" + metro-file-map: "npm:0.87.1" + metro-resolver: "npm:0.87.1" + metro-runtime: "npm:0.87.1" + metro-source-map: "npm:0.87.1" + metro-symbolicate: "npm:0.87.1" + metro-transform-plugins: "npm:0.87.1" + metro-transform-worker: "npm:0.87.1" mime-types: "npm:^3.0.1" nullthrows: "npm:^1.1.1" serialize-error: "npm:^2.1.0" @@ -9760,7 +9813,7 @@ __metadata: yargs: "npm:^17.6.2" bin: metro: src/cli.js - checksum: 10/22369963a965398add8e79939852b6a8906565d81bcb2a764255526fc8548417aed2976e315ec44cc432e104ea03afc616879449a0a9e4c292cfe0e9f252649d + checksum: 10/5d6a8efde5e757e7e8c69ae6645ecf0b8c0c457eacfb38272be5ee7c5d69e496f188dc15822c225f4d10de80a8e9119c8d95db31b8ba449e94ad2a5995d23c27 languageName: node linkType: hard @@ -9955,15 +10008,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.4": - version: 1.0.4 - resolution: "mkdirp@npm:1.0.4" - bin: - mkdirp: bin/cmd.js - checksum: 10/d71b8dcd4b5af2fe13ecf3bd24070263489404fe216488c5ba7e38ece1f54daf219e72a833a3a2dc404331e870e9f44963a33399589490956bff003a3404d3b2 - languageName: node - linkType: hard - "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -10184,21 +10228,21 @@ __metadata: languageName: node linkType: hard -"ob1@npm:0.83.5": - version: 0.83.5 - resolution: "ob1@npm:0.83.5" +"ob1@npm:0.84.4": + version: 0.84.4 + resolution: "ob1@npm:0.84.4" dependencies: flow-enums-runtime: "npm:^0.0.6" - checksum: 10/7a3ed43344d3d10c76060218fc35c652d12e20c0e520cf4bdb3c86c2817f0622b78a3d8c81fd52a05c29d7d2113b65514ee721e61adb352dd547d14a74b6015a + checksum: 10/15621cfa2d6bb196c5046031b3f85259735a245d9d7087f41758be3c31589c464e6eef53d94ec3d680fd8286ef08944782b9112f18d790a99421fbc7e311bb32 languageName: node linkType: hard -"ob1@npm:0.84.4": - version: 0.84.4 - resolution: "ob1@npm:0.84.4" +"ob1@npm:0.87.1": + version: 0.87.1 + resolution: "ob1@npm:0.87.1" dependencies: flow-enums-runtime: "npm:^0.0.6" - checksum: 10/15621cfa2d6bb196c5046031b3f85259735a245d9d7087f41758be3c31589c464e6eef53d94ec3d680fd8286ef08944782b9112f18d790a99421fbc7e311bb32 + checksum: 10/006dfaca8be7128cbf98ead8006c0f530696fb11570f81fb26acd818826a9a7bb3d00f532289496eaf97133dab5bbb0a0067f679e64137a7e880d32ec2fe0df2 languageName: node linkType: hard @@ -10362,13 +10406,14 @@ __metadata: languageName: node linkType: hard -"open@npm:^7.0.3": - version: 7.4.2 - resolution: "open@npm:7.4.2" +"open@npm:^8.4.2": + version: 8.4.2 + resolution: "open@npm:8.4.2" dependencies: - is-docker: "npm:^2.0.0" - is-wsl: "npm:^2.1.1" - checksum: 10/4fc02ed3368dcd5d7247ad3566433ea2695b0713b041ebc0eeb2f0f9e5d4e29fc2068f5cdd500976b3464e77fe8b61662b1b059c73233ccc601fe8b16d6c1cd6 + define-lazy-prop: "npm:^2.0.0" + is-docker: "npm:^2.1.1" + is-wsl: "npm:^2.2.0" + checksum: 10/acd81a1d19879c818acb3af2d2e8e9d81d17b5367561e623248133deb7dd3aefaed527531df2677d3e6aaf0199f84df57b6b2262babff8bf46ea0029aac536c9 languageName: node linkType: hard @@ -11000,9 +11045,9 @@ __metadata: languageName: node linkType: hard -"react-native-gesture-handler@npm:2.31.2": - version: 2.31.2 - resolution: "react-native-gesture-handler@npm:2.31.2" +"react-native-gesture-handler@npm:2.33.0": + version: 2.33.0 + resolution: "react-native-gesture-handler@npm:2.33.0" dependencies: "@egjs/hammerjs": "npm:^2.0.17" "@types/react-test-renderer": "npm:^19.1.0" @@ -11011,7 +11056,7 @@ __metadata: peerDependencies: react: "*" react-native: "*" - checksum: 10/717ae7a0b997e2eba5eb3d78c11c34cfb5b4f5ac86e84037687983e66f217ca4baceb95ee833329f5bb06d81d83cc96bb57009fa43daa759692abae01ea9cfe0 + checksum: 10/eb9a509183852bc0c928066e2800474d730ca06a10b4c640165bb6e6d86477e89d555666801d353ff806f124c0da5730ac5534523586c2856f6016b47815b1ed languageName: node linkType: hard @@ -11053,39 +11098,33 @@ __metadata: languageName: node linkType: hard -"react-native@npm:0.84.1": - version: 0.84.1 - resolution: "react-native@npm:0.84.1" +"react-native@npm:0.88.0-rc.3": + version: 0.88.0-rc.3 + resolution: "react-native@npm:0.88.0-rc.3" dependencies: - "@jest/create-cache-key-function": "npm:^29.7.0" - "@react-native/assets-registry": "npm:0.84.1" - "@react-native/codegen": "npm:0.84.1" - "@react-native/community-cli-plugin": "npm:0.84.1" - "@react-native/gradle-plugin": "npm:0.84.1" - "@react-native/js-polyfills": "npm:0.84.1" - "@react-native/normalize-colors": "npm:0.84.1" - "@react-native/virtualized-lists": "npm:0.84.1" - abort-controller: "npm:^3.0.0" + "@react-native/asset-utils": "npm:0.88.0-rc.3" + "@react-native/codegen": "npm:0.88.0-rc.3" + "@react-native/community-cli-plugin": "npm:0.88.0-rc.3" + "@react-native/gradle-plugin": "npm:0.88.0-rc.3" + "@react-native/normalize-colors": "npm:0.88.0-rc.3" + "@react-native/virtualized-lists": "npm:0.88.0-rc.3" anser: "npm:^1.4.9" ansi-regex: "npm:^5.0.0" - babel-jest: "npm:^29.7.0" - babel-plugin-syntax-hermes-parser: "npm:0.32.0" base64-js: "npm:^1.5.1" - commander: "npm:^12.0.0" flow-enums-runtime: "npm:^0.0.6" - hermes-compiler: "npm:250829098.0.9" + flow-parser: "npm:0.327.0" + hermes-compiler: "npm:260318099.0.4" invariant: "npm:^2.2.4" - jest-environment-node: "npm:^29.7.0" memoize-one: "npm:^5.0.0" - metro-runtime: "npm:^0.83.3" - metro-source-map: "npm:^0.83.3" + metro-runtime: "npm:^0.87.1" + metro-source-map: "npm:^0.87.1" nullthrows: "npm:^1.1.1" pretty-format: "npm:^29.7.0" promise: "npm:^8.3.0" react-devtools-core: "npm:^6.1.5" react-refresh: "npm:^0.14.0" regenerator-runtime: "npm:^0.13.2" - scheduler: "npm:0.27.0" + scheduler: "npm:0.28.0" semver: "npm:^7.1.3" stacktrace-parser: "npm:^0.1.10" tinyglobby: "npm:^0.2.15" @@ -11094,13 +11133,13 @@ __metadata: yargs: "npm:^17.6.2" peerDependencies: "@types/react": ^19.1.1 - react: ^19.2.3 + react: ^19.3.0 peerDependenciesMeta: "@types/react": optional: true bin: react-native: cli.js - checksum: 10/f029d0eb9984fdf3fe04e116d36304bf8b5d4b6198cfd332026788e0bdc5648b34d434485567e880bfda461913f8b9819b666e7e731189fa4afb0cb89132b33c + checksum: 10/0162fcf149f80f7909c9b7e53207235d7e19a8f26c1bfb755bbbf9b4ff041d1f9055b8dfc41c107c69140b4e379a1717994c07269ff75ee2219150c8da97b99f languageName: node linkType: hard @@ -11111,10 +11150,10 @@ __metadata: languageName: node linkType: hard -"react@npm:19.2.3": - version: 19.2.3 - resolution: "react@npm:19.2.3" - checksum: 10/d16b7f35c0d35a56f63d9d1693819762e4abc479c57dd6310298920bed3820fcec7e17a99d44983416d8f5049143ea45b8005d3ab8324bae8973224400502b08 +"react@npm:19.3.0": + version: 19.3.0 + resolution: "react@npm:19.3.0" + checksum: 10/e98669f09750c41abb1bf020af67cc847e018c91a8c5413d3f40ddd737e3daef6e419bcd1521b113fda73fd667ae82d5f0e9d9e3ff462faeb82059c09e7f04b1 languageName: node linkType: hard @@ -11488,10 +11527,10 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:0.27.0": - version: 0.27.0 - resolution: "scheduler@npm:0.27.0" - checksum: 10/eab3c3a8373195173e59c147224fc30dabe6dd453f248f5e610e8458512a5a2ee3a06465dc400ebfe6d35c9f5b7f3bb6b2e41c88c86fd177c25a73e7286a1e06 +"scheduler@npm:0.28.0": + version: 0.28.0 + resolution: "scheduler@npm:0.28.0" + checksum: 10/2a936a3729df438bd42e6af7a16a62b83543796209c9d2e637f3d7b198bd5c25c5909478a9da4f66923d290e01997816338cf740587c440448863783bd33d31d languageName: node linkType: hard @@ -11912,13 +11951,6 @@ __metadata: languageName: node linkType: hard -"strict-url-sanitise@npm:0.0.1": - version: 0.0.1 - resolution: "strict-url-sanitise@npm:0.0.1" - checksum: 10/cab6ae551f998f18ea7fb14176a9d835f5b304e5419c61851de897c830ccc20c2848bbb50ced242227114e06a3f6379dcc9179a84bc0a7b8cf81f5192b5b4789 - languageName: node - linkType: hard - "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -12243,6 +12275,15 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^2.5.0": + version: 2.5.0 + resolution: "ts-api-utils@npm:2.5.0" + peerDependencies: + typescript: ">=4.8.4" + checksum: 10/d5f1936f5618c6ab6942a97b78802217540ced00e7501862ae1f578d9a3aa189fc06050e64cb8951d21f7088e5fd35f53d2bf0d0370a883861c7b05e993ebc44 + languageName: node + linkType: hard + "tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.3.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" From ca71bf33f4af500e54905aeb5d86cfbae91ba89a Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Sat, 3 Oct 2026 01:43:06 +0530 Subject: [PATCH 02/10] chore: add tests --- MendixNative.podspec | 5 + android/build.gradle | 11 + .../mendix/mendixnative/config/AppUrlTest.kt | 35 ++++ .../encryption/MendixEncryptionToolkitTest.kt | 72 +++++++ .../react/download/DownloadHelperTest.kt | 142 +++++++++++++ .../react/ota/NativeOtaModuleTest.kt | 165 +++++++++++++++ .../mendixnative/request/CookieHelpersTest.kt | 58 ++++++ .../src/test/resources/robolectric.properties | 2 + example/__tests__/download-handler.harness.ts | 73 ++++++- example/__tests__/ota.harness.ts | 189 ++++-------------- example/ios/Podfile | 12 ++ example/ios/Podfile.lock | 31 ++- ios/Tests/AppUrlTests.swift | 47 +++++ ios/Tests/NativeFsPathTests.swift | 40 ++++ ios/Tests/OtaDeployTests.swift | 145 ++++++++++++++ package.json | 2 + 16 files changed, 867 insertions(+), 162 deletions(-) create mode 100644 android/src/test/java/com/mendix/mendixnative/config/AppUrlTest.kt create mode 100644 android/src/test/java/com/mendix/mendixnative/encryption/MendixEncryptionToolkitTest.kt create mode 100644 android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt create mode 100644 android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt create mode 100644 android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt create mode 100644 android/src/test/resources/robolectric.properties create mode 100644 ios/Tests/AppUrlTests.swift create mode 100644 ios/Tests/NativeFsPathTests.swift create mode 100644 ios/Tests/OtaDeployTests.swift diff --git a/MendixNative.podspec b/MendixNative.podspec index d21b9a8..e387f79 100644 --- a/MendixNative.podspec +++ b/MendixNative.podspec @@ -14,6 +14,7 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/mendix/mendix-native.git", :tag => "#{s.version}" } s.source_files = "ios/**/*.{h,m,mm,cpp,swift}" + s.exclude_files = "ios/Tests/**" s.public_header_files = ["ios/Modules/Helper/ReactHostHelper.h", "ios/Modules/NativeCookieModule/ObjCExceptionCatcher.h"] s.private_header_files = "ios/TurboModules/**/*.h" @@ -22,4 +23,8 @@ Pod::Spec.new do |s| s.dependency "ReactAppDependencyProvider" install_modules_dependencies(s) + + s.test_spec "Tests" do |test_spec| + test_spec.source_files = "ios/Tests/**/*.swift" + end end diff --git a/android/build.gradle b/android/build.gradle index b7a6b0f..4253cc3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -45,6 +45,12 @@ android { } } + testOptions { + unitTests { + includeAndroidResources = true + } + } + lintOptions { disable "GradleCompatible" } @@ -90,4 +96,9 @@ dependencies { api project(':op-engineering_op-sqlite') api project(':react-native-async-storage_async-storage') api project(':react-native-gesture-handler') + + testImplementation "junit:junit:4.13.2" + testImplementation "org.robolectric:robolectric:4.17" + // Matches the okhttp version resolved for the library. + testImplementation "com.squareup.okhttp3:mockwebserver:4.9.2" } diff --git a/android/src/test/java/com/mendix/mendixnative/config/AppUrlTest.kt b/android/src/test/java/com/mendix/mendixnative/config/AppUrlTest.kt new file mode 100644 index 0000000..31c4bdd --- /dev/null +++ b/android/src/test/java/com/mendix/mendixnative/config/AppUrlTest.kt @@ -0,0 +1,35 @@ +package com.mendix.mendixnative.config + +import org.junit.Assert.assertEquals +import org.junit.Test + +class AppUrlTest { + @Test + fun forRuntimeAddsProtocolAndTrailingSlash() { + assertEquals("http://example.com/", AppUrl.forRuntime("example.com")) + assertEquals("https://example.com/", AppUrl.forRuntime("https://example.com/")) + assertEquals("http://10.0.2.2:8080/", AppUrl.forRuntime("http://10.0.2.2:8080")) + } + + @Test + fun forRuntimeKeepsSubpath() { + assertEquals("https://example.com/app/", AppUrl.forRuntime("https://example.com/app")) + } + + @Test + fun ensureProtocolOnlyAcceptsHttpSchemes() { + assertEquals("https://example.com", AppUrl.ensureProtocol("https://example.com")) + assertEquals("http://ftp://example.com", AppUrl.ensureProtocol("ftp://example.com")) + } + + @Test + fun removeTrailingSlashRemovesOneSlash() { + assertEquals("http://example.com", AppUrl.removeTrailingSlash("http://example.com/")) + assertEquals("http://example.com", AppUrl.removeTrailingSlash("http://example.com")) + } + + @Test + fun forBundleJoinsHostAndPort() { + assertEquals("localhost:8081", AppUrl.forBundle("localhost", 8081)) + } +} diff --git a/android/src/test/java/com/mendix/mendixnative/encryption/MendixEncryptionToolkitTest.kt b/android/src/test/java/com/mendix/mendixnative/encryption/MendixEncryptionToolkitTest.kt new file mode 100644 index 0000000..b57a383 --- /dev/null +++ b/android/src/test/java/com/mendix/mendixnative/encryption/MendixEncryptionToolkitTest.kt @@ -0,0 +1,72 @@ +package com.mendix.mendixnative.encryption + +import android.util.Base64 +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals +import org.junit.Assert.assertThrows +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import javax.crypto.AEADBadTagException +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.spec.IvParameterSpec + +// Robolectric provides android.util.Base64; keys are software keys since there is no AndroidKeyStore. +@RunWith(RobolectricTestRunner::class) +class MendixEncryptionToolkitTest { + private fun aesKey() = KeyGenerator.getInstance("AES").apply { init(256) }.generateKey() + + @Test + fun encryptDecryptRoundTrip() { + val key = aesKey() + val (value, iv, encrypted) = encryptValue("séssion=1; x") { key } + + assertTrue(encrypted) + assertTrue(value.decodeToString().startsWith("v2:")) + assertEquals( + "séssion=1; x", + decryptValue(value.decodeToString(), iv!!.decodeToString(), modernGetPassword = { key }) + ) + } + + @Test + fun encryptUsesFreshIvEachTime() { + val key = aesKey() + val first = encryptValue("value") { key } + val second = encryptValue("value") { key } + + assertNotEquals(first.second!!.decodeToString(), second.second!!.decodeToString()) + assertNotEquals(first.first.decodeToString(), second.first.decodeToString()) + } + + @Test + fun decryptWithWrongKeyFails() { + val (value, iv) = encryptValue("value") { aesKey() } + val wrongKey = aesKey() + + assertThrows(AEADBadTagException::class.java) { + decryptValue(value.decodeToString(), iv!!.decodeToString(), modernGetPassword = { wrongKey }) + } + } + + @Test + fun decryptRequiresIv() { + val (value) = encryptValue("value") { aesKey() } + + assertThrows(IllegalArgumentException::class.java) { + decryptValue(value.decodeToString(), null, modernGetPassword = { aesKey() }) + } + } + + @Test + fun decryptsLegacyCbcValues() { + val key = aesKey() + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding").apply { init(Cipher.ENCRYPT_MODE, key) } + val encrypted = Base64.encodeToString(cipher.doFinal("legacy".toByteArray()), Base64.DEFAULT) + val iv = Base64.encodeToString((cipher.parameters.getParameterSpec(IvParameterSpec::class.java)).iv, Base64.DEFAULT) + + assertEquals("legacy", decryptValue(encrypted, iv, legacyGetPassword = { key })) + } +} diff --git a/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt b/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt new file mode 100644 index 0000000..4ce3a48 --- /dev/null +++ b/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt @@ -0,0 +1,142 @@ +package com.mendix.mendixnative.react.download + +import okhttp3.OkHttpClient +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import java.io.File +import java.net.ConnectException +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +class DownloadHelperTest { + @get:Rule + val tempFolder = TemporaryFolder() + + private lateinit var server: MockWebServer + private val client = OkHttpClient() + + @Before + fun setUp() { + server = MockWebServer().apply { start() } + } + + @After + fun tearDown() { + server.shutdown() + } + + private class Result { + val latch = CountDownLatch(1) + var succeeded = false + var error: Exception? = null + + fun await() = assertTrue("download did not finish", latch.await(5, TimeUnit.SECONDS)) + } + + private fun download(file: File, mimeType: String? = null): Result { + val result = Result() + downloadFile( + client = client, + url = server.url("/file").toString(), + downloadPath = file.absolutePath, + expectedMimeType = mimeType, + onSuccess = { result.succeeded = true; result.latch.countDown() }, + onFailure = { result.error = it; result.latch.countDown() }, + ) + result.await() + return result + } + + @Test + fun downloadsBodyToPathCreatingParentDirectories() { + server.enqueue(MockResponse().setBody("content")) + val file = File(tempFolder.root, "nested/dir/file.txt") + + val result = download(file) + + assertTrue(result.succeeded) + assertEquals("content", file.readText()) + } + + @Test + fun errorStatusFailsAndRemovesFile() { + server.enqueue(MockResponse().setResponseCode(404).setBody("not found")) + val file = File(tempFolder.root, "file.txt") + + val result = download(file) + + assertTrue(result.error is ConnectException) + assertFalse(file.exists()) + } + + @Test + fun mismatchingMimeTypeFailsAndRemovesFile() { + server.enqueue(MockResponse().setHeader("Content-Type", "text/plain").setBody("content")) + val file = File(tempFolder.root, "file.txt") + + val result = download(file, mimeType = "application/zip") + + assertTrue(result.error is DownloadMimeTypeException) + assertFalse(file.exists()) + } + + @Test + fun matchingMimeTypeSucceeds() { + server.enqueue(MockResponse().setHeader("Content-Type", "application/zip").setBody("zip")) + val file = File(tempFolder.root, "file.zip") + + val result = download(file, mimeType = "application/zip") + + assertNull(result.error) + assertEquals("zip", file.readText()) + } + + @Test + fun connectionFailureRemovesFile() { + val file = File(tempFolder.root, "file.txt") + server.shutdown() + + val result = Result() + downloadFile( + client = client, + url = server.url("/file").toString(), + downloadPath = file.absolutePath, + onSuccess = { result.succeeded = true; result.latch.countDown() }, + onFailure = { result.error = it; result.latch.countDown() }, + ) + result.await() + + assertFalse(result.succeeded) + assertFalse(file.exists()) + } + + @Test(expected = FileAlreadyExistsException::class) + fun existingDestinationThrowsBeforeRequesting() { + val file = tempFolder.newFile("existing.txt").apply { writeText("keep") } + try { + downloadFile(client, server.url("/file").toString(), file.absolutePath, {}, {}) + } finally { + assertEquals("keep", file.readText()) + assertEquals(0, server.requestCount) + } + } + + @Test + fun progressInvokerFiresOncePerInterval() { + val calls = mutableListOf() + val invoke = makeProgressCallbackInvoker(10.0) { received, _ -> calls.add(received) } + + listOf(1.0, 9.0, 10.0, 15.0, 19.0, 20.0, 35.0, 40.0).forEach { invoke(it, 100.0) } + + assertEquals(listOf(10.0, 20.0, 35.0), calls) + } +} diff --git a/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt b/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt new file mode 100644 index 0000000..d48cef5 --- /dev/null +++ b/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt @@ -0,0 +1,165 @@ +package com.mendix.mendixnative.react.ota + +import android.content.Context +import com.facebook.react.bridge.JavaOnlyMap +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.BridgeReactContext +import com.facebook.react.bridge.WritableMap +import org.json.JSONObject +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import java.io.File +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream + +@RunWith(RobolectricTestRunner::class) +class NativeOtaModuleTest { + private lateinit var context: Context + private lateinit var module: NativeOtaModule + private lateinit var otaDir: File + + @Before + fun setUp() { + context = RuntimeEnvironment.getApplication() + otaDir = File(getOtaDir(context)).apply { deleteRecursively() } + module = NativeOtaModule(BridgeReactContext(context)) + } + + @After + fun tearDown() { + otaDir.deleteRecursively() + } + + private sealed class Outcome { + object Resolved : Outcome() + data class Rejected(val code: String?) : Outcome() + } + + private class RecordingPromise : Promise { + var outcome: Outcome? = null + override fun resolve(value: Any?) { outcome = Outcome.Resolved } + override fun reject(code: String?, message: String?) { outcome = Outcome.Rejected(code) } + override fun reject(code: String?, throwable: Throwable?) { outcome = Outcome.Rejected(code) } + override fun reject(code: String?, message: String?, throwable: Throwable?) { outcome = Outcome.Rejected(code) } + override fun reject(throwable: Throwable) { outcome = Outcome.Rejected(null) } + override fun reject(throwable: Throwable, userInfo: WritableMap) { outcome = Outcome.Rejected(null) } + override fun reject(code: String?, userInfo: WritableMap) { outcome = Outcome.Rejected(code) } + override fun reject(code: String?, throwable: Throwable?, userInfo: WritableMap) { outcome = Outcome.Rejected(code) } + override fun reject(code: String?, message: String?, userInfo: WritableMap) { outcome = Outcome.Rejected(code) } + override fun reject(code: String?, message: String?, throwable: Throwable?, userInfo: WritableMap?) { outcome = Outcome.Rejected(code) } + @Deprecated("Deprecated in Java") + override fun reject(message: String) { outcome = Outcome.Rejected(null) } + } + + private fun deploy(id: String, pkg: String, extractionDir: String): Outcome { + val promise = RecordingPromise() + module.deploy( + JavaOnlyMap.of("otaDeploymentID", id, "otaPackage", pkg, "extractionDir", extractionDir), + promise + ) + // deploy settles synchronously. + return promise.outcome!! + } + + /** Writes a zip containing index.android.bundle into the OTA dir and returns its file name. */ + private fun makeOtaPackage(name: String, bundleContent: String = "bundle"): String { + ZipOutputStream(File(otaDir, name).outputStream()).use { zip -> + zip.putNextEntry(ZipEntry("index.android.bundle")) + zip.write(bundleContent.toByteArray()) + zip.closeEntry() + } + return name + } + + private fun file(relative: String) = File(otaDir, relative) + + @Test + fun deployExtractsBundleWritesManifestAndRemovesZip() { + val zip = makeOtaPackage("first.zip", "first") + + assertEquals(Outcome.Resolved, deploy("1", zip, "deployment-1")) + + assertEquals("first", file("deployment-1/index.android.bundle").readText()) + assertFalse(file(zip).exists()) + val manifest = JSONObject(File(getOtaManifestFilepath(context)).readText()) + assertEquals("1", manifest.getString(MANIFEST_OTA_DEPLOYMENT_ID_KEY)) + assertEquals("deployment-1/index.android.bundle", manifest.getString(MANIFEST_RELATIVE_BUNDLE_PATH_KEY)) + assertEquals(resolveAppVersion(context), manifest.getString(MANIFEST_APP_VERSION_KEY)) + + assertEquals( + file("deployment-1/index.android.bundle").absolutePath, + OtaJSBundleUrlProvider().getJSBundleFile(context) + ) + } + + @Test + fun newDeploymentRemovesPreviousBundle() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployment-1")) + assertEquals(Outcome.Resolved, deploy("2", makeOtaPackage("second.zip"), "deployment-2")) + + assertFalse(file("deployment-1").exists()) + assertEquals( + file("deployment-2/index.android.bundle").absolutePath, + OtaJSBundleUrlProvider().getJSBundleFile(context) + ) + } + + @Test + fun redeployingActiveDeploymentIsRejectedAndKeepsBundle() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployment-1")) + val zip = makeOtaPackage("again.zip") + + assertEquals(Outcome.Rejected(OTA_ALREADY_DEPLOYED), deploy("1", zip, "deployment-1")) + assertFalse(file(zip).exists()) + assertTrue(file("deployment-1/index.android.bundle").exists()) + } + + @Test + fun redeployingSameIdIsAllowedWhenBundleIsMissing() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployment-1")) + file("deployment-1").deleteRecursively() + + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("again.zip"), "deployment-1")) + assertTrue(file("deployment-1/index.android.bundle").exists()) + } + + @Test + fun missingPackageIsRejected() { + assertEquals(Outcome.Rejected(OTA_ZIP_FILE_MISSING), deploy("1", "missing.zip", "deployment-1")) + assertNull(OtaJSBundleUrlProvider().getJSBundleFile(context)) + } + + @Test + fun invalidZipIsRejectedWithoutManifest() { + file("invalid.zip").writeText("not a zip") + + assertEquals(Outcome.Rejected(OTA_DEPLOYMENT_FAILED), deploy("1", "invalid.zip", "deployment-1")) + assertFalse(file("deployment-1").exists()) + assertFalse(File(getOtaManifestFilepath(context)).exists()) + } + + @Test + fun missingConfigKeyIsRejected() { + val promise = RecordingPromise() + module.deploy(JavaOnlyMap.of("otaPackage", "first.zip", "extractionDir", "deployment-1"), promise) + + assertEquals(Outcome.Rejected(INVALID_DEPLOY_CONFIG), promise.outcome) + } + + @Test + fun bundleIsIgnoredWhenAppVersionChanged() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployment-1")) + val manifestFile = File(getOtaManifestFilepath(context)) + manifestFile.writeText(JSONObject(manifestFile.readText()).put(MANIFEST_APP_VERSION_KEY, "0.0.0-0").toString()) + + assertNull(OtaJSBundleUrlProvider().getJSBundleFile(context)) + } +} diff --git a/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt b/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt new file mode 100644 index 0000000..523331c --- /dev/null +++ b/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt @@ -0,0 +1,58 @@ +package com.mendix.mendixnative.request + +import okhttp3.Request +import org.junit.Assert.assertEquals +import org.junit.Assert.assertSame +import org.junit.Assert.assertTrue +import org.junit.Test + +class CookieHelpersTest { + private fun requestWithCookie(cookie: String) = + Request.Builder().url("https://example.com").header("Cookie", cookie).build() + + @Test + fun cookieValueToDecryptionParamsSplitsValueAndIv() { + assertEquals(Pair("value", "iv"), cookieValueToDecryptionParams("value${ivDelimiter}iv")) + assertEquals(Pair("value", null), cookieValueToDecryptionParams("value")) + } + + @Test + fun encryptionResultToCookieValueJoinsWithIvAndStripsNewlines() { + val value = encryptionResultToCookieValue(Triple("abc\n".toByteArray(), "iv\n".toByteArray(), true)) + assertEquals("\"abc${ivDelimiter}iv\"", value) + } + + @Test + fun encryptionResultToCookieValueOmitsIvWhenNotEncrypted() { + assertEquals("\"abc\"", encryptionResultToCookieValue(Triple("abc".toByteArray(), null, false))) + } + + @Test + fun encryptedCookieNameIsPrefixed() { + assertEquals("${encryptedCookieKeyPrefix}session", getEncryptedCookieName("session")) + } + + @Test + fun makeCookieAppliesFlags() { + val cookie = makeCookie("name", "value", "example.com", "/path", httpOnly = true, secure = true, expiresAt = 1000L) + assertEquals("name", cookie.name) + assertEquals("value", cookie.value) + assertEquals("example.com", cookie.domain) + assertEquals("/path", cookie.path) + assertTrue(cookie.httpOnly) + assertTrue(cookie.secure) + assertTrue(cookie.hostOnly) + } + + @Test + fun requestWithoutCookiesIsUnchanged() { + val request = Request.Builder().url("https://example.com").build() + assertSame(request, request.withDecryptedCookies()) + } + + @Test + fun plainCookiesPassThroughWhenNoneAreEncrypted() { + val request = requestWithCookie("a=1; b=2=3") + assertEquals("a=1; b=2=3", request.withDecryptedCookies().header("Cookie")) + } +} diff --git a/android/src/test/resources/robolectric.properties b/android/src/test/resources/robolectric.properties new file mode 100644 index 0000000..6ede63b --- /dev/null +++ b/android/src/test/resources/robolectric.properties @@ -0,0 +1,2 @@ +# SDK 35+ sandboxes require Java 21; 34 also runs on Java 17. +sdk=34 diff --git a/example/__tests__/download-handler.harness.ts b/example/__tests__/download-handler.harness.ts index 8751d16..92297ea 100644 --- a/example/__tests__/download-handler.harness.ts +++ b/example/__tests__/download-handler.harness.ts @@ -1,16 +1,29 @@ import { beforeEach, describe, expect, test } from 'react-native-harness'; -import { NativeDownloadHandler, NativeFileSystem } from 'mendix-native'; +import { + MxConfiguration, + NativeDownloadHandler, + NativeFileSystem, +} from 'mendix-native'; -const downloadPath = NativeFileSystem.relativeToDocumentsAbsolutePath( +// The example app's runtime URL points at Metro, which is always up while harness tests run. +const runtimeUrl = MxConfiguration.RUNTIME_URL.replace(/\/$/, ''); +const statusUrl = `${runtimeUrl}/status`; + +const invalidUrlPath = NativeFileSystem.relativeToDocumentsAbsolutePath( 'downloads/invalid-url.txt' ); +const downloadPath = NativeFileSystem.relativeToDocumentsAbsolutePath( + 'downloads/status.txt' +); describe('NativeDownloadHandler', () => { beforeEach(async () => { - try { - await NativeFileSystem.remove(downloadPath); - } catch { - // Cleanup is best-effort. + for (const path of [invalidUrlPath, downloadPath]) { + try { + await NativeFileSystem.remove(path); + } catch { + // Cleanup is best-effort. + } } }); @@ -23,12 +36,12 @@ describe('NativeDownloadHandler', () => { await expect( NativeDownloadHandler.download( '://definitely-invalid-url', - downloadPath, + invalidUrlPath, config ) ).rejects.toBeDefined(); - expect(await NativeFileSystem.fileExists(downloadPath)).toBe(false); + expect(await NativeFileSystem.fileExists(invalidUrlPath)).toBe(false); }); test('does not mutate the config object while rejecting invalid downloads', async () => { @@ -39,9 +52,51 @@ describe('NativeDownloadHandler', () => { const originalConfig = { ...config }; await expect( - NativeDownloadHandler.download('://still-invalid', downloadPath, config) + NativeDownloadHandler.download('://still-invalid', invalidUrlPath, config) ).rejects.toBeDefined(); expect(config).toEqual(originalConfig); }); + + test('downloads the response body to the destination path', async () => { + await NativeDownloadHandler.download(statusUrl, downloadPath, {}); + + expect(await NativeFileSystem.readAsText(downloadPath)).toBe( + 'packager-status:running' + ); + }); + + test('rejects an error status without leaving a file behind', async () => { + await expect( + NativeDownloadHandler.download( + `${runtimeUrl}/does-not-exist.txt`, + downloadPath, + {} + ) + ).rejects.toBeDefined(); + + expect(await NativeFileSystem.fileExists(downloadPath)).toBe(false); + }); + + test('rejects an unexpected mime type without leaving a file behind', async () => { + await expect( + NativeDownloadHandler.download(statusUrl, downloadPath, { + mimeType: 'application/zip', + }) + ).rejects.toBeDefined(); + + expect(await NativeFileSystem.fileExists(downloadPath)).toBe(false); + }); + + test('rejects when the destination exists and keeps the existing file', async () => { + await NativeFileSystem.writeJson({ keep: true }, downloadPath); + + await expect( + NativeDownloadHandler.download(statusUrl, downloadPath, {}) + ).rejects.toBeDefined(); + + expect(await NativeFileSystem.readJson(downloadPath)).toEqual({ + keep: true, + }); + }); }); diff --git a/example/__tests__/ota.harness.ts b/example/__tests__/ota.harness.ts index e4bcf78..5b50454 100644 --- a/example/__tests__/ota.harness.ts +++ b/example/__tests__/ota.harness.ts @@ -1,169 +1,56 @@ import { describe, test, expect } from 'react-native-harness'; -import { NativeOta } from 'mendix-native'; +import { MxConfiguration, NativeOta } from 'mendix-native'; -describe('NativeOta', () => { - describe('API surface', () => { - test('should expose download method', () => { - expect(typeof NativeOta.download).toBe('function'); - }); - - test('should expose deploy method', () => { - expect(typeof NativeOta.deploy).toBe('function'); - }); - }); +// The example app's runtime URL points at Metro, which is always up while harness tests run. +const runtimeUrl = MxConfiguration.RUNTIME_URL.replace(/\/$/, ''); +describe('NativeOta', () => { describe('download', () => { - test('should accept OtaDownloadConfig parameter', () => { - const config = { - url: 'https://example.com/ota-package.zip', - }; - - // Should not throw when called with valid config - const result = NativeOta.download(config); - expect(result).toBeInstanceOf(Promise); + test('rejects URLs outside the runtime URL', async () => { + await expect( + NativeOta.download({ url: 'https://example.invalid/ota.zip' }) + ).rejects.toMatchObject({ code: 'INVALID_RUNTIME_URL' }); }); - test('should return a Promise', () => { - const config = { - url: 'https://example.com/ota-package.zip', - }; + test('downloads from the runtime URL and returns a zip file name', async () => { + const { otaPackage } = await NativeOta.download({ + url: `${runtimeUrl}/status`, + }); - const result = NativeOta.download(config); - expect(result).toBeInstanceOf(Promise); + expect(otaPackage).toMatch(/\.zip$/); }); - test('should handle different URL formats', () => { - const configs = [ - { url: 'https://example.com/package.zip' }, - { url: 'http://localhost:8080/bundle.zip' }, - { url: 'https://cdn.example.com/v1.0.0/update.zip' }, - ]; - - configs.forEach((config) => { - const result = NativeOta.download(config); - expect(result).toBeInstanceOf(Promise); - }); + test('rejects when the runtime URL returns an error status', async () => { + await expect( + NativeOta.download({ url: `${runtimeUrl}/does-not-exist.zip` }) + ).rejects.toMatchObject({ code: 'OTA_DOWNLOAD_FAILED' }); }); }); describe('deploy', () => { - test('should accept OtaDeployConfig parameter', () => { - const config = { - otaDeploymentID: 'deployment-123', - otaPackage: '/path/to/package.zip', - extractionDir: '/path/to/extraction/dir', - }; - - const result = NativeOta.deploy(config); - expect(result).toBeInstanceOf(Promise); - }); - - test('should return a Promise', () => { - const config = { - otaDeploymentID: 'deployment-123', - otaPackage: '/path/to/package.zip', - extractionDir: '/path/to/extraction/dir', - }; - - const result = NativeOta.deploy(config); - expect(result).toBeInstanceOf(Promise); - }); - - test('should handle different deployment IDs', () => { - const configs = [ - { - otaDeploymentID: 'deployment-1', - otaPackage: '/path/to/package1.zip', - extractionDir: '/path/to/dir1', - }, - { - otaDeploymentID: 'deployment-2', - otaPackage: '/path/to/package2.zip', - extractionDir: '/path/to/dir2', - }, - { - otaDeploymentID: 'prod-deployment-v1.0.0', - otaPackage: '/path/to/prod.zip', - extractionDir: '/path/to/prod-dir', - }, - ]; - - configs.forEach((config) => { - const result = NativeOta.deploy(config); - expect(result).toBeInstanceOf(Promise); + test('rejects when the OTA package does not exist', async () => { + await expect( + NativeOta.deploy({ + otaDeploymentID: 'harness-missing-package', + otaPackage: 'does-not-exist.zip', + extractionDir: 'harness-missing-package', + }) + ).rejects.toMatchObject({ code: 'OTA_ZIP_FILE_MISSING' }); + }); + + test('rejects a downloaded package that is not a valid zip', async () => { + // Metro's status endpoint returns plain text, so the "package" can't be unzipped. + const { otaPackage } = await NativeOta.download({ + url: `${runtimeUrl}/status`, }); - }); - - test('should handle various path formats', () => { - const configs = [ - { - otaDeploymentID: 'test', - otaPackage: 'package.zip', - extractionDir: 'extraction', - }, - { - otaDeploymentID: 'test', - otaPackage: '/absolute/path/package.zip', - extractionDir: '/absolute/path/extraction', - }, - { - otaDeploymentID: 'test', - otaPackage: './relative/path/package.zip', - extractionDir: './relative/path/extraction', - }, - ]; - - configs.forEach((config) => { - const result = NativeOta.deploy(config); - expect(result).toBeInstanceOf(Promise); - }); - }); - }); - - describe('type safety', () => { - test('download config should require url property', () => { - const config = { - url: 'https://example.com/package.zip', - }; - - // TypeScript should ensure url is present - expect(config.url).toBeDefined(); - expect(typeof config.url).toBe('string'); - }); - - test('deploy config should require all properties', () => { - const config = { - otaDeploymentID: 'deployment-123', - otaPackage: '/path/to/package.zip', - extractionDir: '/path/to/extraction/dir', - }; - - // TypeScript should ensure all required properties are present - expect(config.otaDeploymentID).toBeDefined(); - expect(config.otaPackage).toBeDefined(); - expect(config.extractionDir).toBeDefined(); - }); - }); - - describe('workflow scenarios', () => { - test('should support download then deploy workflow', async () => { - const downloadConfig = { - url: 'https://example.com/ota-package.zip', - }; - - // In a real scenario, download would complete and return package path - // For testing, we just verify the methods can be called in sequence - const downloadPromise = NativeOta.download(downloadConfig); - expect(downloadPromise).toBeInstanceOf(Promise); - - const deployConfig = { - otaDeploymentID: 'deployment-123', - otaPackage: '/path/to/downloaded-package.zip', - extractionDir: '/path/to/extraction', - }; - const deployPromise = NativeOta.deploy(deployConfig); - expect(deployPromise).toBeInstanceOf(Promise); + await expect( + NativeOta.deploy({ + otaDeploymentID: 'harness-invalid-zip', + otaPackage, + extractionDir: 'harness-invalid-zip', + }) + ).rejects.toMatchObject({ code: 'OTA_DEPLOYMENT_FAILED' }); }); }); }); diff --git a/example/ios/Podfile b/example/ios/Podfile index a31e654..4bbc4e3 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -20,6 +20,9 @@ ENV['RCT_USE_RN_DEP'] = '1' ENV['RCT_USE_PREBUILT_RNCORE'] = '1' target 'MendixNativeExample' do + # Declared before autolinking (which skips pods already declared) to install the native unit tests. + pod 'MendixNative', :path => '../..', :testspecs => ['Tests'] + config = use_native_modules! use_react_native!( @@ -37,5 +40,14 @@ target 'MendixNativeExample' do :mac_catalyst_enabled => false, # :ccache_enabled => true ) + + # react_native_post_install only adds the prebuilt React Native headers to library xcconfigs, + # so the MendixNative test target can't import the MendixNative module without these. + Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', 'MendixNative', 'MendixNative.unit-tests.*.xcconfig')).each do |xcconfig_path| + xcconfig = Xcodeproj::Config.new(xcconfig_path) + ReactNativeCoreUtils.add_prebuilt_header_search_paths(xcconfig.attributes, " \"$(PODS_ROOT)/React-Core-prebuilt/Headers\"") + ReactNativePodsUtils.add_flag_to_map_with_inheritance(xcconfig.attributes, 'HEADER_SEARCH_PATHS', " \"$(PODS_ROOT)/ReactNativeDependencies/Headers\"") + xcconfig.save_as(Pathname.new(xcconfig_path)) + end end end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index e8f8031..ed004d7 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -40,6 +40,32 @@ PODS: - RNCAsyncStorage - SSZipArchive - Yoga + - MendixNative/Tests (0.6.2): + - hermes-engine + - RCTRequired + - RCTTypeSafety + - React-bridging + - React-Core + - React-Core-prebuilt + - React-cxxstableapi + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactAppDependencyProvider + - ReactCodegen + - ReactCommon/turbomodule/core + - ReactNativeDependencies + - RNCAsyncStorage + - SSZipArchive + - Yoga - op-sqlite (18.2.5): - hermes-engine - OpenSSL-Universal @@ -1853,6 +1879,7 @@ DEPENDENCIES: - glog (from `build/rndeps-facades/glog`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - MendixNative (from `../..`) + - MendixNative/Tests (from `../..`) - "op-sqlite (from `../node_modules/@op-engineering/op-sqlite`)" - RCT-Folly (from `build/rndeps-facades/RCT-Folly`) - RCTDeprecation (from `build/rncore-facades/RCTDeprecation`) @@ -2133,7 +2160,7 @@ SPEC CHECKSUMS: fmt: ba0886e864ebb21d14c98b2e12e164b8002f5b93 glog: 3cf7cb46f743c4bc758ae3e6d9c15bd1b4cfd6d4 hermes-engine: a1158910bb7e300b9e3d2f1e2d433f817ec1a4b5 - MendixNative: 978e728a9a8766e743e073f344756648959df3c3 + MendixNative: 6de5c0daa7124a30fcc7e73b88342caa3fb31eea op-sqlite: 35c49f420ecc7c3890ce85f00b97cd80e51ca043 OpenSSL-Universal: 9110d21982bb7e8b22a962b6db56a8aa805afde7 RCT-Folly: 82921e585c0400eda46fac1068297aa9dfb035e4 @@ -2219,6 +2246,6 @@ SPEC CHECKSUMS: SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef Yoga: d1c536142c5ff8ec8cd856ab2a7c227a1d875c8e -PODFILE CHECKSUM: 115c3d28fbc33ec0a408f3aba951d5d16e47a401 +PODFILE CHECKSUM: 31d6da66488cd573eddc9abdf8509ba0bbe3e9bf COCOAPODS: 1.15.2 diff --git a/ios/Tests/AppUrlTests.swift b/ios/Tests/AppUrlTests.swift new file mode 100644 index 0000000..54d15a3 --- /dev/null +++ b/ios/Tests/AppUrlTests.swift @@ -0,0 +1,47 @@ +import XCTest +@testable import MendixNative + +final class AppUrlTests: XCTestCase { + + func testForRuntimeAddsProtocolAndTrailingSlash() { + XCTAssertEqual(AppUrl.forRuntime("example.com").absoluteString, "http://example.com/") + XCTAssertEqual(AppUrl.forRuntime("https://example.com/").absoluteString, "https://example.com/") + } + + func testForRuntimeKeepsSubpath() { + XCTAssertEqual(AppUrl.forRuntime("https://example.com/app").absoluteString, "https://example.com/app/") + } + + func testForBundleUsesPortAndDevModeQuery() { + let url = AppUrl.forBundle("localhost", port: 8081, isDebuggingRemotely: false, isDevModeEnabled: true) + XCTAssertEqual(url.absoluteString, "http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false") + } + + func testForBundleUsesProductionQuery() { + let url = AppUrl.forBundle("localhost", port: 8081, isDebuggingRemotely: false, isDevModeEnabled: false) + XCTAssertEqual(url.absoluteString, "http://localhost:8081/index.bundle?platform=ios&dev=false&minify=true") + } + + func testForBundleFallsBackToDefaultPackagerPort() { + let url = AppUrl.forBundle("localhost", port: 0, isDebuggingRemotely: false, isDevModeEnabled: true) + XCTAssertEqual(url.port, AppUrl.defaultPackagerPort) + } + + func testForPackagerStatus() { + XCTAssertEqual(AppUrl.forPackagerStatus("localhost/", port: 8081)?.absoluteString, "http://localhost:8081/status") + } + + func testForRuntimeInfo() { + XCTAssertEqual(AppUrl.forRuntimeInfo("https://example.com")?.absoluteString, "https://example.com/xas/") + } + + func testIsValid() { + XCTAssertTrue(AppUrl.isValid("example.com")) + XCTAssertTrue(AppUrl.isValid("https://example.com/")) + XCTAssertTrue(AppUrl.isValid(" http://10.0.0.1:8080 ")) + XCTAssertFalse(AppUrl.isValid("")) + XCTAssertFalse(AppUrl.isValid(" ")) + XCTAssertFalse(AppUrl.isValid("https://example.com/app")) + XCTAssertFalse(AppUrl.isValid("https://example.com?debug=true")) + } +} diff --git a/ios/Tests/NativeFsPathTests.swift b/ios/Tests/NativeFsPathTests.swift new file mode 100644 index 0000000..2417689 --- /dev/null +++ b/ios/Tests/NativeFsPathTests.swift @@ -0,0 +1,40 @@ +import XCTest +@testable import MendixNative + +final class NativeFsPathTests: XCTestCase { + + private let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + private let caches = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first! + + func testAllowsPathsInsideAllowedRoots() { + XCTAssertNoThrow(try NativeFsModule.ensureWhiteListedPath([ + documents, + "\(documents)/file.json", + "\(documents)/nested/dir/file.json", + "\(caches)/file.json", + NSTemporaryDirectory() + "file.json", + ])) + } + + func testAllowsNormalizedPathsThatStayInsideRoot() { + XCTAssertNoThrow(try NativeFsModule.ensureWhiteListedPath(["\(documents)/a/../file.json"])) + } + + func testRejectsTraversalOutOfRoot() { + XCTAssertThrowsError(try NativeFsModule.ensureWhiteListedPath(["\(documents)/../escape.json"])) + XCTAssertThrowsError(try NativeFsModule.ensureWhiteListedPath(["\(documents)/a/../../escape.json"])) + } + + func testRejectsSiblingWithRootPrefix() { + XCTAssertThrowsError(try NativeFsModule.ensureWhiteListedPath(["\(documents)Evil/file.json"])) + } + + func testRejectsRelativeAndUnrelatedPaths() { + XCTAssertThrowsError(try NativeFsModule.ensureWhiteListedPath(["file.json"])) + XCTAssertThrowsError(try NativeFsModule.ensureWhiteListedPath(["/etc/hosts"])) + } + + func testRejectsWhenAnyPathIsOutsideRoot() { + XCTAssertThrowsError(try NativeFsModule.ensureWhiteListedPath(["\(documents)/ok.json", "/etc/hosts"])) + } +} diff --git a/ios/Tests/OtaDeployTests.swift b/ios/Tests/OtaDeployTests.swift new file mode 100644 index 0000000..da92a42 --- /dev/null +++ b/ios/Tests/OtaDeployTests.swift @@ -0,0 +1,145 @@ +import XCTest +import SSZipArchive +@testable import MendixNative + +final class OtaDeployTests: XCTestCase { + + private var otaDir: String { OtaHelpers.getOtaDir() } + private var module: NativeOtaModule! + + override func setUp() { + super.setUp() + try? FileManager.default.removeItem(atPath: otaDir) + // init creates the OTA directory. + module = NativeOtaModule() + } + + override func tearDown() { + try? FileManager.default.removeItem(atPath: otaDir) + super.tearDown() + } + + // MARK: - Helpers + + private enum Outcome { + case resolved + case rejected(code: String?) + } + + private func deploy(id: String, package: String, extractionDir: String) -> Outcome { + var outcome: Outcome? + let promise = Promise( + resolve: { _ in outcome = .resolved }, + reject: { code, _, _ in outcome = .rejected(code: code) } + ) + module.deploy(OtaDeploymentConfiguration(otaDeploymentID: id, otaPackage: package, extractionDir: extractionDir), promise: promise) + // deploy settles synchronously. + return outcome! + } + + /// Writes a zip containing index.ios.bundle into the OTA dir and returns its file name. + @discardableResult + private func makeOtaPackage(_ name: String, bundleContent: String = "bundle") throws -> String { + let staging = NSTemporaryDirectory() + UUID().uuidString + try FileManager.default.createDirectory(atPath: staging, withIntermediateDirectories: true) + defer { try? FileManager.default.removeItem(atPath: staging) } + try bundleContent.write(toFile: "\(staging)/index.ios.bundle", atomically: true, encoding: .utf8) + + let zipPath = "\(otaDir)/\(name)" + XCTAssertTrue(SSZipArchive.createZipFile(atPath: zipPath, withContentsOfDirectory: staging)) + return name + } + + private func path(_ relative: String) -> String { + OtaHelpers.resolveAbsolutePathRelativeToOtaDir("/\(relative)") + } + + private func assertRejected(_ outcome: Outcome, _ expected: String, file: StaticString = #filePath, line: UInt = #line) { + guard case .rejected(let code) = outcome else { + return XCTFail("Expected rejection with \(expected), got resolve", file: file, line: line) + } + XCTAssertEqual(code, expected, file: file, line: line) + } + + // MARK: - Tests + + func testDeployExtractsBundleWritesManifestAndRemovesZip() throws { + let zip = try makeOtaPackage("first.zip", bundleContent: "first") + + guard case .resolved = deploy(id: "1", package: zip, extractionDir: "deployment-1") else { + return XCTFail("Expected deploy to resolve") + } + + XCTAssertEqual(try String(contentsOfFile: path("deployment-1/index.ios.bundle"), encoding: .utf8), "first") + XCTAssertFalse(FileManager.default.fileExists(atPath: path(zip))) + + let manifest = try XCTUnwrap(OtaHelpers.readManifestAsDictionary()) + XCTAssertEqual(manifest[MANIFEST_OTA_DEPLOYMENT_ID_KEY] as? String, "1") + XCTAssertEqual(manifest[MANIFEST_RELATIVE_BUNDLE_PATH_KEY] as? String, "deployment-1/index.ios.bundle") + XCTAssertEqual(manifest[MANIFEST_APP_VERSION_KEY] as? String, OtaHelpers.resolveAppVersion()) + + XCTAssertEqual(OtaJSBundleFileProvider.getBundleUrl()?.path, path("deployment-1/index.ios.bundle")) + } + + func testNewDeploymentRemovesPreviousBundle() throws { + guard case .resolved = deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployment-1"), + case .resolved = deploy(id: "2", package: try makeOtaPackage("second.zip"), extractionDir: "deployment-2") else { + return XCTFail("Expected both deploys to resolve") + } + + XCTAssertFalse(FileManager.default.fileExists(atPath: path("deployment-1"))) + XCTAssertTrue(FileManager.default.fileExists(atPath: path("deployment-2/index.ios.bundle"))) + XCTAssertEqual(OtaJSBundleFileProvider.getBundleUrl()?.path, path("deployment-2/index.ios.bundle")) + } + + func testRedeployingActiveDeploymentIsRejectedAndKeepsBundle() throws { + guard case .resolved = deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployment-1") else { + return XCTFail("Expected first deploy to resolve") + } + let zip = try makeOtaPackage("again.zip") + + assertRejected(deploy(id: "1", package: zip, extractionDir: "deployment-1"), OTA_ALREADY_DEPLOYED) + XCTAssertFalse(FileManager.default.fileExists(atPath: path(zip))) + XCTAssertTrue(FileManager.default.fileExists(atPath: path("deployment-1/index.ios.bundle"))) + } + + func testRedeployingSameIdIsAllowedWhenBundleIsMissing() throws { + guard case .resolved = deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployment-1") else { + return XCTFail("Expected first deploy to resolve") + } + try FileManager.default.removeItem(atPath: path("deployment-1")) + + guard case .resolved = deploy(id: "1", package: try makeOtaPackage("again.zip"), extractionDir: "deployment-1") else { + return XCTFail("Expected redeploy to resolve") + } + XCTAssertTrue(FileManager.default.fileExists(atPath: path("deployment-1/index.ios.bundle"))) + } + + func testMissingPackageIsRejected() { + assertRejected(deploy(id: "1", package: "missing.zip", extractionDir: "deployment-1"), OTA_ZIP_FILE_MISSING) + XCTAssertNil(OtaJSBundleFileProvider.getBundleUrl()) + } + + func testInvalidZipIsRejectedAndRemoved() throws { + try "not a zip".write(toFile: path("invalid.zip"), atomically: true, encoding: .utf8) + + assertRejected(deploy(id: "1", package: "invalid.zip", extractionDir: "deployment-1"), OTA_DEPLOYMENT_FAILED) + XCTAssertFalse(FileManager.default.fileExists(atPath: path("invalid.zip"))) + XCTAssertNil(OtaHelpers.readManifestAsDictionary()) + } + + func testBundleUrlIsNilWhenAppVersionChanged() throws { + guard case .resolved = deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployment-1") else { + return XCTFail("Expected deploy to resolve") + } + var manifest = try XCTUnwrap(OtaHelpers.readManifestAsDictionary()) + manifest[MANIFEST_APP_VERSION_KEY] = "0.0.0-0" + try JSONSerialization.data(withJSONObject: manifest).write(to: URL(fileURLWithPath: OtaHelpers.getOtaManifestFilepath())) + + XCTAssertNil(OtaJSBundleFileProvider.getBundleUrl()) + } + + func testBundleUrlIsNilWithoutManifest() { + XCTAssertNil(OtaJSBundleFileProvider.getBundleUrl()) + } +} diff --git a/package.json b/package.json index 9031074..6ca98f9 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "*.podspec", "react-native.config.js", "!ios/build", + "!ios/Tests", + "!android/src/test", "!android/build", "!android/gradle", "!android/gradlew", From c7ca249922d9b40ba7e3d320eaf059a1b9678a57 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Sat, 3 Oct 2026 02:32:26 +0530 Subject: [PATCH 03/10] feat: enhance OTA deployment validation and add tests for extraction directory restrictions --- .../react/download/DownloadHelper.kt | 32 +++-- .../mendixnative/react/fs/FileBackend.kt | 28 ++-- .../mendixnative/react/ota/NativeOtaModule.kt | 35 ++--- .../mendixnative/react/ota/OtaHelpers.kt | 10 ++ .../request/MendixNetworkInterceptor.kt | 53 ++++---- .../react/download/DownloadHelperTest.kt | 61 ++++++++- .../react/ota/NativeOtaModuleTest.kt | 128 +++++++++++++++++- .../mendixnative/request/CookieHelpersTest.kt | 33 +++++ example/__tests__/ota.harness.ts | 18 +++ .../NativeDownloadHandler.swift | 7 +- .../NativeOtaModule/NativeOtaModule.swift | 19 ++- ios/Modules/NativeOtaModule/OtaHelpers.swift | 8 ++ ios/Tests/NativeDownloadHandlerTests.swift | 79 +++++++++++ ios/Tests/OtaDeployTests.swift | 78 +++++++++++ 14 files changed, 518 insertions(+), 71 deletions(-) create mode 100644 ios/Tests/NativeDownloadHandlerTests.swift diff --git a/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt b/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt index 9a64aff..a04314f 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt @@ -4,7 +4,6 @@ import okhttp3.* import okhttp3.MediaType.Companion.toMediaTypeOrNull import java.io.* import java.net.ConnectException -import kotlin.math.abs @Throws( IllegalArgumentException::class, @@ -71,6 +70,9 @@ fun downloadFile( } +private const val COPY_BUFFER_SIZE = 64 * 1024 +private const val UNKNOWN_LENGTH_PROGRESS_INTERVAL = 64.0 * 1024 + fun makeProgressCallbackInvoker( bytesInterval: Double, cb: (receivedBytes: Double, totalBytes: Double) -> Unit @@ -110,19 +112,27 @@ class DownloadResponseHandler( BufferedOutputStream(FileOutputStream(outputFile)) val totalBytes = response.body!!.contentLength().toDouble() + var reportedBytes = -1.0 val progressCallbackInvoker = makeProgressCallbackInvoker( - totalBytes / 100, - progressCallback - ) - - var receivedBytes: Double - var data = inputStream.read() - while (data != -1) { - outputStream.write(data) - data = inputStream.read() + // Without a content length (-1), report progress every 64 KB instead of every 1%. + if (totalBytes > 0) totalBytes / 100 else UNKNOWN_LENGTH_PROGRESS_INTERVAL, + ) { received, total -> + reportedBytes = received + progressCallback(received, total) + } - receivedBytes = abs(inputStream.available().toDouble() - totalBytes) + var receivedBytes = 0.0 + val buffer = ByteArray(COPY_BUFFER_SIZE) + var read = inputStream.read(buffer) + while (read != -1) { + outputStream.write(buffer, 0, read) + receivedBytes += read progressCallbackInvoker(receivedBytes, totalBytes) + read = inputStream.read(buffer) + } + // Always report completion, even when the last chunk didn't reach the next interval. + if (reportedBytes != receivedBytes) { + progressCallback(receivedBytes, totalBytes) } outputStream.flush() } catch (e: Exception) { diff --git a/android/src/main/java/com/mendix/mendixnative/react/fs/FileBackend.kt b/android/src/main/java/com/mendix/mendixnative/react/fs/FileBackend.kt index 8bfd54b..1f75a10 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/fs/FileBackend.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/fs/FileBackend.kt @@ -11,7 +11,7 @@ import java.nio.file.Files import java.nio.file.StandardCopyOption import java.security.GeneralSecurityException import java.util.* -import java.util.zip.ZipEntry +import java.util.zip.ZipException import java.util.zip.ZipFile val FILE_ENCRYPTION_SCHEME = EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB @@ -152,16 +152,26 @@ class FileBackend(val context: Context) { } fun unzip(zipPath: String, directory: String) { + val root = File(directory).canonicalFile ZipFile(zipPath).use { zip -> - zip.entries().asSequence().map { zipEntry -> - val file = File(directory, zipEntry.name) + // Resolve every entry before writing anything, so an archive with an entry escaping the + // target directory (Zip Slip) is rejected as a whole. + val entries = zip.entries().asSequence().map { zipEntry -> + val file = File(root, zipEntry.name).canonicalFile + if (file != root && !file.path.startsWith(root.path + File.separator)) { + throw ZipException("Zip entry ${zipEntry.name} is outside of the target directory") + } + zipEntry to file + }.toList() + + entries.forEach { (zipEntry, file) -> + if (zipEntry.isDirectory) { + file.mkdirs() + return@forEach + } file.parentFile?.run { mkdirs() } - listOf(zipEntry, file) - }.filter { - !(it[0] as ZipEntry).isDirectory - }.forEach { - zip.getInputStream(it[0] as ZipEntry).use { input -> - (it[1] as File).outputStream().use { output -> + zip.getInputStream(zipEntry).use { input -> + file.outputStream().use { output -> input.copyTo(output) } } diff --git a/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt b/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt index a263fa7..bb601fb 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt @@ -120,23 +120,26 @@ class NativeOtaModule( INVALID_DEPLOY_CONFIG, "Key $DEPLOY_CONFIG_DEPLOYMENT_ID_KEY is invalid." ) - val zipFile = File( - getOtaZipFilePath( - reactApplicationContext, - deployConfig.getStringOrNull(DEPLOY_CONFIG_OTA_PACKAGE_KEY) - ?: return promise.reject( - INVALID_DEPLOY_CONFIG, - "Key $DEPLOY_CONFIG_OTA_PACKAGE_KEY is invalid." - ) + val otaPackage = deployConfig.getStringOrNull(DEPLOY_CONFIG_OTA_PACKAGE_KEY) + ?: return promise.reject( + INVALID_DEPLOY_CONFIG, + "Key $DEPLOY_CONFIG_OTA_PACKAGE_KEY is invalid." ) - ) - val extractionDir = File( + val zipFile = resolvePathInsideOtaDir(otaDir, otaPackage) + ?: return promise.reject( + INVALID_DEPLOY_CONFIG, + "Key $DEPLOY_CONFIG_OTA_PACKAGE_KEY points outside of the OTA directory." + ) + val extractionDir = resolvePathInsideOtaDir( otaDir, deployConfig.getStringOrNull(DEPLOY_CONFIG_EXTRACTION_DIR_KEY) ?: return promise.reject( INVALID_DEPLOY_CONFIG, "Key $DEPLOY_CONFIG_EXTRACTION_DIR_KEY is invalid." ) + ) ?: return promise.reject( + INVALID_DEPLOY_CONFIG, + "Key $DEPLOY_CONFIG_EXTRACTION_DIR_KEY points outside of the OTA directory." ) val oldManifest = readManifestJson(reactApplicationContext, fileBackend) @@ -194,12 +197,12 @@ class NativeOtaModule( val shouldRemoveOldBundle = oldManifest != null && oldManifest.otaDeploymentID != otaDeploymentID if (shouldRemoveOldBundle) { - File( - resolveAbsolutePathRelativeToOtaDir( - reactApplicationContext, - oldManifest.relativeBundlePath - ) - ).parentFile?.deleteRecursively() + // The manifest is on disk, so only remove its bundle dir if it is inside the OTA dir, + // and never the dir that was just deployed. + File(oldManifest.relativeBundlePath).parent + ?.let { resolvePathInsideOtaDir(otaDir, it) } + ?.takeIf { it.canonicalFile != extractionDir.canonicalFile } + ?.deleteRecursively() } zipFile.delete() } catch (e: Exception) { diff --git a/android/src/main/java/com/mendix/mendixnative/react/ota/OtaHelpers.kt b/android/src/main/java/com/mendix/mendixnative/react/ota/OtaHelpers.kt index 609edfd..80bfe43 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/ota/OtaHelpers.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/ota/OtaHelpers.kt @@ -32,3 +32,13 @@ fun getNativeDependencies(context: Context): Map { val typeRef = object : TypeReference>() {} return ObjectMapper().readValue(nativeDependencies, typeRef).toMap() } + +/** + * Resolves [path] against [otaDir] and returns it only if it stays strictly inside [otaDir], + * so paths received from JS or read from the manifest can't point elsewhere in the app's storage. + */ +fun resolvePathInsideOtaDir(otaDir: String, path: String): File? { + val root = File(otaDir).canonicalFile + val file = File(otaDir, path) + return if (file.canonicalPath.startsWith(root.path + File.separator)) file else null +} diff --git a/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt b/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt index 6cc6361..3699185 100644 --- a/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt +++ b/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt @@ -33,35 +33,42 @@ const val encryptedCookieKeyPrefix = "MxEnc" // Prefix for encrypted cookie keys * Request extension to decrypt possibly encrypted cookies */ fun Request.withDecryptedCookies(): Request { - val cookiePairs = this.header("Cookie")?.split("; ") + // Skip empty segments, e.g. from a trailing "; ". + val cookiePairs = this.header("Cookie")?.split(";")?.map { it.trim() }?.filter { it.isNotEmpty() } + ?: return this val encryptedCookieExists = - cookiePairs?.any { cookie -> cookie.startsWith(encryptedCookieKeyPrefix) } - val decryptedCookies = cookiePairs?.map { - val (key, value) = it.split("=", limit = 2) - - if (encryptedCookieExists!! && key.startsWith(encryptedCookieKeyPrefix)) { - try { - val params = cookieValueToDecryptionParams(value) - val decryptedValue = decryptValue(params.first, params.second) - return@map "${key.removePrefix(encryptedCookieKeyPrefix)}=$decryptedValue" - } catch (e: Exception) { - Log.w("MendixNetworkInterceptor", "Failed to decrypt cookie $key, dropping it", e) - return@map null - } - } else if (!encryptedCookieExists) { - return@map it; + cookiePairs.any { cookie -> cookie.startsWith(encryptedCookieKeyPrefix) } + val decryptedCookies = cookiePairs.mapNotNull { + if (!encryptedCookieExists) { + return@mapNotNull it } - return@map null - }?.filterNotNull()?.joinToString(separator = "; ") + // A cookie without "=" has no value, so it can't be an encrypted one. + val parts = it.split("=", limit = 2) + val key = parts[0] + val value = parts.getOrNull(1) + if (!key.startsWith(encryptedCookieKeyPrefix)) { + return@mapNotNull null + } - return when { - decryptedCookies != null && decryptedCookies.isNotBlank() -> this.newBuilder() - .removeHeader("Cookie") - .addHeader("Cookie", decryptedCookies).build() + try { + val params = cookieValueToDecryptionParams( + value ?: throw IllegalArgumentException("Cookie has no value") + ) + val decryptedValue = decryptValue(params.first, params.second) + return@mapNotNull "${key.removePrefix(encryptedCookieKeyPrefix)}=$decryptedValue" + } catch (e: Exception) { + Log.w("MendixNetworkInterceptor", "Failed to decrypt cookie $key, dropping it", e) + return@mapNotNull null + } + }.joinToString(separator = "; ") - else -> this + val builder = this.newBuilder().removeHeader("Cookie") + // When no cookie is left (e.g. none could be decrypted), send none rather than the encrypted ones. + if (decryptedCookies.isNotBlank()) { + builder.addHeader("Cookie", decryptedCookies) } + return builder.build() } /** diff --git a/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt b/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt index 4ce3a48..9ab2985 100644 --- a/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt @@ -3,6 +3,7 @@ package com.mendix.mendixnative.react.download import okhttp3.OkHttpClient import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer +import okio.Buffer import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -14,6 +15,7 @@ import org.junit.Test import org.junit.rules.TemporaryFolder import java.io.File import java.net.ConnectException +import kotlin.random.Random import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -42,7 +44,11 @@ class DownloadHelperTest { fun await() = assertTrue("download did not finish", latch.await(5, TimeUnit.SECONDS)) } - private fun download(file: File, mimeType: String? = null): Result { + private fun download( + file: File, + mimeType: String? = null, + progress: (receivedBytes: Double, totalBytes: Double) -> Unit = { _, _ -> }, + ): Result { val result = Result() downloadFile( client = client, @@ -51,6 +57,7 @@ class DownloadHelperTest { expectedMimeType = mimeType, onSuccess = { result.succeeded = true; result.latch.countDown() }, onFailure = { result.error = it; result.latch.countDown() }, + progressCallback = progress, ) result.await() return result @@ -139,4 +146,56 @@ class DownloadHelperTest { assertEquals(listOf(10.0, 20.0, 35.0), calls) } + + private fun randomBytes(size: Int) = Random(42).nextBytes(size) + + private fun assertMonotonic(events: List>) { + events.zipWithNext().forEach { (a, b) -> assertTrue("$a then $b", b.first > a.first) } + } + + @Test + fun largeBodyIsWrittenIntactWithBoundedProgress() { + val bytes = randomBytes(1024 * 1024) + // Throttling splits the body over many reads, like a real network. + server.enqueue(MockResponse().setBody(Buffer().write(bytes)).throttleBody(64 * 1024, 5, TimeUnit.MILLISECONDS)) + val file = File(tempFolder.root, "large.bin") + val events = mutableListOf>() + + val result = download(file) { received, total -> events.add(received to total) } + + assertNull(result.error) + assertTrue(bytes.contentEquals(file.readBytes())) + assertTrue("${events.size} events", events.size in 2..101) + assertMonotonic(events) + assertTrue(events.all { it.second == bytes.size.toDouble() && it.first <= it.second }) + assertEquals(bytes.size.toDouble(), events.last().first, 0.0) + } + + @Test + fun bodyWithoutContentLengthReportsProgressPerInterval() { + val bytes = randomBytes(300 * 1024 + 7) + server.enqueue(MockResponse().setChunkedBody(Buffer().write(bytes), 1024)) + val file = File(tempFolder.root, "chunked.bin") + val events = mutableListOf>() + + val result = download(file) { received, total -> events.add(received to total) } + + assertNull(result.error) + assertTrue(bytes.contentEquals(file.readBytes())) + // One event per 64 KB plus the final one. + assertTrue("${events.size} events", events.size in 2..6) + assertMonotonic(events) + assertTrue(events.all { it.second == -1.0 }) + assertEquals(bytes.size.toDouble(), events.last().first, 0.0) + } + + @Test + fun smallBodyReportsCompletion() { + server.enqueue(MockResponse().setBody("content")) + val events = mutableListOf>() + + download(File(tempFolder.root, "small.txt")) { received, total -> events.add(received to total) } + + assertEquals(listOf(7.0 to 7.0), events) + } } diff --git a/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt b/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt index d48cef5..9042806 100644 --- a/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt @@ -70,15 +70,34 @@ class NativeOtaModuleTest { } /** Writes a zip containing index.android.bundle into the OTA dir and returns its file name. */ - private fun makeOtaPackage(name: String, bundleContent: String = "bundle"): String { + private fun makeOtaPackage(name: String, bundleContent: String = "bundle"): String = + makeZip(name, mapOf("index.android.bundle" to bundleContent)) + + /** Writes a zip with the given entries (a null content makes a directory entry) into the OTA dir. */ + private fun makeZip(name: String, entries: Map): String { ZipOutputStream(File(otaDir, name).outputStream()).use { zip -> - zip.putNextEntry(ZipEntry("index.android.bundle")) - zip.write(bundleContent.toByteArray()) - zip.closeEntry() + entries.forEach { (entryName, content) -> + zip.putNextEntry(ZipEntry(entryName)) + content?.let { zip.write(it.toByteArray()) } + zip.closeEntry() + } } return name } + /** A directory next to the OTA dir that deploys must never touch. */ + private fun makeSentinel(): File = + File(otaDir.parentFile, "sentinel").apply { + deleteRecursively() + mkdirs() + File(this, "keep.txt").writeText("keep") + } + + private fun assertSentinelIntact(sentinel: File) { + assertEquals("keep", File(sentinel, "keep.txt").readText()) + sentinel.deleteRecursively() + } + private fun file(relative: String) = File(otaDir, relative) @Test @@ -162,4 +181,105 @@ class NativeOtaModuleTest { assertNull(OtaJSBundleUrlProvider().getJSBundleFile(context)) } + + @Test + fun zipWithEntryOutsideExtractionDirIsRejected() { + val zip = makeZip( + "slip.zip", + mapOf("index.android.bundle" to "bundle", "../escape.txt" to "escaped", "../../escape.txt" to "escaped") + ) + + assertEquals(Outcome.Rejected(OTA_DEPLOYMENT_FAILED), deploy("1", zip, "deployment-1")) + assertFalse(file("escape.txt").exists()) + assertFalse(File(otaDir.parentFile, "escape.txt").exists()) + assertFalse(file("deployment-1").exists()) + assertFalse(File(getOtaManifestFilepath(context)).exists()) + } + + @Test + fun zipWithNestedAndEmptyDirectoriesIsExtracted() { + val zip = makeZip( + "nested.zip", + mapOf( + "index.android.bundle" to "bundle", + "assets/a/b/image.png" to "image", + "empty/" to null, + "./dot.txt" to "dot", + ) + ) + + assertEquals(Outcome.Resolved, deploy("1", zip, "deployment-1")) + assertEquals("image", file("deployment-1/assets/a/b/image.png").readText()) + assertEquals("dot", file("deployment-1/dot.txt").readText()) + assertTrue(file("deployment-1/empty").isDirectory) + } + + @Test + fun extractionDirOutsideOtaDirIsRejected() { + val sentinel = makeSentinel() + + for (extractionDir in listOf("../sentinel", "deployment-1/../../sentinel", "", ".", "deployment-1/..")) { + val zip = makeOtaPackage("first.zip") + assertEquals(extractionDir, Outcome.Rejected(INVALID_DEPLOY_CONFIG), deploy("1", zip, extractionDir)) + assertTrue(file(zip).exists()) + } + assertTrue(otaDir.exists()) + assertFalse(File(getOtaManifestFilepath(context)).exists()) + assertSentinelIntact(sentinel) + } + + @Test + fun otaPackageOutsideOtaDirIsRejected() { + val outsideZip = File(otaDir.parentFile, "outside.zip") + makeOtaPackage("outside.zip") + file("outside.zip").renameTo(outsideZip) + + assertEquals(Outcome.Rejected(INVALID_DEPLOY_CONFIG), deploy("1", "../outside.zip", "deployment-1")) + assertTrue(outsideZip.exists()) + assertFalse(file("deployment-1").exists()) + outsideZip.delete() + } + + @Test + fun extractionDirInSubdirectoryIsAllowed() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployments/1")) + + val manifest = JSONObject(File(getOtaManifestFilepath(context)).readText()) + assertEquals("deployments/1/index.android.bundle", manifest.getString(MANIFEST_RELATIVE_BUNDLE_PATH_KEY)) + } + + @Test + fun oldBundleOutsideOtaDirIsNotRemoved() { + val sentinel = makeSentinel() + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployment-1")) + val manifestFile = File(getOtaManifestFilepath(context)) + manifestFile.writeText( + JSONObject(manifestFile.readText()) + .put(MANIFEST_RELATIVE_BUNDLE_PATH_KEY, "../sentinel/index.android.bundle").toString() + ) + + assertEquals(Outcome.Resolved, deploy("2", makeOtaPackage("second.zip"), "deployment-2")) + assertSentinelIntact(sentinel) + } + + @Test + fun oldBundleInOtaDirRootDoesNotRemoveOtaDir() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip"), "deployment-1")) + val manifestFile = File(getOtaManifestFilepath(context)) + manifestFile.writeText( + JSONObject(manifestFile.readText()).put(MANIFEST_RELATIVE_BUNDLE_PATH_KEY, "index.android.bundle").toString() + ) + + assertEquals(Outcome.Resolved, deploy("2", makeOtaPackage("second.zip"), "deployment-2")) + assertTrue(file("deployment-2/index.android.bundle").exists()) + assertTrue(manifestFile.exists()) + } + + @Test + fun newDeploymentIntoSameDirKeepsNewBundle() { + assertEquals(Outcome.Resolved, deploy("1", makeOtaPackage("first.zip", "first"), "deployment")) + assertEquals(Outcome.Resolved, deploy("2", makeOtaPackage("second.zip", "second"), "deployment")) + + assertEquals("second", file("deployment/index.android.bundle").readText()) + } } diff --git a/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt b/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt index 523331c..f6a1e2a 100644 --- a/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt @@ -2,10 +2,15 @@ package com.mendix.mendixnative.request import okhttp3.Request import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull import org.junit.Assert.assertSame import org.junit.Assert.assertTrue import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +// Robolectric because dropping an undecryptable cookie logs through android.util.Log. +@RunWith(RobolectricTestRunner::class) class CookieHelpersTest { private fun requestWithCookie(cookie: String) = Request.Builder().url("https://example.com").header("Cookie", cookie).build() @@ -55,4 +60,32 @@ class CookieHelpersTest { val request = requestWithCookie("a=1; b=2=3") assertEquals("a=1; b=2=3", request.withDecryptedCookies().header("Cookie")) } + + @Test + fun cookieWithoutValueIsKept() { + assertEquals("a=1; flag", requestWithCookie("a=1; flag").withDecryptedCookies().header("Cookie")) + } + + @Test + fun emptySegmentsAreSkipped() { + assertEquals("a=1", requestWithCookie("a=1; ").withDecryptedCookies().header("Cookie")) + assertEquals("a=1; b=2", requestWithCookie("a=1;;b=2").withDecryptedCookies().header("Cookie")) + } + + @Test + fun cookieWithEmptyNameIsKept() { + assertEquals("=1", requestWithCookie("=1").withDecryptedCookies().header("Cookie")) + } + + @Test + fun undecryptableCookiesAreNotForwarded() { + // Without an IV the value can't be decrypted. + assertNull(requestWithCookie("${encryptedCookieKeyPrefix}session=abc").withDecryptedCookies().header("Cookie")) + } + + @Test + fun plainCookiesAreDroppedWhenEncryptedOnesExist() { + val request = requestWithCookie("a=1; ${encryptedCookieKeyPrefix}session=abc; flag; ${encryptedCookieKeyPrefix}empty") + assertNull(request.withDecryptedCookies().header("Cookie")) + } } diff --git a/example/__tests__/ota.harness.ts b/example/__tests__/ota.harness.ts index 5b50454..5e1a46c 100644 --- a/example/__tests__/ota.harness.ts +++ b/example/__tests__/ota.harness.ts @@ -38,6 +38,24 @@ describe('NativeOta', () => { ).rejects.toMatchObject({ code: 'OTA_ZIP_FILE_MISSING' }); }); + test('rejects paths outside the OTA directory', async () => { + await expect( + NativeOta.deploy({ + otaDeploymentID: 'harness-escape', + otaPackage: 'does-not-exist.zip', + extractionDir: '../escape', + }) + ).rejects.toMatchObject({ code: 'INVALID_DEPLOY_CONFIG' }); + + await expect( + NativeOta.deploy({ + otaDeploymentID: 'harness-escape', + otaPackage: '../does-not-exist.zip', + extractionDir: 'harness-escape', + }) + ).rejects.toMatchObject({ code: 'INVALID_DEPLOY_CONFIG' }); + }); + test('rejects a downloaded package that is not a valid zip', async () => { // Metro's status endpoint returns plain text, so the "package" can't be unzipped. const { otaPackage } = await NativeOta.download({ diff --git a/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift b/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift index 01274fd..f4e1a22 100644 --- a/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift +++ b/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift @@ -36,9 +36,6 @@ class NativeDownloadHandler: NSObject { func download(_ urlString: String, downloadPath: String) { self.downloadPath = downloadPath - let configuration = URLSessionConfiguration.default - let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil) - guard let encodedUrlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: encodedUrlString) else { let error = NSError(domain: NSURLErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) @@ -46,9 +43,13 @@ class NativeDownloadHandler: NSObject { return } + let configuration = URLSessionConfiguration.default + let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil) let request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: TimeInterval(connectionTimeout)) let downloadTask = session.downloadTask(with: request) downloadTask.resume() + // The session retains its delegate (self) until invalidated; release both once the task is done. + session.finishTasksAndInvalidate() } } diff --git a/ios/Modules/NativeOtaModule/NativeOtaModule.swift b/ios/Modules/NativeOtaModule/NativeOtaModule.swift index 86885b2..5c635b3 100644 --- a/ios/Modules/NativeOtaModule/NativeOtaModule.swift +++ b/ios/Modules/NativeOtaModule/NativeOtaModule.swift @@ -140,8 +140,15 @@ public class NativeOtaModule: NSObject { return } - let zipPath = OtaHelpers.resolveAbsolutePathRelativeToOtaDir("/\(zipFile)") - let unzipDir = OtaHelpers.resolveAbsolutePathRelativeToOtaDir("/\(extractionDir)") + guard let zipPath = OtaHelpers.resolvePathInsideOtaDir(zipFile) else { + promise.reject(INVALID_DEPLOY_CONFIG, "Key otaPackage points outside of the OTA directory.", nil) + return + } + + guard let unzipDir = OtaHelpers.resolvePathInsideOtaDir(extractionDir) else { + promise.reject(INVALID_DEPLOY_CONFIG, "Key extractionDir points outside of the OTA directory.", nil) + return + } let oldManifest = OtaHelpers.readManifestAsDictionary() @@ -219,8 +226,12 @@ public class NativeOtaModule: NSObject { if shouldRemoveOldBundle, let oldManifest = oldManifest, let relativeBundlePath = oldManifest[MANIFEST_RELATIVE_BUNDLE_PATH_KEY] as? String { - let oldBundleDir = OtaHelpers.resolveAbsolutePathRelativeToOtaDir("/\((relativeBundlePath as NSString).deletingLastPathComponent)") - removeOldBundle(oldBundleDir) + // The manifest is on disk, so only remove its bundle dir if it is inside the OTA dir, + // and never the dir that was just deployed. + if let oldBundleDir = OtaHelpers.resolvePathInsideOtaDir((relativeBundlePath as NSString).deletingLastPathComponent), + oldBundleDir != unzipDir { + removeOldBundle(oldBundleDir) + } } removeZipFile(zipPath) diff --git a/ios/Modules/NativeOtaModule/OtaHelpers.swift b/ios/Modules/NativeOtaModule/OtaHelpers.swift index 782f67c..94771aa 100644 --- a/ios/Modules/NativeOtaModule/OtaHelpers.swift +++ b/ios/Modules/NativeOtaModule/OtaHelpers.swift @@ -34,6 +34,14 @@ class OtaHelpers: NSObject { return "\(getOtaDir())\(path)" } + /// Resolves `path` against the OTA dir and returns it only if it stays strictly inside the OTA dir, + /// so paths received from JS or read from the manifest can't point elsewhere in the app's storage. + static func resolvePathInsideOtaDir(_ path: String) -> String? { + let otaDir = URL(fileURLWithPath: getOtaDir()).standardizedFileURL.path + let resolved = URL(fileURLWithPath: "\(otaDir)/\(path)").standardizedFileURL.path + return resolved.hasPrefix("\(otaDir)/") ? resolved : nil + } + static func readManifestAsDictionary() -> [String: Any]? { let manifestPath = getOtaManifestFilepath() diff --git a/ios/Tests/NativeDownloadHandlerTests.swift b/ios/Tests/NativeDownloadHandlerTests.swift new file mode 100644 index 0000000..b8c3f50 --- /dev/null +++ b/ios/Tests/NativeDownloadHandlerTests.swift @@ -0,0 +1,79 @@ +import XCTest +@testable import MendixNative + +final class NativeDownloadHandlerTests: XCTestCase { + + private var workDir: String! + + override func setUpWithError() throws { + workDir = NSTemporaryDirectory() + UUID().uuidString + try FileManager.default.createDirectory(atPath: workDir, withIntermediateDirectories: true) + } + + override func tearDown() { + try? FileManager.default.removeItem(atPath: workDir) + super.tearDown() + } + + /// Starts a download, waits for its callback, and returns the handler weakly. + private func download(_ url: String, to destination: String, succeeds: Bool) -> NativeDownloadHandler? { + let finished = expectation(description: "download finished") + weak var weakHandler: NativeDownloadHandler? + // The handler is only referenced locally, as in NativeDownloadModule. + autoreleasepool { + let handler = NativeDownloadHandler( + connectionTimeout: nil, + mimeType: nil, + doneCallback: { + XCTAssertTrue(succeeds, "Expected the download to fail") + finished.fulfill() + }, + progressCallback: nil, + failCallback: { error in + XCTAssertFalse(succeeds, "Unexpected failure: \(error)") + finished.fulfill() + } + ) + weakHandler = handler + handler.download(url, downloadPath: destination) + } + wait(for: [finished], timeout: 5) + return weakHandler + } + + /// The session releases its delegate shortly after the completion callback. + private func assertReleased(_ handler: @autoclosure () -> NativeDownloadHandler?, file: StaticString = #filePath, line: UInt = #line) { + let deadline = Date().addingTimeInterval(2) + while handler() != nil && Date() < deadline { + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + } + XCTAssertNil(handler(), "The download handler leaked", file: file, line: line) + } + + func testHandlerIsReleasedAfterSuccessfulDownload() throws { + let source = "\(workDir!)/source.txt" + try "content".write(toFile: source, atomically: true, encoding: .utf8) + let destination = "\(workDir!)/nested/destination.txt" + + weak var handler = download(URL(fileURLWithPath: source).absoluteString, to: destination, succeeds: true) + + XCTAssertEqual(try String(contentsOfFile: destination, encoding: .utf8), "content") + assertReleased(handler) + } + + func testHandlerIsReleasedAfterFailedDownload() { + weak var handler = download( + URL(fileURLWithPath: "\(workDir!)/missing.txt").absoluteString, + to: "\(workDir!)/destination.txt", + succeeds: false + ) + + assertReleased(handler) + } + + func testHandlerIsReleasedAfterInvalidUrl() { + weak var handler = download("://invalid url", to: "\(workDir!)/destination.txt", succeeds: false) + + assertReleased(handler) + } +} diff --git a/ios/Tests/OtaDeployTests.swift b/ios/Tests/OtaDeployTests.swift index da92a42..35c4d27 100644 --- a/ios/Tests/OtaDeployTests.swift +++ b/ios/Tests/OtaDeployTests.swift @@ -54,6 +54,28 @@ final class OtaDeployTests: XCTestCase { OtaHelpers.resolveAbsolutePathRelativeToOtaDir("/\(relative)") } + /// A directory next to the OTA dir that deploys must never touch. + private func makeSentinel() throws -> String { + let sentinel = ((otaDir as NSString).deletingLastPathComponent as NSString).appendingPathComponent("sentinel") + try? FileManager.default.removeItem(atPath: sentinel) + try FileManager.default.createDirectory(atPath: sentinel, withIntermediateDirectories: true) + try "keep".write(toFile: "\(sentinel)/keep.txt", atomically: true, encoding: .utf8) + addTeardownBlock { try? FileManager.default.removeItem(atPath: sentinel) } + return sentinel + } + + private func setManifestBundlePath(_ relativeBundlePath: String) throws { + var manifest = try XCTUnwrap(OtaHelpers.readManifestAsDictionary()) + manifest[MANIFEST_RELATIVE_BUNDLE_PATH_KEY] = relativeBundlePath + try JSONSerialization.data(withJSONObject: manifest).write(to: URL(fileURLWithPath: OtaHelpers.getOtaManifestFilepath())) + } + + private func assertResolved(_ outcome: Outcome, file: StaticString = #filePath, line: UInt = #line) { + guard case .resolved = outcome else { + return XCTFail("Expected deploy to resolve, got \(outcome)", file: file, line: line) + } + } + private func assertRejected(_ outcome: Outcome, _ expected: String, file: StaticString = #filePath, line: UInt = #line) { guard case .rejected(let code) = outcome else { return XCTFail("Expected rejection with \(expected), got resolve", file: file, line: line) @@ -142,4 +164,60 @@ final class OtaDeployTests: XCTestCase { func testBundleUrlIsNilWithoutManifest() { XCTAssertNil(OtaJSBundleFileProvider.getBundleUrl()) } + + func testExtractionDirOutsideOtaDirIsRejected() throws { + let sentinel = try makeSentinel() + + for extractionDir in ["../sentinel", "deployment-1/../../sentinel", "", ".", "deployment-1/.."] { + let zip = try makeOtaPackage("first.zip") + assertRejected(deploy(id: "1", package: zip, extractionDir: extractionDir), INVALID_DEPLOY_CONFIG) + XCTAssertTrue(FileManager.default.fileExists(atPath: path(zip)), extractionDir) + } + XCTAssertTrue(FileManager.default.fileExists(atPath: otaDir)) + XCTAssertNil(OtaHelpers.readManifestAsDictionary()) + XCTAssertEqual(try String(contentsOfFile: "\(sentinel)/keep.txt", encoding: .utf8), "keep") + } + + func testOtaPackageOutsideOtaDirIsRejected() throws { + let outsideZip = ((otaDir as NSString).deletingLastPathComponent as NSString).appendingPathComponent("outside.zip") + try FileManager.default.moveItem(atPath: path(try makeOtaPackage("outside.zip")), toPath: outsideZip) + defer { try? FileManager.default.removeItem(atPath: outsideZip) } + + assertRejected(deploy(id: "1", package: "../outside.zip", extractionDir: "deployment-1"), INVALID_DEPLOY_CONFIG) + XCTAssertTrue(FileManager.default.fileExists(atPath: outsideZip)) + XCTAssertFalse(FileManager.default.fileExists(atPath: path("deployment-1"))) + } + + func testExtractionDirInSubdirectoryIsAllowed() throws { + assertResolved(deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployments/1")) + + let manifest = try XCTUnwrap(OtaHelpers.readManifestAsDictionary()) + XCTAssertEqual(manifest[MANIFEST_RELATIVE_BUNDLE_PATH_KEY] as? String, "deployments/1/index.ios.bundle") + XCTAssertTrue(FileManager.default.fileExists(atPath: path("deployments/1/index.ios.bundle"))) + } + + func testOldBundleOutsideOtaDirIsNotRemoved() throws { + let sentinel = try makeSentinel() + assertResolved(deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployment-1")) + try setManifestBundlePath("../sentinel/index.ios.bundle") + + assertResolved(deploy(id: "2", package: try makeOtaPackage("second.zip"), extractionDir: "deployment-2")) + XCTAssertEqual(try String(contentsOfFile: "\(sentinel)/keep.txt", encoding: .utf8), "keep") + } + + func testOldBundleInOtaDirRootDoesNotRemoveOtaDir() throws { + assertResolved(deploy(id: "1", package: try makeOtaPackage("first.zip"), extractionDir: "deployment-1")) + try setManifestBundlePath("index.ios.bundle") + + assertResolved(deploy(id: "2", package: try makeOtaPackage("second.zip"), extractionDir: "deployment-2")) + XCTAssertTrue(FileManager.default.fileExists(atPath: path("deployment-2/index.ios.bundle"))) + XCTAssertNotNil(OtaHelpers.readManifestAsDictionary()) + } + + func testNewDeploymentIntoSameDirKeepsNewBundle() throws { + assertResolved(deploy(id: "1", package: try makeOtaPackage("first.zip", bundleContent: "first"), extractionDir: "deployment")) + assertResolved(deploy(id: "2", package: try makeOtaPackage("second.zip", bundleContent: "second"), extractionDir: "deployment")) + + XCTAssertEqual(try String(contentsOfFile: path("deployment/index.ios.bundle"), encoding: .utf8), "second") + } } From 46d8f0f035f4fee62d2261f6c81846f4bd8b97fa Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Sat, 3 Oct 2026 02:48:02 +0530 Subject: [PATCH 04/10] feat: enhance download and OTA deployment error handling --- .../react/download/DownloadHelper.kt | 22 ++- .../react/download/NativeDownloadModule.kt | 79 ++++----- .../mendixnative/react/ota/NativeOtaModule.kt | 2 + .../react/download/DownloadHelperTest.kt | 49 ++++++ .../download/NativeDownloadModuleTest.kt | 162 ++++++++++++++++++ .../react/ota/NativeOtaModuleTest.kt | 1 + example/__tests__/download-handler.harness.ts | 32 +++- example/__tests__/ota.harness.ts | 9 + .../NativeDownloadHandler.swift | 88 +++++++--- .../NativeOtaModule/NativeOtaModule.swift | 6 +- ios/Tests/NativeDownloadHandlerTests.swift | 83 +++++++++ ios/Tests/OtaDeployTests.swift | 17 ++ 12 files changed, 470 insertions(+), 80 deletions(-) create mode 100644 android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt diff --git a/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt b/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt index a04314f..ce31bab 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt @@ -97,13 +97,12 @@ class DownloadResponseHandler( var inputStream: BufferedInputStream? = null var outputStream: BufferedOutputStream? = null try { - if (!response.isSuccessful) throw ConnectException() + if (!response.isSuccessful) throw HttpStatusException(response.code) if (response.body == null) throw NoDataException() val body = response.body - val mediaType = body?.contentType() - if (expectedMimeType != null && mediaType != expectedMimeType - .toMediaTypeOrNull() - ) throw DownloadMimeTypeException() + if (expectedMimeType != null && !mimeTypeMatches(body?.contentType(), expectedMimeType)) { + throw DownloadMimeTypeException() + } inputStream = BufferedInputStream(body!!.byteStream()) @@ -145,6 +144,19 @@ class DownloadResponseHandler( } } +/** + * Compares type and subtype only, so parameters such as `charset` are ignored. + * A response without a content type doesn't match. + */ +internal fun mimeTypeMatches(actual: MediaType?, expected: String): Boolean { + val expectedType = expected.toMediaTypeOrNull() ?: return false + return actual != null && + actual.type.equals(expectedType.type, ignoreCase = true) && + actual.subtype.equals(expectedType.subtype, ignoreCase = true) +} + +/** Thrown for a non-2xx response. Extends ConnectException, which was thrown before, for compatibility. */ +class HttpStatusException(val statusCode: Int) : ConnectException("Download failed with HTTP status $statusCode") class NoDataException : IllegalStateException() class FileCorruptionException : IllegalStateException() class DownloadMimeTypeException : RuntimeException() diff --git a/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt b/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt index 71cd0d0..7ee092e 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt @@ -23,52 +23,25 @@ class NativeDownloadModule( if (config.hasKey(TIMEOUT_KEY)) config.getInt(TIMEOUT_KEY) else TIMEOUT val mimeType = if (config.hasKey(MIME_TYPE_KEY)) config.getString(MIME_TYPE_KEY) else null - downloadFile( - client.newBuilder() - .connectTimeout(timeout.toLong(), TimeUnit.MILLISECONDS).build(), - url, - downloadPath, - mimeType, - { promise.resolve(null) }, - { e -> - when (e) { - is DownloadMimeTypeException -> promise.reject( - ERROR_DOWNLOAD_FAILED, - "Mime type check failed", - e - ) - - is FileAlreadyExistsException -> promise.reject( - FILE_ALREADY_EXISTS, - "File already exists", - e - ) - - is NoDataException -> promise.reject( - ERROR_CONNECTION_FAILED, - "No data found", - e - ) - - is FileCorruptionException -> promise.reject(IO_EXCEPTION, "File corrupted", e) - is IOException -> promise.reject(IO_EXCEPTION, "IO exception", e) - is SecurityException -> promise.reject( - FS_ACCESS_EXCEPTION, - "Access to filesystem denied", - e - ) - - is ConnectException -> promise.reject( - ERROR_DOWNLOAD_FAILED, - "Failed to connect to endpoint", - e - ) - - else -> promise.reject(ERROR_DOWNLOAD_FAILED, "Failed to download file", e) - } + val reject = { e: Exception -> + val (code, message) = downloadErrorFor(e) + promise.reject(code, message, e) + } + try { + downloadFile( + client.newBuilder() + .connectTimeout(timeout.toLong(), TimeUnit.MILLISECONDS).build(), + url, + downloadPath, + mimeType, + { promise.resolve(null) }, + reject + ) { receivedBytes, totalBytes -> + eventEmitter?.invoke(receivedBytes, totalBytes) } - ) { receivedBytes, totalBytes -> - eventEmitter?.invoke(receivedBytes, totalBytes) + } catch (e: Exception) { + // Thrown before the request starts, e.g. for an existing destination or an invalid URL. + reject(e) } } @@ -85,4 +58,18 @@ class NativeDownloadModule( } } - +/** + * Maps a download failure to a rejection code and message. + * Subclasses come before their parents: FileAlreadyExistsException and ConnectException are both IOExceptions. + */ +internal fun downloadErrorFor(e: Exception): Pair = when (e) { + is DownloadMimeTypeException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Mime type check failed" + is FileAlreadyExistsException -> NativeDownloadModule.FILE_ALREADY_EXISTS to "File already exists" + is NoDataException -> NativeDownloadModule.ERROR_CONNECTION_FAILED to "No data found" + is FileCorruptionException -> NativeDownloadModule.IO_EXCEPTION to "File corrupted" + is HttpStatusException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Download failed with HTTP status ${e.statusCode}" + is ConnectException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Failed to connect to endpoint" + is IOException -> NativeDownloadModule.IO_EXCEPTION to "IO exception" + is SecurityException -> NativeDownloadModule.FS_ACCESS_EXCEPTION to "Access to filesystem denied" + else -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Failed to download file" +} diff --git a/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt b/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt index bb601fb..8d520e6 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/ota/NativeOtaModule.kt @@ -207,6 +207,8 @@ class NativeOtaModule( zipFile.delete() } catch (e: Exception) { extractionDir.deleteRecursively() + // A package that failed to deploy won't succeed on retry, so don't keep it (as on iOS). + zipFile.delete() return reject(promise, OTA_DEPLOYMENT_FAILED, "OTA deployment failed", e) } Log.i(TAG, "OTA deployed.") diff --git a/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt b/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt index 9ab2985..c0125d4 100644 --- a/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/react/download/DownloadHelperTest.kt @@ -81,7 +81,9 @@ class DownloadHelperTest { val result = download(file) + // Still a ConnectException, as before, for callers that check for it. assertTrue(result.error is ConnectException) + assertEquals(404, (result.error as HttpStatusException).statusCode) assertFalse(file.exists()) } @@ -107,6 +109,53 @@ class DownloadHelperTest { assertEquals("zip", file.readText()) } + @Test + fun mimeTypeWithParametersMatches() { + server.enqueue(MockResponse().setHeader("Content-Type", "Text/Plain; charset=utf-8").setBody("content")) + val file = File(tempFolder.root, "file.txt") + + val result = download(file, mimeType = "text/plain") + + assertNull(result.error) + assertEquals("content", file.readText()) + } + + @Test + fun expectedMimeTypeWithParametersMatches() { + server.enqueue(MockResponse().setHeader("Content-Type", "text/plain").setBody("content")) + + val result = download(File(tempFolder.root, "file.txt"), mimeType = "text/plain; charset=utf-8") + + assertNull(result.error) + } + + @Test + fun missingContentTypeFailsWhenMimeTypeIsSet() { + server.enqueue(MockResponse().setBody("content")) + val file = File(tempFolder.root, "file.txt") + + val result = download(file, mimeType = "text/plain") + + assertTrue(result.error is DownloadMimeTypeException) + assertFalse(file.exists()) + } + + @Test + fun invalidExpectedMimeTypeFails() { + server.enqueue(MockResponse().setBody("content")) + + val result = download(File(tempFolder.root, "file.txt"), mimeType = "not a mime type") + + assertTrue(result.error is DownloadMimeTypeException) + } + + @Test + fun missingContentTypeSucceedsWithoutMimeType() { + server.enqueue(MockResponse().setBody("content")) + + assertNull(download(File(tempFolder.root, "file.txt")).error) + } + @Test fun connectionFailureRemovesFile() { val file = File(tempFolder.root, "file.txt") diff --git a/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt b/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt new file mode 100644 index 0000000..c9323db --- /dev/null +++ b/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt @@ -0,0 +1,162 @@ +package com.mendix.mendixnative.react.download + +import com.facebook.react.bridge.BridgeReactContext +import com.facebook.react.bridge.JavaOnlyMap +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.WritableMap +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import java.io.File +import java.io.IOException +import java.net.ConnectException +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +@RunWith(RobolectricTestRunner::class) +class NativeDownloadModuleTest { + @get:Rule + val tempFolder = TemporaryFolder() + + private lateinit var server: MockWebServer + private lateinit var module: NativeDownloadModule + + @Before + fun setUp() { + server = MockWebServer().apply { start() } + module = NativeDownloadModule(BridgeReactContext(RuntimeEnvironment.getApplication())) + } + + @After + fun tearDown() { + server.shutdown() + } + + private sealed class Outcome { + object Resolved : Outcome() + data class Rejected(val code: String?) : Outcome() + } + + private class RecordingPromise : Promise { + val latch = CountDownLatch(1) + var outcome: Outcome? = null + + private fun settle(value: Outcome) { + outcome = value + latch.countDown() + } + + override fun resolve(value: Any?) = settle(Outcome.Resolved) + override fun reject(code: String?, message: String?) = settle(Outcome.Rejected(code)) + override fun reject(code: String?, throwable: Throwable?) = settle(Outcome.Rejected(code)) + override fun reject(code: String?, message: String?, throwable: Throwable?) = settle(Outcome.Rejected(code)) + override fun reject(throwable: Throwable) = settle(Outcome.Rejected(null)) + override fun reject(throwable: Throwable, userInfo: WritableMap) = settle(Outcome.Rejected(null)) + override fun reject(code: String?, userInfo: WritableMap) = settle(Outcome.Rejected(code)) + override fun reject(code: String?, throwable: Throwable?, userInfo: WritableMap) = settle(Outcome.Rejected(code)) + override fun reject(code: String?, message: String?, userInfo: WritableMap) = settle(Outcome.Rejected(code)) + override fun reject(code: String?, message: String?, throwable: Throwable?, userInfo: WritableMap?) = + settle(Outcome.Rejected(code)) + + @Deprecated("Deprecated in Java") + override fun reject(message: String) = settle(Outcome.Rejected(null)) + } + + private fun download(url: String, file: File, mimeType: String? = null): Outcome { + val promise = RecordingPromise() + val config = JavaOnlyMap().apply { mimeType?.let { putString("mimeType", it) } } + module.download(url, file.absolutePath, config, promise) + assertTrue("download did not settle", promise.latch.await(5, TimeUnit.SECONDS)) + return promise.outcome!! + } + + private fun file(name: String) = File(tempFolder.root, name) + + @Test + fun successResolves() { + server.enqueue(MockResponse().setBody("content")) + + assertEquals(Outcome.Resolved, download(server.url("/file").toString(), file("file.txt"))) + } + + @Test + fun errorStatusRejectsWithDownloadFailed() { + server.enqueue(MockResponse().setResponseCode(404)) + + assertEquals( + Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), + download(server.url("/file").toString(), file("file.txt")) + ) + } + + @Test + fun existingDestinationRejectsWithFileAlreadyExists() { + val existing = tempFolder.newFile("existing.txt").apply { writeText("keep") } + + assertEquals( + Outcome.Rejected(NativeDownloadModule.FILE_ALREADY_EXISTS), + download(server.url("/file").toString(), existing) + ) + assertEquals("keep", existing.readText()) + assertEquals(0, server.requestCount) + } + + @Test + fun invalidUrlRejectsInsteadOfThrowing() { + val destination = file("file.txt") + + assertEquals( + Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), + download("://invalid", destination) + ) + assertFalse(destination.exists()) + } + + @Test + fun connectionFailureRejectsWithDownloadFailed() { + val url = server.url("/file").toString() + server.shutdown() + + assertEquals(Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), download(url, file("file.txt"))) + } + + @Test + fun mimeTypeWithCharsetResolves() { + server.enqueue(MockResponse().setHeader("Content-Type", "text/plain; charset=utf-8").setBody("content")) + + assertEquals(Outcome.Resolved, download(server.url("/file").toString(), file("file.txt"), "text/plain")) + } + + @Test + fun mismatchingMimeTypeRejectsWithDownloadFailed() { + server.enqueue(MockResponse().setHeader("Content-Type", "text/plain").setBody("content")) + + assertEquals( + Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), + download(server.url("/file").toString(), file("file.zip"), "application/zip") + ) + } + + @Test + fun errorsMapToCodes() { + assertEquals(NativeDownloadModule.FILE_ALREADY_EXISTS, downloadErrorFor(FileAlreadyExistsException(file("x"))).first) + assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(HttpStatusException(500)).first) + assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(ConnectException()).first) + assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(DownloadMimeTypeException()).first) + assertEquals(NativeDownloadModule.ERROR_CONNECTION_FAILED, downloadErrorFor(NoDataException()).first) + assertEquals(NativeDownloadModule.IO_EXCEPTION, downloadErrorFor(FileCorruptionException()).first) + assertEquals(NativeDownloadModule.IO_EXCEPTION, downloadErrorFor(IOException()).first) + assertEquals(NativeDownloadModule.FS_ACCESS_EXCEPTION, downloadErrorFor(SecurityException()).first) + assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(IllegalArgumentException()).first) + } +} diff --git a/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt b/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt index 9042806..fb3dc65 100644 --- a/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/react/ota/NativeOtaModuleTest.kt @@ -163,6 +163,7 @@ class NativeOtaModuleTest { assertEquals(Outcome.Rejected(OTA_DEPLOYMENT_FAILED), deploy("1", "invalid.zip", "deployment-1")) assertFalse(file("deployment-1").exists()) assertFalse(File(getOtaManifestFilepath(context)).exists()) + assertFalse(file("invalid.zip").exists()) } @Test diff --git a/example/__tests__/download-handler.harness.ts b/example/__tests__/download-handler.harness.ts index 92297ea..3d63dbb 100644 --- a/example/__tests__/download-handler.harness.ts +++ b/example/__tests__/download-handler.harness.ts @@ -1,3 +1,4 @@ +import { Platform } from 'react-native'; import { beforeEach, describe, expect, test } from 'react-native-harness'; import { MxConfiguration, @@ -7,7 +8,10 @@ import { // The example app's runtime URL points at Metro, which is always up while harness tests run. const runtimeUrl = MxConfiguration.RUNTIME_URL.replace(/\/$/, ''); +// Sent without a Content-Type. const statusUrl = `${runtimeUrl}/status`; +// A small bundle, sent as "application/javascript; charset=UTF-8". +const bundleUrl = `${runtimeUrl}/index.bundle?platform=${Platform.OS}&dev=true&minify=false&shallow=true&modulesOnly=true&runModule=false`; const invalidUrlPath = NativeFileSystem.relativeToDocumentsAbsolutePath( 'downloads/invalid-url.txt' @@ -39,7 +43,7 @@ describe('NativeDownloadHandler', () => { invalidUrlPath, config ) - ).rejects.toBeDefined(); + ).rejects.toMatchObject({ code: 'ERROR_DOWNLOAD_FAILED' }); expect(await NativeFileSystem.fileExists(invalidUrlPath)).toBe(false); }); @@ -73,17 +77,35 @@ describe('NativeDownloadHandler', () => { downloadPath, {} ) - ).rejects.toBeDefined(); + ).rejects.toMatchObject({ code: 'ERROR_DOWNLOAD_FAILED' }); expect(await NativeFileSystem.fileExists(downloadPath)).toBe(false); }); test('rejects an unexpected mime type without leaving a file behind', async () => { await expect( - NativeDownloadHandler.download(statusUrl, downloadPath, { + NativeDownloadHandler.download(bundleUrl, downloadPath, { mimeType: 'application/zip', }) - ).rejects.toBeDefined(); + ).rejects.toMatchObject({ code: 'ERROR_DOWNLOAD_FAILED' }); + + expect(await NativeFileSystem.fileExists(downloadPath)).toBe(false); + }); + + test('accepts a mime type whose response has parameters', async () => { + await NativeDownloadHandler.download(bundleUrl, downloadPath, { + mimeType: 'application/javascript', + }); + + expect(await NativeFileSystem.fileExists(downloadPath)).toBe(true); + }); + + test('rejects a response without a content type when a mime type is expected', async () => { + await expect( + NativeDownloadHandler.download(statusUrl, downloadPath, { + mimeType: 'text/plain', + }) + ).rejects.toMatchObject({ code: 'ERROR_DOWNLOAD_FAILED' }); expect(await NativeFileSystem.fileExists(downloadPath)).toBe(false); }); @@ -93,7 +115,7 @@ describe('NativeDownloadHandler', () => { await expect( NativeDownloadHandler.download(statusUrl, downloadPath, {}) - ).rejects.toBeDefined(); + ).rejects.toMatchObject({ code: 'FILE_ALREADY_EXISTS' }); expect(await NativeFileSystem.readJson(downloadPath)).toEqual({ keep: true, diff --git a/example/__tests__/ota.harness.ts b/example/__tests__/ota.harness.ts index 5e1a46c..1224980 100644 --- a/example/__tests__/ota.harness.ts +++ b/example/__tests__/ota.harness.ts @@ -38,6 +38,15 @@ describe('NativeOta', () => { ).rejects.toMatchObject({ code: 'OTA_ZIP_FILE_MISSING' }); }); + test('rejects a config with a missing key', async () => { + await expect( + NativeOta.deploy({ + otaPackage: 'does-not-exist.zip', + extractionDir: 'harness-missing-key', + } as unknown as Parameters[0]) + ).rejects.toMatchObject({ code: 'INVALID_DEPLOY_CONFIG' }); + }); + test('rejects paths outside the OTA directory', async () => { await expect( NativeOta.deploy({ diff --git a/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift b/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift index f4e1a22..0991285 100644 --- a/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift +++ b/ios/Modules/NativeDownloadHandler/NativeDownloadHandler.swift @@ -5,10 +5,53 @@ fileprivate func formatMessage(_ message: String) -> String { return "\(String(describing: NativeDownloadHandler.self)): \(message)" } +/// A download failure with the rejection code passed to JS. The codes match Android's. +struct NativeDownloadError: LocalizedError { + static let ERROR_DOWNLOAD_FAILED = "ERROR_DOWNLOAD_FAILED" + static let FILE_ALREADY_EXISTS = "FILE_ALREADY_EXISTS" + static let IO_EXCEPTION = "IO_EXCEPTION" + static let FS_ACCESS_EXCEPTION = "FS_ACCESS_EXCEPTION" + + let code: String + let message: String + let underlyingError: Error? + + init(code: String, message: String, underlyingError: Error? = nil) { + self.code = code + self.message = message + self.underlyingError = underlyingError + } + + var errorDescription: String? { message } + + /// Maps a file system error to FS_ACCESS_EXCEPTION for permission errors, IO_EXCEPTION otherwise. + static func fileSystem(_ error: Error, message: String) -> NativeDownloadError { + let permissionCodes: Set = [CocoaError.fileReadNoPermission.rawValue, CocoaError.fileWriteNoPermission.rawValue] + let nsError = error as NSError + let code = nsError.domain == NSCocoaErrorDomain && permissionCodes.contains(nsError.code) ? FS_ACCESS_EXCEPTION : IO_EXCEPTION + return NativeDownloadError(code: code, message: message, underlyingError: error) + } + + /// The rejection code for any error passed to a download fail callback. + static func code(for error: Error) -> String { + (error as? NativeDownloadError)?.code ?? ERROR_DOWNLOAD_FAILED + } +} + +/// Compares type and subtype only, so parameters such as `charset` are ignored. +/// A response without a MIME type doesn't match. +func mimeTypeMatches(_ actual: String?, expected: String) -> Bool { + func essence(_ mimeType: String) -> String { + mimeType.split(separator: ";", maxSplits: 1).first.map { $0.trimmingCharacters(in: .whitespaces).lowercased() } ?? "" + } + guard let actual else { return false } + return essence(actual) == essence(expected) +} + class NativeDownloadHandler: NSObject { let mimeType: String? - let connectionTimeout: Int + let connectionTimeout: TimeInterval let doneCallback: (() -> Void)? let progressCallback: ((Int64, Int64) -> Void)? let failCallback: ((Error) -> Void)? @@ -22,7 +65,8 @@ class NativeDownloadHandler: NSObject { failCallback: @escaping (Error) -> Void ) { if let connectionTimeout { - self.connectionTimeout = connectionTimeout.intValue / 1000 + // Milliseconds, as on Android; keep fractions so sub-second timeouts don't become 0. + self.connectionTimeout = connectionTimeout.doubleValue / 1000 } else { self.connectionTimeout = 10 } @@ -38,14 +82,19 @@ class NativeDownloadHandler: NSObject { guard let encodedUrlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: encodedUrlString) else { - let error = NSError(domain: NSURLErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) - failCallback?(error) + failCallback?(NativeDownloadError(code: NativeDownloadError.ERROR_DOWNLOAD_FAILED, message: "Invalid URL")) + return + } + + // Fail before downloading, as Android does, so no bandwidth is wasted. Checked again after the download. + if FileManager.default.fileExists(atPath: downloadPath) { + failCallback?(NativeDownloadError(code: NativeDownloadError.FILE_ALREADY_EXISTS, message: "File already exists in the same path.")) return } let configuration = URLSessionConfiguration.default let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil) - let request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: TimeInterval(connectionTimeout)) + let request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: connectionTimeout) let downloadTask = session.downloadTask(with: request) downloadTask.resume() // The session retains its delegate (self) until invalidated; release both once the task is done. @@ -65,29 +114,28 @@ extension NativeDownloadHandler: URLSessionDownloadDelegate { // with a misleading error. Fail explicitly with the status code instead. if let httpResponse = downloadTask.response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) { - let error = NSError( - domain: NSURLErrorDomain, - code: httpResponse.statusCode, - userInfo: [NSLocalizedDescriptionKey: "Download failed with HTTP status \(httpResponse.statusCode)."] + let error = NativeDownloadError( + code: NativeDownloadError.ERROR_DOWNLOAD_FAILED, + message: "Download failed with HTTP status \(httpResponse.statusCode)." ) NSLog("%@", formatMessage("Download failed with HTTP status \(httpResponse.statusCode)")) failCallback?(error) return } - // Check MIME type if specified + // Check MIME type if specified. For HTTP, use the Content-Type header, since URLResponse.mimeType + // is sniffed from the content when the header is missing; a missing header fails, as on Android. + let responseMimeType = (downloadTask.response as? HTTPURLResponse).map { $0.value(forHTTPHeaderField: "Content-Type") } + ?? downloadTask.response?.mimeType if let expectedMimeType = mimeType, - let responseMimeType = downloadTask.response?.mimeType, - responseMimeType != expectedMimeType { - let error = NSError(domain: UserDefaults.argumentDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "MIME type not expected."]) - failCallback?(error) + !mimeTypeMatches(responseMimeType, expected: expectedMimeType) { + failCallback?(NativeDownloadError(code: NativeDownloadError.ERROR_DOWNLOAD_FAILED, message: "MIME type not expected.")) return } // Check if file already exists if fileManager.fileExists(atPath: downloadPath) { - let error = NSError(domain: NSURLErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "File already exists in the same path."]) - failCallback?(error) + failCallback?(NativeDownloadError(code: NativeDownloadError.FILE_ALREADY_EXISTS, message: "File already exists in the same path.")) return } @@ -101,7 +149,7 @@ extension NativeDownloadHandler: URLSessionDownloadDelegate { ) } catch { NSLog("%@", formatMessage("Could not create path: \(error)")) - failCallback?(error) + failCallback?(NativeDownloadError.fileSystem(error, message: "Could not create path: \(error.localizedDescription)")) return } @@ -122,7 +170,7 @@ extension NativeDownloadHandler: URLSessionDownloadDelegate { } catch { try? fileManager.removeItem(at: destinationUrl) NSLog("%@", formatMessage("Could not copy path: \(error)")) - failCallback?(error) + failCallback?(NativeDownloadError.fileSystem(error, message: "Could not copy path: \(error.localizedDescription)")) } } @@ -146,8 +194,6 @@ extension NativeDownloadHandler: URLSessionTaskDelegate { @objcMembers public class NativeDownloadModule: NSObject { - private static let ERROR_DOWNLOAD_FAILED = "ERROR_DOWNLOAD_FAILED" - public func download( _ url: String, downloadPath: String, @@ -167,7 +213,7 @@ public class NativeDownloadModule: NSObject { onProgress?(["receivedBytes": received, "totalBytes": total]) }, failCallback: { error in - promise.reject(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, formatMessage(error.localizedDescription), error) + promise.reject(NativeDownloadError.code(for: error), formatMessage(error.localizedDescription), error) } ) diff --git a/ios/Modules/NativeOtaModule/NativeOtaModule.swift b/ios/Modules/NativeOtaModule/NativeOtaModule.swift index 5c635b3..7254671 100644 --- a/ios/Modules/NativeOtaModule/NativeOtaModule.swift +++ b/ios/Modules/NativeOtaModule/NativeOtaModule.swift @@ -126,17 +126,17 @@ public class NativeOtaModule: NSObject { public func deploy(_ config: OtaDeploymentConfiguration, promise: Promise) { guard let otaDeploymentID = config.otaDeploymentID else { - promise.reject(INVALID_DOWNLOAD_CONFIG, "Key otaDeploymentID is invalid.", nil) + promise.reject(INVALID_DEPLOY_CONFIG, "Key otaDeploymentID is invalid.", nil) return } guard let zipFile = config.otaPackage else { - promise.reject(INVALID_DOWNLOAD_CONFIG, "Key otaPackage is invalid.", nil) + promise.reject(INVALID_DEPLOY_CONFIG, "Key otaPackage is invalid.", nil) return } guard let extractionDir = config.extractionDir else { - promise.reject(INVALID_DOWNLOAD_CONFIG, "Key extractionDir is invalid.", nil) + promise.reject(INVALID_DEPLOY_CONFIG, "Key extractionDir is invalid.", nil) return } diff --git a/ios/Tests/NativeDownloadHandlerTests.swift b/ios/Tests/NativeDownloadHandlerTests.swift index b8c3f50..917e912 100644 --- a/ios/Tests/NativeDownloadHandlerTests.swift +++ b/ios/Tests/NativeDownloadHandlerTests.swift @@ -76,4 +76,87 @@ final class NativeDownloadHandlerTests: XCTestCase { assertReleased(handler) } + + // MARK: - Behaviour shared with Android + + /// Downloads through NativeDownloadModule and returns the rejection code, or nil when it resolved. + private func rejectionCode(_ url: String, to destination: String, mimeType: String? = nil) -> String? { + let finished = expectation(description: "download settled") + var code: String? + let promise = Promise( + resolve: { _ in finished.fulfill() }, + reject: { rejectCode, _, _ in code = rejectCode; finished.fulfill() } + ) + NativeDownloadModule().download(url, downloadPath: destination, connectionTimeout: nil, mimeType: mimeType, onProgress: nil, promise: promise) + wait(for: [finished], timeout: 5) + return code + } + + private func makeSource(_ content: String = "content") throws -> String { + let source = "\(workDir!)/source.txt" + try content.write(toFile: source, atomically: true, encoding: .utf8) + return URL(fileURLWithPath: source).absoluteString + } + + func testExistingDestinationIsRejectedBeforeDownloading() throws { + let destination = "\(workDir!)/existing.txt" + try "keep".write(toFile: destination, atomically: true, encoding: .utf8) + // The source doesn't exist, so a started download would fail with a different code. + let missingSource = URL(fileURLWithPath: "\(workDir!)/missing.txt").absoluteString + + XCTAssertEqual(rejectionCode(missingSource, to: destination), "FILE_ALREADY_EXISTS") + XCTAssertEqual(try String(contentsOfFile: destination, encoding: .utf8), "keep") + } + + func testFailedDownloadIsRejectedWithDownloadFailed() { + let missingSource = URL(fileURLWithPath: "\(workDir!)/missing.txt").absoluteString + + XCTAssertEqual(rejectionCode(missingSource, to: "\(workDir!)/destination.txt"), "ERROR_DOWNLOAD_FAILED") + } + + func testInvalidUrlIsRejectedWithDownloadFailed() { + XCTAssertEqual(rejectionCode("://invalid url", to: "\(workDir!)/destination.txt"), "ERROR_DOWNLOAD_FAILED") + } + + func testMimeTypeWithParametersIsAccepted() throws { + let source = try makeSource() + let destination = "\(workDir!)/destination.txt" + + XCTAssertNil(rejectionCode(source, to: destination, mimeType: "text/plain; charset=utf-8")) + XCTAssertEqual(try String(contentsOfFile: destination, encoding: .utf8), "content") + } + + func testMismatchingMimeTypeIsRejectedWithDownloadFailed() throws { + let destination = "\(workDir!)/destination.zip" + + XCTAssertEqual(rejectionCode(try makeSource(), to: destination, mimeType: "application/zip"), "ERROR_DOWNLOAD_FAILED") + XCTAssertFalse(FileManager.default.fileExists(atPath: destination)) + } + + func testMimeTypeMatching() { + XCTAssertTrue(mimeTypeMatches("text/plain", expected: "text/plain")) + XCTAssertTrue(mimeTypeMatches("text/plain", expected: "Text/Plain; charset=utf-8")) + XCTAssertTrue(mimeTypeMatches("TEXT/PLAIN; charset=utf-8", expected: "text/plain")) + XCTAssertFalse(mimeTypeMatches("text/html", expected: "text/plain")) + XCTAssertFalse(mimeTypeMatches(nil, expected: "text/plain")) + } + + func testConnectionTimeoutKeepsSubSecondValues() { + func handler(_ timeout: NSNumber?) -> NativeDownloadHandler { + NativeDownloadHandler(connectionTimeout: timeout, mimeType: nil, doneCallback: {}, progressCallback: nil, failCallback: { _ in }) + } + + XCTAssertEqual(handler(500).connectionTimeout, 0.5) + XCTAssertEqual(handler(2500).connectionTimeout, 2.5) + XCTAssertEqual(handler(nil).connectionTimeout, 10) + } + + func testFileSystemErrorsMapToCodes() { + let permission = CocoaError(.fileWriteNoPermission) + let other = CocoaError(.fileWriteOutOfSpace) + + XCTAssertEqual(NativeDownloadError.fileSystem(permission, message: "").code, "FS_ACCESS_EXCEPTION") + XCTAssertEqual(NativeDownloadError.fileSystem(other, message: "").code, "IO_EXCEPTION") + XCTAssertEqual(NativeDownloadError.code(for: URLError(.timedOut)), "ERROR_DOWNLOAD_FAILED") + } } diff --git a/ios/Tests/OtaDeployTests.swift b/ios/Tests/OtaDeployTests.swift index 35c4d27..5cc1672 100644 --- a/ios/Tests/OtaDeployTests.swift +++ b/ios/Tests/OtaDeployTests.swift @@ -137,6 +137,23 @@ final class OtaDeployTests: XCTestCase { XCTAssertTrue(FileManager.default.fileExists(atPath: path("deployment-1/index.ios.bundle"))) } + func testMissingConfigKeysAreRejectedWithDeployConfigCode() { + let configs = [ + OtaDeploymentConfiguration(otaDeploymentID: nil, otaPackage: "first.zip", extractionDir: "deployment-1"), + OtaDeploymentConfiguration(otaDeploymentID: "1", otaPackage: nil, extractionDir: "deployment-1"), + OtaDeploymentConfiguration(otaDeploymentID: "1", otaPackage: "first.zip", extractionDir: nil), + ] + for config in configs { + var outcome: Outcome? + let promise = Promise( + resolve: { _ in outcome = .resolved }, + reject: { code, _, _ in outcome = .rejected(code: code) } + ) + module.deploy(config, promise: promise) + assertRejected(try! XCTUnwrap(outcome), INVALID_DEPLOY_CONFIG) + } + } + func testMissingPackageIsRejected() { assertRejected(deploy(id: "1", package: "missing.zip", extractionDir: "deployment-1"), OTA_ZIP_FILE_MISSING) XCTAssertNil(OtaJSBundleFileProvider.getBundleUrl()) From 952b16bb81248bee7afaf6469ecaa71863a9550a Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Sat, 3 Oct 2026 02:59:37 +0530 Subject: [PATCH 05/10] feat: add native unit tests for Android and iOS, improve error handling in download module --- .github/workflows/android.yml | 12 ++++++ .github/workflows/ios.yml | 19 ++++++++ .../react/download/DownloadHelper.kt | 26 ++++++++--- .../react/download/NativeDownloadModule.kt | 8 ++-- .../download/NativeDownloadModuleTest.kt | 43 ++++++++++++++++++- 5 files changed, 98 insertions(+), 10 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index ea55db3..5eee694 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -88,6 +88,18 @@ jobs: working-directory: example run: yarn app:package:android + # JVM unit tests (JUnit, Robolectric, MockWebServer) in android/src/test + - name: Run native unit tests + working-directory: example/android + run: ./gradlew :mendix-native:testDebugUnitTest + + - name: Upload native unit test reports + if: failure() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: android-unit-test-reports + path: android/build/reports/tests/testDebugUnitTest + - name: AVD cache uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.2.0 id: avd-cache diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index fc93106..b9283fe 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -69,6 +69,25 @@ jobs: # Launch simulator with our custom script bash .github/scripts/launch-ios-simulator.sh "${{ env.DEVICE_MODEL }}" "${{ env.IOS_VERSION }}" + # XCTest unit tests in ios/Tests, installed by the MendixNative test spec in the Podfile. + # Shares the app build's derived data so the pods aren't compiled again. + - name: Run native unit tests + working-directory: example/ios + run: | + xcodebuild test \ + -workspace MendixNativeExample.xcworkspace \ + -scheme MendixNative-Unit-Tests \ + -destination "platform=iOS Simulator,name=${{ env.DEVICE_MODEL }},OS=${{ env.IOS_VERSION }}" \ + -derivedDataPath build \ + -resultBundlePath build/unit-tests.xcresult + + - name: Upload native unit test results + if: failure() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: ios-unit-test-results + path: example/ios/build/unit-tests.xcresult + # Install app on simulator - name: Install app on simulator working-directory: example diff --git a/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt b/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt index ce31bab..d52bb4f 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/download/DownloadHelper.kt @@ -39,8 +39,10 @@ fun downloadFile( ) { val outputFile = File(downloadPath) if (outputFile.exists()) throw FileAlreadyExistsException(outputFile) - outputFile.parentFile?.mkdirs() - outputFile.createNewFile() + writingFile { + outputFile.parentFile?.mkdirs() + outputFile.createNewFile() + } try { client.newCall(Request.Builder().url(url).get().build()).enqueue(object : Callback { @@ -107,8 +109,7 @@ class DownloadResponseHandler( inputStream = BufferedInputStream(body!!.byteStream()) - outputStream = - BufferedOutputStream(FileOutputStream(outputFile)) + outputStream = writingFile { BufferedOutputStream(FileOutputStream(outputFile)) } val totalBytes = response.body!!.contentLength().toDouble() var reportedBytes = -1.0 @@ -124,7 +125,7 @@ class DownloadResponseHandler( val buffer = ByteArray(COPY_BUFFER_SIZE) var read = inputStream.read(buffer) while (read != -1) { - outputStream.write(buffer, 0, read) + writingFile { outputStream.write(buffer, 0, read) } receivedBytes += read progressCallbackInvoker(receivedBytes, totalBytes) read = inputStream.read(buffer) @@ -133,7 +134,7 @@ class DownloadResponseHandler( if (reportedBytes != receivedBytes) { progressCallback(receivedBytes, totalBytes) } - outputStream.flush() + writingFile { outputStream.flush() } } catch (e: Exception) { outputFile.delete() throw e @@ -155,6 +156,19 @@ internal fun mimeTypeMatches(actual: MediaType?, expected: String): Boolean { actual.subtype.equals(expectedType.subtype, ignoreCase = true) } +/** + * Thrown when writing the destination file fails, to tell file errors apart from network errors, + * which are plain IOExceptions too. The original exception is the cause. + */ +class DownloadFileException(cause: IOException) : IOException(cause.message, cause) + +private inline fun writingFile(block: () -> T): T = + try { + block() + } catch (e: IOException) { + throw DownloadFileException(e) + } + /** Thrown for a non-2xx response. Extends ConnectException, which was thrown before, for compatibility. */ class HttpStatusException(val statusCode: Int) : ConnectException("Download failed with HTTP status $statusCode") class NoDataException : IllegalStateException() diff --git a/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt b/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt index 7ee092e..55432dd 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/download/NativeDownloadModule.kt @@ -59,8 +59,9 @@ class NativeDownloadModule( } /** - * Maps a download failure to a rejection code and message. - * Subclasses come before their parents: FileAlreadyExistsException and ConnectException are both IOExceptions. + * Maps a download failure to a rejection code and message, using the same codes as iOS. + * Subclasses come before their parents: FileAlreadyExistsException, DownloadFileException and ConnectException + * are all IOExceptions. Any other IOException comes from the network. */ internal fun downloadErrorFor(e: Exception): Pair = when (e) { is DownloadMimeTypeException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Mime type check failed" @@ -68,8 +69,9 @@ internal fun downloadErrorFor(e: Exception): Pair = when (e) { is NoDataException -> NativeDownloadModule.ERROR_CONNECTION_FAILED to "No data found" is FileCorruptionException -> NativeDownloadModule.IO_EXCEPTION to "File corrupted" is HttpStatusException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Download failed with HTTP status ${e.statusCode}" + is DownloadFileException -> NativeDownloadModule.IO_EXCEPTION to "Could not write file" is ConnectException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Failed to connect to endpoint" - is IOException -> NativeDownloadModule.IO_EXCEPTION to "IO exception" + is IOException -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Download failed" is SecurityException -> NativeDownloadModule.FS_ACCESS_EXCEPTION to "Access to filesystem denied" else -> NativeDownloadModule.ERROR_DOWNLOAD_FAILED to "Failed to download file" } diff --git a/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt b/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt index c9323db..761a556 100644 --- a/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/react/download/NativeDownloadModuleTest.kt @@ -6,6 +6,7 @@ import com.facebook.react.bridge.Promise import com.facebook.react.bridge.WritableMap import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.SocketPolicy import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -20,6 +21,7 @@ import org.robolectric.RuntimeEnvironment import java.io.File import java.io.IOException import java.net.ConnectException +import java.net.SocketTimeoutException import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -130,6 +132,42 @@ class NativeDownloadModuleTest { assertEquals(Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), download(url, file("file.txt"))) } + @Test + fun disconnectBeforeResponseRejectsWithDownloadFailed() { + server.enqueue(MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START)) + + assertEquals( + Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), + download(server.url("/file").toString(), file("file.txt")) + ) + } + + @Test + fun disconnectDuringBodyRejectsWithDownloadFailedAndRemovesFile() { + server.enqueue( + MockResponse().setBody("x".repeat(256 * 1024)).setSocketPolicy(SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY) + ) + val destination = file("file.txt") + + assertEquals( + Outcome.Rejected(NativeDownloadModule.ERROR_DOWNLOAD_FAILED), + download(server.url("/file").toString(), destination) + ) + assertFalse(destination.exists()) + } + + @Test + fun unwritableDestinationRejectsWithIoException() { + // The parent is a file, so the destination can't be created. + val parent = tempFolder.newFile("not-a-dir") + + assertEquals( + Outcome.Rejected(NativeDownloadModule.IO_EXCEPTION), + download(server.url("/file").toString(), File(parent, "file.txt")) + ) + assertEquals(0, server.requestCount) + } + @Test fun mimeTypeWithCharsetResolves() { server.enqueue(MockResponse().setHeader("Content-Type", "text/plain; charset=utf-8").setBody("content")) @@ -155,7 +193,10 @@ class NativeDownloadModuleTest { assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(DownloadMimeTypeException()).first) assertEquals(NativeDownloadModule.ERROR_CONNECTION_FAILED, downloadErrorFor(NoDataException()).first) assertEquals(NativeDownloadModule.IO_EXCEPTION, downloadErrorFor(FileCorruptionException()).first) - assertEquals(NativeDownloadModule.IO_EXCEPTION, downloadErrorFor(IOException()).first) + assertEquals(NativeDownloadModule.IO_EXCEPTION, downloadErrorFor(DownloadFileException(IOException())).first) + // Any other IOException comes from the network, as on iOS. + assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(IOException()).first) + assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(SocketTimeoutException()).first) assertEquals(NativeDownloadModule.FS_ACCESS_EXCEPTION, downloadErrorFor(SecurityException()).first) assertEquals(NativeDownloadModule.ERROR_DOWNLOAD_FAILED, downloadErrorFor(IllegalArgumentException()).first) } From 375584cbb762eb8a2fef281e4f2d4264f8e90ed7 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Sat, 3 Oct 2026 03:15:00 +0530 Subject: [PATCH 06/10] feat: reorder build steps in CI workflows for Android and iOS to run unit tests --- .github/workflows/android.yml | 13 +++++++------ .github/workflows/ios.yml | 17 +++++++++-------- example/rn-harness.config.mjs | 4 ++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 5eee694..c53de97 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -83,12 +83,8 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - # Build APK (only if not cached) - - name: Build APK with Gradle - working-directory: example - run: yarn app:package:android - - # JVM unit tests (JUnit, Robolectric, MockWebServer) in android/src/test + # JVM unit tests (JUnit, Robolectric, MockWebServer) in android/src/test. + # They need no emulator or app, so run them before the APK build to fail early. - name: Run native unit tests working-directory: example/android run: ./gradlew :mendix-native:testDebugUnitTest @@ -100,6 +96,11 @@ jobs: name: android-unit-test-reports path: android/build/reports/tests/testDebugUnitTest + # Build APK (only if not cached) + - name: Build APK with Gradle + working-directory: example + run: yarn app:package:android + - name: AVD cache uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.2.0 id: avd-cache diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index b9283fe..a5d6eab 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -47,13 +47,7 @@ jobs: working-directory: example run: yarn pod - # Build iOS app (only if not cached) - - name: Build iOS app for simulator - if: steps.cache-ios-app.outputs.cache-hit != 'true' - working-directory: example - run: yarn app:package:ios - - # Setup simulator (after build) + # Setup simulator - name: Launch iOS Simulator run: | # Install jq if not available @@ -70,7 +64,8 @@ jobs: bash .github/scripts/launch-ios-simulator.sh "${{ env.DEVICE_MODEL }}" "${{ env.IOS_VERSION }}" # XCTest unit tests in ios/Tests, installed by the MendixNative test spec in the Podfile. - # Shares the app build's derived data so the pods aren't compiled again. + # They need no app or Metro, so run them before the app build to fail early. + # The app build shares this derived data, so the pods aren't compiled again. - name: Run native unit tests working-directory: example/ios run: | @@ -88,6 +83,12 @@ jobs: name: ios-unit-test-results path: example/ios/build/unit-tests.xcresult + # Build iOS app (only if not cached) + - name: Build iOS app for simulator + if: steps.cache-ios-app.outputs.cache-hit != 'true' + working-directory: example + run: yarn app:package:ios + # Install app on simulator - name: Install app on simulator working-directory: example diff --git a/example/rn-harness.config.mjs b/example/rn-harness.config.mjs index 5495e15..3190d96 100644 --- a/example/rn-harness.config.mjs +++ b/example/rn-harness.config.mjs @@ -20,12 +20,12 @@ const config = { runners: [ androidPlatform({ name: 'android', - device: androidEmulator('Pixel_10'), + device: androidEmulator('Pixel_API_35'), bundleId: 'mendixnative.example', }), applePlatform({ name: 'ios', - device: appleSimulator('iPhone 17e', '26.5'), + device: appleSimulator('iPhone 17', '26.2'), bundleId: 'mendixnative.example', }), ], From 92c871b8e818a528a774fdd0550d4bf37b6ea009 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Mon, 5 Oct 2026 17:02:20 +0530 Subject: [PATCH 07/10] feat: update native binary version to 41 in Android and iOS configurations --- .../main/java/com/mendix/mendixnative/react/MxConfiguration.kt | 2 +- ios/Modules/MxConfiguration/MxConfiguration.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/mendix/mendixnative/react/MxConfiguration.kt b/android/src/main/java/com/mendix/mendixnative/react/MxConfiguration.kt index fe25954..f95c3bc 100644 --- a/android/src/main/java/com/mendix/mendixnative/react/MxConfiguration.kt +++ b/android/src/main/java/com/mendix/mendixnative/react/MxConfiguration.kt @@ -45,7 +45,7 @@ class MxConfiguration(val reactContext: ReactApplicationContext) { } companion object { - const val NATIVE_BINARY_VERSION: Int = 40 + const val NATIVE_BINARY_VERSION: Int = 41 const val NAME: String = "MxConfiguration" var defaultDatabaseName: String = "default" diff --git a/ios/Modules/MxConfiguration/MxConfiguration.swift b/ios/Modules/MxConfiguration/MxConfiguration.swift index 6df08e6..1790bfa 100644 --- a/ios/Modules/MxConfiguration/MxConfiguration.swift +++ b/ios/Modules/MxConfiguration/MxConfiguration.swift @@ -3,7 +3,7 @@ import Foundation @objcMembers public class MxConfiguration: NSObject { - public static let nativeBinaryVersion: Int = 40 + public static let nativeBinaryVersion: Int = 41 private static let defaultDatabaseName = "default" private static let defaultFilesDirectoryName = "files/default" From e5451a62844ec40b460ba0cfbf9dc5d11f70f247 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Tue, 6 Oct 2026 14:46:11 +0530 Subject: [PATCH 08/10] chore: update tooling versions --- example/package.json | 8 +- package.json | 2 +- yarn.lock | 1096 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 1092 insertions(+), 14 deletions(-) diff --git a/example/package.json b/example/package.json index 67ffd01..521bd60 100644 --- a/example/package.json +++ b/example/package.json @@ -29,9 +29,9 @@ "react-native-gesture-handler": "2.33.0" }, "devDependencies": { - "@babel/core": "7.29.0", - "@babel/preset-env": "7.29.0", - "@babel/runtime": "^7.28.6", + "@babel/core": "7.29.7", + "@babel/preset-env": "7.29.7", + "@babel/runtime": "^7.28.4", "@react-native-community/cli": "20.2.0", "@react-native-community/cli-platform-android": "20.2.0", "@react-native-community/cli-platform-ios": "20.2.0", @@ -41,7 +41,7 @@ "@react-native/babel-preset": "0.88.0-rc.3", "@react-native/metro-config": "0.88.0-rc.3", "@react-native/typescript-config": "0.88.0-rc.3", - "@types/react": "19.2.14", + "@types/react": "19.3.0", "react-native-builder-bob": "0.40.18", "react-native-harness": "1.1.0", "react-native-monorepo-config": "0.3.3" diff --git a/package.json b/package.json index 6ca98f9..552e4b0 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "@react-native/jest-preset": "0.88.0-rc.3", "@release-it/conventional-changelog": "10.0.5", "@types/jest": "29.5.14", - "@types/react": "19.2.14", + "@types/react": "19.3.0", "commitlint": "20.4.3", "del-cli": "7.0.0", "eslint": "9.39.4", diff --git a/yarn.lock b/yarn.lock index 4c4668b..caae0aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,6 +32,17 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/code-frame@npm:7.29.7" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.29.7" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10/84da552e51a55795a50b3589116edb2f9e368a647d266380683775f18effd9acd4521b0246bebd0b049a7f32af1f87b1e8475d3bcb665f876bd04ade8da99697 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.28.6, @babel/compat-data@npm:^7.29.0": version: 7.29.0 resolution: "@babel/compat-data@npm:7.29.0" @@ -39,7 +50,37 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.29.0, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.25.2": +"@babel/compat-data@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/compat-data@npm:7.29.7" + checksum: 10/ad2272714087f68970977f6e2b53597a8503fc9c3028c4a91686474bd77a707dd00903cdde4b73788972016d1bad4dc3fa4e5ff38e1ed8f1c3bde1095352973a + languageName: node + linkType: hard + +"@babel/core@npm:7.29.7": + version: 7.29.7 + resolution: "@babel/core@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/generator": "npm:^7.29.7" + "@babel/helper-compilation-targets": "npm:^7.29.7" + "@babel/helper-module-transforms": "npm:^7.29.7" + "@babel/helpers": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/template": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + "@jridgewell/remapping": "npm:^2.3.5" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10/38e71cf81db790b0bb2a3a0c8140c2b1c87576b61dc6be676de4fab8c3be871af590a739e8c489fe8e8f9a8e5899fa11e35e59e9e09d40b259c6a675f2f98928 + languageName: node + linkType: hard + +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.25.2": version: 7.29.0 resolution: "@babel/core@npm:7.29.0" dependencies: @@ -89,6 +130,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.29.7, @babel/generator@npm:^7.29.8": + version: 7.29.8 + resolution: "@babel/generator@npm:7.29.8" + dependencies: + "@babel/parser": "npm:^7.29.8" + "@babel/types": "npm:^7.29.8" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10/679c3d1302936f391260acee4059e0c3cd5bff6341772f0b85bb142feab1a253d0e155aad0e9c8531e024d6239a2cc5169d1e294c6890901e7d4ab0f7c9eaaaa + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.27.1, @babel/helper-annotate-as-pure@npm:^7.27.3": version: 7.27.3 resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" @@ -98,6 +152,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-annotate-as-pure@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.29.7" + dependencies: + "@babel/types": "npm:^7.29.7" + checksum: 10/acd9e128de634a5144b5d622357d018fa616de45f64c74e42007c048dd15d0a0be213f4d5a2bf02307bdaddf053791b87900a99d183de828c08dc3b556329009 + languageName: node + linkType: hard + "@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-compilation-targets@npm:7.28.6" @@ -111,6 +174,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-compilation-targets@npm:7.29.7" + dependencies: + "@babel/compat-data": "npm:^7.29.7" + "@babel/helper-validator-option": "npm:^7.29.7" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10/af9ed4299ad5cfbe48432a964f37cbbfc200bbeb0f8ba9cbc86448503fa929382d5161d32096274752230c9feb919c9ef595559498833da656fc6a8e24a62383 + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-create-class-features-plugin@npm:7.28.6" @@ -128,6 +204,23 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.29.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.29.7" + "@babel/helper-member-expression-to-functions": "npm:^7.29.7" + "@babel/helper-optimise-call-expression": "npm:^7.29.7" + "@babel/helper-replace-supers": "npm:^7.29.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/74f871e5389beca9fb52670f2bd83abdd6dc7b7a10f34679ffab5eabf91077dccaabf55438b9f3c897258fb81fbb80bfbf469b836a404abb7e64b4d7c141a8da + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.27.1, @babel/helper-create-regexp-features-plugin@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.28.5" @@ -141,6 +234,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-regexp-features-plugin@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.29.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.29.7" + regexpu-core: "npm:^6.3.1" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/bf79ffc671d824d00b43a018555cb9fb3f2bc8be8d8ed8c901131e4cd072cc83e610a2cbb580f5f84b60d70bf4c7a7a8c5a629b7b325e1a27dca86d96d2668e0 + languageName: node + linkType: hard + "@babel/helper-define-polyfill-provider@npm:^0.6.5, @babel/helper-define-polyfill-provider@npm:^0.6.6": version: 0.6.6 resolution: "@babel/helper-define-polyfill-provider@npm:0.6.6" @@ -163,6 +269,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-globals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-globals@npm:7.29.7" + checksum: 10/e53203e87ae24a45f59639edea0c429bc3c63c6d74f1862fe60a35032d89478e7511d2f34855da0fcb65782668d72e59e93d1de5bc00121ba9bc1aa38f1f0ad3 + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" @@ -173,6 +286,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-member-expression-to-functions@npm:7.29.7" + dependencies: + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10/bb8dc59a65b4404260e0b7ff70f491de5a1607876f61736d26605ab3cba5b368827b0551acd3458212f5cfa99cbcd48bb66a96497b0fe00af09a6a2cbea4276b + languageName: node + linkType: hard + "@babel/helper-module-imports@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-imports@npm:7.28.6" @@ -183,6 +306,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-imports@npm:7.29.7" + dependencies: + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10/28ec6f7efd99588d6eebfb25c9f1ccc34cb0cdb0839c4c0f08b3ec0105ccaefbe7e8b4f651f3f55a4f5c4fcb1d979bd32a9b8ee23e3e62163ea22aaa7ee0dfa1 + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-transforms@npm:7.28.6" @@ -196,6 +329,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-transforms@npm:7.29.7" + dependencies: + "@babel/helper-module-imports": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/33251b1fb44d726194a974a0078b1269511d130a2609357ff829b479e9e4dca96ecd5384c534a477095f665ffb01503d3e680699c2002e5b62e6ca1a272f1892 + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-optimise-call-expression@npm:7.27.1" @@ -205,6 +351,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-optimise-call-expression@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.29.7" + dependencies: + "@babel/types": "npm:^7.29.7" + checksum: 10/6b477e01b403fd48349336cb1d94722bff4fa54af2841b5fa950c557b796f4ecc14724052252ed1362ccfc23d1c09c54dc03e182fea59d3dc5bd69f8c626ba25 + languageName: node + linkType: hard + "@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.27.1, @babel/helper-plugin-utils@npm:^7.28.6, @babel/helper-plugin-utils@npm:^7.8.0": version: 7.28.6 resolution: "@babel/helper-plugin-utils@npm:7.28.6" @@ -212,6 +367,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-plugin-utils@npm:7.29.7" + checksum: 10/6d16929fe5c792bbc8e4d67e18d7c1be69d2f18992deaa3d94dc26541fec662e83cbeeaf7553c6867d068eb7aed4e0d5e3e137c1dd4d5bcfa286f8d772f1f457 + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-remap-async-to-generator@npm:7.27.1" @@ -225,6 +387,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-remap-async-to-generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-remap-async-to-generator@npm:7.29.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.29.7" + "@babel/helper-wrap-function": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/98338ad6e34ebb4be2dc23f8d9199d28d6d8ac6a2ce8b90fe9efdf3595b39748321528d9f2540ec0586a6e45f7c84f5f623fbf980c5efa7fa9ba7ce837ea4b20 + languageName: node + linkType: hard + "@babel/helper-replace-supers@npm:^7.27.1, @babel/helper-replace-supers@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-replace-supers@npm:7.28.6" @@ -238,6 +413,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-replace-supers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-replace-supers@npm:7.29.7" + dependencies: + "@babel/helper-member-expression-to-functions": "npm:^7.29.7" + "@babel/helper-optimise-call-expression": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/4aa7b48a6078db99bba24b67f63f97cd08ad9b3c476dcca196c6421dc2080f3566d683fba64c772e2f9597603d42ad4ac2ce9ccf0559643823c540f08cf0efa7 + languageName: node + linkType: hard + "@babel/helper-skip-transparent-expression-wrappers@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.27.1" @@ -248,6 +436,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.29.7" + dependencies: + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10/a5800bfcdca6cef7f6fe33ac02a0f05ff33da9746f97806553f249733f7ba8400290a17f3831d7faa5d91656f254ab749931f53c8a29f301d958d7dd00499637 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-string-parser@npm:7.27.1" @@ -255,6 +453,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-string-parser@npm:7.29.7" + checksum: 10/4d8ef0ef7105f3d9fe4361137c8f42e5b4c7a52b5380b962762f2a528a1ba89064e2c6236090716ce34b63707b886ae0ebf36b2c2fcc2851f27e652febfc3648 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-validator-identifier@npm:7.28.5" @@ -262,6 +467,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-identifier@npm:7.29.7" + checksum: 10/2efa42701eb05babf26dff3332109c9e5e1a3400a71fb9e68ee27af28235036a2a72c2494c04bdab3f909075f42a58b2e8271074372bc7f8e79ec02bd364d7a7 + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-validator-option@npm:7.27.1" @@ -269,6 +481,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-option@npm:7.29.7" + checksum: 10/aeb6aa966f59300d3cc2fea7c68e1dfd7ad011fc10e535c8e2b2de3094b27c859428dc7220f16420350f8b1cde99da120b673be04bcb0c2f37b56258c96bed58 + languageName: node + linkType: hard + "@babel/helper-wrap-function@npm:^7.27.1": version: 7.28.6 resolution: "@babel/helper-wrap-function@npm:7.28.6" @@ -280,6 +499,17 @@ __metadata: languageName: node linkType: hard +"@babel/helper-wrap-function@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-wrap-function@npm:7.29.7" + dependencies: + "@babel/template": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10/fc37b53a93c0814e5443c344fcd42b343c75856d865547ca0d50ddad73e96c27f6a677330d115232644e143066758188e4eb47ce5207124c095312b9e49599ed + languageName: node + linkType: hard + "@babel/helpers@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helpers@npm:7.28.6" @@ -290,6 +520,16 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helpers@npm:7.29.7" + dependencies: + "@babel/template": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10/b4d1ef12c19e896585c009ba29677839097ff04f8b11a2430d335c3fb6bd667b4f9e96a3b185a083fdde6b1137eabbbf2600c32425cb69cefc81d81d5cfe425d + languageName: node + linkType: hard + "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.4, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.0 resolution: "@babel/parser@npm:7.29.0" @@ -301,6 +541,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.29.7, @babel/parser@npm:^7.29.8": + version: 7.29.9 + resolution: "@babel/parser@npm:7.29.9" + dependencies: + "@babel/types": "npm:^7.29.8" + bin: + parser: ./bin/babel-parser.js + checksum: 10/b8d6acda3fc7405c497b839b0b6d46cbd309d81bdb310c349e5760ecd689c3641925e1184574106161ce2c78cf5c09d22544a0b3e4d5f002e3b78c263c6f11e6 + languageName: node + linkType: hard + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": version: 7.28.5 resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" @@ -313,6 +564,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/c0e85e9b4bf8706f23b58c1794ad398e41b69a639416578fd4c0ef5a5472365a8d1d7a533f94137daf3660e4f710a8b7e10bc8a53a91a41773ec92bf1725af98 + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.27.1" @@ -324,6 +587,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/ad06de66ccfb19f0f04e6124d144f3fef72fa5191861b1d04bc32cab87ce43958810d9632eac5881ef991a78b33e68588e3d90e76a63d917bd5a7ff4c96618f8 + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.27.1" @@ -335,6 +609,29 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/2189a2a648948107c59ad3bf028e5b71a85b28c840facfead769a33c5f63ae4ec0f147e6a2e664a91a506d4405f5a8972d2ca628f3b64d03edd7620d770761fb + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/a9bd13c2600bdfcb5b35590e210bcb30f009fda9bd1556567757ea4fcb8ca247750331d6d10774d68127cae4e529bc79abd86a28fe5e2a1cc2cc00e75964ac52 + languageName: node + linkType: hard + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.27.1" @@ -348,6 +645,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.29.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.13.0 + checksum: 10/76a494ec4f52a127b0208c4574a6da36f6ff5f30484306921762db549fa7d9d9183c837759eb68c0c9e5a56013aa247e6e02e02263384d2a103240353ae0ceb6 + languageName: node + linkType: hard + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.28.6" @@ -360,6 +670,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/73125174671241b3eb1fa7c7f53ed0894d3853f2afb280684492a707cf3e4a9c498537acb511c014d364018117e181bb265dbbb975ea0b1a61a6de60bae8f07e + languageName: node + linkType: hard + "@babel/plugin-proposal-export-default-from@npm:^7.24.7": version: 7.27.1 resolution: "@babel/plugin-proposal-export-default-from@npm:7.27.1" @@ -468,6 +790,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-import-assertions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/a7f24858e7e833c2ee25779a355b5eff46e4bc93c98b06bda7ea0fd12faf99c4954e0f71074485512045920432790e0269aa562dd4d2085c3f8660ed1cfde8a1 + languageName: node + linkType: hard + "@babel/plugin-syntax-import-attributes@npm:^7.24.7, @babel/plugin-syntax-import-attributes@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" @@ -479,6 +812,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-import-attributes@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/9f47345d09aae16b7ab52ecaf541cde3e3ae1e57e3eb2d4088e062b29dfbd67db55d42d529840557583d66121e2a98788df7a455401cc6d635c8b7700a02efc9 + languageName: node + linkType: hard + "@babel/plugin-syntax-import-meta@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" @@ -634,6 +978,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-arrow-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/0037fd7563c7c91cddb8ce104e270bc260190d29c7a297df65e4306471010b4343366de13fab4602cf8ee6c672d3b313b34a01b62f27a333cad16908c83368d8 + languageName: node + linkType: hard + "@babel/plugin-transform-async-generator-functions@npm:^7.25.4, @babel/plugin-transform-async-generator-functions@npm:^7.29.0": version: 7.29.0 resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.0" @@ -647,6 +1002,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-async-generator-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-remap-async-to-generator": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/0abb8d8bb21e7293b3eda5a743051678478ab7c0392310a4a9e0417125a2bb8536a0a5f41a8062211d995479339afa7ffab6b0141f0839af8fbba367dd6a99c5 + languageName: node + linkType: hard + "@babel/plugin-transform-async-to-generator@npm:^7.24.7, @babel/plugin-transform-async-to-generator@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-async-to-generator@npm:7.28.6" @@ -660,6 +1028,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-async-to-generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.29.7" + dependencies: + "@babel/helper-module-imports": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-remap-async-to-generator": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/e24db9c4c69121daab25883f9a96e6849fa664c78c6bbcfb77fe0a0c6ab29b81ba39e8497985367463d3a88deac3b5bbe15dd1c5d0e5dd492cfccf8efdd27452 + languageName: node + linkType: hard + "@babel/plugin-transform-block-scoped-functions@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.27.1" @@ -671,6 +1052,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-block-scoped-functions@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/24f9712ade98061cd22088709b86b8e3e19ea416dbe5a69ad504fc3f8f2179af5bdeb32fcb9c24fc861bef515e41ae5ef72cd909e0e42bb0cf15838c4e737149 + languageName: node + linkType: hard + "@babel/plugin-transform-block-scoping@npm:^7.25.0, @babel/plugin-transform-block-scoping@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-block-scoping@npm:7.28.6" @@ -682,6 +1074,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-block-scoping@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-block-scoping@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/9c3cbbdda288b2eff7355ab94fc7b4b18f408d8e7145c2d6bd34e70eef03f200c699f527318ac11d9cd6e99124b5e8d6aeeba4421346ee5cdc224d06175d984f + languageName: node + linkType: hard + "@babel/plugin-transform-class-properties@npm:^7.25.4, @babel/plugin-transform-class-properties@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-class-properties@npm:7.28.6" @@ -694,6 +1097,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-class-properties@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-class-properties@npm:7.29.7" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/0cc5e7a882e29eead360f02ef79f6b2ec3b3813213b1513d8fdaa931d1d1361fccc92fbacc9b399e42495953d9d6fc722f283b5f3aa272fe016a0b5fe1e6a130 + languageName: node + linkType: hard + "@babel/plugin-transform-class-static-block@npm:^7.27.1, @babel/plugin-transform-class-static-block@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-class-static-block@npm:7.28.6" @@ -706,6 +1121,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-class-static-block@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-class-static-block@npm:7.29.7" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.12.0 + checksum: 10/9e7112dafb0e7791de3858cb721a76147e8cfc9b6ba370dd0267bdc193abdbe8a8f78db8d70e0f860d03497d861f0ac7e8cd3e8caf2639c59b57fc74eb3b95d0 + languageName: node + linkType: hard + "@babel/plugin-transform-classes@npm:^7.25.4, @babel/plugin-transform-classes@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-classes@npm:7.28.6" @@ -722,6 +1149,22 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-classes@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-classes@npm:7.29.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.29.7" + "@babel/helper-compilation-targets": "npm:^7.29.7" + "@babel/helper-globals": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-replace-supers": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/ac6387c6bfb9d9b9f9d0702050fa8833e76c123d607bdba1af8d991f691e01a0652130954baa53051f0e16b8a0545e3f3c5a5bc4404a19abac0af2eee748f898 + languageName: node + linkType: hard + "@babel/plugin-transform-computed-properties@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-computed-properties@npm:7.28.6" @@ -734,6 +1177,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-computed-properties@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/template": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/c982355904fc113334ba108282c8a617e3159c6960de717bbe7c5fa86ff777baea04c117edc692fb4de22b01460bfedc62af3c6a9d0ecd81511f5eb8357d8bab + languageName: node + linkType: hard + "@babel/plugin-transform-destructuring@npm:^7.24.8, @babel/plugin-transform-destructuring@npm:^7.28.5": version: 7.28.5 resolution: "@babel/plugin-transform-destructuring@npm:7.28.5" @@ -746,6 +1201,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-destructuring@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-destructuring@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/e53caad0c2d523367724aefcc6b8c8df24fcb1a3f53e9899cb4bb5dc39ccf61e30df0a761d74485a895d9bcaaad49644879cbd3a9fc20c90501a5e831caaac5b + languageName: node + linkType: hard + "@babel/plugin-transform-dotall-regex@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-dotall-regex@npm:7.28.6" @@ -758,6 +1225,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-dotall-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/537df0fb915a420df715a2f4da16ab6c08ce2370521edef9a8a59af23a533314109f6abd836c5e127c8cea4a46bc4a05692670cf7ad64868c286075fa2d7848c + languageName: node + linkType: hard + "@babel/plugin-transform-duplicate-keys@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-duplicate-keys@npm:7.27.1" @@ -769,6 +1248,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-duplicate-keys@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/f0e7ad459dd9c78514c07a576fa509478aa9c7e90c1d7cf3b1d142579f8dadd609878c10b044dd2a3a2b08adbdb51b108fcb261d9a78443e13494a7985f9c2a7 + languageName: node + linkType: hard + "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.29.0": version: 7.29.0 resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.0" @@ -781,6 +1271,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/fa7fcdbede10dbc06fe4f861e90286f7f599d3f3c43e69445e63c3f48422fd34db0b0dd9bbebccd1dbd04a50fca4ab22fd82d28e7bc8fe9b6d5790c9e694d380 + languageName: node + linkType: hard + "@babel/plugin-transform-dynamic-import@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-dynamic-import@npm:7.27.1" @@ -792,6 +1294,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-dynamic-import@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/58c035e6b9103c225f3d181671d9b3dec140351c3ecf12bc3a66b8653be41161f20135ada00a703244c2bfc9dd57b62fc54f77f2f6fe43df6c598358f377e6fa + languageName: node + linkType: hard + "@babel/plugin-transform-explicit-resource-management@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.28.6" @@ -804,6 +1317,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-explicit-resource-management@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/plugin-transform-destructuring": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/a4ea28a18161a7e8c8f33731cb3dfc6981cb089b9a6b57abfa7ff7579a0ca76a4c19c29ebaf775b037ff31503c74c6cf3687ce86cdaa246d1c60afb5abd820df + languageName: node + linkType: hard + "@babel/plugin-transform-exponentiation-operator@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.28.6" @@ -815,6 +1340,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-exponentiation-operator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/bf0366d77d318d4b6eae6880217e3fdfcb6e5f7913f658583de9537fd4fca1f05f9ac4083d8f946a84eaefec068cbba948be90f4a39484c85bc69082def3162d + languageName: node + linkType: hard + "@babel/plugin-transform-export-namespace-from@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-export-namespace-from@npm:7.27.1" @@ -826,6 +1362,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-export-namespace-from@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/d157d62b144d1626b801e557dcede914db33e78f3f4230f487e5709c21efd40648f7f3a47a44a7fce694ad9cd117d2ac3ed796da0102275fd02b4fdb317d906b + languageName: node + linkType: hard + "@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.26.5": version: 7.27.1 resolution: "@babel/plugin-transform-flow-strip-types@npm:7.27.1" @@ -850,6 +1397,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-for-of@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-for-of@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/af79d2859f7330c4b47fefc49a7849fb651ef062532beafdba5500fc13a46b9dfe1a853a27b73257a092d7e65a7b9956a8df9971c9908825d2f3b86b00c35c38 + languageName: node + linkType: hard + "@babel/plugin-transform-function-name@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-function-name@npm:7.27.1" @@ -863,6 +1422,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-function-name@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-function-name@npm:7.29.7" + dependencies: + "@babel/helper-compilation-targets": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/87a6329442ef8085fbc160e659f64562f0f5b63be65403b8bbb8e18c67dd7d03b82fb2e1371fdde734e2f05b13a72f88ed8d8cb03807150063954b9604d082cf + languageName: node + linkType: hard + "@babel/plugin-transform-json-strings@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-json-strings@npm:7.28.6" @@ -874,6 +1446,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-json-strings@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-json-strings@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/3af97e144e0d986522f01803ffa0f90741530d1610952ac6a92511c356ecbf5616092ab1d21401d25bc7cb8ac90d73c2c7ff35e41766df2708c29d7e588cfa7f + languageName: node + linkType: hard + "@babel/plugin-transform-literals@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-literals@npm:7.27.1" @@ -885,6 +1468,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-literals@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/aadb2b3fe85186c274a07d5486aeef9496ce374e534fbc7b54f77985c75513422d9acec4c532f67b027e939644d93a69c00505b8909e259184c3ee5c5c62c46b + languageName: node + linkType: hard + "@babel/plugin-transform-logical-assignment-operators@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.28.6" @@ -896,6 +1490,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-logical-assignment-operators@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/374d83dfbb2de5e339d2966487c0f0d766cd67422addbd0172104ff2788b60317858172a7ab2cb6ee7d5bffad72ce07120fec009a2ef3b35551013fce4908686 + languageName: node + linkType: hard + "@babel/plugin-transform-member-expression-literals@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-member-expression-literals@npm:7.27.1" @@ -907,6 +1512,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-member-expression-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/698cbc9500e8caea1d36b48248112d60e023cea9d0772ac1ecf1639b38b662d9352043747dbe617fe1f6f17709bc17601534f7bf2f22c791fb86f7e2ab43e39f + languageName: node + linkType: hard + "@babel/plugin-transform-modules-amd@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-modules-amd@npm:7.27.1" @@ -919,6 +1535,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-amd@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-amd@npm:7.29.7" + dependencies: + "@babel/helper-module-transforms": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/a25cfc84db14a943cee1717030114e052152487af8784c015762a4fc11ee7b45127036c074044636b10c7251eb310c172904028a6f36abcae816e0cc685553b8 + languageName: node + linkType: hard + "@babel/plugin-transform-modules-commonjs@npm:^7.24.8, @babel/plugin-transform-modules-commonjs@npm:^7.27.1, @babel/plugin-transform-modules-commonjs@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.28.6" @@ -931,6 +1559,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-commonjs@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.29.7" + dependencies: + "@babel/helper-module-transforms": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/7d816febde2d65bde5607ef355d751ba6c5a2d68ffe47c37b809e3ed2f829603751d4b5a5506f4299936d95fc73909243f9074f98dd32201277ec4131fc3ff33 + languageName: node + linkType: hard + "@babel/plugin-transform-modules-systemjs@npm:^7.29.0": version: 7.29.0 resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.0" @@ -945,6 +1585,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-systemjs@npm:^7.29.7": + version: 7.29.8 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.8" + dependencies: + "@babel/helper-module-transforms": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.8" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/926dcc428282f4a29e4b650e8f25131891f675cd9c9430587828f9453f9847077ae7d87d71abacfbb1ec5a9c7f97835f57bd84b834134541184c185b21e0e96e + languageName: node + linkType: hard + "@babel/plugin-transform-modules-umd@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" @@ -957,6 +1611,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-umd@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-modules-umd@npm:7.29.7" + dependencies: + "@babel/helper-module-transforms": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/74024ae1ecb702a766af6b3131a44be8b50d3614860ba857f8bb1e29c38acbecb14f66e2847082ccc5e188547aaa9678d9bbd67c20cef6f2e597f977a81f34dd + languageName: node + linkType: hard + "@babel/plugin-transform-named-capturing-groups-regex@npm:^7.24.7, @babel/plugin-transform-named-capturing-groups-regex@npm:^7.29.0": version: 7.29.0 resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.0" @@ -969,6 +1635,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/3a481be133e9ca5d25570b5ed62daae323a51663bacf30fed0d1980e912047ebd34d6326533182db625fc0bbd086d1a23ed68ebb6108e7a68a8650c228afc084 + languageName: node + linkType: hard + "@babel/plugin-transform-new-target@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-new-target@npm:7.27.1" @@ -980,6 +1658,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-new-target@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-new-target@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/6ef505da7107e46afe170a7c3dc69a2afb2a58276c172189cbba86ed669e64bf2884a16deb007257af399fcc3c2381c688b8bbed612c986ded82ac9fa43ab5b1 + languageName: node + linkType: hard + "@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.7, @babel/plugin-transform-nullish-coalescing-operator@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.28.6" @@ -991,6 +1680,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/4bff79355c240342e18e02cee282ce5c30bafa4335a250f4a47e822fde6def70afa19708e04fec3cc942252da16ea3a28a21279180cc92734c2a2d9826600bb3 + languageName: node + linkType: hard + "@babel/plugin-transform-numeric-separator@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-numeric-separator@npm:7.28.6" @@ -1002,6 +1702,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-numeric-separator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/6177df9e1a8a190bf4a360f8cbcfa614b70ededba61201bd0a38929770b6d00a8a54a19f8fda82cf60688d9bab938427a9fe5dae0a9e8cd8ed79c88a3b2dbcd7 + languageName: node + linkType: hard + "@babel/plugin-transform-object-rest-spread@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.6" @@ -1017,6 +1728,21 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-object-rest-spread@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.29.7" + dependencies: + "@babel/helper-compilation-targets": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/plugin-transform-destructuring": "npm:^7.29.7" + "@babel/plugin-transform-parameters": "npm:^7.29.7" + "@babel/traverse": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/36b906179d21a2a3287fac5283b25584bd7b79eb2707c62fa8e75ab79b21b4e11b2670e6b2eafb99fb448495153587dc5cdeec1d8433ba175060e5c8101292b0 + languageName: node + linkType: hard + "@babel/plugin-transform-object-super@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-object-super@npm:7.27.1" @@ -1029,6 +1755,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-object-super@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-object-super@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-replace-supers": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/65ed8719563572c4917f19b32c476c9a9062fccf89bfd44a418bb734cd866034d66049499cace58e2bb4589da779983f534078bd989333f36268b9da08d4b33c + languageName: node + linkType: hard + "@babel/plugin-transform-optional-catch-binding@npm:^7.24.7, @babel/plugin-transform-optional-catch-binding@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.28.6" @@ -1040,6 +1778,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-catch-binding@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/4b6e41e1dc5dbd02cfe0b96214130cca5fd3bd879551fc82188bb3d9a2782af9bab50f2140af9ff946a8ee23b9478ee42810641fb99aa3e033884d7c6103d138 + languageName: node + linkType: hard + "@babel/plugin-transform-optional-chaining@npm:^7.24.8, @babel/plugin-transform-optional-chaining@npm:^7.27.1, @babel/plugin-transform-optional-chaining@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.6" @@ -1052,6 +1801,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/2fd8f0135d8b051e4873ba097443bd753abd12a32f910fd19ae4c2f94a183129cf0936aed7aa14b417a68752aa1eec7a9fe43befdab736dbb24bbf192b7e5edc + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.27.7": version: 7.27.7 resolution: "@babel/plugin-transform-parameters@npm:7.27.7" @@ -1063,6 +1824,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-parameters@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-parameters@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/05faa7bbe1ae81eda6ab9bfca35476d7e55049b1ad182471a6e5a45a888ef1208977a0cbe0ee23b6920d4754d2386cd94026d705e32acff7a036b9db4110b566 + languageName: node + linkType: hard + "@babel/plugin-transform-private-methods@npm:^7.24.7, @babel/plugin-transform-private-methods@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-private-methods@npm:7.28.6" @@ -1075,6 +1847,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-private-methods@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-private-methods@npm:7.29.7" + dependencies: + "@babel/helper-create-class-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/5055af2b86a95acbf6bd1a14256edf439ba4f214707f6aa9f6a29d1168c882e5709853c4ff225f55575f88d3a58effbed952d25c5cd70f93785106541f992cdd + languageName: node + linkType: hard + "@babel/plugin-transform-private-property-in-object@npm:^7.24.7, @babel/plugin-transform-private-property-in-object@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-private-property-in-object@npm:7.28.6" @@ -1088,6 +1872,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-private-property-in-object@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.29.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.29.7" + "@babel/helper-create-class-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/72464fe21457daa2002b8fb8ab222dfc4a5fa4df33b99a371ca5594a28c933491d4373349cbff95caff33d8b5506d0350b1b7b0f4fde04ebd1defcdd5d7d9751 + languageName: node + linkType: hard + "@babel/plugin-transform-property-literals@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-property-literals@npm:7.27.1" @@ -1099,6 +1896,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-property-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-property-literals@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/7e7a557df8feb50cd6913158c6d12df0e8a9da58e3f73e7cbfc08af399055b03e77a22b12c73d5bf6bb49239617d6189ccb6021ab03f0225bc54f9c74a880b62 + languageName: node + linkType: hard + "@babel/plugin-transform-react-display-name@npm:^7.24.7, @babel/plugin-transform-react-display-name@npm:^7.28.0": version: 7.28.0 resolution: "@babel/plugin-transform-react-display-name@npm:7.28.0" @@ -1181,6 +1989,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-regenerator@npm:^7.29.7": + version: 7.29.8 + resolution: "@babel/plugin-transform-regenerator@npm:7.29.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/4dd85d21b9483ef84aea3292aa618ec468fb75178a45f651e2c9d540201580ed9d0c491a160b45d2c220e0a2d91d7f8284a70a9ae721ac5fc4c0aa68b23235fa + languageName: node + linkType: hard + "@babel/plugin-transform-regexp-modifiers@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.28.6" @@ -1193,6 +2012,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-regexp-modifiers@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/bfbc6b898ace99b8412eb6e902b90856188c692e69672d42d48c5e22a5bf9b0d15d35424fda8501bfb06ba0504acc5f1b9e13eacaba232aa58af74472d6068dc + languageName: node + linkType: hard + "@babel/plugin-transform-reserved-words@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-reserved-words@npm:7.27.1" @@ -1204,6 +2035,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-reserved-words@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-reserved-words@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/ffd7f86ddce36c6ded2dd9218f81be8cbae35b1ed01100ac0a98623bd0a76c059188b70953ab5accae8f8430451e8ed4779d533ac5e35c523f5004a981208b7c + languageName: node + linkType: hard + "@babel/plugin-transform-runtime@npm:^7.24.7": version: 7.29.0 resolution: "@babel/plugin-transform-runtime@npm:7.29.0" @@ -1231,6 +2073,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-shorthand-properties@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/c57ef27853f334a6147da9aa00f8a8f4c3a1c217eb2efa73cba2e118edda10754fa23cec2c0c7f7408279ad28fef92c1f663dfec137a7503813331569c3e02f9 + languageName: node + linkType: hard + "@babel/plugin-transform-spread@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-spread@npm:7.28.6" @@ -1243,6 +2096,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-spread@npm:^7.29.7": + version: 7.29.8 + resolution: "@babel/plugin-transform-spread@npm:7.29.8" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/bcb0d92a87a534ff2ea46bfc9bd3190ca6f18cf7791ca291f7cfa856a9d74d8f4d930e53bd4a44c1d40e513039d133b08082233e9373b51b9e07406bc1d7720f + languageName: node + linkType: hard + "@babel/plugin-transform-sticky-regex@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-sticky-regex@npm:7.27.1" @@ -1254,6 +2119,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-sticky-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/16b570c0270a59c2a29b2118c00e463882e9dda49b51a17dde3ae6b2886995d49f4bf2161a4c743ad1bca39d2aeb3ac963400e095682e105c7f751e6a2156c28 + languageName: node + linkType: hard + "@babel/plugin-transform-strict-mode@npm:^7.24.7": version: 7.27.1 resolution: "@babel/plugin-transform-strict-mode@npm:7.27.1" @@ -1276,6 +2152,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-template-literals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-template-literals@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/d1014dab020f0f802089de17bba82d929eda6ac87fde5f58fb9763885b8d645ce63fc1df97055c06a12d95a8788334a93b559fcaf1da6d7777a191e5f9c5646e + languageName: node + linkType: hard + "@babel/plugin-transform-typeof-symbol@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-typeof-symbol@npm:7.27.1" @@ -1287,6 +2174,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-typeof-symbol@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/a22bbe6c46cc4b5dda7aeb907d0263f3c3f93763c0ea6f5cac3c511673ec0be3fc6d9f3d9e65450b14e231cb4ae1cdead29ca9e6b4a94d30485baeab50513f85 + languageName: node + linkType: hard + "@babel/plugin-transform-typescript@npm:^7.25.2, @babel/plugin-transform-typescript@npm:^7.28.5": version: 7.28.6 resolution: "@babel/plugin-transform-typescript@npm:7.28.6" @@ -1313,6 +2211,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-unicode-escapes@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/69ae159d4c7b5518c8009e96e406c5110c8238412d5f120b382c6f4fa2ff1226c3951d3fdc835461b81b29af78fe9131da51100b8fd47ef7eefe27d7d6d18b29 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-property-regex@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.28.6" @@ -1325,6 +2234,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-unicode-property-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/03ee0b5d27eee08ba71bc09e919eb648094123985b7adc7dc875e4172100596a47ab68337abf6814cbd3140c6552cf1044135eb0ec1ec78345e1270e5e6aabba + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-regex@npm:^7.24.7, @babel/plugin-transform-unicode-regex@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-unicode-regex@npm:7.27.1" @@ -1337,6 +2258,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-unicode-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/1ade0672ae5bbbf2ec1ea0a8de1b5d804ae414283215620097ab21cf7f05dae8916f5b0548a18c6f080ec17135018f5edd2d38f8fa9ca052af570cab5c712786 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-sets-regex@npm:^7.28.6": version: 7.28.6 resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.28.6" @@ -1349,7 +2282,100 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:7.29.0, @babel/preset-env@npm:^7.25.2": +"@babel/plugin-transform-unicode-sets-regex@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.29.7" + dependencies: + "@babel/helper-create-regexp-features-plugin": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10/680c22e2a63bffbf6798b0c2f599b06beb7ea4d29ee37a56c9192014143d396c479b12783d9c343e107fa491aeeb65b1ca774fd76825ffb306eef7fb5e7b4b2c + languageName: node + linkType: hard + +"@babel/preset-env@npm:7.29.7": + version: 7.29.7 + resolution: "@babel/preset-env@npm:7.29.7" + dependencies: + "@babel/compat-data": "npm:^7.29.7" + "@babel/helper-compilation-targets": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/helper-validator-option": "npm:^7.29.7" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.29.7" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.29.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.29.7" + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "npm:^7.29.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.29.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.29.7" + "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions": "npm:^7.29.7" + "@babel/plugin-syntax-import-attributes": "npm:^7.29.7" + "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" + "@babel/plugin-transform-arrow-functions": "npm:^7.29.7" + "@babel/plugin-transform-async-generator-functions": "npm:^7.29.7" + "@babel/plugin-transform-async-to-generator": "npm:^7.29.7" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.29.7" + "@babel/plugin-transform-block-scoping": "npm:^7.29.7" + "@babel/plugin-transform-class-properties": "npm:^7.29.7" + "@babel/plugin-transform-class-static-block": "npm:^7.29.7" + "@babel/plugin-transform-classes": "npm:^7.29.7" + "@babel/plugin-transform-computed-properties": "npm:^7.29.7" + "@babel/plugin-transform-destructuring": "npm:^7.29.7" + "@babel/plugin-transform-dotall-regex": "npm:^7.29.7" + "@babel/plugin-transform-duplicate-keys": "npm:^7.29.7" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.29.7" + "@babel/plugin-transform-dynamic-import": "npm:^7.29.7" + "@babel/plugin-transform-explicit-resource-management": "npm:^7.29.7" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.29.7" + "@babel/plugin-transform-export-namespace-from": "npm:^7.29.7" + "@babel/plugin-transform-for-of": "npm:^7.29.7" + "@babel/plugin-transform-function-name": "npm:^7.29.7" + "@babel/plugin-transform-json-strings": "npm:^7.29.7" + "@babel/plugin-transform-literals": "npm:^7.29.7" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.29.7" + "@babel/plugin-transform-member-expression-literals": "npm:^7.29.7" + "@babel/plugin-transform-modules-amd": "npm:^7.29.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.29.7" + "@babel/plugin-transform-modules-systemjs": "npm:^7.29.7" + "@babel/plugin-transform-modules-umd": "npm:^7.29.7" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.29.7" + "@babel/plugin-transform-new-target": "npm:^7.29.7" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.29.7" + "@babel/plugin-transform-numeric-separator": "npm:^7.29.7" + "@babel/plugin-transform-object-rest-spread": "npm:^7.29.7" + "@babel/plugin-transform-object-super": "npm:^7.29.7" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.29.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.29.7" + "@babel/plugin-transform-parameters": "npm:^7.29.7" + "@babel/plugin-transform-private-methods": "npm:^7.29.7" + "@babel/plugin-transform-private-property-in-object": "npm:^7.29.7" + "@babel/plugin-transform-property-literals": "npm:^7.29.7" + "@babel/plugin-transform-regenerator": "npm:^7.29.7" + "@babel/plugin-transform-regexp-modifiers": "npm:^7.29.7" + "@babel/plugin-transform-reserved-words": "npm:^7.29.7" + "@babel/plugin-transform-shorthand-properties": "npm:^7.29.7" + "@babel/plugin-transform-spread": "npm:^7.29.7" + "@babel/plugin-transform-sticky-regex": "npm:^7.29.7" + "@babel/plugin-transform-template-literals": "npm:^7.29.7" + "@babel/plugin-transform-typeof-symbol": "npm:^7.29.7" + "@babel/plugin-transform-unicode-escapes": "npm:^7.29.7" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.29.7" + "@babel/plugin-transform-unicode-regex": "npm:^7.29.7" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.29.7" + "@babel/preset-modules": "npm:0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2: "npm:^0.4.15" + babel-plugin-polyfill-corejs3: "npm:^0.14.0" + babel-plugin-polyfill-regenerator: "npm:^0.6.6" + core-js-compat: "npm:^3.48.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/08df2b7dc47108cdd66f807bc6390caa20e54cc4780a320cf5a8049c37af49f3c03889e10bc7911a51bfd854360e120b9443fa039b51356a805784215b81b451 + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.25.2": version: 7.29.0 resolution: "@babel/preset-env@npm:7.29.0" dependencies: @@ -1473,13 +2499,20 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.25.0, @babel/runtime@npm:^7.28.6": +"@babel/runtime@npm:^7.25.0": version: 7.28.6 resolution: "@babel/runtime@npm:7.28.6" checksum: 10/fbcd439cb74d4a681958eb064c509829e3f46d8a4bfaaf441baa81bb6733d1e680bccc676c813883d7741bcaada1d0d04b15aa320ef280b5734e2192b50decf9 languageName: node linkType: hard +"@babel/runtime@npm:^7.28.4": + version: 7.29.7 + resolution: "@babel/runtime@npm:7.29.7" + checksum: 10/9883b4951787779fd382b121f22f92966d85f19434841f65fb00b2dfec232107e139683f47c6f252891826ad8ee18317b46c3a0e4819116a9885f47b46d7126a + languageName: node + linkType: hard + "@babel/template@npm:^7.28.6, @babel/template@npm:^7.3.3": version: 7.28.6 resolution: "@babel/template@npm:7.28.6" @@ -1491,6 +2524,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/template@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10/da92f7a5b61e05d2fb3934a44f18cec6006ee3c595116c17a3b44cb9756ecd43205c7360dbfa326fa8f4d00aaeb9e777342a881070d11c2305e9c694bc3ca6ff + languageName: node + linkType: hard + "@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": version: 7.29.0 resolution: "@babel/traverse@npm:7.29.0" @@ -1506,6 +2550,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.29.7, @babel/traverse@npm:^7.29.8": + version: 7.29.8 + resolution: "@babel/traverse@npm:7.29.8" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/generator": "npm:^7.29.8" + "@babel/helper-globals": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.8" + "@babel/template": "npm:^7.29.7" + "@babel/types": "npm:^7.29.8" + debug: "npm:^4.3.1" + checksum: 10/91f0b4799d27b50ffd5c2ab4ba537065221196858e0899275d8474489c57dd0b53150508b2c0d9b308520e5985bde63049a401d32aa1ac4f1e10e466e2a3f447 + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" @@ -1516,6 +2575,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.29.7, @babel/types@npm:^7.29.8": + version: 7.29.8 + resolution: "@babel/types@npm:7.29.8" + dependencies: + "@babel/helper-string-parser": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + checksum: 10/ff2becf0f8b432f0820f286fb9319d7f3819b2d0eb95bc26957fbc6250a3ca0ae3656feb98ecb5f171f9e04b34a4c08f5036447f17459ed7bfc32ff649d9b71e + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -3858,7 +4927,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:19.2.14": +"@types/react@npm:*": version: 19.2.14 resolution: "@types/react@npm:19.2.14" dependencies: @@ -3867,6 +4936,15 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:19.3.0": + version: 19.3.0 + resolution: "@types/react@npm:19.3.0" + dependencies: + csstype: "npm:^3.2.2" + checksum: 10/2f4589222fd9c512e1ef78e65f334ade8777400add8ec0803fcc3a044761679b7984ba8410a890af24255383c3251a568bb692b60acfa22397ba0a64b2e032bf + languageName: node + linkType: hard + "@types/stack-utils@npm:^2.0.0, @types/stack-utils@npm:^2.0.3": version: 2.0.3 resolution: "@types/stack-utils@npm:2.0.3" @@ -9264,9 +10342,9 @@ __metadata: version: 0.0.0-use.local resolution: "mendix-native-example@workspace:example" dependencies: - "@babel/core": "npm:7.29.0" - "@babel/preset-env": "npm:7.29.0" - "@babel/runtime": "npm:^7.28.6" + "@babel/core": "npm:7.29.7" + "@babel/preset-env": "npm:7.29.7" + "@babel/runtime": "npm:^7.28.4" "@op-engineering/op-sqlite": "npm:18.2.5" "@react-native-async-storage/async-storage": "npm:2.2.0" "@react-native-community/cli": "npm:20.2.0" @@ -9278,7 +10356,7 @@ __metadata: "@react-native/babel-preset": "npm:0.88.0-rc.3" "@react-native/metro-config": "npm:0.88.0-rc.3" "@react-native/typescript-config": "npm:0.88.0-rc.3" - "@types/react": "npm:19.2.14" + "@types/react": "npm:19.3.0" react: "npm:19.3.0" react-native: "npm:0.88.0-rc.3" react-native-builder-bob: "npm:0.40.18" @@ -9304,7 +10382,7 @@ __metadata: "@react-native/jest-preset": "npm:0.88.0-rc.3" "@release-it/conventional-changelog": "npm:10.0.5" "@types/jest": "npm:29.5.14" - "@types/react": "npm:19.2.14" + "@types/react": "npm:19.3.0" commitlint: "npm:20.4.3" del-cli: "npm:7.0.0" eslint: "npm:9.39.4" From 8cee8fb7108e94e4bf853e7bb01212af09a4b3a2 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Tue, 6 Oct 2026 15:10:22 +0530 Subject: [PATCH 09/10] chore: address audit issues --- package.json | 28 +- turbo.json | 42 - yarn.lock | 2409 ++++++++------------------------------------------ 3 files changed, 387 insertions(+), 2092 deletions(-) delete mode 100644 turbo.json diff --git a/package.json b/package.json index 552e4b0..93d380a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib", "prepare": "bob build", - "release": "release-it --only-version", "dev:ios": "yarn prepare && (cd example && yarn pod && xed ios && watchman watch-del-all && yarn start)" }, "keywords": [ @@ -62,7 +61,7 @@ "registry": "https://registry.npmjs.org/" }, "devDependencies": { - "@commitlint/config-conventional": "20.4.3", + "@commitlint/config-conventional": "20.5.0", "@eslint/compat": "1.4.1", "@eslint/eslintrc": "3.3.5", "@eslint/js": "9.39.4", @@ -72,10 +71,9 @@ "@react-native/babel-preset": "0.88.0-rc.3", "@react-native/eslint-config": "0.88.0-rc.3", "@react-native/jest-preset": "0.88.0-rc.3", - "@release-it/conventional-changelog": "10.0.5", "@types/jest": "29.5.14", "@types/react": "19.3.0", - "commitlint": "20.4.3", + "commitlint": "20.5.0", "del-cli": "7.0.0", "eslint": "9.39.4", "eslint-config-prettier": "10.1.8", @@ -87,8 +85,6 @@ "react-native": "0.88.0-rc.3", "react-native-builder-bob": "0.40.18", "react-native-gesture-handler": "2.33.0", - "release-it": "19.2.4", - "turbo": "2.8.21", "typescript": "5.9.3" }, "peerDependencies": { @@ -114,25 +110,6 @@ "@commitlint/config-conventional" ] }, - "release-it": { - "git": { - "commitMessage": "chore: release ${version}", - "tagName": "v${version}" - }, - "npm": { - "publish": true - }, - "github": { - "release": true - }, - "plugins": { - "@release-it/conventional-changelog": { - "preset": { - "name": "angular" - } - } - } - }, "prettier": { "quoteProps": "consistent", "singleQuote": true, @@ -173,7 +150,6 @@ "tools": [ "eslint", "lefthook", - "release-it", "jest" ], "version": "0.55.1" diff --git a/turbo.json b/turbo.json deleted file mode 100644 index c4d78c4..0000000 --- a/turbo.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "globalDependencies": [".nvmrc", ".yarnrc.yml"], - "globalEnv": ["NODE_ENV"], - "tasks": { - "build:android": { - "env": ["ANDROID_HOME", "ORG_GRADLE_PROJECT_newArchEnabled"], - "inputs": [ - "package.json", - "android", - "!android/build", - "src/*.ts", - "src/*.tsx", - "example/package.json", - "example/android", - "!example/android/.gradle", - "!example/android/build", - "!example/android/app/build" - ], - "outputs": [] - }, - "build:ios": { - "env": [ - "RCT_NEW_ARCH_ENABLED", - "RCT_USE_RN_DEP", - "RCT_USE_PREBUILT_RNCORE" - ], - "inputs": [ - "package.json", - "*.podspec", - "ios", - "src/*.ts", - "src/*.tsx", - "example/package.json", - "example/ios", - "!example/ios/build", - "!example/ios/Pods" - ], - "outputs": [] - } - } -} diff --git a/yarn.lock b/yarn.lock index caae0aa..13afa7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -57,7 +57,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:7.29.7": +"@babel/core@npm:7.29.7, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.25.2": version: 7.29.7 resolution: "@babel/core@npm:7.29.7" dependencies: @@ -80,29 +80,6 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.23.9, @babel/core@npm:^7.24.4, @babel/core@npm:^7.25.2": - version: 7.29.0 - resolution: "@babel/core@npm:7.29.0" - dependencies: - "@babel/code-frame": "npm:^7.29.0" - "@babel/generator": "npm:^7.29.0" - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-module-transforms": "npm:^7.28.6" - "@babel/helpers": "npm:^7.28.6" - "@babel/parser": "npm:^7.29.0" - "@babel/template": "npm:^7.28.6" - "@babel/traverse": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" - "@jridgewell/remapping": "npm:^2.3.5" - convert-source-map: "npm:^2.0.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.3" - semver: "npm:^6.3.1" - checksum: 10/25f4e91688cdfbaf1365831f4f245b436cdaabe63d59389b75752013b8d61819ee4257101b52fc328b0546159fd7d0e74457ed7cf12c365fea54be4fb0a40229 - languageName: node - linkType: hard - "@babel/eslint-parser@npm:^7.25.1": version: 7.28.6 resolution: "@babel/eslint-parser@npm:7.28.6" @@ -510,16 +487,6 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helpers@npm:7.28.6" - dependencies: - "@babel/template": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10/213485cdfffc4deb81fc1bf2cefed61bc825049322590ef69690e223faa300a2a4d1e7d806c723bb1f1f538226b9b1b6c356ca94eb47fa7c6d9e9f251ee425e6 - languageName: node - linkType: hard - "@babel/helpers@npm:^7.29.7": version: 7.29.7 resolution: "@babel/helpers@npm:7.29.7" @@ -1571,21 +1538,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.0" - dependencies: - "@babel/helper-module-transforms": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-validator-identifier": "npm:^7.28.5" - "@babel/traverse": "npm:^7.29.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10/b3e64728eef02d829510778226da4c06be740fe52e0d45d4aa68b24083096d8ad7df67f2e9e67198b2e85f3237d42bd66f5771f85846f7a746105d05ca2e0cae - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-systemjs@npm:^7.29.7": +"@babel/plugin-transform-modules-systemjs@npm:^7.29.0, @babel/plugin-transform-modules-systemjs@npm:^7.29.7": version: 7.29.8 resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.8" dependencies: @@ -2613,54 +2566,50 @@ __metadata: languageName: node linkType: hard -"@commitlint/cli@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/cli@npm:20.4.3" +"@commitlint/cli@npm:^20.5.0": + version: 20.5.3 + resolution: "@commitlint/cli@npm:20.5.3" dependencies: - "@commitlint/format": "npm:^20.4.3" - "@commitlint/lint": "npm:^20.4.3" - "@commitlint/load": "npm:^20.4.3" - "@commitlint/read": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" + "@commitlint/format": "npm:^20.5.0" + "@commitlint/lint": "npm:^20.5.3" + "@commitlint/load": "npm:^20.5.3" + "@commitlint/read": "npm:^20.5.0" + "@commitlint/types": "npm:^20.5.0" tinyexec: "npm:^1.0.0" yargs: "npm:^17.0.0" bin: commitlint: ./cli.js - checksum: 10/73f63d032441522dfd8ed340e63d6971102def80622d3cf25902020a1c491f0305fdf3067b33f1467e8c39af0e5a223e04afd0b44b0e370f0008858ff87bcee6 + checksum: 10/a849f47638e42c3a5f1e46f924bad76041396d4b43f21ef00242710592e488461b845b5e993cb892482a21b76d2770e7a4ee0deae4758a6cbc3980034bf43d2b languageName: node linkType: hard -"@commitlint/config-conventional@npm:20.4.3": - version: 20.4.3 - resolution: "@commitlint/config-conventional@npm:20.4.3" +"@commitlint/config-conventional@npm:20.5.0": + version: 20.5.0 + resolution: "@commitlint/config-conventional@npm:20.5.0" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^20.5.0" conventional-changelog-conventionalcommits: "npm:^9.2.0" - checksum: 10/9eaaaa08770fa4dc2f4e50ca42f715a4c0b038a715edaeb0f362f7876e3053f4bd9bf57b1b57d3a4863144aad744d0946001950a746b5f6f77171d32853d0b21 + checksum: 10/1088e1cd39dee173999bcda49417533e0c7f649faa1835e0309eddf3b21e9d2238757d7774f17e69572e894ff1c02efd2880a2e2da734c343ec2c68155af12f8 languageName: node linkType: hard -"@commitlint/config-validator@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/config-validator@npm:20.4.3" +"@commitlint/config-validator@npm:^20.5.0": + version: 20.5.0 + resolution: "@commitlint/config-validator@npm:20.5.0" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^20.5.0" ajv: "npm:^8.11.0" - checksum: 10/b7ef0cd817967d0de956d530b04a874592682d353c9e59d33a59133f6a6e76ec53c8e951a2ec78e21ac22c89b5ea6c065f11499653cfa5cd1def464411e201a0 + checksum: 10/6ba9955f01a2aa570a557a3a84fbb5f98a7200b9b07f0eda03f921473aee56c35bd5eab930627ced8d31339d31dd129702165c69739408e3dffe5b0d635ea6b2 languageName: node linkType: hard -"@commitlint/ensure@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/ensure@npm:20.4.3" +"@commitlint/ensure@npm:^20.5.3": + version: 20.5.3 + resolution: "@commitlint/ensure@npm:20.5.3" dependencies: - "@commitlint/types": "npm:^20.4.3" - lodash.camelcase: "npm:^4.3.0" - lodash.kebabcase: "npm:^4.1.1" - lodash.snakecase: "npm:^4.1.1" - lodash.startcase: "npm:^4.4.0" - lodash.upperfirst: "npm:^4.3.1" - checksum: 10/aeeda3a37e404353cf1e73c1719c9a0d06bbe7866b703db17171262cf2634c86c616d7e4031cc5467d173fc85d5f6ffe2a5f51e82f62c3e77c46b3501b2f2d39 + "@commitlint/types": "npm:^20.5.0" + es-toolkit: "npm:^1.46.0" + checksum: 10/fb063bbbabf5e58091bda952f0d04e168aaf704d49e7a325d8f54bcb708b50d8230cd0735248503559e55b2ae827f052c854e78131b518dd2fe3213d7c041834 languageName: node linkType: hard @@ -2671,52 +2620,52 @@ __metadata: languageName: node linkType: hard -"@commitlint/format@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/format@npm:20.4.3" +"@commitlint/format@npm:^20.5.0": + version: 20.5.0 + resolution: "@commitlint/format@npm:20.5.0" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^20.5.0" picocolors: "npm:^1.1.1" - checksum: 10/78fae7e4142f057bdd8f469fa3f9f41c332ae42ade4339f310232e0d32bee76abc5d7bf94d6489d3848a1cdde6211aa9c078b58b5c6d7c62fbde4d3a7e605a0c + checksum: 10/16c462f5d9fe1e65fb0029f4b9d5d0fa389de16783d78be7984f54779ce3f1bb047c7e8c46a475b44f21db2f725eb4656c4599d6843679372ce1745944376696 languageName: node linkType: hard -"@commitlint/is-ignored@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/is-ignored@npm:20.4.3" +"@commitlint/is-ignored@npm:^20.5.0": + version: 20.5.0 + resolution: "@commitlint/is-ignored@npm:20.5.0" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^20.5.0" semver: "npm:^7.6.0" - checksum: 10/bd264605964dfef777cb287b0df7042d8f22ebaa3299acfe6f0aaf46fd505a8f0239bcfe61869755ba05ccace6475875ada8f5fc8695c638d808d4f0a80180b0 + checksum: 10/d3a8308a16ee52d320a4d95c702f2edc450b44279e5459996982bc61c40679c3b89c0a60a838e73bbf38373c5eb9ee8157b88bc54d8c02374083d28b241724dc languageName: node linkType: hard -"@commitlint/lint@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/lint@npm:20.4.3" +"@commitlint/lint@npm:^20.5.3": + version: 20.5.3 + resolution: "@commitlint/lint@npm:20.5.3" dependencies: - "@commitlint/is-ignored": "npm:^20.4.3" - "@commitlint/parse": "npm:^20.4.3" - "@commitlint/rules": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" - checksum: 10/76e443b7dfced7277203aa6b35c344d5a7a4d9219984597a4268cda96374c1ec6bf3f31aee4982074847e67bb3103581b745120eb4855c99a805a71ed49e484b + "@commitlint/is-ignored": "npm:^20.5.0" + "@commitlint/parse": "npm:^20.5.0" + "@commitlint/rules": "npm:^20.5.3" + "@commitlint/types": "npm:^20.5.0" + checksum: 10/3a4e676745d4a6c95dc8e1d59b4f8f07f7b86faa77015d9f378bf544192c4cb5c35c89d59c50836355cbbe0c734b87d2a1cc5d0b2d12720c5958dfc935b1b7bd languageName: node linkType: hard -"@commitlint/load@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/load@npm:20.4.3" +"@commitlint/load@npm:^20.5.3": + version: 20.5.3 + resolution: "@commitlint/load@npm:20.5.3" dependencies: - "@commitlint/config-validator": "npm:^20.4.3" + "@commitlint/config-validator": "npm:^20.5.0" "@commitlint/execute-rule": "npm:^20.0.0" - "@commitlint/resolve-extends": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" + "@commitlint/resolve-extends": "npm:^20.5.3" + "@commitlint/types": "npm:^20.5.0" cosmiconfig: "npm:^9.0.1" cosmiconfig-typescript-loader: "npm:^6.1.0" + es-toolkit: "npm:^1.46.0" is-plain-obj: "npm:^4.1.0" - lodash.mergewith: "npm:^4.6.2" picocolors: "npm:^1.1.1" - checksum: 10/ab1cad2d2f44a1bdd7f434e9201092f79ec1ccebd95905d03c010deb1a59bd2582d4b44ee2135de59fcb407244154a26ee0fe70ac682b21aee60b3a6036641e7 + checksum: 10/c2d65c21f73df9739927ed086afe49285107515a00acb3557628675c29a4196c02c147eadb0a118d95a5726d2c26d8f696ec971e42e2094074ff017314ce6ac9 languageName: node linkType: hard @@ -2727,53 +2676,53 @@ __metadata: languageName: node linkType: hard -"@commitlint/parse@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/parse@npm:20.4.3" +"@commitlint/parse@npm:^20.5.0": + version: 20.5.0 + resolution: "@commitlint/parse@npm:20.5.0" dependencies: - "@commitlint/types": "npm:^20.4.3" + "@commitlint/types": "npm:^20.5.0" conventional-changelog-angular: "npm:^8.2.0" conventional-commits-parser: "npm:^6.3.0" - checksum: 10/96705f08d3f401e6480dd4eac752dd4b26efd0b302140ba659345e9ef3e07871863cd954dd41ac067da27baf47360060a87800cb2287be53ed015184d0bc73c5 + checksum: 10/33b961e2be0d812b365a3916160ea552112754c8a0349e2297721f1861754af715f42311cb6f89f2b3ae832000b7de54b7aa495840bb103f445d3f396d817c02 languageName: node linkType: hard -"@commitlint/read@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/read@npm:20.4.3" +"@commitlint/read@npm:^20.5.0": + version: 20.5.0 + resolution: "@commitlint/read@npm:20.5.0" dependencies: "@commitlint/top-level": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" - git-raw-commits: "npm:^4.0.0" + "@commitlint/types": "npm:^20.5.0" + git-raw-commits: "npm:^5.0.0" minimist: "npm:^1.2.8" tinyexec: "npm:^1.0.0" - checksum: 10/efdeafaac6f425816326786959b3d411ebeeb70ff37649d48d020e7b0bd8f9bed965cbc4e22345e5e62fe37d726ab1b1eb0250be57269987c04dfd18a346cf17 + checksum: 10/8fa1a9923bcb670669dafc01d2283b21eb7e6e5ea653a93b89e8fce70a04cd403af0cb8bc58940ce81b886038f8ef3f6b07c4e0e0597d12fdbc12a5654da1089 languageName: node linkType: hard -"@commitlint/resolve-extends@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/resolve-extends@npm:20.4.3" +"@commitlint/resolve-extends@npm:^20.5.3": + version: 20.5.3 + resolution: "@commitlint/resolve-extends@npm:20.5.3" dependencies: - "@commitlint/config-validator": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" - global-directory: "npm:^4.0.1" + "@commitlint/config-validator": "npm:^20.5.0" + "@commitlint/types": "npm:^20.5.0" + es-toolkit: "npm:^1.46.0" + global-directory: "npm:^5.0.0" import-meta-resolve: "npm:^4.0.0" - lodash.mergewith: "npm:^4.6.2" resolve-from: "npm:^5.0.0" - checksum: 10/1987415a67817cc493bb72fa807e006343e4c8fdc5fa868fd880baf12334bba958464dfdca75765710d512f851064420ca936861a800666821cb18142fc9c444 + checksum: 10/29577b825e058d058b7acf1e6df6fcf729a2ca58ec0e2e375555ccb14d90a804b0f86e8d3c2db4b7594013553817e2c57833190518f5994747990b837132fea1 languageName: node linkType: hard -"@commitlint/rules@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/rules@npm:20.4.3" +"@commitlint/rules@npm:^20.5.3": + version: 20.5.3 + resolution: "@commitlint/rules@npm:20.5.3" dependencies: - "@commitlint/ensure": "npm:^20.4.3" + "@commitlint/ensure": "npm:^20.5.3" "@commitlint/message": "npm:^20.4.3" "@commitlint/to-lines": "npm:^20.0.0" - "@commitlint/types": "npm:^20.4.3" - checksum: 10/746b416edd62564c781cfc6ea8142078c15d35e935769455ddc3daf0634757b8d42a4ed58b2ef9e2f374896b3ba8f4392fd5a97d67eb75f5d6974ae2bf5be590 + "@commitlint/types": "npm:^20.5.0" + checksum: 10/f2f518d096e65a15c03c88851f63907af3b918234dbd5c9da439048476976045becbbdec5e3eda3c646403830f64e31eaca7455f63da21b0160abf5e60924ccb languageName: node linkType: hard @@ -2793,32 +2742,32 @@ __metadata: languageName: node linkType: hard -"@commitlint/types@npm:^20.4.3": - version: 20.4.3 - resolution: "@commitlint/types@npm:20.4.3" +"@commitlint/types@npm:^20.5.0": + version: 20.5.0 + resolution: "@commitlint/types@npm:20.5.0" dependencies: conventional-commits-parser: "npm:^6.3.0" picocolors: "npm:^1.1.1" - checksum: 10/a61640a8e1ca25c2ccaf503f30ab12214e8908b4a9a7dd584b18553f0193cfca0ecc33cb34c1bd0fb95e3e63a2fbd8560678f397f9c37d0331055ba420a0a41d + checksum: 10/4ba62acd297549991fb3d126d2f97039d07ce52d5d96d41347ebebec9ac14223aac78dd23e8ac74d388fa042c7b0bc026c43662978b2a60dfdd11158fd7907ef languageName: node linkType: hard -"@conventional-changelog/git-client@npm:^2.5.1, @conventional-changelog/git-client@npm:^2.6.0": - version: 2.6.0 - resolution: "@conventional-changelog/git-client@npm:2.6.0" +"@conventional-changelog/git-client@npm:^2.6.0": + version: 2.7.0 + resolution: "@conventional-changelog/git-client@npm:2.7.0" dependencies: "@simple-libs/child-process-utils": "npm:^1.0.0" "@simple-libs/stream-utils": "npm:^1.2.0" semver: "npm:^7.5.2" peerDependencies: conventional-commits-filter: ^5.0.0 - conventional-commits-parser: ^6.3.0 + conventional-commits-parser: ^6.4.0 peerDependenciesMeta: conventional-commits-filter: optional: true conventional-commits-parser: optional: true - checksum: 10/20886451e594ecf569351806be05764a24310bd90bdbb428bbef5208f4e6499966dc2014a35b1aa66ff8c4cd08cd5a43e3b35d70b607cda813de0915a85780e9 + checksum: 10/d170ae97ce9771aa77c4ab66127ddbdd154e6b0801b3315d38f3a57bff2d515239140f0cdf0110641f732072493020ef281295209daf68601982b9675c23ba2f languageName: node linkType: hard @@ -2892,7 +2841,7 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:3.3.5, @eslint/eslintrc@npm:^3.3.5": +"@eslint/eslintrc@npm:3.3.5": version: 3.3.5 resolution: "@eslint/eslintrc@npm:3.3.5" dependencies: @@ -2909,6 +2858,23 @@ __metadata: languageName: node linkType: hard +"@eslint/eslintrc@npm:^3.3.5": + version: 3.3.7 + resolution: "@eslint/eslintrc@npm:3.3.7" + dependencies: + ajv: "npm:^6.14.0" + debug: "npm:^4.3.2" + espree: "npm:^10.0.1" + globals: "npm:^14.0.0" + ignore: "npm:^5.2.0" + import-fresh: "npm:^3.2.1" + js-yaml: "npm:^4.3.2" + minimatch: "npm:^3.1.5" + strip-json-comments: "npm:^3.1.1" + checksum: 10/8d778a0f3d1dd3cde8333a5943086bc3497d1adfe804600827dfd76369b83543a9b8884850556be2dd2e5f11838a8c83a32beda43a79aa42f149c75a39de1dbe + languageName: node + linkType: hard + "@eslint/js@npm:9.39.4": version: 9.39.4 resolution: "@eslint/js@npm:9.39.4" @@ -2958,20 +2924,30 @@ __metadata: languageName: node linkType: hard -"@humanfs/core@npm:^0.19.1": - version: 0.19.1 - resolution: "@humanfs/core@npm:0.19.1" - checksum: 10/270d936be483ab5921702623bc74ce394bf12abbf57d9145a69e8a0d1c87eb1c768bd2d93af16c5705041e257e6d9cc7529311f63a1349f3678abc776fc28523 +"@humanfs/core@npm:^0.19.2": + version: 0.19.2 + resolution: "@humanfs/core@npm:0.19.2" + dependencies: + "@humanfs/types": "npm:^0.15.0" + checksum: 10/c6c0273721ec8df3d36a57c390a11a168d0a2f513d78bceb25165bded4fcb73609b1a317edc6c8f331cefd4b47285dde0b1e6679e08ef7f062232ec14fe05312 languageName: node linkType: hard "@humanfs/node@npm:^0.16.6": - version: 0.16.7 - resolution: "@humanfs/node@npm:0.16.7" + version: 0.16.8 + resolution: "@humanfs/node@npm:0.16.8" dependencies: - "@humanfs/core": "npm:^0.19.1" + "@humanfs/core": "npm:^0.19.2" + "@humanfs/types": "npm:^0.15.0" "@humanwhocodes/retry": "npm:^0.4.0" - checksum: 10/b3633d3dce898592cac515ba5e6693c78e6be92863541d3eaf2c009b10f52b2fa62ff6e6e06f240f2447ddbe7b5f1890bc34e9308470675c876eee207553a08d + checksum: 10/ed01b3c066d9cec7526d139b9e71ca00ee4a30b3b5f5f5c198eb069c3509a3e167e180ba7e1e5a83b9571e906c4908bd20402b47586887452311af7354995e95 + languageName: node + linkType: hard + +"@humanfs/types@npm:^0.15.0": + version: 0.15.0 + resolution: "@humanfs/types@npm:0.15.0" + checksum: 10/dea3cc7fd8f8d4d088ed8d0a9921cf12bd8e1cdf40a6133106b03a6e2aebcc9a6f1771b3643b7ec71baae90d08245db34069dfcc861da8d678662741e6c3c986 languageName: node linkType: hard @@ -2989,253 +2965,6 @@ __metadata: languageName: node linkType: hard -"@inquirer/ansi@npm:^1.0.2": - version: 1.0.2 - resolution: "@inquirer/ansi@npm:1.0.2" - checksum: 10/d1496e573a63ee6752bcf3fc93375cdabc55b0d60f0588fe7902282c710b223252ad318ff600ee904e48555634663b53fda517f5b29ce9fbda90bfae18592fbc - languageName: node - linkType: hard - -"@inquirer/checkbox@npm:^4.3.2": - version: 4.3.2 - resolution: "@inquirer/checkbox@npm:4.3.2" - dependencies: - "@inquirer/ansi": "npm:^1.0.2" - "@inquirer/core": "npm:^10.3.2" - "@inquirer/figures": "npm:^1.0.15" - "@inquirer/type": "npm:^3.0.10" - yoctocolors-cjs: "npm:^2.1.3" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/4ac5dd2679981e23f066c51c605cb1c63ccda9ea6e1ad895e675eb26702aaf6cf961bf5ca3acd832efba5edcf9883b6742002c801673d2b35c123a7fa7db7b23 - languageName: node - linkType: hard - -"@inquirer/confirm@npm:^5.1.21": - version: 5.1.21 - resolution: "@inquirer/confirm@npm:5.1.21" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/type": "npm:^3.0.10" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/a107aa0073965ea510affb9e5b55baf40333503d600970c458c07770cd4e0eee01efc4caba66f0409b0fadc9550d127329622efb543cffcabff3ad0e7f865372 - languageName: node - linkType: hard - -"@inquirer/core@npm:^10.3.2": - version: 10.3.2 - resolution: "@inquirer/core@npm:10.3.2" - dependencies: - "@inquirer/ansi": "npm:^1.0.2" - "@inquirer/figures": "npm:^1.0.15" - "@inquirer/type": "npm:^3.0.10" - cli-width: "npm:^4.1.0" - mute-stream: "npm:^2.0.0" - signal-exit: "npm:^4.1.0" - wrap-ansi: "npm:^6.2.0" - yoctocolors-cjs: "npm:^2.1.3" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/eb434bdf0ae7d904367003c772bcd80cbf679f79c087c99a4949fd7288e9a2f713ec3ea63381b9a001f52389ab56a77fcd88d64d81a03b1195193410ce8971c2 - languageName: node - linkType: hard - -"@inquirer/editor@npm:^4.2.23": - version: 4.2.23 - resolution: "@inquirer/editor@npm:4.2.23" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/external-editor": "npm:^1.0.3" - "@inquirer/type": "npm:^3.0.10" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/f91b9aadba6ea28a0f4ea5f075af421e076262aebbd737e1b9779f086fa9d559d064e9942a581544645d1dcf56d6b685e8063fe46677880fbca73f6de4e4e7c5 - languageName: node - linkType: hard - -"@inquirer/expand@npm:^4.0.23": - version: 4.0.23 - resolution: "@inquirer/expand@npm:4.0.23" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/type": "npm:^3.0.10" - yoctocolors-cjs: "npm:^2.1.3" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/73ad1d6376e5efe2a452c33494d6d16ee2670c638ae470a795fdff4acb59a8e032e38e141f87b603b6e96320977519b375dac6471d86d5e3087a9c1db40e3111 - languageName: node - linkType: hard - -"@inquirer/external-editor@npm:^1.0.3": - version: 1.0.3 - resolution: "@inquirer/external-editor@npm:1.0.3" - dependencies: - chardet: "npm:^2.1.1" - iconv-lite: "npm:^0.7.0" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/c95d7237a885b32031715089f92820525731d4d3c2bd7afdb826307dc296cc2b39e7a644b0bb265441963348cca42e7785feb29c3aaf18fd2b63131769bf6587 - languageName: node - linkType: hard - -"@inquirer/figures@npm:^1.0.15": - version: 1.0.15 - resolution: "@inquirer/figures@npm:1.0.15" - checksum: 10/3f858807f361ca29f41ec1076bbece4098cc140d86a06159d42c6e3f6e4d9bec9e10871ccfcbbaa367d6a8462b01dff89f2b1b157d9de6e8726bec85533f525c - languageName: node - linkType: hard - -"@inquirer/input@npm:^4.3.1": - version: 4.3.1 - resolution: "@inquirer/input@npm:4.3.1" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/type": "npm:^3.0.10" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/713aaa4c94263299fbd7adfd65378f788cac1b5047f2b7e1ea349ca669db6c7c91b69ab6e2f6660cdbc28c7f7888c5c77ab4433bd149931597e43976d1ba5f34 - languageName: node - linkType: hard - -"@inquirer/number@npm:^3.0.23": - version: 3.0.23 - resolution: "@inquirer/number@npm:3.0.23" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/type": "npm:^3.0.10" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/50694807b71746e15ed69d100aae3c8014d83c90aa660e8a179fe0db1046f26d727947542f64e24cc8b969a61659cb89fe36208cc2b59c1816382b598e686dd2 - languageName: node - linkType: hard - -"@inquirer/password@npm:^4.0.23": - version: 4.0.23 - resolution: "@inquirer/password@npm:4.0.23" - dependencies: - "@inquirer/ansi": "npm:^1.0.2" - "@inquirer/core": "npm:^10.3.2" - "@inquirer/type": "npm:^3.0.10" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/97364970b01c85946a4a50ad876c53ef0c1857a9144e24fad65e5dfa4b4e5dd42564fbcdfa2b49bb049a25d127efbe0882cb18afcdd47b166ebd01c6c4b5e825 - languageName: node - linkType: hard - -"@inquirer/prompts@npm:^7.10.1": - version: 7.10.1 - resolution: "@inquirer/prompts@npm:7.10.1" - dependencies: - "@inquirer/checkbox": "npm:^4.3.2" - "@inquirer/confirm": "npm:^5.1.21" - "@inquirer/editor": "npm:^4.2.23" - "@inquirer/expand": "npm:^4.0.23" - "@inquirer/input": "npm:^4.3.1" - "@inquirer/number": "npm:^3.0.23" - "@inquirer/password": "npm:^4.0.23" - "@inquirer/rawlist": "npm:^4.1.11" - "@inquirer/search": "npm:^3.2.2" - "@inquirer/select": "npm:^4.4.2" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/b3e3386edd255e4e91c7908050674f8a2e69b043883c00feec2f87d697be37bc6e8cd4a360e7e3233a9825ae7ea044a2ac63d5700926d27f9959013d8566f890 - languageName: node - linkType: hard - -"@inquirer/rawlist@npm:^4.1.11": - version: 4.1.11 - resolution: "@inquirer/rawlist@npm:4.1.11" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/type": "npm:^3.0.10" - yoctocolors-cjs: "npm:^2.1.3" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/0d8f6484cfc20749190e95eecfb2d034bafb3644ec4907b84b1673646f5dd71730e38e35565ea98dfd240d8851e3cff653edafcc4e0af617054b127b407e3229 - languageName: node - linkType: hard - -"@inquirer/search@npm:^3.2.2": - version: 3.2.2 - resolution: "@inquirer/search@npm:3.2.2" - dependencies: - "@inquirer/core": "npm:^10.3.2" - "@inquirer/figures": "npm:^1.0.15" - "@inquirer/type": "npm:^3.0.10" - yoctocolors-cjs: "npm:^2.1.3" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/abaed2df7763633ff4414b58d1c87233b69ed3cd2ac77629f0d54b72b8b585dc4806c7a2a8261daba58af5b0a2147e586d079fdc82060b6bcf56b75d3d03f3a7 - languageName: node - linkType: hard - -"@inquirer/select@npm:^4.4.2": - version: 4.4.2 - resolution: "@inquirer/select@npm:4.4.2" - dependencies: - "@inquirer/ansi": "npm:^1.0.2" - "@inquirer/core": "npm:^10.3.2" - "@inquirer/figures": "npm:^1.0.15" - "@inquirer/type": "npm:^3.0.10" - yoctocolors-cjs: "npm:^2.1.3" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/795ec0ac77d575f20bd6a12fb1c040093e62217ac0c80194829a8d3c3d1e09f70ad738e9a9dd6095cc8358fff4e13882209c09bdf8eb0864a86dcabef5b0a6a6 - languageName: node - linkType: hard - -"@inquirer/type@npm:^3.0.10": - version: 3.0.10 - resolution: "@inquirer/type@npm:3.0.10" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/57d113a9db7abc73326491e29bedc88ef362e53779f9f58a1b61225e0be068ce0c54e33cd65f4a13ca46131676fb72c3ef488463c4c9af0aa89680684c55d74c - languageName: node - linkType: hard - "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -3648,6 +3377,13 @@ __metadata: languageName: node linkType: hard +"@nodable/entities@npm:^3.0.1": + version: 3.1.0 + resolution: "@nodable/entities@npm:3.1.0" + checksum: 10/b07d97b1dac8e0bc8a124ea52cdb6d6a50a8a750592acf540e47c4740a8b96b5add8d9dcce4dfbe74e08b2ab95303c1a2078cf4ba01a085a6de88a879f45576e + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -3675,15 +3411,6 @@ __metadata: languageName: node linkType: hard -"@nodeutils/defaults-deep@npm:1.1.0": - version: 1.1.0 - resolution: "@nodeutils/defaults-deep@npm:1.1.0" - dependencies: - lodash: "npm:^4.15.0" - checksum: 10/4651c6e2179b0207f1a848f1e13eff7f2c24e7b6e52c965a8a5ef5140aea5df1fdafbf714026559e4f1f5828d3723eb35fe1b18dc2c7b0ec2265dc70b577bc34 - languageName: node - linkType: hard - "@npmcli/agent@npm:^4.0.0": version: 4.0.0 resolution: "@npmcli/agent@npm:4.0.0" @@ -3706,131 +3433,6 @@ __metadata: languageName: node linkType: hard -"@octokit/auth-token@npm:^6.0.0": - version: 6.0.0 - resolution: "@octokit/auth-token@npm:6.0.0" - checksum: 10/a30f5c4c984964b57193de5b6f67169f74e4779fedbe716157dd3558dd9de3ca5c105cae521b7bd8ce1ae180773a2ef01afe2306ad5a329f4fd291eba2b7c7d1 - languageName: node - linkType: hard - -"@octokit/core@npm:^7.0.6": - version: 7.0.6 - resolution: "@octokit/core@npm:7.0.6" - dependencies: - "@octokit/auth-token": "npm:^6.0.0" - "@octokit/graphql": "npm:^9.0.3" - "@octokit/request": "npm:^10.0.6" - "@octokit/request-error": "npm:^7.0.2" - "@octokit/types": "npm:^16.0.0" - before-after-hook: "npm:^4.0.0" - universal-user-agent: "npm:^7.0.0" - checksum: 10/852d41fc3150d2a891156427dd0575c77889f1c7a109894ee541594e3fd47c0d4e0a93fee22966c507dfd6158b522e42846c2ac46b9d896078194c95fa81f4ae - languageName: node - linkType: hard - -"@octokit/endpoint@npm:^11.0.3": - version: 11.0.3 - resolution: "@octokit/endpoint@npm:11.0.3" - dependencies: - "@octokit/types": "npm:^16.0.0" - universal-user-agent: "npm:^7.0.2" - checksum: 10/21b67d76fb1ea28bd87ca467c12dfab648af55522b936760316d70f8ccdd638f170d636ee72606857f0cd8f343f40c8a4e8f55993d6b1f5b9ecf102e072044c5 - languageName: node - linkType: hard - -"@octokit/graphql@npm:^9.0.3": - version: 9.0.3 - resolution: "@octokit/graphql@npm:9.0.3" - dependencies: - "@octokit/request": "npm:^10.0.6" - "@octokit/types": "npm:^16.0.0" - universal-user-agent: "npm:^7.0.0" - checksum: 10/7b16f281f8571dce55280b3986fbb8d15465a7236164a5f6497ded7597ff9ee95d5796924555b979903fe8c6706fe6be1b3e140d807297f85ac8edeadc28f9fe - languageName: node - linkType: hard - -"@octokit/openapi-types@npm:^27.0.0": - version: 27.0.0 - resolution: "@octokit/openapi-types@npm:27.0.0" - checksum: 10/5cd2cdf4e41fdf522e15e3d53f3ece8380d98dda9173a6fc905828fb2c33e8733d5f5d2a757ae3a572525f4749748e66cb40e7939372132988d8eb4ba978d54f - languageName: node - linkType: hard - -"@octokit/plugin-paginate-rest@npm:^14.0.0": - version: 14.0.0 - resolution: "@octokit/plugin-paginate-rest@npm:14.0.0" - dependencies: - "@octokit/types": "npm:^16.0.0" - peerDependencies: - "@octokit/core": ">=6" - checksum: 10/57ddd857528dad9c02431bc6254c2374c06057872cf9656a4a88b162ebe1c2bc9f34fbec360f2ccff72c940f29b120758ce14e8135bd027223d381eb1b8b6579 - languageName: node - linkType: hard - -"@octokit/plugin-request-log@npm:^6.0.0": - version: 6.0.0 - resolution: "@octokit/plugin-request-log@npm:6.0.0" - peerDependencies: - "@octokit/core": ">=6" - checksum: 10/8a79973b1429bfead9113c4117f418aaef5ff368795daded3415ba14623d97d5fc08d1e822dbd566ecc9f041119e1a48a11853a9c48d9eb1caa62baa79c17f83 - languageName: node - linkType: hard - -"@octokit/plugin-rest-endpoint-methods@npm:^17.0.0": - version: 17.0.0 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:17.0.0" - dependencies: - "@octokit/types": "npm:^16.0.0" - peerDependencies: - "@octokit/core": ">=6" - checksum: 10/e9d9ad4d9755cc7fb82fdcbfa870ddea8a432180f0f76c8469095557fd1e26f8caea8cae58401209be17c4f3d8cc48c0e16a3643e37e48f4d23c39e058bf2c55 - languageName: node - linkType: hard - -"@octokit/request-error@npm:^7.0.2": - version: 7.1.0 - resolution: "@octokit/request-error@npm:7.1.0" - dependencies: - "@octokit/types": "npm:^16.0.0" - checksum: 10/c1d447ff7482382c69f7a4b2eaa44c672906dd111d8a9196a5d07f2adc4ae0f0e12ec4ce0063f14f9b2fb5f0cef4451c95ec961a7a711bd900e5d6441d546570 - languageName: node - linkType: hard - -"@octokit/request@npm:^10.0.6": - version: 10.0.8 - resolution: "@octokit/request@npm:10.0.8" - dependencies: - "@octokit/endpoint": "npm:^11.0.3" - "@octokit/request-error": "npm:^7.0.2" - "@octokit/types": "npm:^16.0.0" - fast-content-type-parse: "npm:^3.0.0" - json-with-bigint: "npm:^3.5.3" - universal-user-agent: "npm:^7.0.2" - checksum: 10/db1dc1f9b9b4717107ce777e1cfb497e3fbc1cbd68c98b33e1356b824f353c6db025014b030410a0a6f11d35c9bfa7837230ddc3c4df9d723a210e701a40f804 - languageName: node - linkType: hard - -"@octokit/rest@npm:22.0.1": - version: 22.0.1 - resolution: "@octokit/rest@npm:22.0.1" - dependencies: - "@octokit/core": "npm:^7.0.6" - "@octokit/plugin-paginate-rest": "npm:^14.0.0" - "@octokit/plugin-request-log": "npm:^6.0.0" - "@octokit/plugin-rest-endpoint-methods": "npm:^17.0.0" - checksum: 10/ec2e94cfa8766716faeb3ca18527d9af746482d35aaa6e4265a30cb669ae3f31f4ebb6235edebe5ae62bc2cec2b8e88902584f698df2e7cabac3a15fd27da665 - languageName: node - linkType: hard - -"@octokit/types@npm:^16.0.0": - version: 16.0.0 - resolution: "@octokit/types@npm:16.0.0" - dependencies: - "@octokit/openapi-types": "npm:^27.0.0" - checksum: 10/03d5cfc29556a9b53eae8beb1bf15c0b704dc722db2c51b53f093f3c3ee6c1d8e20b682be8117a3a17034b458be7746d1b22aaefb959ceb5152ad7589b39e2c9 - languageName: node - linkType: hard - "@op-engineering/op-sqlite@npm:18.2.5": version: 18.2.5 resolution: "@op-engineering/op-sqlite@npm:18.2.5" @@ -3859,13 +3461,6 @@ __metadata: languageName: node linkType: hard -"@phun-ky/typeof@npm:2.0.3": - version: 2.0.3 - resolution: "@phun-ky/typeof@npm:2.0.3" - checksum: 10/ca7daa8e520ca3e947c2cd47e25ab1f299acc87c05d5750747665c531a70395b8e4e5e510347bebc98d89d6c65dbe16b8d6604da2327d832aa5abe91703d0598 - languageName: node - linkType: hard - "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -4614,23 +4209,6 @@ __metadata: languageName: node linkType: hard -"@release-it/conventional-changelog@npm:10.0.5": - version: 10.0.5 - resolution: "@release-it/conventional-changelog@npm:10.0.5" - dependencies: - "@conventional-changelog/git-client": "npm:^2.5.1" - concat-stream: "npm:^2.0.0" - conventional-changelog: "npm:^7.1.1" - conventional-changelog-angular: "npm:^8.1.0" - conventional-changelog-conventionalcommits: "npm:^9.1.0" - conventional-recommended-bump: "npm:^11.2.0" - semver: "npm:^7.7.3" - peerDependencies: - release-it: ^18.0.0 || ^19.0.0 - checksum: 10/995cd1b29a329bfa07666f0f754b4477c7bfbf1fc37d602a9f3abd7556160ca2822f572931920b361dc801d318256dd20f2b3aa3818b0d9677106138692af784 - languageName: node - linkType: hard - "@sideway/address@npm:^4.1.5": version: 4.1.5 resolution: "@sideway/address@npm:4.1.5" @@ -4663,13 +4241,6 @@ __metadata: languageName: node linkType: hard -"@simple-libs/hosted-git-info@npm:^1.0.2": - version: 1.0.2 - resolution: "@simple-libs/hosted-git-info@npm:1.0.2" - checksum: 10/c5d3c4e743611124b3d5be12ec5d536cb9f16ce699e1d911b0e05b96d9c7b4f1afd2606e1baaf0889c843a111dd2f8648fd162eb0d09e20fddf9f13b0e7d2090 - languageName: node - linkType: hard - "@simple-libs/stream-utils@npm:^1.2.0": version: 1.2.0 resolution: "@simple-libs/stream-utils@npm:1.2.0" @@ -4723,55 +4294,6 @@ __metadata: languageName: node linkType: hard -"@tootallnate/quickjs-emscripten@npm:^0.23.0": - version: 0.23.0 - resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0" - checksum: 10/95cbad451d195b9d8f312103abafcc010741eb9256e98d7953e7c026d4c1ed4abb2248a14018bf49e3201c350104fc643137b23aa0bbed2744c795c39dc48a28 - languageName: node - linkType: hard - -"@turbo/darwin-64@npm:2.8.21": - version: 2.8.21 - resolution: "@turbo/darwin-64@npm:2.8.21" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@turbo/darwin-arm64@npm:2.8.21": - version: 2.8.21 - resolution: "@turbo/darwin-arm64@npm:2.8.21" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@turbo/linux-64@npm:2.8.21": - version: 2.8.21 - resolution: "@turbo/linux-64@npm:2.8.21" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@turbo/linux-arm64@npm:2.8.21": - version: 2.8.21 - resolution: "@turbo/linux-arm64@npm:2.8.21" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@turbo/windows-64@npm:2.8.21": - version: 2.8.21 - resolution: "@turbo/windows-64@npm:2.8.21" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@turbo/windows-arm64@npm:2.8.21": - version: 2.8.21 - resolution: "@turbo/windows-arm64@npm:2.8.21" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "@types/babel__core@npm:^7.1.14": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -4904,20 +4426,6 @@ __metadata: languageName: node linkType: hard -"@types/normalize-package-data@npm:^2.4.4": - version: 2.4.4 - resolution: "@types/normalize-package-data@npm:2.4.4" - checksum: 10/65dff72b543997b7be8b0265eca7ace0e34b75c3e5fee31de11179d08fa7124a7a5587265d53d0409532ecb7f7fba662c2012807963e1f9b059653ec2c83ee05 - languageName: node - linkType: hard - -"@types/parse-path@npm:^7.0.0": - version: 7.0.3 - resolution: "@types/parse-path@npm:7.0.3" - checksum: 10/21a12c228d38f5a75659dfd7cb127dc2001ed3f6acbd1b2e0575d1348c735594c0bab06a97fe849c151438384829f20ea5971cb045f7ecd37d53c76a9fcb9de3 - languageName: node - linkType: hard - "@types/react-test-renderer@npm:^19.1.0": version: 19.1.0 resolution: "@types/react-test-renderer@npm:19.1.0" @@ -5409,6 +4917,13 @@ __metadata: languageName: node linkType: hard +"anynum@npm:^1.0.1": + version: 1.0.1 + resolution: "anynum@npm:1.0.1" + checksum: 10/096acef76cc8b9f34d43ec37ae9ba7a3d4e2e8c722a0dd59a78995248a8eb4021713ee91b55de106366ac4eaa47578ceb0fffe9829ef01d78b20f9fd6d412a88 + languageName: node + linkType: hard + "appdirsjs@npm:^1.2.4": version: 1.2.7 resolution: "appdirsjs@npm:1.2.7" @@ -5572,15 +5087,6 @@ __metadata: languageName: node linkType: hard -"ast-types@npm:^0.13.4": - version: 0.13.4 - resolution: "ast-types@npm:0.13.4" - dependencies: - tslib: "npm:^2.0.1" - checksum: 10/c55b375b9aaf44713d8c0f77a08215ab6d44f368b13e44f2141c421022af3c62b615a30c8ea629457f0cbaec409c713401c0188a124552c8fe4a5ad6b17ff3c3 - languageName: node - linkType: hard - "astral-regex@npm:^1.0.0": version: 1.0.0 resolution: "astral-regex@npm:1.0.0" @@ -5609,15 +5115,6 @@ __metadata: languageName: node linkType: hard -"async-retry@npm:1.3.3": - version: 1.3.3 - resolution: "async-retry@npm:1.3.3" - dependencies: - retry: "npm:0.13.1" - checksum: 10/38a7152ff7265a9321ea214b9c69e8224ab1febbdec98efbbde6e562f17ff68405569b796b1c5271f354aef8783665d29953f051f68c1fc45306e61aec82fdc4 - languageName: node - linkType: hard - "available-typed-arrays@npm:^1.0.7": version: 1.0.7 resolution: "available-typed-arrays@npm:1.0.7" @@ -5815,26 +5312,12 @@ __metadata: languageName: node linkType: hard -"baseline-browser-mapping@npm:^2.9.0": - version: 2.10.0 - resolution: "baseline-browser-mapping@npm:2.10.0" +"baseline-browser-mapping@npm:^2.11.26": + version: 2.11.27 + resolution: "baseline-browser-mapping@npm:2.11.27" bin: baseline-browser-mapping: dist/cli.cjs - checksum: 10/8145e076e4299f04c7a412e6ea63803e330153cd89c47b5303f9b56b58078f4c3d5a5b5332c1069da889e76facacca4d43f8940375f7e73ce0a4d96214332953 - languageName: node - linkType: hard - -"basic-ftp@npm:^5.0.2": - version: 5.2.0 - resolution: "basic-ftp@npm:5.2.0" - checksum: 10/f5a15d789aa98859af4da9e976154b2aeae19052e1762dc68d259d2bce631dafa40c667aa06d7346cd630aa6f9cc9a26f515b468e0bd24243fbae2149c7d01ad - languageName: node - linkType: hard - -"before-after-hook@npm:^4.0.0": - version: 4.0.0 - resolution: "before-after-hook@npm:4.0.0" - checksum: 10/9fd52bc0c3cca0fb115e04dacbeeaacff38fa23e1af725d62392254c31ef433b15da60efcba61552e44d64e26f25ea259f72dba005115924389e88d2fd56e19f + checksum: 10/234125ebaf9d5b8311158653b2c06a1f60093427eb68c4d3f83f105baa2a170c721c8f763a5941b6884bb0e217ad35df230da0b7d2f9d69f2a3f09aa533c31ea languageName: node linkType: hard @@ -5857,47 +5340,47 @@ __metadata: linkType: hard "body-parser@npm:^2.2.2": - version: 2.2.2 - resolution: "body-parser@npm:2.2.2" + version: 2.3.0 + resolution: "body-parser@npm:2.3.0" dependencies: bytes: "npm:^3.1.2" - content-type: "npm:^1.0.5" + content-type: "npm:^2.0.0" debug: "npm:^4.4.3" - http-errors: "npm:^2.0.0" - iconv-lite: "npm:^0.7.0" + http-errors: "npm:^2.0.1" + iconv-lite: "npm:^0.7.2" on-finished: "npm:^2.4.1" - qs: "npm:^6.14.1" - raw-body: "npm:^3.0.1" - type-is: "npm:^2.0.1" - checksum: 10/69671f67d4d5ae5974593901a92d639757231da1725ed6de4d35e86cde9ce7650afdf1cd28df9b6f7892ea7f9eb03ccb30c70fe27d679275ae4cb4aae5ce1b21 + qs: "npm:^6.15.2" + raw-body: "npm:^3.0.2" + type-is: "npm:^2.1.0" + checksum: 10/94f741ff525358dd0d47f0a042936dc61b9d2e348ff1228c5ffd79f1902c673a317bbb9495b3f7d1db4483befe6ffed1c42bc4cdd8da8f41690530810cfe4dad languageName: node linkType: hard "brace-expansion@npm:^1.1.7": - version: 1.1.12 - resolution: "brace-expansion@npm:1.1.12" + version: 1.1.21 + resolution: "brace-expansion@npm:1.1.21" dependencies: balanced-match: "npm:^1.0.0" concat-map: "npm:0.0.1" - checksum: 10/12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 + checksum: 10/6c0ed34107cb3bd3f44c01d90ec8c01baa3ed75b7755617e2e5797b5908bbf20b313edf575612b200a783b84c7d1826aec2f7a2f03de9905bbfae5dc3dea6a95 languageName: node linkType: hard "brace-expansion@npm:^2.0.2": - version: 2.0.2 - resolution: "brace-expansion@npm:2.0.2" + version: 2.1.7 + resolution: "brace-expansion@npm:2.1.7" dependencies: balanced-match: "npm:^1.0.0" - checksum: 10/01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488 + checksum: 10/4763be07b688136db4f98f71ab96c4a1a73b6785f69864c130c748f4429be961c6a9a4129c0a81aad4f9cfb08e31a3cf2809b2427509bf2990d1490b7b5dd2d0 languageName: node linkType: hard "brace-expansion@npm:^5.0.2": - version: 5.0.4 - resolution: "brace-expansion@npm:5.0.4" + version: 5.0.12 + resolution: "brace-expansion@npm:5.0.12" dependencies: balanced-match: "npm:^4.0.2" - checksum: 10/cfd57e20d8ded9578149e47ae4d3fff2b2f78d06b54a32a73057bddff65c8e9b930613f0cbcfefedf12dd117151e19d4da16367d5127c54f3bff02d8a4479bb2 + checksum: 10/65b550f1836e3b43f512f12afbc3be96616eee5c353e16d70181b7dffec8c08beabffb51d69a3bbdb27d675840725cbab025fda9d10716b5cda7dd864dc7bc4a languageName: node linkType: hard @@ -5911,17 +5394,17 @@ __metadata: linkType: hard "browserslist@npm:^4.20.4, browserslist@npm:^4.24.0, browserslist@npm:^4.28.1": - version: 4.28.1 - resolution: "browserslist@npm:4.28.1" - dependencies: - baseline-browser-mapping: "npm:^2.9.0" - caniuse-lite: "npm:^1.0.30001759" - electron-to-chromium: "npm:^1.5.263" - node-releases: "npm:^2.0.27" - update-browserslist-db: "npm:^1.2.0" + version: 4.29.3 + resolution: "browserslist@npm:4.29.3" + dependencies: + baseline-browser-mapping: "npm:^2.11.26" + caniuse-lite: "npm:^1.0.30001813" + electron-to-chromium: "npm:^1.5.439" + node-releases: "npm:^2.0.57" + update-browserslist-db: "npm:^1.3.3" bin: browserslist: cli.js - checksum: 10/64f2a97de4bce8473c0e5ae0af8d76d1ead07a5b05fc6bc87b848678bb9c3a91ae787b27aa98cdd33fc00779607e6c156000bed58fefb9cf8e4c5a183b994cdb + checksum: 10/9649d4d73fff11f7c0b19948f08f9f287c184feb0965ac0b489cee7e1a9f430e747809db0d6014a30fdbcc42755e7a4dd047dfd7e28f62982072dcd0f8291eb0 languageName: node linkType: hard @@ -5951,15 +5434,6 @@ __metadata: languageName: node linkType: hard -"bundle-name@npm:^4.1.0": - version: 4.1.0 - resolution: "bundle-name@npm:4.1.0" - dependencies: - run-applescript: "npm:^7.0.0" - checksum: 10/1d966c8d2dbf4d9d394e53b724ac756c2414c45c01340b37743621f59cc565a435024b394ddcb62b9b335d1c9a31f4640eb648c3fec7f97ee74dc0694c9beb6c - languageName: node - linkType: hard - "bytes@npm:3.1.2, bytes@npm:^3.1.2, bytes@npm:~3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" @@ -5967,31 +5441,6 @@ __metadata: languageName: node linkType: hard -"c12@npm:3.3.3": - version: 3.3.3 - resolution: "c12@npm:3.3.3" - dependencies: - chokidar: "npm:^5.0.0" - confbox: "npm:^0.2.2" - defu: "npm:^6.1.4" - dotenv: "npm:^17.2.3" - exsolve: "npm:^1.0.8" - giget: "npm:^2.0.0" - jiti: "npm:^2.6.1" - ohash: "npm:^2.0.11" - pathe: "npm:^2.0.3" - perfect-debounce: "npm:^2.0.0" - pkg-types: "npm:^2.3.0" - rc9: "npm:^2.1.2" - peerDependencies: - magicast: "*" - peerDependenciesMeta: - magicast: - optional: true - checksum: 10/058026b87656fba996ab9f05d2f5c037f057a314df2ea7410bd812a6eb5881faa585485a337cbbc291a4c0e90c1ecbe5ae704104db72005e9c41c6373414b990 - languageName: node - linkType: hard - "cacache@npm:^20.0.1": version: 20.0.3 resolution: "cacache@npm:20.0.3" @@ -6064,10 +5513,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001759": - version: 1.0.30001776 - resolution: "caniuse-lite@npm:1.0.30001776" - checksum: 10/7a140cfcb5b56597139e700ac624df342995ec670e43e17b0b636b4b215ce6f05d3932c16a4b8c740b5fe57bc94ef5cac157f5b0e3ccb049d80c57f409c576a8 +"caniuse-lite@npm:^1.0.30001813": + version: 1.0.30001814 + resolution: "caniuse-lite@npm:1.0.30001814" + checksum: 10/387fa630eeb43c9a6ff5e669da4cc3010b611bfb43118ffa4d6ff89374b6245e95643bb4ca20058caf7d5ab3e46cf87f4a3f05346cc85ad23631618a5295754d languageName: node linkType: hard @@ -6088,13 +5537,6 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^5.6.2": - version: 5.6.2 - resolution: "chalk@npm:5.6.2" - checksum: 10/1b2f48f6fba1370670d5610f9cd54c391d6ede28f4b7062dd38244ea5768777af72e5be6b74fb6c6d54cb84c4a2dff3f3afa9b7cb5948f7f022cfd3d087989e0 - languageName: node - linkType: hard - "char-regex@npm:^1.0.2": version: 1.0.2 resolution: "char-regex@npm:1.0.2" @@ -6102,22 +5544,6 @@ __metadata: languageName: node linkType: hard -"chardet@npm:^2.1.1": - version: 2.1.1 - resolution: "chardet@npm:2.1.1" - checksum: 10/d56913b65e45c5c86f331988e2ef6264c131bfeadaae098ee719bf6610546c77740e37221ffec802dde56b5e4466613a4c754786f4da6b5f6c5477243454d324 - languageName: node - linkType: hard - -"chokidar@npm:^5.0.0": - version: 5.0.0 - resolution: "chokidar@npm:5.0.0" - dependencies: - readdirp: "npm:^5.0.0" - checksum: 10/a1c2a4ee6ee81ba6409712c295a47be055fb9de1186dfbab33c1e82f28619de962ba02fc5f9d433daaedc96c35747460d8b2079ac2907de2c95e3f7cce913113 - languageName: node - linkType: hard - "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -6139,29 +5565,13 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^4.2.0, ci-info@npm:^4.3.1": +"ci-info@npm:^4.2.0": version: 4.4.0 resolution: "ci-info@npm:4.4.0" checksum: 10/dfded0c630267d89660c8abb988ac8395a382bdfefedcc03e3e2858523312c5207db777c239c34774e3fcff11f015477c19d2ac8a58ea58aa476614a2e64f434 languageName: node linkType: hard -"citty@npm:^0.1.6": - version: 0.1.6 - resolution: "citty@npm:0.1.6" - dependencies: - consola: "npm:^3.2.3" - checksum: 10/3208947e73abb699a12578ee2bfee254bf8dd1ce0d5698e8a298411cabf16bd3620d63433aef5bd88cdb2b9da71aef18adefa3b4ffd18273bb62dd1d28c344f5 - languageName: node - linkType: hard - -"citty@npm:^0.2.0": - version: 0.2.1 - resolution: "citty@npm:0.2.1" - checksum: 10/fa3b1f70d5298623396851a78e4a21d904ce5a4313d67d93a6b4119617a30ad9e03fc7dc913a80ed70e5d4afe983c0b65d8f4bfef7212248d11268043cbe53b1 - languageName: node - linkType: hard - "cjs-module-lexer@npm:^1.0.0": version: 1.4.3 resolution: "cjs-module-lexer@npm:1.4.3" @@ -6185,15 +5595,6 @@ __metadata: languageName: node linkType: hard -"cli-cursor@npm:^5.0.0": - version: 5.0.0 - resolution: "cli-cursor@npm:5.0.0" - dependencies: - restore-cursor: "npm:^5.0.0" - checksum: 10/1eb9a3f878b31addfe8d82c6d915ec2330cec8447ab1f117f4aa34f0137fbb3137ec3466e1c9a65bcb7557f6e486d343f2da57f253a2f668d691372dfa15c090 - languageName: node - linkType: hard - "cli-spinners@npm:^2.5.0": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" @@ -6201,20 +5602,6 @@ __metadata: languageName: node linkType: hard -"cli-spinners@npm:^3.2.0": - version: 3.4.0 - resolution: "cli-spinners@npm:3.4.0" - checksum: 10/6a4021c1999011fc34ae714f055dcdafb56309abc1f8fb021ea7d9370dfc524485fe8684226015e5fe6053dd30544e74270184ff7edc3fa4d37043b8efd0a054 - languageName: node - linkType: hard - -"cli-width@npm:^4.1.0": - version: 4.1.0 - resolution: "cli-width@npm:4.1.0" - checksum: 10/b58876fbf0310a8a35c79b72ecfcf579b354e18ad04e6b20588724ea2b522799a758507a37dfe132fafaf93a9922cafd9514d9e1598e6b2cd46694853aed099f - languageName: node - linkType: hard - "cliui@npm:^6.0.0": version: 6.0.0 resolution: "cliui@npm:6.0.0" @@ -6325,15 +5712,15 @@ __metadata: languageName: node linkType: hard -"commitlint@npm:20.4.3": - version: 20.4.3 - resolution: "commitlint@npm:20.4.3" +"commitlint@npm:20.5.0": + version: 20.5.0 + resolution: "commitlint@npm:20.5.0" dependencies: - "@commitlint/cli": "npm:^20.4.3" - "@commitlint/types": "npm:^20.4.3" + "@commitlint/cli": "npm:^20.5.0" + "@commitlint/types": "npm:^20.5.0" bin: commitlint: cli.js - checksum: 10/9f82d934498f8abf4380a192cfadf2de1e875402529515311d265bd902042cc3ad26f7f3153d7b30a47609d0cca6b3738373b3f85a3300e3fbf8592918f4533d + checksum: 10/d2dd7ee649e5688d3872893ac86ddc669c0bb942493edd09b39eddc6cb394a00026b93363c9da4756402c787caec64a8090d5c16175e512586db01061140b4bb languageName: node linkType: hard @@ -6357,17 +5744,18 @@ __metadata: linkType: hard "compression@npm:^1.7.1": - version: 1.8.1 - resolution: "compression@npm:1.8.1" + version: 1.8.2 + resolution: "compression@npm:1.8.2" dependencies: bytes: "npm:3.1.2" compressible: "npm:~2.0.18" debug: "npm:2.6.9" + destroy: "npm:1.2.0" negotiator: "npm:~0.6.4" on-headers: "npm:~1.1.0" safe-buffer: "npm:5.2.1" vary: "npm:~1.1.2" - checksum: 10/e7552bfbd780f2003c6fe8decb44561f5cc6bc82f0c61e81122caff5ec656f37824084f52155b1e8ef31d7656cecbec9a2499b7a68e92e20780ffb39b479abb7 + checksum: 10/5b17675cf4abcaff03b83f4be417fb256df4568c7626a65fc4b38cb8ebeb9c0f3917ee79df20cbec90e53d5758ad0d9ae51d5d4669256e22247b16308d290a04 languageName: node linkType: hard @@ -6378,25 +5766,6 @@ __metadata: languageName: node linkType: hard -"concat-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "concat-stream@npm:2.0.0" - dependencies: - buffer-from: "npm:^1.0.0" - inherits: "npm:^2.0.3" - readable-stream: "npm:^3.0.2" - typedarray: "npm:^0.0.6" - checksum: 10/250e576d0617e7c58e1c4b2dd6fe69560f316d2c962a409f9f3aac794018499ddb31948b1e4296f217008e124cd5d526432097745157fe504b5d9f3dc469eadb - languageName: node - linkType: hard - -"confbox@npm:^0.2.2": - version: 0.2.4 - resolution: "confbox@npm:0.2.4" - checksum: 10/10243036f2eca8f02c85f1c8c99f492d2b690e41b5fb9c6bf91afbaca8972eb760bf9fafb7b669433c1ea0c98f12e910d4d1e73b017cd06b72150d080a2c78b6 - languageName: node - linkType: hard - "connect@npm:^3.6.5, connect@npm:^3.7.0": version: 3.7.0 resolution: "connect@npm:3.7.0" @@ -6409,26 +5778,10 @@ __metadata: languageName: node linkType: hard -"consola@npm:^3.2.3, consola@npm:^3.4.0": - version: 3.4.2 - resolution: "consola@npm:3.4.2" - checksum: 10/32192c9f50d7cac27c5d7c4ecd3ff3679aea863e6bf5bd6a9cc2b05d1cd78addf5dae71df08c54330c142be8e7fbd46f051030129b57c6aacdd771efe409c4b2 - languageName: node - linkType: hard - -"content-type@npm:^1.0.5": - version: 1.0.5 - resolution: "content-type@npm:1.0.5" - checksum: 10/585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662 - languageName: node - linkType: hard - -"conventional-changelog-angular@npm:^8.1.0": - version: 8.2.0 - resolution: "conventional-changelog-angular@npm:8.2.0" - dependencies: - compare-func: "npm:^2.0.0" - checksum: 10/d40512899c87b5b07e48406190962f28ecc341a481565dda2e6e4e47f9766ef0dec94315f8a300caa7afedd73af87e7b339641d7f0b0e1e515a36ed417ab3c44 +"content-type@npm:^2.0.0": + version: 2.1.0 + resolution: "content-type@npm:2.1.0" + checksum: 10/8aac907922538f430d8bfab1d8fe2fbdc1eb890a0fa7a619f712db4bfefe24be951ba464f972007df64840c775bf2db284ca8223547ac5317ad9ab2ee8e6501b languageName: node linkType: hard @@ -6441,15 +5794,6 @@ __metadata: languageName: node linkType: hard -"conventional-changelog-conventionalcommits@npm:^9.1.0": - version: 9.2.0 - resolution: "conventional-changelog-conventionalcommits@npm:9.2.0" - dependencies: - compare-func: "npm:^2.0.0" - checksum: 10/957c841ba9f1ed0ddc7601ca7d6a71cc13d90a9b6d4c347af8f0718febdade75d6cb693a674964a080213ede9b789773c1d225cad13dc6a553feeebe37d02e78 - languageName: node - linkType: hard - "conventional-changelog-conventionalcommits@npm:^9.2.0": version: 9.3.0 resolution: "conventional-changelog-conventionalcommits@npm:9.3.0" @@ -6459,55 +5803,7 @@ __metadata: languageName: node linkType: hard -"conventional-changelog-preset-loader@npm:^5.0.0": - version: 5.0.0 - resolution: "conventional-changelog-preset-loader@npm:5.0.0" - checksum: 10/7630c2826b43f8f546f0575b46d3eb8c2ac2b5bcfae60b7d1186e9a87f07b7a689d9463afc125a40ab84a030574c9ce7965dd96e6506323e5a7d1ac2b9f2df19 - languageName: node - linkType: hard - -"conventional-changelog-writer@npm:^8.3.0": - version: 8.3.0 - resolution: "conventional-changelog-writer@npm:8.3.0" - dependencies: - "@simple-libs/stream-utils": "npm:^1.2.0" - conventional-commits-filter: "npm:^5.0.0" - handlebars: "npm:^4.7.7" - meow: "npm:^13.0.0" - semver: "npm:^7.5.2" - bin: - conventional-changelog-writer: dist/cli/index.js - checksum: 10/14ca83a9e7b3c34adc5788c3c815dc571cb0f712051fe83fa3566cbf69df8171e2ecf21940e15b9635c79c102e8d6cd6a8c2dac0503d6bfc8cd87b6d64bd5e9f - languageName: node - linkType: hard - -"conventional-changelog@npm:^7.1.1": - version: 7.2.0 - resolution: "conventional-changelog@npm:7.2.0" - dependencies: - "@conventional-changelog/git-client": "npm:^2.6.0" - "@simple-libs/hosted-git-info": "npm:^1.0.2" - "@types/normalize-package-data": "npm:^2.4.4" - conventional-changelog-preset-loader: "npm:^5.0.0" - conventional-changelog-writer: "npm:^8.3.0" - conventional-commits-parser: "npm:^6.3.0" - fd-package-json: "npm:^2.0.0" - meow: "npm:^13.0.0" - normalize-package-data: "npm:^7.0.0" - bin: - conventional-changelog: dist/cli/index.js - checksum: 10/ece669e6f653832d00b18dfdc71f321e81f5bb3026e72f9a59fe1a1f30234b41221388add3eb9a7f251200278282ccf69a70ec94b958744d0dd78ee0cdabdd36 - languageName: node - linkType: hard - -"conventional-commits-filter@npm:^5.0.0": - version: 5.0.0 - resolution: "conventional-commits-filter@npm:5.0.0" - checksum: 10/2345546ea9e40412558d508311d7729b38f8d4c0fd554837c10721a432e8598ec1152320f6b601a9c11c023a31bccbb5a12067736b2227de8591f4de707e11a7 - languageName: node - linkType: hard - -"conventional-commits-parser@npm:^6.1.0, conventional-commits-parser@npm:^6.3.0": +"conventional-commits-parser@npm:^6.3.0": version: 6.3.0 resolution: "conventional-commits-parser@npm:6.3.0" dependencies: @@ -6519,21 +5815,6 @@ __metadata: languageName: node linkType: hard -"conventional-recommended-bump@npm:^11.2.0": - version: 11.2.0 - resolution: "conventional-recommended-bump@npm:11.2.0" - dependencies: - "@conventional-changelog/git-client": "npm:^2.5.1" - conventional-changelog-preset-loader: "npm:^5.0.0" - conventional-commits-filter: "npm:^5.0.0" - conventional-commits-parser: "npm:^6.1.0" - meow: "npm:^13.0.0" - bin: - conventional-recommended-bump: dist/cli/index.js - checksum: 10/b6330542675399d1053c9092c5ddcc4ab0904046b5f767478f9434ada2cb1e9adbd9555e6952e1ad5a3bae6775cf67a14062b0be3b5c61b93c22abc702b00175 - languageName: node - linkType: hard - "convert-source-map@npm:^2.0.0": version: 2.0.0 resolution: "convert-source-map@npm:2.0.0" @@ -6615,20 +5896,6 @@ __metadata: languageName: node linkType: hard -"dargs@npm:^8.0.0": - version: 8.1.0 - resolution: "dargs@npm:8.1.0" - checksum: 10/33f1b8f5f08e72c8a28355a87c0e1a9b6a0fec99252ecd9cf4735e65dd5f2e19747c860251ed5747b38e7204c7915fd7a7146aee5aaef5882c69169aae8b1d09 - languageName: node - linkType: hard - -"data-uri-to-buffer@npm:^6.0.2": - version: 6.0.2 - resolution: "data-uri-to-buffer@npm:6.0.2" - checksum: 10/8b6927c33f9b54037f442856be0aa20e5fd49fa6c9c8ceece408dc306445d593ad72d207d57037c529ce65f413b421da800c6827b1dbefb607b8056f17123a61 - languageName: node - linkType: hard - "data-view-buffer@npm:^1.0.2": version: 1.0.2 resolution: "data-view-buffer@npm:1.0.2" @@ -6730,23 +5997,6 @@ __metadata: languageName: node linkType: hard -"default-browser-id@npm:^5.0.0": - version: 5.0.1 - resolution: "default-browser-id@npm:5.0.1" - checksum: 10/52c637637bcd76bfe974462a2f1dd75cb04784c2852935575760f82e1fd338e5e80d3c45a9b01fdbb1e450553a830bb163b004d2eca223c5573989f82232a072 - languageName: node - linkType: hard - -"default-browser@npm:^5.2.1": - version: 5.5.0 - resolution: "default-browser@npm:5.5.0" - dependencies: - bundle-name: "npm:^4.1.0" - default-browser-id: "npm:^5.0.0" - checksum: 10/c5c5d84a4abd82850e98f06798a55dee87fc1064538bea00cc14c0fb2dccccbff5e9e07eeea80385fa653202d5d92509838b4239d610ddfa1c76a04a1f65e767 - languageName: node - linkType: hard - "defaults@npm:^1.0.3": version: 1.0.4 resolution: "defaults@npm:1.0.4" @@ -6774,13 +6024,6 @@ __metadata: languageName: node linkType: hard -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 10/f28421cf9ee86eecaf5f3b8fe875f13d7009c2625e97645bfff7a2a49aca678270b86c39f9c32939e5ca7ab96b551377ed4139558c795e076774287ad3af1aa4 - languageName: node - linkType: hard - "define-properties@npm:^1.1.3, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" @@ -6792,24 +6035,6 @@ __metadata: languageName: node linkType: hard -"defu@npm:^6.1.4": - version: 6.1.4 - resolution: "defu@npm:6.1.4" - checksum: 10/aeffdb47300f45b4fdef1c5bd3880ac18ea7a1fd5b8a8faf8df29350ff03bf16dd34f9800205cab513d476e4c0a3783aa0cff0a433aff0ac84a67ddc4c8a2d64 - languageName: node - linkType: hard - -"degenerator@npm:^5.0.0": - version: 5.0.1 - resolution: "degenerator@npm:5.0.1" - dependencies: - ast-types: "npm:^0.13.4" - escodegen: "npm:^2.1.0" - esprima: "npm:^4.0.1" - checksum: 10/a64fa39cdf6c2edd75188157d32338ee9de7193d7dbb2aeb4acb1eb30fa4a15ed80ba8dae9bd4d7b085472cf174a5baf81adb761aaa8e326771392c922084152 - languageName: node - linkType: hard - "del-cli@npm:7.0.0": version: 7.0.0 resolution: "del-cli@npm:7.0.0" @@ -6862,13 +6087,6 @@ __metadata: languageName: node linkType: hard -"destr@npm:^2.0.3": - version: 2.0.5 - resolution: "destr@npm:2.0.5" - checksum: 10/0e4fba62a55a4188c7ab13eed5ebeeda037ead1ab21cf6be40ca39828b258475ad9eb1e7de50a5ea8041705d454a4d090caf9f92b89f03b04d2e229716f7da0a - languageName: node - linkType: hard - "destroy@npm:1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" @@ -6917,13 +6135,6 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^17.2.3": - version: 17.3.1 - resolution: "dotenv@npm:17.3.1" - checksum: 10/4dde6571dff22c2323a3e33ac25e1e7d51c4b6d60dc884f59e3efe85c8fd3cc8800d6b3925d05c46b19dca08cba821a0a24e22f75a1b9b768c859b98bb927b04 - languageName: node - linkType: hard - "dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": version: 1.0.1 resolution: "dunder-proto@npm:1.0.1" @@ -6949,10 +6160,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.5.263": - version: 1.5.307 - resolution: "electron-to-chromium@npm:1.5.307" - checksum: 10/a72af3f89b83d81d151872c28a0886817b1da973e00629c0189c928ed46efa3e975c856969727bf6ebb32ec5ea8362c96e765f307260beaef3003d50fa5fbc11 +"electron-to-chromium@npm:^1.5.439": + version: 1.5.445 + resolution: "electron-to-chromium@npm:1.5.445" + checksum: 10/26cee5ee82a27e77588fc89a378121da0cbfdc941a0f26024422351c6b11700391dd6c63520b956122572b95466ca0131e3ceb8b8539696f35de1c82c0e70365 languageName: node linkType: hard @@ -7185,6 +6396,20 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.46.0": + version: 1.52.0 + resolution: "es-toolkit@npm:1.52.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + vitepress-plugin-sandpack@1.1.4: + unplugged: true + checksum: 10/d36768a16c17cedc3255c108176a8472d56b3b7e51d909c22905fb9ba163296d058ad17a82d6e65883d5aa65aedf8c268c1b31d7979353968e030c9d104b15c0 + languageName: node + linkType: hard + "escalade@npm:^3.1.1, escalade@npm:^3.2.0": version: 3.2.0 resolution: "escalade@npm:3.2.0" @@ -7227,24 +6452,6 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^2.1.0": - version: 2.1.0 - resolution: "escodegen@npm:2.1.0" - dependencies: - esprima: "npm:^4.0.1" - estraverse: "npm:^5.2.0" - esutils: "npm:^2.0.2" - source-map: "npm:~0.6.1" - dependenciesMeta: - source-map: - optional: true - bin: - escodegen: bin/escodegen.js - esgenerate: bin/esgenerate.js - checksum: 10/47719a65b2888b4586e3fa93769068b275961c13089e90d5d01a96a6e8e95871b1c3893576814c8fbf08a4a31a496f37e7b2c937cf231270f4d81de012832c7c - languageName: node - linkType: hard - "eslint-config-prettier@npm:10.1.8": version: 10.1.8 resolution: "eslint-config-prettier@npm:10.1.8" @@ -7502,7 +6709,7 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0, esprima@npm:^4.0.1": +"esprima@npm:^4.0.0": version: 4.0.1 resolution: "esprima@npm:4.0.1" bin: @@ -7551,13 +6758,6 @@ __metadata: languageName: node linkType: hard -"eta@npm:4.5.0": - version: 4.5.0 - resolution: "eta@npm:4.5.0" - checksum: 10/e9012cc58538c2c3735b0a25daa53b30dfe7af5e4e9a5a1e25ef9e161bfa5cfe41ae3dae08a9e50456e64790e0857b06f0f8a3e5c273789cbdfbdecd27cebff6 - languageName: node - linkType: hard - "etag@npm:~1.8.1": version: 1.8.1 resolution: "etag@npm:1.8.1" @@ -7606,23 +6806,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^8.0.1": - version: 8.0.1 - resolution: "execa@npm:8.0.1" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^8.0.1" - human-signals: "npm:^5.0.0" - is-stream: "npm:^3.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^5.1.0" - onetime: "npm:^6.0.0" - signal-exit: "npm:^4.1.0" - strip-final-newline: "npm:^3.0.0" - checksum: 10/d2ab5fe1e2bb92b9788864d0713f1fce9a07c4594e272c0c97bc18c90569897ab262e4ea58d27a694d288227a2e24f16f5e2575b44224ad9983b799dc7f1098d - languageName: node - linkType: hard - "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -7650,20 +6833,6 @@ __metadata: languageName: node linkType: hard -"exsolve@npm:^1.0.7, exsolve@npm:^1.0.8": - version: 1.0.8 - resolution: "exsolve@npm:1.0.8" - checksum: 10/e7e8eac048af9f6856628a46df15529ab37428bdb5f7bc5b7824614383223de1aff60ebe85f44d9c8d4ee218d98c71df1a3e2d336f7d022a4dccd97a0651ec5b - languageName: node - linkType: hard - -"fast-content-type-parse@npm:^3.0.0": - version: 3.0.0 - resolution: "fast-content-type-parse@npm:3.0.0" - checksum: 10/8616a8aa6c9b4f8f4f3c90eaa4e7bfc2240cfa6f41f0eef5b5aa2b2c8b38bd9ad435f1488b6d817ffd725c54651e2777b882ae9dd59366e71e7896f1ec11d473 - languageName: node - linkType: hard - "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -7706,28 +6875,35 @@ __metadata: linkType: hard "fast-uri@npm:^3.0.1": - version: 3.1.0 - resolution: "fast-uri@npm:3.1.0" - checksum: 10/818b2c96dc913bcf8511d844c3d2420e2c70b325c0653633f51821e4e29013c2015387944435cd0ef5322c36c9beecc31e44f71b257aeb8e0b333c1d62bb17c2 + version: 3.1.8 + resolution: "fast-uri@npm:3.1.8" + checksum: 10/d3dfa29fd2e5fa2371833699f3f78c975b79f65e52e0ce37604db10dffb85b5b448b5075e93453272cb95fb1c6a759495164e60649ffd69e59ec43f20d44f791 languageName: node linkType: hard -"fast-xml-builder@npm:^1.0.0": - version: 1.0.0 - resolution: "fast-xml-builder@npm:1.0.0" - checksum: 10/06c04d80545e5c9f4d1d6cca00567b5cc09953a92c6328fa48cfb4d7f42630313b8c2bb62e9cb81accee7bb5e1c5312fcae06c3d20dbe52d969a5938233316da +"fast-xml-builder@npm:^1.2.0": + version: 1.3.1 + resolution: "fast-xml-builder@npm:1.3.1" + dependencies: + path-expression-matcher: "npm:^1.6.2" + xml-naming: "npm:^0.3.0" + checksum: 10/6e2774b07a089c325dbf9d193325a1bf78592e7f3877dfdb643f4898d89a154aa17054cea7270b8b3cc4a7a1145988b0d8a5a974c7086f0e28a6af22a536f55f languageName: node linkType: hard "fast-xml-parser@npm:^5.3.6": - version: 5.4.2 - resolution: "fast-xml-parser@npm:5.4.2" - dependencies: - fast-xml-builder: "npm:^1.0.0" - strnum: "npm:^2.1.2" + version: 5.11.2 + resolution: "fast-xml-parser@npm:5.11.2" + dependencies: + "@nodable/entities": "npm:^3.0.1" + fast-xml-builder: "npm:^1.2.0" + is-unsafe: "npm:^2.0.0" + path-expression-matcher: "npm:^1.6.2" + strnum: "npm:^2.4.2" + xml-naming: "npm:^0.3.0" bin: fxparser: src/cli/cli.js - checksum: 10/12585d5dd77113411d01cf41818cfecbbaf8f3d9e8448b1c35f50a7eb51205408bc8db27af5733173a77f96f72d7e121d9e675674f71334569157c77845aba39 + checksum: 10/aa88bd2af831876b458a51c302a84f83a92bbd747606a1f0a85f7085461e2f3c52cb7438f4ef2dc136fbcb0cb33d450d007178a24b23c148d8a84b5ccfb70c58 languageName: node linkType: hard @@ -7758,15 +6934,6 @@ __metadata: languageName: node linkType: hard -"fd-package-json@npm:^2.0.0": - version: 2.0.0 - resolution: "fd-package-json@npm:2.0.0" - dependencies: - walk-up-path: "npm:^4.0.0" - checksum: 10/e595a1a23f8e208815cdcf26c92218240da00acce80468324408dc4a5cb6c26b6efb5076f0458a02f044562a1e60253731187a627d5416b4961468ddfc0ae426 - languageName: node - linkType: hard - "fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -7843,9 +7010,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.4 - resolution: "flatted@npm:3.3.4" - checksum: 10/185b93176da0f54a97f88f56f9b8bccca9cbbb6ff1caaf264ae8b6ee4d3c041d7df131301060208695d7b573925dbee7162951be5ffd1efb5b6969495e83dba8 + version: 3.4.4 + resolution: "flatted@npm:3.4.4" + checksum: 10/5a6682ab87ed15e125419c61352c4bef26f310adceece03eae5f22c119d64ed47bfc0ee1948a77d0122559eaa86395ea06ef45b59bfe3db4fb13fb4cdff876de languageName: node linkType: hard @@ -8020,13 +7187,6 @@ __metadata: languageName: node linkType: hard -"get-east-asian-width@npm:^1.5.0": - version: 1.5.0 - resolution: "get-east-asian-width@npm:1.5.0" - checksum: 10/60bc34cd1e975055ab99f0f177e31bed3e516ff7cee9c536474383954a976abaa6b94a51d99ad158ef1e372790fa096cab7d07f166bb0778f6587954c0fbe946 - languageName: node - linkType: hard - "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": version: 1.3.1 resolution: "get-intrinsic@npm:1.3.1" @@ -8081,13 +7241,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^8.0.1": - version: 8.0.1 - resolution: "get-stream@npm:8.0.1" - checksum: 10/dde5511e2e65a48e9af80fea64aff11b4921b14b6e874c6f8294c50975095af08f41bfb0b680c887f28b566dd6ec2cb2f960f9d36a323359be324ce98b766e9e - languageName: node - linkType: hard - "get-symbol-description@npm:^1.1.0": version: 1.1.0 resolution: "get-symbol-description@npm:1.1.0" @@ -8099,62 +7252,15 @@ __metadata: languageName: node linkType: hard -"get-uri@npm:^6.0.1": - version: 6.0.5 - resolution: "get-uri@npm:6.0.5" - dependencies: - basic-ftp: "npm:^5.0.2" - data-uri-to-buffer: "npm:^6.0.2" - debug: "npm:^4.3.4" - checksum: 10/6daa56eb367dc030ae7bf6db4b5d36f200c9bb47ab00593c142176e4f33f22e129a294ac94329c6bcaebda19b7506080267a336742d20a915fb2bef9c400347f - languageName: node - linkType: hard - -"giget@npm:^2.0.0": - version: 2.0.0 - resolution: "giget@npm:2.0.0" - dependencies: - citty: "npm:^0.1.6" - consola: "npm:^3.4.0" - defu: "npm:^6.1.4" - node-fetch-native: "npm:^1.6.6" - nypm: "npm:^0.6.0" - pathe: "npm:^2.0.3" - bin: - giget: dist/cli.mjs - checksum: 10/3ee0f4aa06bdaeda9d4d31791d6a1e4349f15e20ff1dbe60535c709d3acc03f29f36a648cd047851a332fc1a0e9997ab6c5036410cc1629c09ad45ee155ee6dd - languageName: node - linkType: hard - -"git-raw-commits@npm:^4.0.0": - version: 4.0.0 - resolution: "git-raw-commits@npm:4.0.0" +"git-raw-commits@npm:^5.0.0": + version: 5.0.1 + resolution: "git-raw-commits@npm:5.0.1" dependencies: - dargs: "npm:^8.0.0" - meow: "npm:^12.0.1" - split2: "npm:^4.0.0" + "@conventional-changelog/git-client": "npm:^2.6.0" + meow: "npm:^13.0.0" bin: - git-raw-commits: cli.mjs - checksum: 10/95546f4afcb33cf00ff638f7fec55ad61d4d927447737900e1f6fcbbdbb341b3f150908424cc62acb6d9faaea6f1e8f55d0697b899f0589af9d2733afb20abfb - languageName: node - linkType: hard - -"git-up@npm:^8.1.0": - version: 8.1.1 - resolution: "git-up@npm:8.1.1" - dependencies: - is-ssh: "npm:^1.4.0" - parse-url: "npm:^9.2.0" - checksum: 10/475bfb816ee6003c505f25f2d6859148eedf684b2381f59774a8b4baf279d603710b888ecd1c5f5619fd7a582b131c2c52f8d247d59c7cc10bb7f7edffc704f7 - languageName: node - linkType: hard - -"git-url-parse@npm:16.1.0": - version: 16.1.0 - resolution: "git-url-parse@npm:16.1.0" - dependencies: - git-up: "npm:^8.1.0" - checksum: 10/1522e86ce89bb854ac5eaab13e71f9a72e93c4eb9897559d9731e03b700a7e2d38d16a77dddede9f79c8dac6f50633e2e420702bb1677580e797312e9b55379d + git-raw-commits: src/cli.js + checksum: 10/15073e815e6deabcaf28077ea93d8aad3b3062e6bff6a66e71e096c63cb0c6eb2a1e480be7dac9b99789c04bbf77805a0d555465457680e50946074ff408deb9 languageName: node linkType: hard @@ -8217,12 +7323,12 @@ __metadata: languageName: node linkType: hard -"global-directory@npm:^4.0.1": - version: 4.0.1 - resolution: "global-directory@npm:4.0.1" +"global-directory@npm:^5.0.0": + version: 5.0.0 + resolution: "global-directory@npm:5.0.0" dependencies: - ini: "npm:4.1.1" - checksum: 10/5b4df24438a4e5f21e43fbdd9e54f5e12bb48dce01a0a83b415d8052ce91be2d3a97e0c8f98a535e69649b2190036155e9f0f7d3c62f9318f31bdc3fd4f235f5 + ini: "npm:6.0.0" + checksum: 10/90b61b09736a8c6fea010e87bf42cefefe534ce6d5c21c09ab9eb06edc0082dfc41edf0d31da5f7355e9a07eae9c5238d4ecc01ac425d8456cbce9bd1b292dc2 languageName: node linkType: hard @@ -8285,24 +7391,6 @@ __metadata: languageName: node linkType: hard -"handlebars@npm:^4.7.7": - version: 4.7.8 - resolution: "handlebars@npm:4.7.8" - dependencies: - minimist: "npm:^1.2.5" - neo-async: "npm:^2.6.2" - source-map: "npm:^0.6.1" - uglify-js: "npm:^3.1.4" - wordwrap: "npm:^1.0.0" - dependenciesMeta: - uglify-js: - optional: true - bin: - handlebars: bin/handlebars - checksum: 10/bd528f4dd150adf67f3f857118ef0fa43ff79a153b1d943fa0a770f2599e38b25a7a0dbac1a3611a4ec86970fd2325a81310fb788b5c892308c9f8743bd02e11 - languageName: node - linkType: hard - "has-bigints@npm:^1.0.2": version: 1.1.0 resolution: "has-bigints@npm:1.1.0" @@ -8447,15 +7535,6 @@ __metadata: languageName: node linkType: hard -"hosted-git-info@npm:^8.0.0": - version: 8.1.0 - resolution: "hosted-git-info@npm:8.1.0" - dependencies: - lru-cache: "npm:^10.0.1" - checksum: 10/872a1f3b5da6bff9d99410b96cf7ecb6415ef7d8c8842579cfb690144f40be4581cc4ea50d978829a5fc1ef0b1097151a722d14f905beaf3f09330e8ca40fa4c - languageName: node - linkType: hard - "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -8464,13 +7543,13 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.1": - version: 4.2.0 - resolution: "http-cache-semantics@npm:4.2.0" - checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 + version: 4.3.0 + resolution: "http-cache-semantics@npm:4.3.0" + checksum: 10/3f7b17565d3a046f069ecfc220d790ccfbef4a94a486502c5d1a23c50d71880393175416845579487a91bfefca393614d16a99bd566d474807a4ebb1139da9cd languageName: node linkType: hard -"http-errors@npm:^2.0.0, http-errors@npm:~2.0.1": +"http-errors@npm:^2.0.1, http-errors@npm:~2.0.1": version: 2.0.1 resolution: "http-errors@npm:2.0.1" dependencies: @@ -8483,7 +7562,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.1": +"http-proxy-agent@npm:^7.0.0": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" dependencies: @@ -8493,7 +7572,7 @@ __metadata: languageName: node linkType: hard -"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.5, https-proxy-agent@npm:^7.0.6": +"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.5": version: 7.0.6 resolution: "https-proxy-agent@npm:7.0.6" dependencies: @@ -8517,14 +7596,7 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^5.0.0": - version: 5.0.0 - resolution: "human-signals@npm:5.0.0" - checksum: 10/30f8870d831cdcd2d6ec0486a7d35d49384996742052cee792854273fa9dd9e7d5db06bb7985d4953e337e10714e994e0302e90dc6848069171b05ec836d65b0 - languageName: node - linkType: hard - -"iconv-lite@npm:^0.7.0, iconv-lite@npm:^0.7.2, iconv-lite@npm:~0.7.0": +"iconv-lite@npm:^0.7.2, iconv-lite@npm:~0.7.0": version: 0.7.2 resolution: "iconv-lite@npm:0.7.2" dependencies: @@ -8625,30 +7697,10 @@ __metadata: languageName: node linkType: hard -"ini@npm:4.1.1": - version: 4.1.1 - resolution: "ini@npm:4.1.1" - checksum: 10/64c7102301742a7527bb17257d18451410eacf63b4b5648a20e108816c355c21c4e8a1761bbcbf3fe8c4ded3297f1b832b885d5e3e485d781e293ebfaf56fea6 - languageName: node - linkType: hard - -"inquirer@npm:12.11.1": - version: 12.11.1 - resolution: "inquirer@npm:12.11.1" - dependencies: - "@inquirer/ansi": "npm:^1.0.2" - "@inquirer/core": "npm:^10.3.2" - "@inquirer/prompts": "npm:^7.10.1" - "@inquirer/type": "npm:^3.0.10" - mute-stream: "npm:^2.0.0" - run-async: "npm:^4.0.6" - rxjs: "npm:^7.8.2" - peerDependencies: - "@types/node": ">=18" - peerDependenciesMeta: - "@types/node": - optional: true - checksum: 10/1405b1a10e3d49bc992965ebe003cfa2b2a61004f2274e251bec636013f4821b84f50bf526bc5c7e79d377650e2d2bbbb0b9916e9e2c4f087fe90c4a572c950c +"ini@npm:6.0.0": + version: 6.0.0 + resolution: "ini@npm:6.0.0" + checksum: 10/e87d8cde86d091ddb104580d42dfdc8306593627269990ca0f5176ccc60c936268bad56856398fef924cdf0af33b1a9c21e84f85914820037e003ee45443cc85 languageName: node linkType: hard @@ -8673,9 +7725,9 @@ __metadata: linkType: hard "ip-address@npm:^10.0.1": - version: 10.1.0 - resolution: "ip-address@npm:10.1.0" - checksum: 10/a6979629d1ad9c1fb424bc25182203fad739b40225aebc55ec6243bbff5035faf7b9ed6efab3a097de6e713acbbfde944baacfa73e11852bb43989c45a68d79e + version: 10.7.3 + resolution: "ip-address@npm:10.7.3" + checksum: 10/04655aa25ad682bb26ecb82281c9d3ecd99da8ecde9c95146f0a96685de90a359432d905bf6c53b5732fed0bfb1f93763cd3c91c3f266eec96cc41bfea987197 languageName: node linkType: hard @@ -8785,15 +7837,6 @@ __metadata: languageName: node linkType: hard -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: 10/b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 - languageName: node - linkType: hard - "is-extglob@npm:^2.1.1": version: 2.1.1 resolution: "is-extglob@npm:2.1.1" @@ -8873,17 +7916,6 @@ __metadata: languageName: node linkType: hard -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: "npm:^3.0.0" - bin: - is-inside-container: cli.js - checksum: 10/c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 - languageName: node - linkType: hard - "is-interactive@npm:^1.0.0": version: 1.0.0 resolution: "is-interactive@npm:1.0.0" @@ -8891,13 +7923,6 @@ __metadata: languageName: node linkType: hard -"is-interactive@npm:^2.0.0": - version: 2.0.0 - resolution: "is-interactive@npm:2.0.0" - checksum: 10/e8d52ad490bed7ae665032c7675ec07732bbfe25808b0efbc4d5a76b1a1f01c165f332775c63e25e9a03d319ebb6b24f571a9e902669fc1e40b0a60b5be6e26c - languageName: node - linkType: hard - "is-map@npm:^2.0.3": version: 2.0.3 resolution: "is-map@npm:2.0.3" @@ -9015,15 +8040,6 @@ __metadata: languageName: node linkType: hard -"is-ssh@npm:^1.4.0": - version: 1.4.1 - resolution: "is-ssh@npm:1.4.1" - dependencies: - protocols: "npm:^2.0.1" - checksum: 10/f60910cd83fa94e9874655a672c3849312c12af83c0fe3dbff9945755fe838a73985d8f94e32ebf5626ba4148ee10eef51b7240b0218dbb6e9a43a06899b0529 - languageName: node - linkType: hard - "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -9031,13 +8047,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^3.0.0": - version: 3.0.0 - resolution: "is-stream@npm:3.0.0" - checksum: 10/172093fe99119ffd07611ab6d1bcccfe8bc4aa80d864b15f43e63e54b7abc71e779acd69afdb854c4e2a67fdc16ae710e370eda40088d1cfc956a50ed82d8f16 - languageName: node - linkType: hard - "is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" @@ -9084,10 +8093,10 @@ __metadata: languageName: node linkType: hard -"is-unicode-supported@npm:^2.0.0, is-unicode-supported@npm:^2.1.0": - version: 2.1.0 - resolution: "is-unicode-supported@npm:2.1.0" - checksum: 10/f254e3da6b0ab1a57a94f7273a7798dd35d1d45b227759f600d0fa9d5649f9c07fa8d3c8a6360b0e376adf916d151ec24fc9a50c5295c58bae7ca54a76a063f9 +"is-unsafe@npm:^2.0.0": + version: 2.0.2 + resolution: "is-unsafe@npm:2.0.2" + checksum: 10/ebd5b9abfa1e66b221649c9e7f6ed5f1de51dc9913a5c35b192be81b2aeeccb99ef97ae11535d1aa32817e43f73538fb9271c709148f634173b78cebe2eebd2e languageName: node linkType: hard @@ -9140,15 +8149,6 @@ __metadata: languageName: node linkType: hard -"is-wsl@npm:^3.1.0": - version: 3.1.1 - resolution: "is-wsl@npm:3.1.1" - dependencies: - is-inside-container: "npm:^1.0.0" - checksum: 10/513d95b89af0e60b43d7b17ecb7eb78edea0a439136a3da37b1b56e215379cc46a9221474ad5b2de044824ca72d7869dee6e015273dc3f71f2bb87c715f9f1dc - languageName: node - linkType: hard - "isarray@npm:^2.0.5": version: 2.0.5 resolution: "isarray@npm:2.0.5" @@ -9170,19 +8170,6 @@ __metadata: languageName: node linkType: hard -"issue-parser@npm:7.0.1": - version: 7.0.1 - resolution: "issue-parser@npm:7.0.1" - dependencies: - lodash.capitalize: "npm:^4.2.1" - lodash.escaperegexp: "npm:^4.1.2" - lodash.isplainobject: "npm:^4.0.6" - lodash.isstring: "npm:^4.0.1" - lodash.uniqby: "npm:^4.7.0" - checksum: 10/04d14d987567008a270f5ed165e9464e131faf9c1d373b13c53bc7a1fe78b4e3aa91fcf2a1be2bac73983624084260b72957926fa35a1df4d60afbb61b645c95 - languageName: node - linkType: hard - "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -9762,15 +8749,15 @@ __metadata: linkType: hard "joi@npm:^17.2.1": - version: 17.13.3 - resolution: "joi@npm:17.13.3" + version: 17.13.8 + resolution: "joi@npm:17.13.8" dependencies: "@hapi/hoek": "npm:^9.3.0" "@hapi/topo": "npm:^5.1.0" "@sideway/address": "npm:^4.1.5" "@sideway/formula": "npm:^3.0.1" "@sideway/pinpoint": "npm:^2.0.0" - checksum: 10/4c150db0c820c3a52f4a55c82c1fc5e144a5b5f4da9ffebc7339a15469d1a447ebb427ced446efcb9709ab56bd71a06c4c67c9381bc1b9f9ae63fc7c89209bdf + checksum: 10/7d8ccb06cee958516748519cb46430b1bf5b732f54428a5daf8f8630290c928be1abb7d3c3c2506d68ba76d1c1abe480e087255c34b839aae47b2ee2c76f587d languageName: node linkType: hard @@ -9782,25 +8769,25 @@ __metadata: linkType: hard "js-yaml@npm:^3.13.1": - version: 3.14.2 - resolution: "js-yaml@npm:3.14.2" + version: 3.15.2 + resolution: "js-yaml@npm:3.15.2" dependencies: argparse: "npm:^1.0.7" esprima: "npm:^4.0.0" bin: js-yaml: bin/js-yaml.js - checksum: 10/172e0b6007b0bf0fc8d2469c94424f7dd765c64a047d2b790831fecef2204a4054eabf4d911eb73ab8c9a3256ab8ba1ee8d655b789bf24bf059c772acc2075a1 + checksum: 10/320b5471c1b7309a15d9c0068ba273e2da7382a369038a9746c92ef649087c3d6d2a5c676810154efb4eb2ca9584179c8ae14e2fc2e4bd558d964e6bf4fafd3d languageName: node linkType: hard -"js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1": - version: 4.1.1 - resolution: "js-yaml@npm:4.1.1" +"js-yaml@npm:^4.1.0, js-yaml@npm:^4.1.1, js-yaml@npm:^4.3.2": + version: 4.3.2 + resolution: "js-yaml@npm:4.3.2" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10/a52d0519f0f4ef5b4adc1cde466cb54c50d56e2b4a983b9d5c9c0f2f99462047007a6274d7e95617a21d3c91fde3ee6115536ed70991cd645ba8521058b78f77 + checksum: 10/05c44b9c73e4901d92703b155e76518df64bf01ac62e4c036b47de4b391e19b72e32656e8954d51b436307f08cc9d0c0d4ec617d061cf2f65fffee9f3114bee7 languageName: node linkType: hard @@ -9855,13 +8842,6 @@ __metadata: languageName: node linkType: hard -"json-with-bigint@npm:^3.5.3": - version: 3.5.7 - resolution: "json-with-bigint@npm:3.5.7" - checksum: 10/7f8c9e81e0bd1c5015ec9aad986f5b5101bceb7accf0cc17d56f81a3d2d0ac9438a051c33f4e767a98ece07b50f7f9d579c0f711cdfdeca314a6a59d6214a8a9 - languageName: node - linkType: hard - "json5@npm:^2.2.1, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" @@ -9932,12 +8912,12 @@ __metadata: linkType: hard "launch-editor@npm:^2.9.1": - version: 2.13.1 - resolution: "launch-editor@npm:2.13.1" + version: 2.14.2 + resolution: "launch-editor@npm:2.14.2" dependencies: picocolors: "npm:^1.1.1" - shell-quote: "npm:^1.8.3" - checksum: 10/641aafaad6bafe5d33a13d89eff29082b032c1c5c1aa19fb9fa3b54ffcf26a3419f461a7583f6450bd5b11863b061b60049e38c2d5135492bf46f2ed3a2cbc0e + shell-quote: "npm:^1.10.0" + checksum: 10/8a3a82314ed6705d8f6795c409ea31ed2a106d0f0bc0528a60f8b53ec972cce1db9088bb4647987b2ef4bb16b804fcc85e54529acaa26aae22f39eaba704401b languageName: node linkType: hard @@ -10094,20 +9074,6 @@ __metadata: languageName: node linkType: hard -"lodash.camelcase@npm:^4.3.0": - version: 4.3.0 - resolution: "lodash.camelcase@npm:4.3.0" - checksum: 10/c301cc379310441dc73cd6cebeb91fb254bea74e6ad3027f9346fc43b4174385153df420ffa521654e502fd34c40ef69ca4e7d40ee7129a99e06f306032bfc65 - languageName: node - linkType: hard - -"lodash.capitalize@npm:^4.2.1": - version: 4.2.1 - resolution: "lodash.capitalize@npm:4.2.1" - checksum: 10/54d61121bd040212954faee94703a999282987a104fab4ea6a85027d5fb2ce482a737478b76d292d07753da1c15911541adf0f6db840abf121c4cab85b92e962 - languageName: node - linkType: hard - "lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -10115,62 +9081,13 @@ __metadata: languageName: node linkType: hard -"lodash.escaperegexp@npm:^4.1.2": - version: 4.1.2 - resolution: "lodash.escaperegexp@npm:4.1.2" - checksum: 10/6d99452b1cfd6073175a9b741a9b09ece159eac463f86f02ea3bee2e2092923fce812c8d2bf446309cc52d1d61bf9af51c8118b0d7421388e6cead7bd3798f0f - languageName: node - linkType: hard - -"lodash.isplainobject@npm:^4.0.6": - version: 4.0.6 - resolution: "lodash.isplainobject@npm:4.0.6" - checksum: 10/29c6351f281e0d9a1d58f1a4c8f4400924b4c79f18dfc4613624d7d54784df07efaff97c1ff2659f3e085ecf4fff493300adc4837553104cef2634110b0d5337 - languageName: node - linkType: hard - -"lodash.isstring@npm:^4.0.1": - version: 4.0.1 - resolution: "lodash.isstring@npm:4.0.1" - checksum: 10/eaac87ae9636848af08021083d796e2eea3d02e80082ab8a9955309569cb3a463ce97fd281d7dc119e402b2e7d8c54a23914b15d2fc7fff56461511dc8937ba0 - languageName: node - linkType: hard - -"lodash.kebabcase@npm:^4.1.1": - version: 4.1.1 - resolution: "lodash.kebabcase@npm:4.1.1" - checksum: 10/d84ec5441ef8e5c718c50315f35b0a045a77c7e8ee3e54472c06dc31f6f3602e95551a16c0923d689198b51deb8902c4bbc54fc9b965b26c1f86e21df3a05f34 - languageName: node - linkType: hard - -"lodash.merge@npm:4.6.2, lodash.merge@npm:^4.6.2": +"lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2" checksum: 10/d0ea2dd0097e6201be083865d50c3fb54fbfbdb247d9cc5950e086c991f448b7ab0cdab0d57eacccb43473d3f2acd21e134db39f22dac2d6c9ba6bf26978e3d6 languageName: node linkType: hard -"lodash.mergewith@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.mergewith@npm:4.6.2" - checksum: 10/aea75a4492541a4902ac7e551dc6c54b722da0c187f84385d02e8fc33a7ae3454b837822446e5f63fcd5ad1671534ea408740b776670ea4d9c7890b10105fce0 - languageName: node - linkType: hard - -"lodash.snakecase@npm:^4.1.1": - version: 4.1.1 - resolution: "lodash.snakecase@npm:4.1.1" - checksum: 10/82ed40935d840477ef8fee64f9f263f75989c6cde36b84aae817246d95826228e1b5a7f6093c51de324084f86433634c7af244cb89496633cacfe443071450d0 - languageName: node - linkType: hard - -"lodash.startcase@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.startcase@npm:4.4.0" - checksum: 10/3091048a54a2f92bcf2c6441d2bd9a706fb133d5f461ae7c310d6dca1530338a06c91e9e42a5b14b12e875ddae1814d448050dc02afe2cec09b3995d8e836837 - languageName: node - linkType: hard - "lodash.throttle@npm:^4.1.1": version: 4.1.1 resolution: "lodash.throttle@npm:4.1.1" @@ -10178,24 +9095,10 @@ __metadata: languageName: node linkType: hard -"lodash.uniqby@npm:^4.7.0": - version: 4.7.0 - resolution: "lodash.uniqby@npm:4.7.0" - checksum: 10/256616bd1bd6be84d8a5eceb61338a0ab8d8b34314ba7bfd5f0de35227d0e2c1e659c61ff4ac31eba6a664085cc7e397bc34c3534fba208102db660a4f98f211 - languageName: node - linkType: hard - -"lodash.upperfirst@npm:^4.3.1": - version: 4.3.1 - resolution: "lodash.upperfirst@npm:4.3.1" - checksum: 10/3e849d4eb4dbf26faee6435edda8e707b65a5dbd2f10f8def5a16a57bbbf38d3b7506950f0dd455e9c46ba73af35f1de75df4ef83952106949413d64eed59333 - languageName: node - linkType: hard - -"lodash@npm:^4.15.0, lodash@npm:^4.17.21": - version: 4.17.23 - resolution: "lodash@npm:4.17.23" - checksum: 10/82504c88250f58da7a5a4289f57a4f759c44946c005dd232821c7688b5fcfbf4a6268f6a6cdde4b792c91edd2f3b5398c1d2a0998274432cff76def48735e233 +"lodash@npm:^4.17.21": + version: 4.18.1 + resolution: "lodash@npm:4.18.1" + checksum: 10/306fea53dfd39dad1f03d45ba654a2405aebd35797b673077f401edb7df2543623dc44b9effbb98f69b32152295fff725a4cec99c684098947430600c6af0c3f languageName: node linkType: hard @@ -10209,16 +9112,6 @@ __metadata: languageName: node linkType: hard -"log-symbols@npm:^7.0.1": - version: 7.0.1 - resolution: "log-symbols@npm:7.0.1" - dependencies: - is-unicode-supported: "npm:^2.0.0" - yoctocolors: "npm:^2.1.1" - checksum: 10/0862313d84826b551582e39659b8586c56b65130c5f4f976420e2c23985228334f2a26fc4251ac22bf0a5b415d9430e86bf332557d934c10b036f9a549d63a09 - languageName: node - linkType: hard - "logkitty@npm:^0.7.1": version: 0.7.1 resolution: "logkitty@npm:0.7.1" @@ -10243,7 +9136,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a @@ -10266,20 +9159,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.14.1": - version: 7.18.3 - resolution: "lru-cache@npm:7.18.3" - checksum: 10/6029ca5aba3aacb554e919d7ef804fffd4adfc4c83db00fac8248c7c78811fb6d4b6f70f7fd9d55032b3823446546a007edaa66ad1f2377ae833bd983fac5d98 - languageName: node - linkType: hard - -"macos-release@npm:^3.3.0": - version: 3.4.0 - resolution: "macos-release@npm:3.4.0" - checksum: 10/f4c0cb8b3f93b05d73c502b4bbe2b811c44facfc9bd072c13a30ff2a8ba1cad5d9de517d10be8b31e2b917643245a81587a2eec8300e66a7364419d11402ab02 - languageName: node - linkType: hard - "make-dir@npm:^4.0.0": version: 4.0.0 resolution: "make-dir@npm:4.0.0" @@ -10370,7 +9249,7 @@ __metadata: version: 0.0.0-use.local resolution: "mendix-native@workspace:." dependencies: - "@commitlint/config-conventional": "npm:20.4.3" + "@commitlint/config-conventional": "npm:20.5.0" "@eslint/compat": "npm:1.4.1" "@eslint/eslintrc": "npm:3.3.5" "@eslint/js": "npm:9.39.4" @@ -10380,10 +9259,9 @@ __metadata: "@react-native/babel-preset": "npm:0.88.0-rc.3" "@react-native/eslint-config": "npm:0.88.0-rc.3" "@react-native/jest-preset": "npm:0.88.0-rc.3" - "@release-it/conventional-changelog": "npm:10.0.5" "@types/jest": "npm:29.5.14" "@types/react": "npm:19.3.0" - commitlint: "npm:20.4.3" + commitlint: "npm:20.5.0" del-cli: "npm:7.0.0" eslint: "npm:9.39.4" eslint-config-prettier: "npm:10.1.8" @@ -10395,8 +9273,6 @@ __metadata: react-native: "npm:0.88.0-rc.3" react-native-builder-bob: "npm:0.40.18" react-native-gesture-handler: "npm:2.33.0" - release-it: "npm:19.2.4" - turbo: "npm:2.8.21" typescript: "npm:5.9.3" peerDependencies: "@op-engineering/op-sqlite": "*" @@ -10407,13 +9283,6 @@ __metadata: languageName: unknown linkType: soft -"meow@npm:^12.0.1": - version: 12.1.1 - resolution: "meow@npm:12.1.1" - checksum: 10/8594c319f4671a562c1fef584422902f1bbbad09ea49cdf9bb26dc92f730fa33398dd28a8cf34fcf14167f1d1148d05a867e50911fc4286751a4fb662fdd2dc2 - languageName: node - linkType: hard - "meow@npm:^13.0.0": version: 13.2.0 resolution: "meow@npm:13.2.0" @@ -10919,7 +9788,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:3.0.2, mime-types@npm:^3.0.0, mime-types@npm:^3.0.1": +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.1": version: 3.0.2 resolution: "mime-types@npm:3.0.2" dependencies: @@ -10962,20 +9831,6 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: 10/995dcece15ee29aa16e188de6633d43a3db4611bcf93620e7e62109ec41c79c0f34277165b8ce5e361205049766e371851264c21ac64ca35499acb5421c2ba56 - languageName: node - linkType: hard - -"mimic-function@npm:^5.0.0": - version: 5.0.1 - resolution: "mimic-function@npm:5.0.1" - checksum: 10/eb5893c99e902ccebbc267c6c6b83092966af84682957f79313311edb95e8bb5f39fb048d77132b700474d1c86d90ccc211e99bae0935447a4834eb4c882982c - languageName: node - linkType: hard - "minimatch@npm:^10.2.2": version: 10.2.4 resolution: "minimatch@npm:10.2.4" @@ -11003,7 +9858,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.5, minimist@npm:^1.2.8": +"minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f @@ -11100,13 +9955,6 @@ __metadata: languageName: node linkType: hard -"mute-stream@npm:^2.0.0": - version: 2.0.0 - resolution: "mute-stream@npm:2.0.0" - checksum: 10/d2e4fd2f5aa342b89b98134a8d899d8ef9b0a6d69274c4af9df46faa2d97aeb1f2ce83d867880d6de63643c52386579b99139801e24e7526c3b9b0a6d1e18d6c - languageName: node - linkType: hard - "nano-spawn@npm:^1.0.2": version: 1.0.3 resolution: "nano-spawn@npm:1.0.3" @@ -11142,29 +9990,6 @@ __metadata: languageName: node linkType: hard -"neo-async@npm:^2.6.2": - version: 2.6.2 - resolution: "neo-async@npm:2.6.2" - checksum: 10/1a7948fea86f2b33ec766bc899c88796a51ba76a4afc9026764aedc6e7cde692a09067031e4a1bf6db4f978ccd99e7f5b6c03fe47ad9865c3d4f99050d67e002 - languageName: node - linkType: hard - -"netmask@npm:^2.0.2": - version: 2.0.2 - resolution: "netmask@npm:2.0.2" - checksum: 10/375cabe898a5832816958664f26206f0a1e9f3605aa1816bfce803e060ff20f9d6ce56a2377e46f1470938358c31c27b3a8086f4a5e3ef678896147884d63ffa - languageName: node - linkType: hard - -"new-github-release-url@npm:2.0.0": - version: 2.0.0 - resolution: "new-github-release-url@npm:2.0.0" - dependencies: - type-fest: "npm:^2.5.1" - checksum: 10/3d4ae0f3b775623ceed8e558b6f9850e897aea981a9c937d3ad4e018669c829beccb2c4b5a6af996726ebf86c5b7638368dfc01f3ac2e395d1df29309bc0c5ca - languageName: node - linkType: hard - "nocache@npm:^3.0.1": version: 3.0.4 resolution: "nocache@npm:3.0.4" @@ -11191,13 +10016,6 @@ __metadata: languageName: node linkType: hard -"node-fetch-native@npm:^1.6.6": - version: 1.6.7 - resolution: "node-fetch-native@npm:1.6.7" - checksum: 10/b8a99e6adafbdbdd9373a6784c467ca5c7b95eeed4896ee2d604f0729962fda8d07cf7a85edd1e8bb3ee51e791dc55c30cbebeb46cbd1f086d74141b3769a680 - languageName: node - linkType: hard - "node-gyp@npm:latest": version: 12.2.0 resolution: "node-gyp@npm:12.2.0" @@ -11225,10 +10043,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.27": - version: 2.0.27 - resolution: "node-releases@npm:2.0.27" - checksum: 10/f6c78ddb392ae500719644afcbe68a9ea533242c02312eb6a34e8478506eb7482a3fb709c70235b01c32fe65625b68dfa9665113f816d87f163bc3819b62b106 +"node-releases@npm:^2.0.57": + version: 2.0.57 + resolution: "node-releases@npm:2.0.57" + checksum: 10/aaffaea5ab8885f88df52ce5f96d59737f9d3fe122ae65cd94caf8876628ff2260afabcfaec04d0ec64f4f52994d99f888ea8a2373cf2203ef8c2b3b14314ce6 languageName: node linkType: hard @@ -11250,17 +10068,6 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^7.0.0": - version: 7.0.1 - resolution: "normalize-package-data@npm:7.0.1" - dependencies: - hosted-git-info: "npm:^8.0.0" - semver: "npm:^7.3.5" - validate-npm-package-license: "npm:^3.0.4" - checksum: 10/8150d7e663303fb5b06b616416b512812c5805a7a2ed34272448beb000bc8fdfdb0aeea0c997f875a326bc0b8fa263819f765902dc67dd0f5c6b4350ebc22821 - languageName: node - linkType: hard - "normalize-path@npm:^3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -11277,15 +10084,6 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^5.1.0": - version: 5.3.0 - resolution: "npm-run-path@npm:5.3.0" - dependencies: - path-key: "npm:^4.0.0" - checksum: 10/ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 - languageName: node - linkType: hard - "nullthrows@npm:^1.1.1": version: 1.1.1 resolution: "nullthrows@npm:1.1.1" @@ -11293,19 +10091,6 @@ __metadata: languageName: node linkType: hard -"nypm@npm:^0.6.0": - version: 0.6.5 - resolution: "nypm@npm:0.6.5" - dependencies: - citty: "npm:^0.2.0" - pathe: "npm:^2.0.3" - tinyexec: "npm:^1.0.2" - bin: - nypm: dist/cli.mjs - checksum: 10/8151c6923c58b2010796c3a68eb7efef189fa651642f4f8232dc0b87042785bbc545b63820db7273fe1253ed416f4fac09d1f31dd12dfd0fa6764c8b0d58504d - languageName: node - linkType: hard - "ob1@npm:0.84.4": version: 0.84.4 resolution: "ob1@npm:0.84.4" @@ -11395,13 +10180,6 @@ __metadata: languageName: node linkType: hard -"ohash@npm:^2.0.11": - version: 2.0.11 - resolution: "ohash@npm:2.0.11" - checksum: 10/6b0423f42cc95c3d643f390a88364aac824178b7788dccb4e8c64e2124463d0069e60d4d90bad88ed9823808368d051e088aa27058ca4722b1397a201ffbfa4b - languageName: node - linkType: hard - "on-finished@npm:^2.4.1, on-finished@npm:~2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -11445,36 +10223,6 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^6.0.0": - version: 6.0.0 - resolution: "onetime@npm:6.0.0" - dependencies: - mimic-fn: "npm:^4.0.0" - checksum: 10/0846ce78e440841335d4e9182ef69d5762e9f38aa7499b19f42ea1c4cd40f0b4446094c455c713f9adac3f4ae86f613bb5e30c99e52652764d06a89f709b3788 - languageName: node - linkType: hard - -"onetime@npm:^7.0.0": - version: 7.0.0 - resolution: "onetime@npm:7.0.0" - dependencies: - mimic-function: "npm:^5.0.0" - checksum: 10/eb08d2da9339819e2f9d52cab9caf2557d80e9af8c7d1ae86e1a0fef027d00a88e9f5bd67494d350df360f7c559fbb44e800b32f310fb989c860214eacbb561c - languageName: node - linkType: hard - -"open@npm:10.2.0": - version: 10.2.0 - resolution: "open@npm:10.2.0" - dependencies: - default-browser: "npm:^5.2.1" - define-lazy-prop: "npm:^3.0.0" - is-inside-container: "npm:^1.0.0" - wsl-utils: "npm:^0.1.0" - checksum: 10/e6ad9474734eac3549dcc7d85e952394856ccaee48107c453bd6a725b82e3b8ed5f427658935df27efa76b411aeef62888edea8a9e347e8e7c82632ec966b30e - languageName: node - linkType: hard - "open@npm:^6.2.0": version: 6.4.0 resolution: "open@npm:6.4.0" @@ -11509,23 +10257,6 @@ __metadata: languageName: node linkType: hard -"ora@npm:9.0.0": - version: 9.0.0 - resolution: "ora@npm:9.0.0" - dependencies: - chalk: "npm:^5.6.2" - cli-cursor: "npm:^5.0.0" - cli-spinners: "npm:^3.2.0" - is-interactive: "npm:^2.0.0" - is-unicode-supported: "npm:^2.1.0" - log-symbols: "npm:^7.0.1" - stdin-discarder: "npm:^0.2.2" - string-width: "npm:^8.1.0" - strip-ansi: "npm:^7.1.2" - checksum: 10/b6074c9cec4a39c1b4f41c2ce2741982a99c53c86bd6f07a28fb6274857263af7fe1a340136629939934b553af35b03fc62ca2a88baa6803b2f9bfdf269fb850 - languageName: node - linkType: hard - "ora@npm:^5.4.1": version: 5.4.1 resolution: "ora@npm:5.4.1" @@ -11543,16 +10274,6 @@ __metadata: languageName: node linkType: hard -"os-name@npm:6.1.0": - version: 6.1.0 - resolution: "os-name@npm:6.1.0" - dependencies: - macos-release: "npm:^3.3.0" - windows-release: "npm:^6.1.0" - checksum: 10/d69a2060bea01dc502bd9a08802f43bebce85e95adde7740d0629a8522c16a92c05e0ee052819cac49f82aa61324ff038a3b79e015e26f122bbc08b40aa4ead3 - languageName: node - linkType: hard - "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -11632,32 +10353,6 @@ __metadata: languageName: node linkType: hard -"pac-proxy-agent@npm:^7.1.0": - version: 7.2.0 - resolution: "pac-proxy-agent@npm:7.2.0" - dependencies: - "@tootallnate/quickjs-emscripten": "npm:^0.23.0" - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - get-uri: "npm:^6.0.1" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.6" - pac-resolver: "npm:^7.0.1" - socks-proxy-agent: "npm:^8.0.5" - checksum: 10/187656be62d5a6b983d90a86d64106a38b1a9ee78f591fabb27b3cf0d51e5d528456a9faaaf981c93dd54dc9c9ee8d33e35a51072b73a19ec1a8e0d0c36a2b99 - languageName: node - linkType: hard - -"pac-resolver@npm:^7.0.1": - version: 7.0.1 - resolution: "pac-resolver@npm:7.0.1" - dependencies: - degenerator: "npm:^5.0.0" - netmask: "npm:^2.0.2" - checksum: 10/839134328781b80d49f9684eae1f5c74f50a1d4482076d44c84fc2f3ca93da66fa11245a4725a057231e06b311c20c989fd0681e662a0792d17f644d8fe62a5e - languageName: node - linkType: hard - "package-json-from-dist@npm:^1.0.0": version: 1.0.1 resolution: "package-json-from-dist@npm:1.0.1" @@ -11686,25 +10381,6 @@ __metadata: languageName: node linkType: hard -"parse-path@npm:^7.0.0": - version: 7.1.0 - resolution: "parse-path@npm:7.1.0" - dependencies: - protocols: "npm:^2.0.0" - checksum: 10/6da6c6803fa73bacfee98e694c6c95fa55caae632c765369e4fd917f1043ef71f35ecaae420ef0e39e933bd1f939c4bc1e01522b62145191cdbe72e58d37a8ab - languageName: node - linkType: hard - -"parse-url@npm:^9.2.0": - version: 9.2.0 - resolution: "parse-url@npm:9.2.0" - dependencies: - "@types/parse-path": "npm:^7.0.0" - parse-path: "npm:^7.0.0" - checksum: 10/d2746f0dbcd34d39df966a0726c00ede272aa34d825513baca721ad95480786c664f91ab22cf4e79cdb130468056e41834f6c9cc912b9180539f73aa5bafa982 - languageName: node - linkType: hard - "parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -11719,6 +10395,13 @@ __metadata: languageName: node linkType: hard +"path-expression-matcher@npm:^1.6.2": + version: 1.6.2 + resolution: "path-expression-matcher@npm:1.6.2" + checksum: 10/d7786b170933dd82ed897144daed7d54dbe2e7b7d8684182ee9bf51a966cc92548788e2f49280922202a0186409008d816aefa37ed4650e4038184181a73c4bd + languageName: node + linkType: hard + "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -11733,13 +10416,6 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 10/8e6c314ae6d16b83e93032c61020129f6f4484590a777eed709c4a01b50e498822b00f76ceaf94bc64dbd90b327df56ceadce27da3d83393790f1219e07721d7 - languageName: node - linkType: hard - "path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -11781,20 +10457,6 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^2.0.3": - version: 2.0.3 - resolution: "pathe@npm:2.0.3" - checksum: 10/01e9a69928f39087d96e1751ce7d6d50da8c39abf9a12e0ac2389c42c83bc76f78c45a475bd9026a02e6a6f79be63acc75667df855862fe567d99a00a540d23d - languageName: node - linkType: hard - -"perfect-debounce@npm:^2.0.0": - version: 2.1.0 - resolution: "perfect-debounce@npm:2.1.0" - checksum: 10/1e45b92ab585fa1bfafaf01783b693b6d164a4da3b80865487f716a010d95e3d8b1131693258e342da25da671312c194cddb103c4743161f57dcf26574273fe6 - languageName: node - linkType: hard - "picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -11803,16 +10465,16 @@ __metadata: linkType: hard "picomatch@npm:^2.0.4, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 10/60c2595003b05e4535394d1da94850f5372c9427ca4413b71210f437f7b2ca091dbd611c45e8b37d10036fa8eade25c1b8951654f9d3973bfa66a2ff4d3b08bc + version: 2.3.2 + resolution: "picomatch@npm:2.3.2" + checksum: 10/b788ef8148a2415b9dec12f0bb350ae6a5830f8f1950e472abc2f5225494debf7d1b75eb031df0ceaea9e8ec3e7bad599e8dbf3c60d61b42be429ba41bff4426 languageName: node linkType: hard "picomatch@npm:^4.0.2, picomatch@npm:^4.0.3": - version: 4.0.3 - resolution: "picomatch@npm:4.0.3" - checksum: 10/57b99055f40b16798f2802916d9c17e9744e620a0db136554af01d19598b96e45e2f00014c91d1b8b13874b80caa8c295b3d589a3f72373ec4aaf54baa5962d5 + version: 4.0.7 + resolution: "picomatch@npm:4.0.7" + checksum: 10/66e1df34bc39c72fa3756be4069f7887ea3e35e94bba1c3f6167763007698cb04b8a0a365161d186fda6e9571a2d3efb606b2966eb6a7dea6252911224dc2f48 languageName: node linkType: hard @@ -11843,17 +10505,6 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^2.3.0": - version: 2.3.0 - resolution: "pkg-types@npm:2.3.0" - dependencies: - confbox: "npm:^0.2.2" - exsolve: "npm:^1.0.7" - pathe: "npm:^2.0.3" - checksum: 10/4b36e4eb12693a1beb145573c564ec6fb74b1008d3b457eaa1f0072331edf05cb7c479c47fe0c4bfdec76c2caff5b68215ff270e5fe49634c07984a7a0197118 - languageName: node - linkType: hard - "pngjs@npm:^7.0.0": version: 7.0.0 resolution: "pngjs@npm:7.0.0" @@ -11959,36 +10610,6 @@ __metadata: languageName: node linkType: hard -"protocols@npm:^2.0.0, protocols@npm:^2.0.1": - version: 2.0.2 - resolution: "protocols@npm:2.0.2" - checksum: 10/031cc068eb800468a50eb7c1e1c528bf142fb8314f5df9b9ea3c3f9df1697a19f97b9915b1229cef694d156812393172d9c3051ef7878d26eaa8c6faa5cccec4 - languageName: node - linkType: hard - -"proxy-agent@npm:6.5.0": - version: 6.5.0 - resolution: "proxy-agent@npm:6.5.0" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - http-proxy-agent: "npm:^7.0.1" - https-proxy-agent: "npm:^7.0.6" - lru-cache: "npm:^7.14.1" - pac-proxy-agent: "npm:^7.1.0" - proxy-from-env: "npm:^1.1.0" - socks-proxy-agent: "npm:^8.0.5" - checksum: 10/56d5a494d96dafad94868870af776939e7b9aaca172465a5c251d2523496a8353b029c32d2a72a012bd62622cdc9a43ba3df59b5738ab7b740bc6b362e9f9477 - languageName: node - linkType: hard - -"proxy-from-env@npm:^1.1.0": - version: 1.1.0 - resolution: "proxy-from-env@npm:1.1.0" - checksum: 10/f0bb4a87cfd18f77bc2fba23ae49c3b378fb35143af16cc478171c623eebe181678f09439707ad80081d340d1593cd54a33a0113f3ccb3f4bc9451488780ee23 - languageName: node - linkType: hard - "pump@npm:^3.0.0": version: 3.0.4 resolution: "pump@npm:3.0.4" @@ -12013,12 +10634,13 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.14.1": - version: 6.15.0 - resolution: "qs@npm:6.15.0" +"qs@npm:^6.15.2": + version: 6.16.0 + resolution: "qs@npm:6.16.0" dependencies: - side-channel: "npm:^1.1.0" - checksum: 10/a3458f2f389285c3512e0ebc55522ee370ac7cb720ba9f0eff3e30fb2bb07631caf556c08e2a3d4481a371ac14faa9ceb7442a0610c5a7e55b23a5bdee7b701c + es-define-property: "npm:^1.0.1" + side-channel: "npm:^1.1.1" + checksum: 10/7fbf9c2eb9c9bbd8997700caecc4b057ac259635873deefd5027fb26d06d79426cf468da55da87ffd147a24e93d3641352d8ac6664bd84688ad5b2f0b8d04828 languageName: node linkType: hard @@ -12045,7 +10667,7 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:^3.0.1": +"raw-body@npm:^3.0.2": version: 3.0.2 resolution: "raw-body@npm:3.0.2" dependencies: @@ -12057,16 +10679,6 @@ __metadata: languageName: node linkType: hard -"rc9@npm:^2.1.2": - version: 2.1.2 - resolution: "rc9@npm:2.1.2" - dependencies: - defu: "npm:^6.1.4" - destr: "npm:^2.0.3" - checksum: 10/0694d2a80579983a5e4f0452092d9f6a06b785b104b32f48f3d6bb263f637e53d9ebd1fd77a41b157b84c1c7e8e4ecc87c3824907738653a296e6d2faf3d1844 - languageName: node - linkType: hard - "react-devtools-core@npm:^6.1.5": version: 6.1.5 resolution: "react-devtools-core@npm:6.1.5" @@ -12235,7 +10847,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.0.2, readable-stream@npm:^3.4.0": +"readable-stream@npm:^3.4.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" dependencies: @@ -12246,13 +10858,6 @@ __metadata: languageName: node linkType: hard -"readdirp@npm:^5.0.0": - version: 5.0.0 - resolution: "readdirp@npm:5.0.0" - checksum: 10/a17a591b51d8b912083660df159e8bd17305dc1a9ef27c869c818bd95ff59e3a6496f97e91e724ef433e789d559d24e39496ea1698822eb5719606dc9c1a923d - languageName: node - linkType: hard - "reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9": version: 1.0.10 resolution: "reflect.getprototypeof@npm:1.0.10" @@ -12338,39 +10943,6 @@ __metadata: languageName: node linkType: hard -"release-it@npm:19.2.4": - version: 19.2.4 - resolution: "release-it@npm:19.2.4" - dependencies: - "@nodeutils/defaults-deep": "npm:1.1.0" - "@octokit/rest": "npm:22.0.1" - "@phun-ky/typeof": "npm:2.0.3" - async-retry: "npm:1.3.3" - c12: "npm:3.3.3" - ci-info: "npm:^4.3.1" - eta: "npm:4.5.0" - git-url-parse: "npm:16.1.0" - inquirer: "npm:12.11.1" - issue-parser: "npm:7.0.1" - lodash.merge: "npm:4.6.2" - mime-types: "npm:3.0.2" - new-github-release-url: "npm:2.0.0" - open: "npm:10.2.0" - ora: "npm:9.0.0" - os-name: "npm:6.1.0" - proxy-agent: "npm:6.5.0" - semver: "npm:7.7.3" - tinyglobby: "npm:0.2.15" - undici: "npm:6.23.0" - url-join: "npm:5.0.0" - wildcard-match: "npm:5.1.4" - yargs-parser: "npm:21.1.1" - bin: - release-it: bin/release-it.js - checksum: 10/f47ad2c379ff6c651500899cdf1434d3449f51ae686cc692af21b5964459b3365f3dd143f45834cfa52e2fcb97d5613eee127f456b3d3e9dfa7b2ea1514b133d - languageName: node - linkType: hard - "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -12490,17 +11062,7 @@ __metadata: languageName: node linkType: hard -"restore-cursor@npm:^5.0.0": - version: 5.1.0 - resolution: "restore-cursor@npm:5.1.0" - dependencies: - onetime: "npm:^7.0.0" - signal-exit: "npm:^4.1.0" - checksum: 10/838dd54e458d89cfbc1a923b343c1b0f170a04100b4ce1733e97531842d7b440463967e521216e8ab6c6f8e89df877acc7b7f4c18ec76e99fb9bf5a60d358d2c - languageName: node - linkType: hard - -"retry@npm:0.13.1, retry@npm:^0.13.1": +"retry@npm:^0.13.1": version: 0.13.1 resolution: "retry@npm:0.13.1" checksum: 10/6125ec2e06d6e47e9201539c887defba4e47f63471db304c59e4b82fc63c8e89ca06a77e9d34939a9a42a76f00774b2f46c0d4a4cbb3e287268bd018ed69426d @@ -12525,20 +11087,6 @@ __metadata: languageName: node linkType: hard -"run-applescript@npm:^7.0.0": - version: 7.1.0 - resolution: "run-applescript@npm:7.1.0" - checksum: 10/8659fb5f2717b2b37a68cbfe5f678254cf24b5a82a6df3372b180c80c7c137dcd757a4166c3887e459f59a090ca414e8ea7ca97cf3ee5123db54b3b4006d7b7a - languageName: node - linkType: hard - -"run-async@npm:^4.0.6": - version: 4.0.6 - resolution: "run-async@npm:4.0.6" - checksum: 10/d23929e36d0422b871a8964d5cfcb1b88295950ea5f72e1dfed458d4c3f3a33a7395e08167d8a4446f2110cfaac7d7653d9c804d2becab8afa8a63e16b97da81 - languageName: node - linkType: hard - "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -12548,15 +11096,6 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.8.2": - version: 7.8.2 - resolution: "rxjs@npm:7.8.2" - dependencies: - tslib: "npm:^2.1.0" - checksum: 10/03dff09191356b2b87d94fbc1e97c4e9eb3c09d4452399dddd451b09c2f1ba8d56925a40af114282d7bc0c6fe7514a2236ca09f903cf70e4bbf156650dddb49d - languageName: node - linkType: hard - "safe-array-concat@npm:^1.1.3": version: 1.1.3 resolution: "safe-array-concat@npm:1.1.3" @@ -12612,15 +11151,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.7.3": - version: 7.7.3 - resolution: "semver@npm:7.7.3" - bin: - semver: bin/semver.js - checksum: 10/8dbc3168e057a38fc322af909c7f5617483c50caddba135439ff09a754b20bdd6482a5123ff543dad4affa488ecf46ec5fb56d61312ad20bb140199b88dfaea9 - languageName: node - linkType: hard - "semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -12746,10 +11276,10 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.6.1, shell-quote@npm:^1.8.3": - version: 1.8.3 - resolution: "shell-quote@npm:1.8.3" - checksum: 10/5473e354637c2bd698911224129c9a8961697486cff1fb221f234d71c153fc377674029b0223d1d3c953a68d451d79366abfe53d1a0b46ee1f28eb9ade928f4c +"shell-quote@npm:^1.10.0, shell-quote@npm:^1.6.1": + version: 1.12.0 + resolution: "shell-quote@npm:1.12.0" + checksum: 10/18b3e382272804e79fd3187c18877cfd4e736b5afb576bf1ab66a561b0a0e26eada4b7c8eb45473d1f17268ffcf12d0aaa90b9235132123eb673df5d0a5df943 languageName: node linkType: hard @@ -12763,6 +11293,16 @@ __metadata: languageName: node linkType: hard +"side-channel-list@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-list@npm:1.0.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + checksum: 10/3499671cd52adaee739eac1e14d07530b8e3530192741aeb05e7fe4ad1b51d1368ceea2cd3c21b0f62b05410a5c70a7c4d997ba4b143303ef73d0c65dfd1c252 + languageName: node + linkType: hard + "side-channel-map@npm:^1.0.1": version: 1.0.1 resolution: "side-channel-map@npm:1.0.1" @@ -12801,6 +11341,19 @@ __metadata: languageName: node linkType: hard +"side-channel@npm:^1.1.1": + version: 1.1.1 + resolution: "side-channel@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + side-channel-list: "npm:^1.0.1" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10/5fa6393ff6ad25d8b4a38e9ba095481e498c8ebe5ab78481c1455146255a3d18ca37a6f936595cc671a6149134cdc295bbd2fa017620bdc73cbc7380634fa2fc + languageName: node + linkType: hard + "signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" @@ -12808,7 +11361,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": +"signal-exit@npm:^4.0.1": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 10/c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f @@ -12854,7 +11407,7 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^8.0.3, socks-proxy-agent@npm:^8.0.5": +"socks-proxy-agent@npm:^8.0.3": version: 8.0.5 resolution: "socks-proxy-agent@npm:8.0.5" dependencies: @@ -12902,54 +11455,13 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": +"source-map@npm:^0.6.0, source-map@npm:^0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" checksum: 10/59ef7462f1c29d502b3057e822cdbdae0b0e565302c4dd1a95e11e793d8d9d62006cdc10e0fd99163ca33ff2071360cf50ee13f90440806e7ed57d81cba2f7ff languageName: node linkType: hard -"spdx-correct@npm:^3.0.0": - version: 3.2.0 - resolution: "spdx-correct@npm:3.2.0" - dependencies: - spdx-expression-parse: "npm:^3.0.0" - spdx-license-ids: "npm:^3.0.0" - checksum: 10/cc2e4dbef822f6d12142116557d63f5facf3300e92a6bd24e907e4865e17b7e1abd0ee6b67f305cae6790fc2194175a24dc394bfcc01eea84e2bdad728e9ae9a - languageName: node - linkType: hard - -"spdx-exceptions@npm:^2.1.0": - version: 2.5.0 - resolution: "spdx-exceptions@npm:2.5.0" - checksum: 10/bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 - languageName: node - linkType: hard - -"spdx-expression-parse@npm:^3.0.0": - version: 3.0.1 - resolution: "spdx-expression-parse@npm:3.0.1" - dependencies: - spdx-exceptions: "npm:^2.1.0" - spdx-license-ids: "npm:^3.0.0" - checksum: 10/a1c6e104a2cbada7a593eaa9f430bd5e148ef5290d4c0409899855ce8b1c39652bcc88a725259491a82601159d6dc790bedefc9016c7472f7de8de7361f8ccde - languageName: node - linkType: hard - -"spdx-license-ids@npm:^3.0.0": - version: 3.0.23 - resolution: "spdx-license-ids@npm:3.0.23" - checksum: 10/fead6be44478e4dd73a0721ae569f4a04f358846d8d82e8d92efae64aca928592e380cf17e8b84c25c948f3a7d8a0b4fc781a1830f3911ca87d52733265176b5 - languageName: node - linkType: hard - -"split2@npm:^4.0.0": - version: 4.2.0 - resolution: "split2@npm:4.2.0" - checksum: 10/09bbefc11bcf03f044584c9764cd31a252d8e52cea29130950b26161287c11f519807c5e54bd9e5804c713b79c02cefe6a98f4688630993386be353e03f534ab - languageName: node - linkType: hard - "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -13012,13 +11524,6 @@ __metadata: languageName: node linkType: hard -"stdin-discarder@npm:^0.2.2": - version: 0.2.2 - resolution: "stdin-discarder@npm:0.2.2" - checksum: 10/642ffd05bd5b100819d6b24a613d83c6e3857c6de74eb02fc51506fa61dc1b0034665163831873868157c4538d71e31762bcf319be86cea04c3aba5336470478 - languageName: node - linkType: hard - "stop-iteration-iterator@npm:^1.1.0": version: 1.1.0 resolution: "stop-iteration-iterator@npm:1.1.0" @@ -13068,16 +11573,6 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^8.1.0": - version: 8.2.0 - resolution: "string-width@npm:8.2.0" - dependencies: - get-east-asian-width: "npm:^1.5.0" - strip-ansi: "npm:^7.1.2" - checksum: 10/c4f62877ec08fca155e84a260eb4f58f473cfe5169bd1c1e21ffb563d8e0b7f6d705cc3d250f2ed6bb4f30ee9732ad026f54afaac77aa487e3d1dc1b1969e51b - languageName: node - linkType: hard - "string.prototype.matchall@npm:^4.0.12": version: 4.0.12 resolution: "string.prototype.matchall@npm:4.0.12" @@ -13174,7 +11669,7 @@ __metadata: languageName: node linkType: hard -"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.2": +"strip-ansi@npm:^7.0.1": version: 7.2.0 resolution: "strip-ansi@npm:7.2.0" dependencies: @@ -13197,13 +11692,6 @@ __metadata: languageName: node linkType: hard -"strip-final-newline@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-final-newline@npm:3.0.0" - checksum: 10/23ee263adfa2070cd0f23d1ac14e2ed2f000c9b44229aec9c799f1367ec001478469560abefd00c5c99ee6f0b31c137d53ec6029c53e9f32a93804e18c201050 - languageName: node - linkType: hard - "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -13211,10 +11699,12 @@ __metadata: languageName: node linkType: hard -"strnum@npm:^2.1.2": - version: 2.2.0 - resolution: "strnum@npm:2.2.0" - checksum: 10/2969dbc8441f5af1b55db1d2fcea64a8f912de18515b57f85574e66bdb8f30ae76c419cf1390b343d72d687e2aea5aca82390f18b9e0de45d6bcc6d605eb9385 +"strnum@npm:^2.4.2": + version: 2.4.2 + resolution: "strnum@npm:2.4.2" + dependencies: + anynum: "npm:^1.0.1" + checksum: 10/c624b2f1a4ba0962cfa66e645b583782e868d0f0ab2e038c3c554e81c2040c3e48463d1e078ff1d6ab4932a0b352f34bc51fdd4f8bbd9bf8da66bf9332c85cf4 languageName: node linkType: hard @@ -13253,15 +11743,15 @@ __metadata: linkType: hard "tar@npm:^7.5.4": - version: 7.5.9 - resolution: "tar@npm:7.5.9" + version: 7.5.22 + resolution: "tar@npm:7.5.22" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10/1213cdde9c22d6acf8809ba5d2a025212ce3517bc99c4a4c6981b7dc0489bf3b164db9c826c9517680889194c9ba57448c8ff0da35eca9a60bb7689bf0b3897d + checksum: 10/129606384b3c895f422aaca48bf316357be6dc7aa35c1066c3f06c28acfff0be5b356e1b0a0be7c53a7a8945534ac06cec6d8e296d170d8a09c8bff67b29300e languageName: node linkType: hard @@ -13297,14 +11787,14 @@ __metadata: languageName: node linkType: hard -"tinyexec@npm:^1.0.0, tinyexec@npm:^1.0.2": +"tinyexec@npm:^1.0.0": version: 1.0.2 resolution: "tinyexec@npm:1.0.2" checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405 languageName: node linkType: hard -"tinyglobby@npm:0.2.15, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -13362,42 +11852,13 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.3.0": +"tslib@npm:^2.3.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 languageName: node linkType: hard -"turbo@npm:2.8.21": - version: 2.8.21 - resolution: "turbo@npm:2.8.21" - dependencies: - "@turbo/darwin-64": "npm:2.8.21" - "@turbo/darwin-arm64": "npm:2.8.21" - "@turbo/linux-64": "npm:2.8.21" - "@turbo/linux-arm64": "npm:2.8.21" - "@turbo/windows-64": "npm:2.8.21" - "@turbo/windows-arm64": "npm:2.8.21" - dependenciesMeta: - "@turbo/darwin-64": - optional: true - "@turbo/darwin-arm64": - optional: true - "@turbo/linux-64": - optional: true - "@turbo/linux-arm64": - optional: true - "@turbo/windows-64": - optional: true - "@turbo/windows-arm64": - optional: true - bin: - turbo: bin/turbo - checksum: 10/f7f6e391b9babae5da3275e7c63cad481c4362b0559b8769739f43d6cec216458924482b8635744cdda5ed4916e06db2f4fd847a6203de3c8095ecac0d8a6d5d - languageName: node - linkType: hard - "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -13428,21 +11889,14 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^2.5.1": - version: 2.19.0 - resolution: "type-fest@npm:2.19.0" - checksum: 10/7bf9e8fdf34f92c8bb364c0af14ca875fac7e0183f2985498b77be129dc1b3b1ad0a6b3281580f19e48c6105c037fb966ad9934520c69c6434d17fd0af4eed78 - languageName: node - linkType: hard - -"type-is@npm:^2.0.1": - version: 2.0.1 - resolution: "type-is@npm:2.0.1" +"type-is@npm:^2.1.0": + version: 2.1.0 + resolution: "type-is@npm:2.1.0" dependencies: - content-type: "npm:^1.0.5" + content-type: "npm:^2.0.0" media-typer: "npm:^1.1.0" mime-types: "npm:^3.0.0" - checksum: 10/bacdb23c872dacb7bd40fbd9095e6b2fca2895eedbb689160c05534d7d4810a7f4b3fd1ae87e96133c505958f6d602967a68db5ff577b85dd6be76eaa75d58af + checksum: 10/f011885fefb6c6882f36fab89cc596596b96eab1d208a3774628537cad7ce1f91232a6d758115e1a6ed03f0f8c21e9654bb6d280a5c6827ff72a35f6df0fa182 languageName: node linkType: hard @@ -13499,13 +11953,6 @@ __metadata: languageName: node linkType: hard -"typedarray@npm:^0.0.6": - version: 0.0.6 - resolution: "typedarray@npm:0.0.6" - checksum: 10/2cc1bcf7d8c1237f6a16c04efc06637b2c5f2d74e58e84665445cf87668b85a21ab18dd751fa49eee6ae024b70326635d7b79ad37b1c370ed2fec6aeeeb52714 - languageName: node - linkType: hard - "typescript@npm:5.9.3": version: 5.9.3 resolution: "typescript@npm:5.9.3" @@ -13526,15 +11973,6 @@ __metadata: languageName: node linkType: hard -"uglify-js@npm:^3.1.4": - version: 3.19.3 - resolution: "uglify-js@npm:3.19.3" - bin: - uglifyjs: bin/uglifyjs - checksum: 10/6b9639c1985d24580b01bb0ab68e78de310d38eeba7db45bec7850ab4093d8ee464d80ccfaceda9c68d1c366efbee28573b52f95e69ac792354c145acd380b11 - languageName: node - linkType: hard - "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -13561,13 +11999,6 @@ __metadata: languageName: node linkType: hard -"undici@npm:6.23.0": - version: 6.23.0 - resolution: "undici@npm:6.23.0" - checksum: 10/56950995e7b628e62c996430445d17995ca9b70f6f2afe760a63da54205660d968bd08f0741b6f4fb008f40aa35c69cce979cd96ced399585d8c897a76a4f1d1 - languageName: node - linkType: hard - "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.1 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1" @@ -13624,13 +12055,6 @@ __metadata: languageName: node linkType: hard -"universal-user-agent@npm:^7.0.0, universal-user-agent@npm:^7.0.2": - version: 7.0.3 - resolution: "universal-user-agent@npm:7.0.3" - checksum: 10/c497e85f8b11eb8fa4dce584d7a39cc98710164959f494cafc3c269b51abb20fff269951838efd7424d15f6b3d001507f3cb8b52bb5676fdb642019dfd17e63e - languageName: node - linkType: hard - "universalify@npm:^0.1.0": version: 0.1.2 resolution: "universalify@npm:0.1.2" @@ -13652,9 +12076,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.2.0": - version: 1.2.3 - resolution: "update-browserslist-db@npm:1.2.3" +"update-browserslist-db@npm:^1.3.3": + version: 1.3.3 + resolution: "update-browserslist-db@npm:1.3.3" dependencies: escalade: "npm:^3.2.0" picocolors: "npm:^1.1.1" @@ -13662,7 +12086,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10/059f774300efb4b084a49293143c511f3ae946d40397b5c30914e900cd5691a12b8e61b41dd54ed73d3b56c8204165a0333107dd784ccf8f8c81790bcc423175 + checksum: 10/c60c18c53ba53915b377830db55049cd3ee31129633b4e386d2e48f9a1a15ade7503a80a57dd11d66cbac583a8ad3f2d61e938895b1c2155323fd4367530f5b2 languageName: node linkType: hard @@ -13675,13 +12099,6 @@ __metadata: languageName: node linkType: hard -"url-join@npm:5.0.0": - version: 5.0.0 - resolution: "url-join@npm:5.0.0" - checksum: 10/5921384a8ad4395b49ce4b50aa26efbc429cebe0bc8b3660ad693dd12fd859747b5369be0443e60e53a7850b2bc9d7d0687bcb94386662b40e743596bbf38101 - languageName: node - linkType: hard - "use-sync-external-store@npm:^1.6.0": version: 1.6.0 resolution: "use-sync-external-store@npm:1.6.0" @@ -13716,16 +12133,6 @@ __metadata: languageName: node linkType: hard -"validate-npm-package-license@npm:^3.0.4": - version: 3.0.4 - resolution: "validate-npm-package-license@npm:3.0.4" - dependencies: - spdx-correct: "npm:^3.0.0" - spdx-expression-parse: "npm:^3.0.0" - checksum: 10/86242519b2538bb8aeb12330edebb61b4eb37fd35ef65220ab0b03a26c0592c1c8a7300d32da3cde5abd08d18d95e8dabfad684b5116336f6de9e6f207eec224 - languageName: node - linkType: hard - "vary@npm:~1.1.2": version: 1.1.2 resolution: "vary@npm:1.1.2" @@ -13740,13 +12147,6 @@ __metadata: languageName: node linkType: hard -"walk-up-path@npm:^4.0.0": - version: 4.0.0 - resolution: "walk-up-path@npm:4.0.0" - checksum: 10/6a230b20e5de296895116dc12b09dafaec1f72b8060c089533d296e241aff059dfaebe0d015c77467f857e4b40c78e08f7481add76f340233a1f34fa8af9ed63 - languageName: node - linkType: hard - "walker@npm:^1.0.7, walker@npm:^1.0.8": version: 1.0.8 resolution: "walker@npm:1.0.8" @@ -13880,22 +12280,6 @@ __metadata: languageName: node linkType: hard -"wildcard-match@npm:5.1.4": - version: 5.1.4 - resolution: "wildcard-match@npm:5.1.4" - checksum: 10/4a6821e91def808a38aa7c7c2e774c5b6dc8c6eb37743f18fae182802af52f19f19375de1bc1d465ff1e6b188489eab2716bf3eba1789b25b3f495f55e10fc57 - languageName: node - linkType: hard - -"windows-release@npm:^6.1.0": - version: 6.1.0 - resolution: "windows-release@npm:6.1.0" - dependencies: - execa: "npm:^8.0.1" - checksum: 10/2af39c94d5e4e250c3239e70177f3a97291c505e364b85a7ae63ca9d06c91496e8bd3a75c55e03184d9c27e58c0a0fa21a4a8457ac72cc560d8796a75f12d0a3 - languageName: node - linkType: hard - "word-wrap@npm:^1.2.5": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" @@ -13903,13 +12287,6 @@ __metadata: languageName: node linkType: hard -"wordwrap@npm:^1.0.0": - version: 1.0.0 - resolution: "wordwrap@npm:1.0.0" - checksum: 10/497d40beb2bdb08e6d38754faa17ce20b0bf1306327f80cb777927edb23f461ee1f6bc659b3c3c93f26b08e1cf4b46acc5bae8fda1f0be3b5ab9a1a0211034cd - languageName: node - linkType: hard - "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -13961,17 +12338,17 @@ __metadata: linkType: hard "ws@npm:^6.2.3": - version: 6.2.3 - resolution: "ws@npm:6.2.3" + version: 6.2.6 + resolution: "ws@npm:6.2.6" dependencies: async-limiter: "npm:~1.0.0" - checksum: 10/19f8d1608317f4c98f63da6eebaa85260a6fe1ba459cbfedd83ebe436368177fb1e2944761e2392c6b7321cbb7a375c8a81f9e1be35d555b6b4647eb61eadd46 + checksum: 10/2a3cb5d0a96c5792f0dc230f6f5c696c996e2a83caef4593190128f92bcc1eeaa11f6acc80c7f6196bad044c94348caea705b36cbefc420fbff43858226958f9 languageName: node linkType: hard "ws@npm:^7, ws@npm:^7.5.10": - version: 7.5.10 - resolution: "ws@npm:7.5.10" + version: 7.5.13 + resolution: "ws@npm:7.5.13" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -13980,13 +12357,13 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/9c796b84ba80ffc2c2adcdfc9c8e9a219ba99caa435c9a8d45f9ac593bba325563b3f83edc5eb067cc6d21b9a6bf2c930adf76dd40af5f58a5ca6859e81858f0 + checksum: 10/0873c813ce75c466b026ce0a4ce9a8b5b5f1dc9ef0dd7ae9690fa4025c66afb165d3a45550357080b29d66a0e3028cd13c72ccefc83ce10723b4822a574ebc99 languageName: node linkType: hard "ws@npm:^8.18.2": - version: 8.19.0 - resolution: "ws@npm:8.19.0" + version: 8.22.0 + resolution: "ws@npm:8.22.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -13995,16 +12372,14 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/26e4901e93abaf73af9f26a93707c95b4845e91a7a347ec8c569e6e9be7f9df066f6c2b817b2d685544e208207898a750b78461e6e8d810c11a370771450c31b + checksum: 10/ed771c2766bdb5724a66872f60ffc1a39f06e1a5bc8849f453c273e97c91a40ed5a224f06dc0e22f44b4a9e03938bf746fc5938d6887433cc0f4c416237d3b10 languageName: node linkType: hard -"wsl-utils@npm:^0.1.0": - version: 0.1.0 - resolution: "wsl-utils@npm:0.1.0" - dependencies: - is-wsl: "npm:^3.1.0" - checksum: 10/de4c92187e04c3c27b4478f410a02e81c351dc85efa3447bf1666f34fc80baacd890a6698ec91995631714086992036013286aea3d77e6974020d40a08e00aec +"xml-naming@npm:^0.3.0": + version: 0.3.0 + resolution: "xml-naming@npm:0.3.0" + checksum: 10/1a09c3f14747bf243d4bbcfdb9917c40e9cbb4b6464f2b9fe6927976770dfa38eedfe94190b5b6db470f22429fd4bda688b1831ca36a769a6745ccb9bb595150 languageName: node linkType: hard @@ -14044,18 +12419,11 @@ __metadata: linkType: hard "yaml@npm:^2.2.1, yaml@npm:^2.6.1": - version: 2.8.2 - resolution: "yaml@npm:2.8.2" + version: 2.9.1 + resolution: "yaml@npm:2.9.1" bin: yaml: bin.mjs - checksum: 10/4eab0074da6bc5a5bffd25b9b359cf7061b771b95d1b3b571852098380db3b1b8f96e0f1f354b56cc7216aa97cea25163377ccbc33a2e9ce00316fe8d02f4539 - languageName: node - linkType: hard - -"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.1.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: 10/9dc2c217ea3bf8d858041252d43e074f7166b53f3d010a8c711275e09cd3d62a002969a39858b92bbda2a6a63a585c7127014534a560b9c69ed2d923d113406e + checksum: 10/123c5e56a26f4962d3d5954971b2071a533d17041e00ae9ff6a5e634aed2503639bbdeea143b1610eac29613aad95a3a1d10f5fbda87b92203c039ce63934295 languageName: node linkType: hard @@ -14069,6 +12437,13 @@ __metadata: languageName: node linkType: hard +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10/9dc2c217ea3bf8d858041252d43e074f7166b53f3d010a8c711275e09cd3d62a002969a39858b92bbda2a6a63a585c7127014534a560b9c69ed2d923d113406e + languageName: node + linkType: hard + "yargs@npm:^15.1.0": version: 15.4.1 resolution: "yargs@npm:15.4.1" @@ -14117,20 +12492,6 @@ __metadata: languageName: node linkType: hard -"yoctocolors-cjs@npm:^2.1.3": - version: 2.1.3 - resolution: "yoctocolors-cjs@npm:2.1.3" - checksum: 10/b2144b38807673a4254dae06fe1a212729550609e606289c305e45c585b36fab1dbba44fe6cde90db9b28be465ec63f4c2a50867aeec6672f6bc36b6c9a361a0 - languageName: node - linkType: hard - -"yoctocolors@npm:^2.1.1": - version: 2.1.2 - resolution: "yoctocolors@npm:2.1.2" - checksum: 10/6ee42d665a4cc161c7de3f015b2a65d6c65d2808bfe3b99e228bd2b1b784ef1e54d1907415c025fc12b400f26f372bfc1b71966c6c738d998325ca422eb39363 - languageName: node - linkType: hard - "zod-validation-error@npm:^3.5.0 || ^4.0.0": version: 4.0.2 resolution: "zod-validation-error@npm:4.0.2" From f93725be70e2d87626e6f7d6d1b57179aa6235c6 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Wed, 7 Oct 2026 12:21:53 +0530 Subject: [PATCH 10/10] revert: cookie encryption changes --- .../request/MendixNetworkInterceptor.kt | 53 ++++++++----------- .../mendixnative/request/CookieHelpersTest.kt | 33 ------------ 2 files changed, 23 insertions(+), 63 deletions(-) diff --git a/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt b/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt index 3699185..6cc6361 100644 --- a/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt +++ b/android/src/main/java/com/mendix/mendixnative/request/MendixNetworkInterceptor.kt @@ -33,42 +33,35 @@ const val encryptedCookieKeyPrefix = "MxEnc" // Prefix for encrypted cookie keys * Request extension to decrypt possibly encrypted cookies */ fun Request.withDecryptedCookies(): Request { - // Skip empty segments, e.g. from a trailing "; ". - val cookiePairs = this.header("Cookie")?.split(";")?.map { it.trim() }?.filter { it.isNotEmpty() } - ?: return this + val cookiePairs = this.header("Cookie")?.split("; ") val encryptedCookieExists = - cookiePairs.any { cookie -> cookie.startsWith(encryptedCookieKeyPrefix) } - val decryptedCookies = cookiePairs.mapNotNull { - if (!encryptedCookieExists) { - return@mapNotNull it - } + cookiePairs?.any { cookie -> cookie.startsWith(encryptedCookieKeyPrefix) } + val decryptedCookies = cookiePairs?.map { + val (key, value) = it.split("=", limit = 2) - // A cookie without "=" has no value, so it can't be an encrypted one. - val parts = it.split("=", limit = 2) - val key = parts[0] - val value = parts.getOrNull(1) - if (!key.startsWith(encryptedCookieKeyPrefix)) { - return@mapNotNull null + if (encryptedCookieExists!! && key.startsWith(encryptedCookieKeyPrefix)) { + try { + val params = cookieValueToDecryptionParams(value) + val decryptedValue = decryptValue(params.first, params.second) + return@map "${key.removePrefix(encryptedCookieKeyPrefix)}=$decryptedValue" + } catch (e: Exception) { + Log.w("MendixNetworkInterceptor", "Failed to decrypt cookie $key, dropping it", e) + return@map null + } + } else if (!encryptedCookieExists) { + return@map it; } - try { - val params = cookieValueToDecryptionParams( - value ?: throw IllegalArgumentException("Cookie has no value") - ) - val decryptedValue = decryptValue(params.first, params.second) - return@mapNotNull "${key.removePrefix(encryptedCookieKeyPrefix)}=$decryptedValue" - } catch (e: Exception) { - Log.w("MendixNetworkInterceptor", "Failed to decrypt cookie $key, dropping it", e) - return@mapNotNull null - } - }.joinToString(separator = "; ") + return@map null + }?.filterNotNull()?.joinToString(separator = "; ") + + return when { + decryptedCookies != null && decryptedCookies.isNotBlank() -> this.newBuilder() + .removeHeader("Cookie") + .addHeader("Cookie", decryptedCookies).build() - val builder = this.newBuilder().removeHeader("Cookie") - // When no cookie is left (e.g. none could be decrypted), send none rather than the encrypted ones. - if (decryptedCookies.isNotBlank()) { - builder.addHeader("Cookie", decryptedCookies) + else -> this } - return builder.build() } /** diff --git a/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt b/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt index f6a1e2a..523331c 100644 --- a/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt +++ b/android/src/test/java/com/mendix/mendixnative/request/CookieHelpersTest.kt @@ -2,15 +2,10 @@ package com.mendix.mendixnative.request import okhttp3.Request import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull import org.junit.Assert.assertSame import org.junit.Assert.assertTrue import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -// Robolectric because dropping an undecryptable cookie logs through android.util.Log. -@RunWith(RobolectricTestRunner::class) class CookieHelpersTest { private fun requestWithCookie(cookie: String) = Request.Builder().url("https://example.com").header("Cookie", cookie).build() @@ -60,32 +55,4 @@ class CookieHelpersTest { val request = requestWithCookie("a=1; b=2=3") assertEquals("a=1; b=2=3", request.withDecryptedCookies().header("Cookie")) } - - @Test - fun cookieWithoutValueIsKept() { - assertEquals("a=1; flag", requestWithCookie("a=1; flag").withDecryptedCookies().header("Cookie")) - } - - @Test - fun emptySegmentsAreSkipped() { - assertEquals("a=1", requestWithCookie("a=1; ").withDecryptedCookies().header("Cookie")) - assertEquals("a=1; b=2", requestWithCookie("a=1;;b=2").withDecryptedCookies().header("Cookie")) - } - - @Test - fun cookieWithEmptyNameIsKept() { - assertEquals("=1", requestWithCookie("=1").withDecryptedCookies().header("Cookie")) - } - - @Test - fun undecryptableCookiesAreNotForwarded() { - // Without an IV the value can't be decrypted. - assertNull(requestWithCookie("${encryptedCookieKeyPrefix}session=abc").withDecryptedCookies().header("Cookie")) - } - - @Test - fun plainCookiesAreDroppedWhenEncryptedOnesExist() { - val request = requestWithCookie("a=1; ${encryptedCookieKeyPrefix}session=abc; flag; ${encryptedCookieKeyPrefix}empty") - assertNull(request.withDecryptedCookies().header("Cookie")) - } }