diff --git a/.gitignore b/.gitignore index a46d06d84..27010c382 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,4 @@ dist/ yalc.lock # Perf tests -.reassure +.reassure \ No newline at end of file diff --git a/README.md b/README.md index 9d70edc9d..38a4d5294 100644 --- a/README.md +++ b/README.md @@ -423,4 +423,4 @@ you to edit the Onyx source directly in the Onyx repo, and have those changes ho Now you can make changes directly to the `react-native-onyx` source code and your React Native project should-hot reload with those changes in realtime. -_Note:_ If you want to unlink `react-native-onyx`, simply run `npm install` from your React Native project directory again. That will reinstall `react-native-onyx` from npm. +_Note:_ If you want to unlink `react-native-onyx`, simply run `npm install` from your React Native project directory again. That will reinstall `react-native-onyx` from npm. \ No newline at end of file diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 000000000..35d42adab --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.16) +project(OnyxNativeBufferStore LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# --------------------------------------------------------------------------- +# NativeBufferStore (C++ -- thread-safe buffer HybridObject) +# --------------------------------------------------------------------------- +# Pure buffer with std::shared_mutex. No SQLite, no background thread. +# The Worklet Worker Runtime handles persistence via react-native-nitro-sqlite. +add_library(onyx_native_buffer_store STATIC NativeBufferStore.cpp) +target_include_directories(onyx_native_buffer_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +# --------------------------------------------------------------------------- +# Test harness +# --------------------------------------------------------------------------- +if(BUILD_TESTING) + add_executable(native_buffer_store_test test_native_buffer_store.cpp) + target_link_libraries(native_buffer_store_test PRIVATE onyx_native_buffer_store) +endif() diff --git a/cpp/NativeBufferStore.cpp b/cpp/NativeBufferStore.cpp new file mode 100644 index 000000000..de5a78f77 --- /dev/null +++ b/cpp/NativeBufferStore.cpp @@ -0,0 +1,74 @@ +/** + * NativeBufferStore implementation. + * + * Pure thread-safe buffer -- no background thread, no SQLite. + * Uses std::shared_mutex for reader-writer locking: + * - shared_lock for reads (get, has, size, entries) + * - unique_lock for writes (set, erase, clear, drain) + */ + +#include "NativeBufferStore.h" + +#include + +namespace onyx { + +const NativeBufferEntry* NativeBufferStore::get(const std::string& key) { + std::shared_lock lock(mutex_); + auto it = buffer_.find(key); + if (it == buffer_.end()) { + return nullptr; + } + return &it->second; +} + +void NativeBufferStore::set(const std::string& key, NativeBufferEntry entry) { + std::unique_lock lock(mutex_); + buffer_[key] = std::move(entry); +} + +bool NativeBufferStore::erase(const std::string& key) { + std::unique_lock lock(mutex_); + return buffer_.erase(key) > 0; +} + +bool NativeBufferStore::has(const std::string& key) { + std::shared_lock lock(mutex_); + return buffer_.find(key) != buffer_.end(); +} + +size_t NativeBufferStore::size() { + std::shared_lock lock(mutex_); + return buffer_.size(); +} + +void NativeBufferStore::clear() { + std::unique_lock lock(mutex_); + buffer_.clear(); +} + +std::vector> NativeBufferStore::entries() { + std::shared_lock lock(mutex_); + std::vector> result; + result.reserve(buffer_.size()); + for (const auto& [key, entry] : buffer_) { + result.emplace_back(key, entry); + } + return result; +} + +std::vector> NativeBufferStore::drain() { + std::unique_lock lock(mutex_); + + // Move all entries out of the buffer atomically + std::vector> result; + result.reserve(buffer_.size()); + for (auto& [key, entry] : buffer_) { + result.emplace_back(std::move(key), std::move(entry)); + } + buffer_.clear(); + + return result; +} + +} // namespace onyx diff --git a/cpp/NativeBufferStore.h b/cpp/NativeBufferStore.h new file mode 100644 index 000000000..d80fe04c5 --- /dev/null +++ b/cpp/NativeBufferStore.h @@ -0,0 +1,142 @@ +/** + * NativeBufferStore -- Thread-safe buffer backed by a shared_mutex. + * + * This is the C++ backing store for the native (iOS/Android) BufferStore + * HybridObject. It provides a simple key-value buffer where: + * + * - The main JS thread populates entries via set() + * - The Worklet Worker Runtime drains all entries atomically via drain() + * + * Thread safety: + * - Read methods (get, has, size) use shared_lock (concurrent readers OK) + * - Write methods (set, erase, clear) use unique_lock (exclusive access) + * - drain() uses unique_lock and atomically swaps out the entire buffer + * + * This class stores values as AnyValue-equivalent C++ types (std::string + * for JSON, since the actual AnyMap-to-JSON serialization happens on the + * Worklet Worker Runtime side after draining). The Worklet Worker Runtime + * handles JSON.stringify and calls react-native-nitro-sqlite for persistence. + * + * Future optimization: store AnyMap values directly (no JSON strings) and + * serialize to JSON using Glaze on a pure C++ worker thread, eliminating + * the JS round-trip entirely. + */ + +#pragma once + +#include +#include +#include +#include + +namespace onyx { + +/** + * Entry types matching the TypeScript BufferEntry.entryType. + */ +enum class NativeEntryType { + Set, + Merge, +}; + +/** + * A single buffer entry, storing the key, JSON value, and type. + * + * The value is stored as a JSON string. In the current architecture, + * Nitro's JSIConverter converts JS objects to AnyValue (deep C++ copy) + * on the main thread. The Worklet Worker Runtime then calls drain(), + * converts AnyValue back to JS objects (on the worker thread), and + * JSON.stringifies them for SQLite persistence. + * + * For the C++ buffer, we store pre-serialized JSON strings since the + * BufferStore interface on the TS side handles the AnyMap -> JS + * conversion. This keeps the C++ side simple and focused on + * thread-safe buffering. + */ +struct NativeBufferEntry { + std::string key; + std::string valueJSON; + NativeEntryType entryType; + // replaceNullPatches stored as serialized JSON array string + std::string replaceNullPatchesJSON; +}; + +class NativeBufferStore { +public: + NativeBufferStore() = default; + ~NativeBufferStore() = default; + + // Non-copyable, non-movable + NativeBufferStore(const NativeBufferStore&) = delete; + NativeBufferStore& operator=(const NativeBufferStore&) = delete; + NativeBufferStore(NativeBufferStore&&) = delete; + NativeBufferStore& operator=(NativeBufferStore&&) = delete; + + // ----------------------------------------------------------------------- + // BufferStore interface (called from JS main thread via JSI) + // ----------------------------------------------------------------------- + + /** + * Get a buffer entry by key, or nullptr if not found. + * Thread-safe: acquires shared_lock (allows concurrent readers). + */ + const NativeBufferEntry* get(const std::string& key); + + /** + * Insert or replace a buffer entry. + * Thread-safe: acquires unique_lock (exclusive access). + */ + void set(const std::string& key, NativeBufferEntry entry); + + /** + * Delete a key from the buffer. + * Thread-safe: acquires unique_lock. + */ + bool erase(const std::string& key); + + /** + * Check if a key exists in the buffer. + * Thread-safe: acquires shared_lock. + */ + bool has(const std::string& key); + + /** + * Get the number of pending entries. + * Thread-safe: acquires shared_lock. + */ + size_t size(); + + /** + * Clear all pending entries. + * Thread-safe: acquires unique_lock. + */ + void clear(); + + /** + * Get a snapshot of all entries (for the TS side to iterate). + * Thread-safe: acquires shared_lock. + */ + std::vector> entries(); + + // ----------------------------------------------------------------------- + // Drain (called from Worklet Worker Runtime) + // ----------------------------------------------------------------------- + + /** + * Atomically drain all pending entries from the buffer. + * + * Returns all entries and clears the buffer in a single atomic operation. + * The lock is held only for the duration of a swap -- microseconds. + * The caller (Worklet Worker Runtime) gets sole ownership of the + * returned data and can take its time serializing and persisting. + * + * Thread-safe: acquires unique_lock. + */ + std::vector> drain(); + +private: + mutable std::shared_mutex mutex_; + std::unordered_map buffer_; +}; + +} // namespace onyx diff --git a/cpp/test_native_buffer_store.cpp b/cpp/test_native_buffer_store.cpp new file mode 100644 index 000000000..290a92524 --- /dev/null +++ b/cpp/test_native_buffer_store.cpp @@ -0,0 +1,183 @@ +/** + * Test harness for the simplified NativeBufferStore. + * + * Verifies the thread-safe buffer operations (set, get, erase, clear, + * entries, drain) using std::shared_mutex. No SQLite or background thread. + * + * Run via: + * cd cpp/build && cmake .. -DBUILD_TESTING=ON && make && ./native_buffer_store_test + */ + +#include "NativeBufferStore.h" + +#include +#include +#include + +using namespace onyx; + +static void test_set_and_get() { + std::cout << "test_set_and_get... "; + NativeBufferStore store; + + store.set("key1", {"key1", R"("hello")", NativeEntryType::Set, ""}); + + auto* entry = store.get("key1"); + assert(entry != nullptr); + assert(entry->key == "key1"); + assert(entry->valueJSON == R"("hello")"); + assert(entry->entryType == NativeEntryType::Set); + + assert(store.has("key1")); + assert(!store.has("nonexistent")); + assert(store.size() == 1); + + std::cout << "PASS\n"; +} + +static void test_erase_and_clear() { + std::cout << "test_erase_and_clear... "; + NativeBufferStore store; + + store.set("k1", {"k1", R"(1)", NativeEntryType::Set, ""}); + store.set("k2", {"k2", R"(2)", NativeEntryType::Set, ""}); + store.set("k3", {"k3", R"(3)", NativeEntryType::Set, ""}); + + assert(store.size() == 3); + assert(store.erase("k2")); + assert(store.size() == 2); + assert(!store.has("k2")); + + store.clear(); + assert(store.size() == 0); + + std::cout << "PASS\n"; +} + +static void test_entries() { + std::cout << "test_entries... "; + NativeBufferStore store; + + store.set("a", {"a", R"("va")", NativeEntryType::Set, ""}); + store.set("b", {"b", R"("vb")", NativeEntryType::Merge, ""}); + + auto ents = store.entries(); + assert(ents.size() == 2); + + std::cout << "PASS\n"; +} + +static void test_drain() { + std::cout << "test_drain... "; + NativeBufferStore store; + + store.set("d1", {"d1", R"("v1")", NativeEntryType::Set, ""}); + store.set("d2", {"d2", R"("v2")", NativeEntryType::Merge, ""}); + store.set("d3", {"d3", R"("v3")", NativeEntryType::Set, ""}); + + assert(store.size() == 3); + + // Drain should return all entries and clear the buffer + auto drained = store.drain(); + assert(drained.size() == 3); + assert(store.size() == 0); + + // Verify the drained entries contain expected data + bool found_d1 = false, found_d2 = false, found_d3 = false; + for (const auto& [key, entry] : drained) { + if (key == "d1") { + assert(entry.valueJSON == R"("v1")"); + assert(entry.entryType == NativeEntryType::Set); + found_d1 = true; + } else if (key == "d2") { + assert(entry.valueJSON == R"("v2")"); + assert(entry.entryType == NativeEntryType::Merge); + found_d2 = true; + } else if (key == "d3") { + assert(entry.valueJSON == R"("v3")"); + assert(entry.entryType == NativeEntryType::Set); + found_d3 = true; + } + } + assert(found_d1 && found_d2 && found_d3); + + // Drain again should return empty + auto drained2 = store.drain(); + assert(drained2.empty()); + + std::cout << "PASS\n"; +} + +static void test_drain_during_writes() { + std::cout << "test_drain_during_writes... "; + NativeBufferStore store; + + // Add some entries, drain, then add more and drain again + store.set("before1", {"before1", R"("b1")", NativeEntryType::Set, ""}); + store.set("before2", {"before2", R"("b2")", NativeEntryType::Set, ""}); + + auto first_drain = store.drain(); + assert(first_drain.size() == 2); + assert(store.size() == 0); + + // New entries after drain should be independent + store.set("after1", {"after1", R"("a1")", NativeEntryType::Set, ""}); + + auto second_drain = store.drain(); + assert(second_drain.size() == 1); + assert(second_drain[0].first == "after1"); + assert(store.size() == 0); + + std::cout << "PASS\n"; +} + +static void test_concurrent_set_and_drain() { + std::cout << "test_concurrent_set_and_drain... "; + NativeBufferStore store; + + // Simulate the main thread writing while worker thread drains + std::atomic total_drained{0}; + std::atomic done_writing{false}; + + // Writer thread (simulates main JS thread) + std::thread writer([&store, &done_writing]() { + for (int i = 0; i < 100; ++i) { + std::string key = "key_" + std::to_string(i); + std::string val = "\"value_" + std::to_string(i) + "\""; + store.set(key, {key, val, NativeEntryType::Set, ""}); + } + done_writing = true; + }); + + // Drainer thread (simulates Worklet Worker Runtime) + std::thread drainer([&store, &total_drained, &done_writing]() { + while (!done_writing || store.size() > 0) { + auto drained = store.drain(); + total_drained += static_cast(drained.size()); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + }); + + writer.join(); + drainer.join(); + + // All 100 entries should have been drained total + assert(total_drained == 100); + assert(store.size() == 0); + + std::cout << "PASS\n"; +} + +int main() { + std::cout << "=== NativeBufferStore C++ Tests ===\n"; + + test_set_and_get(); + test_erase_and_clear(); + test_entries(); + test_drain(); + test_drain_during_writes(); + test_concurrent_set_and_drain(); + + std::cout << "\n=== All tests passed! ===\n"; + return 0; +} diff --git a/jestSetup.js b/jestSetup.js index f51f0d54f..96ae00100 100644 --- a/jestSetup.js +++ b/jestSetup.js @@ -2,10 +2,60 @@ jest.mock('./lib/storage'); jest.mock('./lib/storage/platforms/index.native', () => require('./lib/storage/__mocks__')); jest.mock('./lib/storage/platforms/index', () => require('./lib/storage/__mocks__')); -jest.mock('react-native-device-info', () => ({getFreeDiskStorage: () => {}})); +// Mock react-native-nitro-sqlite for native provider tests jest.mock('react-native-nitro-sqlite', () => ({ - open: () => ({execute: () => {}}), - enableSimpleNullHandling: () => undefined, + open: jest.fn(() => ({ + execute: jest.fn(() => ({rows: {length: 0, item: () => null, _array: []}})), + executeAsync: jest.fn(() => Promise.resolve({rows: {length: 0, item: () => null, _array: []}})), + executeBatch: jest.fn(), + executeBatchAsync: jest.fn(() => Promise.resolve()), + })), + enableSimpleNullHandling: jest.fn(), +})); + +// Mock react-native-device-info for native provider +jest.mock('react-native-device-info', () => ({ + getFreeDiskStorage: jest.fn(() => Promise.resolve(Number.POSITIVE_INFINITY)), +})); + +// Mock react-native-nitro-modules for BufferStore HybridObject +jest.mock('react-native-nitro-modules', () => ({ + NitroModules: { + createHybridObject: jest.fn(() => { + throw new Error('NitroModules not available in test environment'); + }), + }, +})); + +// Mock react-native-worklets-core for NativeFlushWorker +jest.mock('react-native-worklets-core', () => ({ + Worklets: { + createContext: jest.fn(() => ({ + name: 'OnyxFlushWorker', + addDecorator: jest.fn(), + createRunAsync: jest.fn( + (fn) => + (...args) => + Promise.resolve(fn(...args)), + ), + runAsync: jest.fn((fn) => Promise.resolve(fn())), + })), + createSharedValue: jest.fn((value) => ({value})), + createRunOnJS: jest.fn((fn) => fn), + runOnJS: jest.fn((fn) => Promise.resolve(fn())), + getCurrentThreadId: jest.fn(() => 0), + defaultContext: { + name: 'default', + addDecorator: jest.fn(), + createRunAsync: jest.fn( + (fn) => + (...args) => + Promise.resolve(fn(...args)), + ), + runAsync: jest.fn((fn) => Promise.resolve(fn())), + }, + currentContext: undefined, + }, })); jest.useRealTimers(); diff --git a/lib/index.ts b/lib/index.ts index bb6df0e0c..c6189110c 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -21,7 +21,6 @@ import type { import type {FetchStatus, ResultMetadata, UseOnyxResult, UseOnyxOptions} from './useOnyx'; import type {Connection} from './OnyxConnectionManager'; import useOnyx from './useOnyx'; -import type {OnyxSQLiteKeyValuePair} from './storage/providers/SQLiteProvider'; export default Onyx; export {useOnyx}; @@ -49,5 +48,4 @@ export type { UseOnyxResult, Connection, UseOnyxOptions, - OnyxSQLiteKeyValuePair, }; diff --git a/lib/storage/BufferStore/index.native.ts b/lib/storage/BufferStore/index.native.ts new file mode 100644 index 000000000..df4d52a37 --- /dev/null +++ b/lib/storage/BufferStore/index.native.ts @@ -0,0 +1,82 @@ +/** + * Native (iOS/Android) BufferStore implementation. + * + * This is a NitroModules HybridObject wrapping a thread-safe C++ buffer + * protected by std::shared_mutex. The HybridObject provides shared memory + * access between the main JS thread and the Worklet Worker Runtime: + * + * Main JS Thread: + * - Onyx.set/merge -> WriteBuffer -> bufferStore.set() -> Nitro fromJSI (deep copy to AnyValue) + * - C++ side acquires unique_lock, inserts entry, releases lock + * + * Worklet Worker Runtime: + * - NativeFlushWorker calls bufferStore.drain() + * - C++ side acquires unique_lock, atomically swaps out all entries, releases lock + * - Nitro toJSI converts AnyValue back to JS objects (on worker thread) + * - Worker does JSON.stringify + nitroSqlite.execute (on worker thread) + * + * When the NitroModules bridge is not available (e.g., in test environments), + * falls back to a plain JS Map implementation. + */ + +import type {NitroModules} from 'react-native-nitro-modules'; +import type {OnyxKey} from '../../types'; +import type {BufferEntry} from '../WriteBuffer'; +import type BufferStoreType from './types'; + +/** + * Creates a native BufferStore backed by a C++ NativeBufferStore HybridObject. + * + * The HybridObject is created via NitroModules.createHybridObject() and + * wraps a std::shared_mutex-protected C++ unordered_map. The drain() method + * atomically returns and clears all pending entries. + * + * When the NitroModules bridge is not available (e.g., in test environments), + * falls back to a plain JS Map implementation. + */ +function createNativeBufferStore(): BufferStoreType { + // Attempt to use the NitroModules HybridObject + try { + const {NitroModules: NM} = require('react-native-nitro-modules') as {NitroModules: typeof NitroModules}; + + // The HybridObject is generated by nitrogen codegen from the C++ + // NativeBufferStore class. It exposes the same interface as BufferStore. + // We use `as unknown as BufferStoreType` because NM.createHybridObject + // constrains T to HybridObject<{}>, but at runtime the object satisfies + // BufferStoreType. The nitrogen-generated spec bridges the gap. + const nativeStore = NM.createHybridObject('NativeBufferStore') as unknown as BufferStoreType; + + return nativeStore; + } catch { + // NitroModules not available -- fall back to JS Map + // This happens in test environments or when the native module isn't linked + console.error('[Onyx] NativeBufferStore not available, falling back to JS Map'); + + const map = new Map(); + return { + get(key: OnyxKey): BufferEntry | undefined { + return map.get(key); + }, + set(key: OnyxKey, entry: BufferEntry): void { + map.set(key, entry); + }, + delete(key: OnyxKey): boolean { + return map.delete(key); + }, + has(key: OnyxKey): boolean { + return map.has(key); + }, + get size(): number { + return map.size; + }, + clear(): void { + map.clear(); + }, + entries(): IterableIterator<[OnyxKey, BufferEntry]> { + return map.entries(); + }, + }; + } +} + +export default createNativeBufferStore; diff --git a/lib/storage/BufferStore/index.ts b/lib/storage/BufferStore/index.ts new file mode 100644 index 000000000..5ed4af0ea --- /dev/null +++ b/lib/storage/BufferStore/index.ts @@ -0,0 +1,41 @@ +/** + * Web default BufferStore implementation. + * + * A trivial wrapper around a JS `Map`. This is the + * default backing store for the WriteBuffer on all platforms that don't + * provide a native override (i.e., web). + */ +import type {OnyxKey} from '../../types'; +import type {BufferEntry} from '../WriteBuffer'; +import type BufferStoreType from './types'; + +function createBufferStore(): BufferStoreType { + const map = new Map(); + + return { + get(key: OnyxKey): BufferEntry | undefined { + return map.get(key); + }, + set(key: OnyxKey, entry: BufferEntry): void { + map.set(key, entry); + }, + delete(key: OnyxKey): boolean { + return map.delete(key); + }, + has(key: OnyxKey): boolean { + return map.has(key); + }, + get size(): number { + return map.size; + }, + clear(): void { + map.clear(); + }, + entries(): IterableIterator<[OnyxKey, BufferEntry]> { + return map.entries(); + }, + }; +} + +export default createBufferStore; +export type {BufferStoreType as BufferStore}; diff --git a/lib/storage/BufferStore/types.ts b/lib/storage/BufferStore/types.ts new file mode 100644 index 000000000..4da842dc1 --- /dev/null +++ b/lib/storage/BufferStore/types.ts @@ -0,0 +1,22 @@ +import type {OnyxKey} from '../../types'; +import type {BufferEntry} from '../WriteBuffer'; + +/** + * Interface for the backing data structure of the WriteBuffer. + * + * Platform-specific implementations: + * - `index.ts` (web default): simple JS `Map` wrapper + * - `index.native.ts` (iOS/Android): NitroModules HybridObject with + * mutex-protected shared C++ memory and background flush thread + */ +interface BufferStore { + get(key: OnyxKey): BufferEntry | undefined; + set(key: OnyxKey, entry: BufferEntry): void; + delete(key: OnyxKey): boolean; + has(key: OnyxKey): boolean; + readonly size: number; + clear(): void; + entries(): IterableIterator<[OnyxKey, BufferEntry]>; +} + +export default BufferStore; diff --git a/lib/storage/InstanceSync/index.web.ts b/lib/storage/InstanceSync/index.web.ts index cb1a3c5bb..c59d54fe6 100644 --- a/lib/storage/InstanceSync/index.web.ts +++ b/lib/storage/InstanceSync/index.web.ts @@ -1,59 +1,160 @@ /** - * The InstancesSync object provides data-changed events like the ones that exist - * when using LocalStorage APIs in the browser. These events are great because multiple tabs can listen for when - * data changes and then stay up-to-date with everything happening in Onyx. + * The InstancesSync object provides data-changed events across browser tabs. + * + * This implementation listens on the unified `onyx-sync` BroadcastChannel for + * value-bearing messages from the storage worker. When another tab's worker + * persists changes, it broadcasts the values directly, so this tab can update + * its cache without re-reading from storage. + * + * For merge operations, the raw patch is broadcast and applied against the + * local cache using fastMerge. If the key is not in cache, we fall back to + * reading from the storage provider. + * + * The InstanceSync also retains its sending capabilities (setItem, multiSet, etc.) + * for the IDB fallback path. When the worker handles broadcasting (the normal + * case), these send methods are skipped by storage/index.ts. */ import type {OnyxKey} from '../../types'; +import cache from '../../OnyxCache'; +import utils from '../../utils'; import NoopProvider from '../providers/NoopProvider'; import type {StorageKeyList, OnStorageKeyChanged} from '../providers/types'; import type StorageProvider from '../providers/types'; -const SYNC_ONYX = 'SYNC_ONYX'; +const SYNC_CHANNEL_NAME = 'onyx-sync'; /** - * Raise an event through `localStorage` to let other tabs know a value changed - * @param {String} onyxKey + * Legacy channel for key-only messages from the IDB fallback path. + * Once IDB is moved to a worker, this can be removed. + */ +const LEGACY_CHANNEL_NAME = 'onyx-instance-sync'; + +let syncChannel: BroadcastChannel | null = null; +let legacyChannel: BroadcastChannel | null = null; +let storage: StorageProvider = NoopProvider; + +/** + * Broadcast a single key change to other tabs (legacy IDB fallback path). */ function raiseStorageSyncEvent(onyxKey: OnyxKey) { - global.localStorage.setItem(SYNC_ONYX, onyxKey); - global.localStorage.removeItem(SYNC_ONYX); + legacyChannel?.postMessage({type: 'keyChanged', key: onyxKey}); } +/** + * Broadcast multiple key changes to other tabs in a single message (legacy IDB fallback path). + */ function raiseStorageSyncManyKeysEvent(onyxKeys: StorageKeyList) { - for (const onyxKey of onyxKeys) { - raiseStorageSyncEvent(onyxKey); - } + if (onyxKeys.length === 0) return; + legacyChannel?.postMessage({type: 'keysChanged', keys: onyxKeys}); } -let storage = NoopProvider; - const InstanceSync = { shouldBeUsed: true, + /** - * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync + * Initialize the BroadcastChannel listeners for cross-tab synchronization. + * + * Two channels are set up: + * 1. `onyx-sync` - Value-bearing messages from the unified worker. This is + * the primary sync path for both SQLite and IDB (since both now run in + * the worker). Messages carry actual values/patches, avoiding re-reads. + * 2. `onyx-instance-sync` - Legacy key-only messages. Retained as fallback + * for any edge cases. Will be removed once fully migrated. + * + * @param onStorageKeyChanged - Callback invoked when another tab changes a key + * @param store - The storage provider to read updated values from (fallback only) */ init: (onStorageKeyChanged: OnStorageKeyChanged, store: StorageProvider) => { storage = store; - // This listener will only be triggered by events coming from other tabs - global.addEventListener('storage', (event) => { - // Ignore events that don't originate from the SYNC_ONYX logic - if (event.key !== SYNC_ONYX || !event.newValue) { - return; + // Close any existing channels before creating new ones + if (syncChannel) { + syncChannel.close(); + } + if (legacyChannel) { + legacyChannel.close(); + } + + // --- Primary channel: value-bearing messages from the worker --- + syncChannel = new BroadcastChannel(SYNC_CHANNEL_NAME); + syncChannel.onmessage = (event: MessageEvent) => { + const data = event.data; + if (!data) return; + + if (data.type === 'set' && Array.isArray(data.pairs)) { + // SET: full values included, no storage reads needed + for (const [key, value] of data.pairs) { + onStorageKeyChanged(key, value); + } + } else if (data.type === 'merge' && Array.isArray(data.pairs)) { + // MERGE: raw patch included, apply fastMerge against cache + for (const [key, patch] of data.pairs) { + const cachedValue = cache.get(key); + if (cachedValue !== undefined) { + // Fast path: merge against cached value + const mergedValue = utils.fastMerge(cachedValue as Record, patch as Record, { + shouldRemoveNestedNulls: true, + objectRemovalMode: 'replace', + }).result; + onStorageKeyChanged(key, mergedValue); + } else { + // Slow path: key not in cache, read from storage then apply merge + storage.getItem(key).then((storedValue) => { + if (storedValue !== null && storedValue !== undefined) { + const mergedValue = utils.fastMerge(storedValue as Record, patch as Record, { + shouldRemoveNestedNulls: true, + objectRemovalMode: 'replace', + }).result; + onStorageKeyChanged(key, mergedValue); + } else { + // No stored value either -- treat the patch as the full value + onStorageKeyChanged(key, patch); + } + }); + } + } + } else if (data.type === 'remove' && Array.isArray(data.keys)) { + // REMOVE: notify with null value + for (const key of data.keys) { + onStorageKeyChanged(key, null); + } + } else if (data.type === 'clear') { + // CLEAR: notify all cached keys with null + const allCachedKeys = cache.getAllKeys(); + for (const key of allCachedKeys) { + onStorageKeyChanged(key, null); + } } + }; - const onyxKey = event.newValue; + // --- Legacy channel: key-only messages (IDB fallback) --- + legacyChannel = new BroadcastChannel(LEGACY_CHANNEL_NAME); + legacyChannel.onmessage = (event: MessageEvent) => { + const data = event.data; + if (!data) return; - storage.getItem(onyxKey).then((value) => onStorageKeyChanged(onyxKey, value)); - }); + if (data.type === 'keyChanged' && data.key) { + storage.getItem(data.key).then((value) => onStorageKeyChanged(data.key, value)); + } else if (data.type === 'keysChanged' && Array.isArray(data.keys)) { + for (const key of data.keys) { + storage.getItem(key).then((value) => onStorageKeyChanged(key, value)); + } + } else if (data.type === 'clear' && Array.isArray(data.keys)) { + for (const key of data.keys) { + storage.getItem(key).then((value) => onStorageKeyChanged(key, value)); + } + } + }; }, + setItem: raiseStorageSyncEvent, removeItem: raiseStorageSyncEvent, removeItems: raiseStorageSyncManyKeysEvent, multiMerge: raiseStorageSyncManyKeysEvent, multiSet: raiseStorageSyncManyKeysEvent, mergeItem: raiseStorageSyncEvent, - clear: (clearImplementation: () => void) => { + + clear: (clearImplementation: () => Promise) => { let allKeys: StorageKeyList; // The keys must be retrieved before storage is cleared or else the list of keys would be empty @@ -64,9 +165,8 @@ const InstanceSync = { }) .then(() => clearImplementation()) .then(() => { - // Now that storage is cleared, the storage sync event can happen which is a more atomic action - // for other browser tabs - raiseStorageSyncManyKeysEvent(allKeys); + // Now that storage is cleared, broadcast the clear event with all affected keys + legacyChannel?.postMessage({type: 'clear', keys: allKeys}); }); }, }; diff --git a/lib/storage/NativeFlushWorker.ts b/lib/storage/NativeFlushWorker.ts new file mode 100644 index 000000000..75744bd85 --- /dev/null +++ b/lib/storage/NativeFlushWorker.ts @@ -0,0 +1,186 @@ +/** + * NativeFlushWorker -- Manages the Worklet Worker Runtime for native persistence. + * + * Creates a background JS thread using react-native-worklets-core's context API. + * The flush worklet periodically: + * 1. Calls bufferStore.drain() on the shared HybridObject (shared memory, no postMessage) + * 2. JSON.stringifies the drained entries (on the worker thread, not main thread) + * 3. Calls react-native-nitro-sqlite sync APIs to persist to SQLite + * + * The main thread only pays the cost of AnyMap conversion (via Nitro's fromJSI) + * when populating the buffer. All serialization and I/O happens on the worker. + * + * Architecture symmetry: This is the native analog of the web's worker.ts + + * WorkerStorageProvider, but uses shared memory instead of postMessage. + */ + +import type {IWorkletContext, IWorkletNativeApi} from 'react-native-worklets-core'; +import type {BufferEntry} from './WriteBuffer'; +import type BufferStore from './BufferStore/types'; +import type {StorageKeyValuePair} from './providers/types'; + +type NativeFlushWorker = ReturnType; + +/** + * Flush interval in milliseconds. The worker thread wakes up at this + * cadence to drain and persist any buffered writes. + */ +const FLUSH_INTERVAL_MS = 200; + +/** + * Creates and starts the native flush worker. + * + * Uses react-native-worklets-core to create a dedicated background context + * ("OnyxFlushWorker") that runs flush worklets. The SQLite provider and + * buffer store are injected into the context as decorators so they're + * accessible inside worklets without closure capturing. + * + * @param bufferStore - The HybridObject-backed BufferStore shared with the main thread + * @returns Object with start(), stop(), flushNow(), and getProvider() + */ +function createNativeFlushWorker(bufferStore: BufferStore) { + let flushInterval: ReturnType | null = null; + let isRunning = false; + let workerContext: IWorkletContext | null = null; + + // Import the native SQLite provider lazily to avoid circular deps + // eslint-disable-next-line @typescript-eslint/no-require-imports + const nativeSQLiteProvider = require('./providers/SQLiteProvider/index.native').default; + + /** + * Perform a single flush cycle: drain the buffer and persist to SQLite. + * + * This is called from the Worklet context (background thread). The + * bufferStore.drain() operation is a shared-memory read (no postMessage), + * and JSON.stringify + SQLite execute happen entirely off the main thread. + */ + function flush(): void { + if (bufferStore.size === 0) { + return; + } + + // Drain all entries from the shared buffer atomically + const entries = Array.from(bufferStore.entries()); + bufferStore.clear(); + + if (entries.length === 0) { + return; + } + + // Separate SET and MERGE entries for the provider + const setPairs: StorageKeyValuePair[] = []; + const mergePairs: StorageKeyValuePair[] = []; + + for (const [, entry] of entries) { + const typedEntry = entry as BufferEntry; + if (typedEntry.entryType === 'set') { + setPairs.push([typedEntry.key, typedEntry.value]); + } else { + mergePairs.push([typedEntry.key, typedEntry.value, typedEntry.replaceNullPatches]); + } + } + + // Persist to SQLite using sync APIs (on the worker thread) + try { + if (setPairs.length > 0) { + nativeSQLiteProvider.multiSet(setPairs); + } + if (mergePairs.length > 0) { + nativeSQLiteProvider.multiMerge(mergePairs); + } + } catch (error) { + console.error('[Onyx] NativeFlushWorker: flush error:', error); + } + } + + /** + * Schedule periodic flush on the Worklet context. + * The main thread triggers a runAsync on the worker context at FLUSH_INTERVAL_MS + * cadence. The actual drain + serialize + persist all execute on the worker thread. + */ + function schedulePeriodicFlush(): void { + if (flushInterval !== null) { + return; + } + + if (workerContext) { + // Use the Worklet context to run flush on the background thread. + // createRunAsync memoizes the worklet so repeated calls are efficient. + const runFlush = workerContext.createRunAsync(flush); + flushInterval = setInterval(() => { + runFlush().catch((error) => { + console.error('[Onyx] NativeFlushWorker: scheduled flush error:', error); + }); + }, FLUSH_INTERVAL_MS); + } else { + // Fallback: no Worklet context available (e.g., test environment). + // Run flush directly on the main thread. + flushInterval = setInterval(flush, FLUSH_INTERVAL_MS); + } + } + + return { + /** + * Start the flush worker. Initializes the SQLite provider, creates + * the Worklet context, and begins periodic flushing. + */ + start(): void { + if (isRunning) { + return; + } + + // Initialize the native SQLite provider + nativeSQLiteProvider.init(); + + // Create the Worklet context for background flush + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const {Worklets} = require('react-native-worklets-core') as {Worklets: IWorkletNativeApi}; + workerContext = Worklets.createContext('OnyxFlushWorker'); + } catch { + console.error('[Onyx] react-native-worklets-core not available, flush will run on main thread'); + workerContext = null; + } + + isRunning = true; + schedulePeriodicFlush(); + }, + + /** + * Stop the flush worker and perform a final flush to ensure all + * pending writes are persisted. + */ + stop(): void { + if (!isRunning) { + return; + } + + isRunning = false; + if (flushInterval !== null) { + clearInterval(flushInterval); + flushInterval = null; + } + + // Final flush to persist any remaining entries + flush(); + }, + + /** + * Force an immediate flush (e.g., on app background/shutdown). + */ + flushNow(): void { + flush(); + }, + + /** + * Get the underlying SQLite provider for read operations. + * Read operations go directly to the provider, bypassing the buffer. + */ + getProvider() { + return nativeSQLiteProvider; + }, + }; +} + +export default createNativeFlushWorker; +export type {NativeFlushWorker}; diff --git a/lib/storage/WorkerStorageProvider.ts b/lib/storage/WorkerStorageProvider.ts new file mode 100644 index 000000000..1c2ea9e54 --- /dev/null +++ b/lib/storage/WorkerStorageProvider.ts @@ -0,0 +1,196 @@ +/** + * Worker Storage Provider + * + * Main-thread proxy that communicates with the storage Web Worker + * (lib/storage/worker.ts). Implements the StorageProvider interface + * so it can be used as a drop-in replacement for any storage backend on web. + * + * The caller chooses the backend at creation time: + * - 'sqlite': @sqlite.org/sqlite-wasm with opfs-sahpool VFS + * - 'idb': IDBKeyValProvider fallback for browsers without OPFS + * + * All database operations are offloaded to the worker. This provider only + * manages the postMessage protocol and Promise resolution. Values pass + * through structured clone (native JS objects), so no JSON.parse is needed + * on the main thread. + */ + +import utils from '../utils'; +import type StorageProvider from './providers/types'; +import type {StorageKeyList, StorageKeyValuePair} from './providers/types'; + +// Message counter for matching responses to requests +let nextMessageId = 0; + +// Promise registry keyed by message ID +const pendingRequests = new Map void; reject: (reason: unknown) => void}>(); + +/** + * Generate a unique message ID for request-response matching. + */ +function generateId(): string { + nextMessageId += 1; + return `msg_${nextMessageId}_${Date.now()}`; +} + +/** + * The worker instance (created during init). + */ +let worker: Worker | null = null; + +/** + * Send a message to the worker and return a Promise that resolves with the result. + */ +function postToWorker(message: Record): Promise { + return new Promise((resolve, reject) => { + if (!worker) { + reject(new Error('Storage worker not initialized')); + return; + } + + const id = generateId(); + pendingRequests.set(id, { + resolve: resolve as (value: unknown) => void, + reject, + }); + + worker.postMessage({...message, id}); + }); +} + +/** + * Handle messages from the worker. Matches response to pending request by ID. + */ +function handleWorkerMessage(event: MessageEvent): void { + const {type, id, data, error} = event.data; + if (type !== 'result') return; + + const pending = pendingRequests.get(id); + if (!pending) return; + pendingRequests.delete(id); + + if (error) { + pending.reject(new Error(error)); + } else { + pending.resolve(data); + } +} + +/** + * Create a WorkerStorageProvider that delegates all operations to the + * storage web worker. The caller specifies the backend to use: + * - 'sqlite': @sqlite.org/sqlite-wasm with opfs-sahpool VFS (preferred) + * - 'idb': IDBKeyValProvider fallback + * + * @param backend - The storage backend for the worker to use + */ +function createWorkerStorageProvider(backend: 'sqlite' | 'idb'): StorageProvider { + const provider: StorageProvider = { + store: null, + + /** + * The name of the provider that can be printed to the logs + */ + name: `WorkerStorageProvider (${backend})`, + + /** + * Initializes the storage provider by spawning the web worker. + * The worker is told which backend to use via the init message. + * + * Returns a Promise that resolves once the worker has finished + * initializing its storage backend (SQLite or IDB). This ensures + * that callers waiting on Storage.init() don't proceed until the + * worker is actually ready to accept data operations. + */ + init() { + // Create the worker. The bundler (webpack/vite) will handle the URL resolution. + // The import.meta.url syntax is required for bundlers to resolve the worker path. + // At build time, the library is compiled with "module": "commonjs" (tsconfig.json), + // but consumers (App) rebundle this file with webpack/vite which support import.meta. + // @ts-expect-error import.meta is valid at runtime in bundler environments + worker = new Worker(new URL('./worker.js', import.meta.url), {type: 'module'}); + worker.onmessage = handleWorkerMessage; + worker.onerror = (error) => { + console.error('[Onyx] Storage worker error:', error); + }; + + provider.store = worker; + + // Send init message with the chosen backend and return the Promise + // so that Storage.init() can await worker readiness. + return postToWorker({type: 'init', backend}).catch((error) => { + console.error('[Onyx] Failed to initialize storage worker:', error); + }); + }, + + getItem(key) { + // The worker returns the deserialized value via structured clone. + // We cast to satisfy the generic return type; the value shape is + // determined by what was stored under that key. + return postToWorker({type: 'getItem', key}) as Promise; + }, + + multiGet(keys) { + return postToWorker({type: 'multiGet', keys}).then((results) => results ?? []); + }, + + setItem(key, value) { + return postToWorker({type: 'setItem', key, value}); + }, + + multiSet(pairs) { + if (utils.isEmptyObject(pairs)) { + return Promise.resolve(); + } + const normalized = pairs.map(([key, value]) => [key, value === undefined ? null : value]); + return postToWorker({type: 'multiSet', pairs: normalized}); + }, + + multiMerge(pairs) { + const nonNullishPairs = pairs.filter((pair) => pair[1] !== undefined); + const prepared = nonNullishPairs.map(([key, value, replaceNullPatches]) => [key, value, replaceNullPatches]); + return postToWorker({type: 'multiMerge', pairs: prepared}); + }, + + mergeItem(key, change, replaceNullPatches) { + return provider.multiMerge([[key, change, replaceNullPatches]]); + }, + + getAllKeys() { + return postToWorker({type: 'getAllKeys'}).then((keys) => (keys ?? []) as StorageKeyList); + }, + + getAll() { + return postToWorker({type: 'getAll'}).then((results) => results ?? []); + }, + + removeItem(key) { + return postToWorker({type: 'removeItem', key}); + }, + + removeItems(keys) { + return postToWorker({type: 'removeItems', keys}); + }, + + clear() { + return postToWorker({type: 'clear'}); + }, + + getDatabaseSize() { + return postToWorker<{bytesUsed: number; bytesRemaining: number}>({type: 'getDatabaseSize'}).then((size) => { + // Supplement with StorageManager if available for more accurate remaining space + if (typeof navigator !== 'undefined' && navigator.storage && navigator.storage.estimate) { + return navigator.storage.estimate().then((estimate) => ({ + bytesUsed: size.bytesUsed, + bytesRemaining: (estimate.quota ?? 0) - (estimate.usage ?? 0), + })); + } + return size; + }); + }, + }; + + return provider; +} + +export default createWorkerStorageProvider; diff --git a/lib/storage/WriteBuffer.ts b/lib/storage/WriteBuffer.ts new file mode 100644 index 000000000..848d3a40a --- /dev/null +++ b/lib/storage/WriteBuffer.ts @@ -0,0 +1,354 @@ +/** + * WriteBuffer implements a patch-staging layer for storage operations. + * + * It tracks two types of pending entries: + * - SET entries: full values from set()/multiSet(), flushed via multiSet + * - MERGE entries: accumulated patch deltas from merge operations, flushed via + * multiMerge (preserving JSON_PATCH efficiency on SQLite) + * + * Multiple writes to the same key are coalesced: successive sets replace the + * value, successive merges accumulate patches, and a set after a merge discards + * the pending patch. A merge after a set applies the patch to the full value + * in-memory (unavoidable since the set hasn't been persisted yet). + * + * The backing data structure is pluggable via the `BufferStore` interface: + * - Web: JS `Map` (BufferStore/index.ts) + * - Native: NitroModules HybridObject with shared C++ memory + * (BufferStore/index.native.ts) + * + * Flush scheduling is also pluggable. On web, `requestIdleCallback` is used. + * On native, the background C++ thread handles flushing, so the scheduler is + * a no-op. + */ + +import type {OnyxKey, OnyxValue} from '../types'; +import type {FastMergeReplaceNullPatch} from '../utils'; +import utils from '../utils'; +import type {StorageKeyValuePair} from './providers/types'; +import type BufferStore from './BufferStore/types'; + +type EntryType = 'set' | 'merge'; + +type BufferEntry = { + key: OnyxKey; + value: OnyxValue; + entryType: EntryType; + replaceNullPatches?: FastMergeReplaceNullPatch[]; +}; + +/** Flush handlers for the two entry types. */ +type FlushHandlers = { + multiSet: (pairs: StorageKeyValuePair[]) => Promise; + multiMerge: (pairs: StorageKeyValuePair[]) => Promise; +}; + +/** + * A function that schedules a flush. The implementation is platform-specific: + * - Web: schedules via requestIdleCallback with a timeout + * - Native: no-op (the native BufferStore's background thread handles it) + * + * Returns a handle that can be passed to `cancelFlush`, or null if no + * cancellation is needed. + */ +type FlushScheduler = (doFlush: () => void) => number | null; + +/** + * A function that cancels a previously scheduled flush. + */ +type CancelFlush = (handle: number) => void; + +/** + * Maximum delay before a scheduled flush is forced, in milliseconds. + * + * Under normal conditions, requestIdleCallback fires during the next idle + * period (often within a few ms). This timeout is a safety net: if the + * browser stays busy for longer than FLUSH_TIMEOUT_MS, the flush is forced. + * + * 200ms lets typical write bursts (10-50ms) fully coalesce before flushing, + * while still being well under perceptible delay. The WriteBuffer's + * read-through ensures in-memory consistency regardless of flush timing. + */ +const FLUSH_TIMEOUT_MS = 200; + +/** Default web flush scheduler using requestIdleCallback with setTimeout fallback. */ +function defaultScheduleFlush(doFlush: () => void): number | null { + if (typeof requestIdleCallback === 'function') { + return requestIdleCallback(doFlush, {timeout: FLUSH_TIMEOUT_MS}) as unknown as number; + } + return setTimeout(doFlush, FLUSH_TIMEOUT_MS) as unknown as number; +} + +/** Default web cancel flush using cancelIdleCallback with clearTimeout fallback. */ +function defaultCancelFlush(handle: number): void { + if (typeof cancelIdleCallback === 'function') { + cancelIdleCallback(handle); + } else { + clearTimeout(handle); + } +} + +type WriteBufferConfig = { + handlers: FlushHandlers; + store: BufferStore; + scheduleFlush?: FlushScheduler; + cancelFlush?: CancelFlush; +}; + +class WriteBuffer { + /** The pluggable backing store for pending buffer entries. */ + private store: BufferStore; + + /** Handle returned by the scheduled flush, used for cancellation. */ + private flushHandle: number | null = null; + + /** Whether a flush is currently in progress. */ + private isFlushing = false; + + /** The handlers called on flush for each entry type. */ + private readonly handlers: FlushHandlers; + + /** Platform-specific flush scheduler. */ + private readonly scheduleFlushFn: FlushScheduler; + + /** Platform-specific flush cancellation. */ + private readonly cancelFlushFn: CancelFlush; + + constructor(config: WriteBufferConfig) { + this.handlers = config.handlers; + this.store = config.store; + this.scheduleFlushFn = config.scheduleFlush ?? defaultScheduleFlush; + this.cancelFlushFn = config.cancelFlush ?? defaultCancelFlush; + } + + /** + * Stage a full value for a key (SET entry). If the key had a pending MERGE, + * the set replaces it entirely. A flush is scheduled if not already pending. + */ + set(key: OnyxKey, value: OnyxValue): void { + this.store.set(key, {key, value, entryType: 'set'}); + this.scheduleFlush(); + } + + /** + * Stage full values for multiple keys (all as SET entries). + */ + setMany(pairs: StorageKeyValuePair[]): void { + for (const [key, value] of pairs) { + this.store.set(key, {key, value, entryType: 'set'}); + } + this.scheduleFlush(); + } + + /** + * Stage a merge patch for a key (MERGE entry). Interaction with existing entries: + * - No existing entry: create a MERGE entry with just the patch + * - Existing SET entry: apply patch to the full value in-memory, keep as SET + * - Existing MERGE entry: merge patches together, keep as MERGE + */ + merge(key: OnyxKey, patch: OnyxValue, replaceNullPatches?: FastMergeReplaceNullPatch[]): void { + const existing = this.store.get(key); + + if (!existing) { + // No pending write -- stage as a MERGE entry (just the patch) + this.store.set(key, {key, value: patch, entryType: 'merge', replaceNullPatches}); + } else if (existing.entryType === 'set') { + // Pending SET -- apply patch to the full value, stay as SET + const {result: merged} = utils.fastMerge(existing.value as Record, patch as Record, { + shouldRemoveNestedNulls: true, + objectRemovalMode: 'replace', + }); + this.store.set(key, {key, value: merged as OnyxValue, entryType: 'set'}); + } else { + // Pending MERGE -- merge patches together, stay as MERGE + const {result: mergedPatch} = utils.fastMerge(existing.value as Record, patch as Record, { + shouldRemoveNestedNulls: false, // preserve nulls -- provider handles them + }); + const combinedPatches = [...(existing.replaceNullPatches ?? []), ...(replaceNullPatches ?? [])]; + this.store.set(key, { + key, + value: mergedPatch as OnyxValue, + entryType: 'merge', + replaceNullPatches: combinedPatches.length > 0 ? combinedPatches : undefined, + }); + } + + this.scheduleFlush(); + } + + /** + * Remove a key from the write buffer. This is used when a key is being + * removed from storage entirely (not just set to null). + */ + remove(key: OnyxKey): void { + this.store.delete(key); + } + + /** + * Remove multiple keys from the write buffer. + */ + removeMany(keys: OnyxKey[]): void { + for (const key of keys) { + this.store.delete(key); + } + } + + /** + * Read-through for SET entries only. Returns the pending full value if the + * key has a SET entry, or undefined otherwise. MERGE entries are not served + * because they contain only a patch, not a complete value -- the caller + * should fall through to the provider for those. + */ + get(key: OnyxKey): OnyxValue | undefined { + const entry = this.store.get(key); + if (entry?.entryType === 'set') { + return entry.value; + } + return undefined; + } + + /** + * Check whether the given key has a pending SET entry (suitable for + * read-through). Returns false for MERGE entries since those only + * contain a patch, not a complete value. + */ + has(key: OnyxKey): boolean { + const entry = this.store.get(key); + return entry?.entryType === 'set'; + } + + /** + * Check whether the key has any pending entry (SET or MERGE). + */ + hasAny(key: OnyxKey): boolean { + return this.store.has(key); + } + + /** + * Returns the number of pending entries (both SET and MERGE). + */ + get size(): number { + return this.store.size; + } + + /** + * Clear all pending entries and cancel any scheduled flush. + */ + clear(): void { + this.store.clear(); + this.cancelScheduledFlush(); + } + + /** + * Immediately flush all pending entries to the storage provider. + * + * SET entries use reference identity: they stay in the map during flush and + * are only removed afterward if their reference hasn't changed (handling + * concurrent set-during-flush correctly). + * + * MERGE entries are removed from the map at flush start. New merges during + * flush create fresh entries, avoiding double-application of patches. + */ + // eslint-disable-next-line @lwc/lwc/no-async-await + async flushNow(): Promise { + if (this.isFlushing) { + // Wait for the current flush to finish, then flush again + return new Promise((resolve) => { + const waitForFlush = () => { + if (!this.isFlushing) { + resolve(this.flushNow()); + return; + } + setTimeout(waitForFlush, 5); + }; + waitForFlush(); + }); + } + + this.cancelScheduledFlush(); + + if (this.store.size === 0) { + return; + } + + this.isFlushing = true; + try { + // Separate entries by type + const setPairs: StorageKeyValuePair[] = []; + const setSnapshot = new Map(); + const mergePairs: StorageKeyValuePair[] = []; + const mergeKeys: OnyxKey[] = []; + + for (const [key, entry] of this.store.entries()) { + if (entry.entryType === 'set') { + setPairs.push([entry.key, entry.value]); + setSnapshot.set(key, entry); + } else { + mergePairs.push([entry.key, entry.value, entry.replaceNullPatches]); + mergeKeys.push(key); + } + } + + // Remove MERGE entries from the map at flush start. + // New merges during flush will create fresh entries. + for (const key of mergeKeys) { + this.store.delete(key); + } + + // Flush both types concurrently + const promises: Array> = []; + if (setPairs.length > 0) { + promises.push(this.handlers.multiSet(setPairs)); + } + if (mergePairs.length > 0) { + promises.push(this.handlers.multiMerge(mergePairs)); + } + + await Promise.all(promises); + + // For SET entries: only remove if the reference hasn't changed + // (i.e., no set or merge was applied to this key during flush) + for (const [key, flushedEntry] of setSnapshot) { + if (this.store.get(key) === flushedEntry) { + this.store.delete(key); + } + } + } finally { + this.isFlushing = false; + } + + // If new entries were added during flush, schedule another one + if (this.store.size > 0) { + this.scheduleFlush(); + } + } + + /** + * Schedule a flush using the platform-specific scheduler. + * If a flush is already scheduled, this is a no-op. + */ + private scheduleFlush(): void { + if (this.flushHandle !== null) { + return; + } + + this.flushHandle = this.scheduleFlushFn(() => { + this.flushHandle = null; + this.flushNow(); + }); + } + + /** + * Cancel any pending scheduled flush. + */ + private cancelScheduledFlush(): void { + if (this.flushHandle === null) { + return; + } + + this.cancelFlushFn(this.flushHandle); + this.flushHandle = null; + } +} + +export default WriteBuffer; +export type {FlushHandlers, BufferEntry, EntryType, FlushScheduler, CancelFlush, WriteBufferConfig}; diff --git a/lib/storage/index.ts b/lib/storage/index.ts index c143c8e85..304ebaf95 100644 --- a/lib/storage/index.ts +++ b/lib/storage/index.ts @@ -1,12 +1,13 @@ import * as Logger from '../Logger'; - +import type {OnyxKey, OnyxValue} from '../types'; import PlatformStorage from './platforms'; import InstanceSync from './InstanceSync'; import MemoryOnlyProvider from './providers/MemoryOnlyProvider'; import type StorageProvider from './providers/types'; +import WriteBuffer from './WriteBuffer'; +import createBufferStore from './BufferStore'; let provider = PlatformStorage as StorageProvider; -let shouldKeepInstancesSync = false; let finishInitalization: (value?: unknown) => void; const initPromise = new Promise((resolve) => { finishInitalization = resolve; @@ -55,6 +56,24 @@ function tryOrDegradePerformance(fn: () => Promise | T, waitForInitializat }); } +/** + * The WriteBuffer is a patch-staging layer between Onyx's cache and the storage + * provider. It tracks two types of pending entries: + * - SET entries (full values) flushed via provider.multiSet() + * - MERGE entries (accumulated patches) flushed via provider.multiMerge(), + * preserving JSON_PATCH efficiency on SQLite + * + * All writes (set, merge) return immediately after staging in the WriteBuffer. + * Persistence happens asynchronously in coalesced batches. + */ +const writeBuffer = new WriteBuffer({ + handlers: { + multiSet: (pairs) => provider.multiSet(pairs), + multiMerge: (pairs) => provider.multiMerge(pairs), + }, + store: createBufferStore(), +}); + const storage: Storage = { /** * Returns the storage provider currently in use @@ -65,118 +84,158 @@ const storage: Storage = { /** * Initializes all providers in the list of storage providers - * and enables fallback providers if necessary + * and enables fallback providers if necessary. + * + * If the provider's init() returns a Promise (e.g. WorkerStorageProvider + * waiting for the web worker to finish setting up its backend), we await + * it so that finishInitalization() only fires after the provider is truly + * ready for data operations. */ init() { - tryOrDegradePerformance(provider.init, false).finally(() => { + tryOrDegradePerformance(() => { + const result = provider.init(); + // provider.init() may return void or Promise + return result instanceof Promise ? result : Promise.resolve(); + }, false).finally(() => { finishInitalization(); }); }, /** - * Get the value of a given key or return `null` if it's not available + * Get the value of a given key or return `null` if it's not available. + * + * - If the key has a pending SET entry, it is returned directly from memory. + * - If the key has a pending MERGE entry (a patch delta, not a full value), + * the write buffer is flushed first so the provider has the correct merged + * value on disk, then the read proceeds normally. + * - Otherwise, the read goes straight to the provider. */ - getItem: (key) => tryOrDegradePerformance(() => provider.getItem(key)), + getItem: (key: TKey) => + tryOrDegradePerformance>(() => { + if (writeBuffer.has(key)) { + return Promise.resolve(writeBuffer.get(key) as OnyxValue); + } + if (writeBuffer.hasAny(key)) { + return writeBuffer.flushNow().then(() => provider.getItem(key)); + } + return provider.getItem(key); + }), /** - * Get multiple key-value pairs for the give array of keys in a batch + * Get multiple key-value pairs for the give array of keys in a batch. + * + * Keys with pending SET entries are served from memory. If any remaining + * keys have pending MERGE entries, the write buffer is flushed before + * reading from the provider so the on-disk values are up to date. */ - multiGet: (keys) => tryOrDegradePerformance(() => provider.multiGet(keys)), + multiGet: (keys) => + tryOrDegradePerformance(() => { + const bufferedKeys: string[] = []; + const cleanKeys: string[] = []; + let hasPendingMerges = false; + + for (const key of keys) { + if (writeBuffer.has(key)) { + bufferedKeys.push(key); + } else { + cleanKeys.push(key); + if (writeBuffer.hasAny(key)) { + hasPendingMerges = true; + } + } + } + + // If all keys have SET entries, skip the provider call entirely + if (cleanKeys.length === 0) { + return Promise.resolve(bufferedKeys.map((key) => [key, writeBuffer.get(key)])); + } + + // If any clean keys have pending MERGE entries, flush first + const readyPromise = hasPendingMerges ? writeBuffer.flushNow() : Promise.resolve(); + + return readyPromise.then(() => + provider.multiGet(cleanKeys).then((providerResults) => { + const bufferedResults = bufferedKeys.map((key) => [key, writeBuffer.get(key)] as [string, unknown]); + return [...providerResults, ...bufferedResults]; + }), + ); + }), /** - * Sets the value for a given key. The only requirement is that the value should be serializable to JSON string + * Sets the value for a given key. The value is staged in the write buffer + * as a SET entry and flushed to storage asynchronously in a coalesced batch. + * + * Cross-tab broadcasting is handled by the unified worker after persistence, + * so no InstanceSync send calls are needed here. */ setItem: (key, value) => tryOrDegradePerformance(() => { - const promise = provider.setItem(key, value); - - if (shouldKeepInstancesSync) { - return promise.then(() => InstanceSync.setItem(key)); - } - - return promise; + writeBuffer.set(key, value); + return Promise.resolve(); }), /** - * Stores multiple key-value pairs in a batch + * Stores multiple key-value pairs. All values are staged in the write buffer + * as SET entries and flushed to storage asynchronously in a coalesced batch. */ multiSet: (pairs) => tryOrDegradePerformance(() => { - const promise = provider.multiSet(pairs); - - if (shouldKeepInstancesSync) { - return promise.then(() => InstanceSync.multiSet(pairs.map((pair) => pair[0]))); - } - - return promise; + writeBuffer.setMany(pairs); + return Promise.resolve(); }), /** - * Merging an existing value with a new one + * Merging an existing value with a new one. + * The patch is staged in the write buffer as a MERGE entry. If the key + * already has a pending SET, the patch is applied to the full value + * in-memory. If it already has a pending MERGE, patches are accumulated. + * Returns immediately -- no flushNow() needed. */ mergeItem: (key, change, replaceNullPatches) => tryOrDegradePerformance(() => { - const promise = provider.mergeItem(key, change, replaceNullPatches); - - if (shouldKeepInstancesSync) { - return promise.then(() => InstanceSync.mergeItem(key)); - } - - return promise; + writeBuffer.merge(key, change, replaceNullPatches); + return Promise.resolve(); }), /** - * Multiple merging of existing and new values in a batch - * This function also removes all nested null values from an object. + * Multiple merging of existing and new values in a batch. + * Each pair's patch is staged in the write buffer as a MERGE entry. + * Returns immediately -- no flushNow() needed. */ multiMerge: (pairs) => tryOrDegradePerformance(() => { - const promise = provider.multiMerge(pairs); - - if (shouldKeepInstancesSync) { - return promise.then(() => InstanceSync.multiMerge(pairs.map((pair) => pair[0]))); + for (const [key, value, replaceNullPatches] of pairs) { + writeBuffer.merge(key, value, replaceNullPatches); } - - return promise; + return Promise.resolve(); }), /** - * Removes given key and its value + * Removes given key and its value. + * Also removes the key from the write buffer if it has a pending write. */ removeItem: (key) => tryOrDegradePerformance(() => { - const promise = provider.removeItem(key); - - if (shouldKeepInstancesSync) { - return promise.then(() => InstanceSync.removeItem(key)); - } - - return promise; + writeBuffer.remove(key); + return provider.removeItem(key); }), /** - * Remove given keys and their values + * Remove given keys and their values. + * Also removes the keys from the write buffer if they have pending writes. */ removeItems: (keys) => tryOrDegradePerformance(() => { - const promise = provider.removeItems(keys); - - if (shouldKeepInstancesSync) { - return promise.then(() => InstanceSync.removeItems(keys)); - } - - return promise; + writeBuffer.removeMany(keys); + return provider.removeItems(keys); }), /** - * Clears everything + * Clears everything. Clears the write buffer first, then the provider. */ clear: () => tryOrDegradePerformance(() => { - if (shouldKeepInstancesSync) { - return InstanceSync.clear(() => provider.clear()); - } - + writeBuffer.clear(); return provider.clear(); }), @@ -196,13 +255,17 @@ const storage: Storage = { getDatabaseSize: () => tryOrDegradePerformance(() => provider.getDatabaseSize()), /** - * @param onStorageKeyChanged - Storage synchronization mechanism keeping all opened tabs in sync (web only) + * Initializes the cross-tab sync receiver. On web, InstanceSync listens on + * BroadcastChannel for value-bearing messages from other tabs' workers and + * calls onStorageKeyChanged to update the cache. No send-side logic is + * needed here -- the unified worker handles broadcasting after persistence. + * + * @param onStorageKeyChanged - Callback invoked when another tab changes a key */ keepInstancesSync(onStorageKeyChanged) { // If InstanceSync shouldn't be used, it means we're on a native platform and we don't need to keep instances in sync if (!InstanceSync.shouldBeUsed) return; - shouldKeepInstancesSync = true; InstanceSync.init(onStorageKeyChanged, this); }, }; diff --git a/lib/storage/platforms/index.native.ts b/lib/storage/platforms/index.native.ts index 95822c4a5..5718ba9eb 100644 --- a/lib/storage/platforms/index.native.ts +++ b/lib/storage/platforms/index.native.ts @@ -1,3 +1,57 @@ -import NativeStorage from '../providers/SQLiteProvider'; +/** + * Native (iOS/Android) storage platform selection. + * + * Uses the native SQLite provider (react-native-nitro-sqlite) with persistence + * managed by the NativeFlushWorker. The WriteBuffer populates a HybridObject- + * backed BufferStore (shared memory), and the NativeFlushWorker periodically + * drains it and persists to SQLite. + * + * Read operations go directly to the SQLite provider (bypassing the buffer). + * The WriteBuffer's read-through handles in-flight writes. + * + * NOTE: The NativeFlushWorker currently uses setInterval as a transitional + * implementation. Once react-native-worklets integration is complete, the + * flush logic will run on a true Worklet Worker Runtime background thread. + */ +import createNativeFlushWorker from '../NativeFlushWorker'; +import createNativeBufferStore from '../BufferStore/index.native'; +import type StorageProvider from '../providers/types'; + +// Create the shared buffer (HybridObject or JS Map fallback) +const bufferStore = createNativeBufferStore(); + +// Create and start the flush worker +const flushWorker = createNativeFlushWorker(bufferStore); +flushWorker.start(); + +// The native provider is accessed via the flush worker for read operations +const nativeProvider = flushWorker.getProvider() as StorageProvider; + +/** + * Native storage provider that delegates reads to the SQLite provider + * and uses the WriteBuffer + NativeFlushWorker for writes. + */ +const NativeStorage: StorageProvider = { + store: nativeProvider.store, + name: nativeProvider.name, + + init() { + // Already initialized by flushWorker.start() + }, + + getItem: (key) => nativeProvider.getItem(key), + multiGet: (keys) => nativeProvider.multiGet(keys), + setItem: (key, value) => nativeProvider.setItem(key, value), + multiSet: (pairs) => nativeProvider.multiSet(pairs), + multiMerge: (pairs) => nativeProvider.multiMerge(pairs), + mergeItem: (key, change, replaceNullPatches) => nativeProvider.mergeItem(key, change, replaceNullPatches), + getAllKeys: () => nativeProvider.getAllKeys(), + getAll: () => nativeProvider.getAll(), + removeItem: (key) => nativeProvider.removeItem(key), + removeItems: (keys) => nativeProvider.removeItems(keys), + clear: () => nativeProvider.clear(), + getDatabaseSize: () => nativeProvider.getDatabaseSize(), +}; export default NativeStorage; +export {bufferStore, flushWorker}; diff --git a/lib/storage/platforms/index.ts b/lib/storage/platforms/index.ts index 0b95dc97d..167f05c2f 100644 --- a/lib/storage/platforms/index.ts +++ b/lib/storage/platforms/index.ts @@ -1,3 +1,42 @@ -import WebStorage from '../providers/IDBKeyValProvider'; +/** + * Web storage platform selection. + * + * Uses the WorkerStorageProvider to run all persistence off the main thread. + * Detects OPFS support to choose the best backend: + * - OPFS + Worker available: SQLite via @sqlite.org/sqlite-wasm with opfs-sahpool VFS + * - No OPFS: IDBKeyValProvider fallback (still runs in a worker) + */ +import createWorkerStorageProvider from '../WorkerStorageProvider'; + +/** + * Check if Web Workers are supported in the current environment. + */ +function isWorkerSupported(): boolean { + return typeof Worker !== 'undefined'; +} + +/** + * Check if the Origin Private File System (OPFS) is available. + * OPFS is required for SQLite persistence via the opfs-sahpool VFS. + * This is a synchronous heuristic -- actual OPFS availability is confirmed + * by the SQLite WASM library at init time. + */ +function isOPFSSupported(): boolean { + return typeof navigator !== 'undefined' && typeof navigator.storage !== 'undefined' && typeof navigator.storage.getDirectory === 'function'; +} + +/** + * Select the best backend based on browser capabilities. + * Falls back to IDB if OPFS is not available. + */ +function selectBackend(): 'sqlite' | 'idb' { + if (isWorkerSupported() && isOPFSSupported()) { + return 'sqlite'; + } + return 'idb'; +} + +const backend = selectBackend(); +const WebStorage = createWorkerStorageProvider(backend); export default WebStorage; diff --git a/lib/storage/providers/SQLiteProvider.ts b/lib/storage/providers/SQLiteProvider/index.native.ts similarity index 53% rename from lib/storage/providers/SQLiteProvider.ts rename to lib/storage/providers/SQLiteProvider/index.native.ts index d3b6fee67..ed24a7602 100644 --- a/lib/storage/providers/SQLiteProvider.ts +++ b/lib/storage/providers/SQLiteProvider/index.native.ts @@ -1,14 +1,22 @@ /** - * The SQLiteStorage provider stores everything in a key/value store by - * converting the value to a JSON string + * Native SQLite Storage Provider + * + * Implements the StorageProvider interface using react-native-nitro-sqlite. + * This module is called from the Worklet Worker Runtime (background JS thread) + * managed by NativeFlushWorker, NOT from the main thread. + * + * Uses synchronous APIs (execute, executeBatch) since the Worklet Worker Runtime + * runs on a dedicated background thread where blocking is acceptable and avoids + * unnecessary Promise overhead. */ import type {BatchQueryCommand, NitroSQLiteConnection} from 'react-native-nitro-sqlite'; import {open} from 'react-native-nitro-sqlite'; import {getFreeDiskStorage} from 'react-native-device-info'; -import type {FastMergeReplaceNullPatch} from '../../utils'; -import utils from '../../utils'; -import type StorageProvider from './types'; -import type {StorageKeyList, StorageKeyValuePair} from './types'; +import type {FastMergeReplaceNullPatch} from '../../../utils'; +import utils from '../../../utils'; +import type StorageProvider from '../types'; +import type {StorageKeyList, StorageKeyValuePair} from '../types'; +import * as Queries from '../SQLiteQueries'; /** * The type of the key-value pair stored in the SQLite database @@ -69,63 +77,59 @@ const provider: StorageProvider = { init() { provider.store = open({name: DB_NAME}); - provider.store.execute('CREATE TABLE IF NOT EXISTS keyvaluepairs (record_key TEXT NOT NULL PRIMARY KEY , valueJSON JSON NOT NULL) WITHOUT ROWID;'); + provider.store.execute(Queries.CREATE_TABLE); // All of the 3 pragmas below were suggested by SQLite team. // You can find more info about them here: https://www.sqlite.org/pragma.html - provider.store.execute('PRAGMA CACHE_SIZE=-20000;'); - provider.store.execute('PRAGMA synchronous=NORMAL;'); - provider.store.execute('PRAGMA journal_mode=WAL;'); + provider.store.execute(Queries.PRAGMA_CACHE_SIZE); + provider.store.execute(Queries.PRAGMA_SYNCHRONOUS); + provider.store.execute(Queries.PRAGMA_JOURNAL_MODE); }, getItem(key) { if (!provider.store) { throw new Error('Store is not initialized!'); } - return provider.store.executeAsync('SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key = ?;', [key]).then(({rows}) => { - if (!rows || rows?.length === 0) { - return null; - } - const result = rows?.item(0); - - if (result == null) { - return null; - } - - return JSON.parse(result.valueJSON); - }); + const {rows} = provider.store.execute(Queries.GET_ITEM, [key]); + if (!rows || rows.length === 0) { + return Promise.resolve(null); + } + const result = rows.item(0); + if (result == null) { + return Promise.resolve(null); + } + return Promise.resolve(JSON.parse(result.valueJSON)); }, multiGet(keys) { if (!provider.store) { throw new Error('Store is not initialized!'); } - const placeholders = keys.map(() => '?').join(','); - const command = `SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key IN (${placeholders});`; - return provider.store.executeAsync(command, keys).then(({rows}) => { - // eslint-disable-next-line no-underscore-dangle - const result = rows?._array.map((row) => [row.record_key, JSON.parse(row.valueJSON)]); - return (result ?? []) as StorageKeyValuePair[]; - }); + const command = Queries.buildMultiGetQuery(keys.length); + const {rows} = provider.store.execute(command, keys); + // eslint-disable-next-line no-underscore-dangle + const result = rows?._array.map((row) => [row.record_key, JSON.parse(row.valueJSON)]); + return Promise.resolve((result ?? []) as StorageKeyValuePair[]); }, setItem(key, value) { if (!provider.store) { throw new Error('Store is not initialized!'); } - return provider.store.executeAsync('REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, ?);', [key, JSON.stringify(value)]).then(() => undefined); + provider.store.execute(Queries.SET_ITEM, [key, JSON.stringify(value)]); + return Promise.resolve(); }, multiSet(pairs) { if (!provider.store) { throw new Error('Store is not initialized!'); } - const query = 'REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, ?);'; const params = pairs.map((pair) => [pair[0], JSON.stringify(pair[1] === undefined ? null : pair[1])]); if (utils.isEmptyObject(params)) { return Promise.resolve(); } - return provider.store.executeBatchAsync([{query, params}]).then(() => undefined); + provider.store.executeBatch([{query: Queries.MULTI_SET_ITEM, params}]); + return Promise.resolve(); }, multiMerge(pairs) { if (!provider.store) { @@ -134,23 +138,7 @@ const provider: StorageProvider = { const commands: BatchQueryCommand[] = []; - // Query to merge the change into the DB value. - const patchQuery = `INSERT INTO keyvaluepairs (record_key, valueJSON) - VALUES (:key, :value) - ON CONFLICT DO UPDATE - SET valueJSON = JSON_PATCH(valueJSON, :value); - `; const patchQueryArguments: string[][] = []; - - // Query to fully replace the nested objects of the DB value. - // NOTE: The JSON() wrapper around the replacement value is required here. Unlike JSON_PATCH (which - // parses both arguments as JSON internally), JSON_REPLACE treats a plain TEXT binding as a quoted - // JSON string. Without JSON(), objects would be stored as string values (e.g. "{...}") instead of - // actual JSON objects, corrupting the stored data. - const replaceQuery = `UPDATE keyvaluepairs - SET valueJSON = JSON_REPLACE(valueJSON, ?, JSON(?)) - WHERE record_key = ?; - `; const replaceQueryArguments: string[][] = []; const nonNullishPairs = pairs.filter((pair) => pair[1] !== undefined); @@ -169,12 +157,13 @@ const provider: StorageProvider = { } } - commands.push({query: patchQuery, params: patchQueryArguments}); + commands.push({query: Queries.MERGE_ITEM_PATCH, params: patchQueryArguments}); if (replaceQueryArguments.length > 0) { - commands.push({query: replaceQuery, params: replaceQueryArguments}); + commands.push({query: Queries.MERGE_ITEM_REPLACE, params: replaceQueryArguments}); } - return provider.store.executeBatchAsync(commands).then(() => undefined); + provider.store.executeBatch(commands); + return Promise.resolve(); }, mergeItem(key, change, replaceNullPatches) { // Since Onyx already merged the existing value with the changes, we can just set the value directly. @@ -185,11 +174,10 @@ const provider: StorageProvider = { throw new Error('Store is not initialized!'); } - return provider.store.executeAsync('SELECT record_key FROM keyvaluepairs;').then(({rows}) => { - // eslint-disable-next-line no-underscore-dangle - const result = rows?._array.map((row) => row.record_key); - return (result ?? []) as StorageKeyList; - }); + const {rows} = provider.store.execute<{record_key: string}>(Queries.GET_ALL_KEYS); + // eslint-disable-next-line no-underscore-dangle + const result = rows?._array.map((row) => row.record_key); + return Promise.resolve((result ?? []) as StorageKeyList); }, getAll() { if (!provider.store) { @@ -207,39 +195,40 @@ const provider: StorageProvider = { throw new Error('Store is not initialized!'); } - return provider.store.executeAsync('DELETE FROM keyvaluepairs WHERE record_key = ?;', [key]).then(() => undefined); + provider.store.execute(Queries.REMOVE_ITEM, [key]); + return Promise.resolve(); }, removeItems(keys) { if (!provider.store) { throw new Error('Store is not initialized!'); } - const placeholders = keys.map(() => '?').join(','); - const query = `DELETE FROM keyvaluepairs WHERE record_key IN (${placeholders});`; - return provider.store.executeAsync(query, keys).then(() => undefined); + const query = Queries.buildRemoveItemsQuery(keys.length); + provider.store.execute(query, keys); + return Promise.resolve(); }, clear() { if (!provider.store) { throw new Error('Store is not initialized!'); } - return provider.store.executeAsync('DELETE FROM keyvaluepairs;', []).then(() => undefined); + provider.store.execute(Queries.CLEAR, []); + return Promise.resolve(); }, getDatabaseSize() { if (!provider.store) { throw new Error('Store is not initialized!'); } - return Promise.all([provider.store.executeAsync('PRAGMA page_size;'), provider.store.executeAsync('PRAGMA page_count;'), getFreeDiskStorage()]).then( - ([pageSizeResult, pageCountResult, bytesRemaining]) => { - const pageSize = pageSizeResult.rows?.item(0)?.page_size ?? 0; - const pageCount = pageCountResult.rows?.item(0)?.page_count ?? 0; - return { - bytesUsed: pageSize * pageCount, - bytesRemaining, - }; - }, - ); + const pageSizeResult = provider.store.execute(Queries.PRAGMA_PAGE_SIZE); + const pageCountResult = provider.store.execute(Queries.PRAGMA_PAGE_COUNT); + const pageSize = pageSizeResult.rows?.item(0)?.page_size ?? 0; + const pageCount = pageCountResult.rows?.item(0)?.page_count ?? 0; + + return getFreeDiskStorage().then((bytesRemaining) => ({ + bytesUsed: pageSize * pageCount, + bytesRemaining, + })); }, }; diff --git a/lib/storage/providers/SQLiteProvider/index.web.ts b/lib/storage/providers/SQLiteProvider/index.web.ts new file mode 100644 index 000000000..be362095f --- /dev/null +++ b/lib/storage/providers/SQLiteProvider/index.web.ts @@ -0,0 +1,272 @@ +/** + * Web SQLite Storage Provider + * + * Implements the StorageProvider interface using @sqlite.org/sqlite-wasm with + * the opfs-sahpool VFS for OPFS-backed persistence. This module is imported + * by the unified storage worker (lib/storage/worker.ts), NOT by the main thread. + * + * All methods are synchronous (SQLite WASM operations are sync), but conform + * to the StorageProvider interface which returns Promises. + */ + +import type {FastMergeReplaceNullPatch} from '../../../utils'; +import utils from '../../../utils'; +import type StorageProvider from '../types'; +import type {StorageKeyList, StorageKeyValuePair} from '../types'; +import * as Queries from '../SQLiteQueries'; + +// Type declarations for the SQLite WASM API +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type SQLiteDB = any; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type SQLiteStmt = any; + +// --------------------------------------------------------------------------- +// SQLite WASM and database state +// --------------------------------------------------------------------------- + +let db: SQLiteDB | null = null; + +// Prepared statements (initialized once, reused for all operations) +let stmtGetItem: SQLiteStmt | null = null; +let stmtSetItem: SQLiteStmt | null = null; +let stmtSetItemJson: SQLiteStmt | null = null; +let stmtMergePatch: SQLiteStmt | null = null; +let stmtMergeReplace: SQLiteStmt | null = null; +let stmtRemoveItem: SQLiteStmt | null = null; +let stmtGetAllKeys: SQLiteStmt | null = null; +let stmtGetAll: SQLiteStmt | null = null; +let stmtClear: SQLiteStmt | null = null; + +/** + * Marker key used by fastMerge to flag object replacements. + * Duplicated here from utils to avoid importing the full utils module into the worker. + */ +const ONYX_INTERNALS__REPLACE_OBJECT_MARK = 'ONYX_INTERNALS__REPLACE_OBJECT_MARK'; + +/** + * JSON.stringify replacer that strips internal object-replacement markers + * before persisting merge patches. + */ +function objectMarkRemover(key: string, value: unknown) { + if (key === ONYX_INTERNALS__REPLACE_OBJECT_MARK) return undefined; + return value; +} + +/** + * Transforms replaceNullPatches into [jsonPath, valueJSON, key] tuples for + * the JSON_REPLACE prepared statement. + */ +function generateJSONReplaceSQLQueries(key: string, patches: FastMergeReplaceNullPatch[]): string[][] { + return patches.map(([pathArray, value]) => { + const jsonPath = `$.${pathArray.join('.')}`; + return [jsonPath, JSON.stringify(value), key]; + }); +} + +const provider: StorageProvider = { + store: null, + + /** + * The name of the provider that can be printed to the logs + */ + name: 'SQLiteProvider (Web)', + + /** + * Initialize the SQLite WASM database with opfs-sahpool VFS. + */ + init() { + // Actual async initialization happens via initAsync() below. + // The worker calls initAsync() and awaits it. + }, + + getItem(key) { + stmtGetItem.bind([key]); + if (stmtGetItem.step()) { + const valueJSON = stmtGetItem.getString(1) as string; + stmtGetItem.reset(); + return Promise.resolve(JSON.parse(valueJSON)); + } + stmtGetItem.reset(); + return Promise.resolve(null); + }, + + multiGet(keys) { + const results: StorageKeyValuePair[] = []; + for (const key of keys) { + stmtGetItem.bind([key]); + if (stmtGetItem.step()) { + results.push([stmtGetItem.getString(0) as string, JSON.parse(stmtGetItem.getString(1) as string)]); + } + stmtGetItem.reset(); + } + return Promise.resolve(results); + }, + + setItem(key, value) { + const valueJSON = JSON.stringify(value); + stmtSetItem.bind([key, valueJSON]); + stmtSetItem.stepReset(); + return Promise.resolve(); + }, + + multiSet(pairs) { + if (utils.isEmptyObject(pairs)) { + return Promise.resolve(); + } + db.exec('BEGIN;'); + try { + for (const [key, value] of pairs) { + const valueJSON = JSON.stringify(value === undefined ? null : value); + stmtSetItemJson.bind([key, valueJSON]); + stmtSetItemJson.stepReset(); + } + db.exec('COMMIT;'); + } catch (e) { + db.exec('ROLLBACK;'); + throw e; + } + return Promise.resolve(); + }, + + multiMerge(pairs) { + const nonNullishPairs = pairs.filter((pair) => pair[1] !== undefined); + db.exec('BEGIN;'); + try { + for (const [key, change, replaceNullPatches] of nonNullishPairs) { + // Stringify the change, stripping internal object-replacement markers + const changeJSON = JSON.stringify(change, objectMarkRemover); + + // Apply JSON_PATCH merge (named params match SQLiteQueries.MERGE_ITEM_PATCH) + stmtMergePatch.bind({':key': key, ':value': changeJSON}); + stmtMergePatch.stepReset(); + + // Generate and apply JSON_REPLACE patches if any + const patches = replaceNullPatches ?? []; + if (patches.length > 0) { + const replaceQueries = generateJSONReplaceSQLQueries(key, patches); + for (const [jsonPath, patchValue, replaceKey] of replaceQueries) { + stmtMergeReplace.bind([jsonPath, patchValue, replaceKey]); + stmtMergeReplace.stepReset(); + } + } + } + db.exec('COMMIT;'); + } catch (e) { + db.exec('ROLLBACK;'); + throw e; + } + return Promise.resolve(); + }, + + mergeItem(key, change, replaceNullPatches) { + return provider.multiMerge([[key, change, replaceNullPatches]]); + }, + + getAllKeys() { + const keys: StorageKeyList = []; + while (stmtGetAllKeys.step()) { + keys.push(stmtGetAllKeys.getString(0) as string); + } + stmtGetAllKeys.reset(); + return Promise.resolve(keys); + }, + + getAll() { + const results: StorageKeyValuePair[] = []; + while (stmtGetAll.step()) { + results.push([stmtGetAll.getString(0) as string, JSON.parse(stmtGetAll.getString(1) as string)]); + } + stmtGetAll.reset(); + return Promise.resolve(results); + }, + + removeItem(key) { + stmtRemoveItem.bind([key]); + stmtRemoveItem.stepReset(); + return Promise.resolve(); + }, + + removeItems(keys) { + db.exec('BEGIN;'); + try { + for (const key of keys) { + stmtRemoveItem.bind([key]); + stmtRemoveItem.stepReset(); + } + db.exec('COMMIT;'); + } catch (e) { + db.exec('ROLLBACK;'); + throw e; + } + return Promise.resolve(); + }, + + clear() { + stmtClear.stepReset(); + return Promise.resolve(); + }, + + getDatabaseSize() { + const pageSizeRow = db.exec('PRAGMA page_size;', {returnValue: 'resultRows'}); + const pageCountRow = db.exec('PRAGMA page_count;', {returnValue: 'resultRows'}); + + const pageSize = pageSizeRow?.[0]?.[0] ?? 0; + const pageCount = pageCountRow?.[0]?.[0] ?? 0; + + return Promise.resolve({ + bytesUsed: (pageSize as number) * (pageCount as number), + bytesRemaining: Number.POSITIVE_INFINITY, + }); + }, +}; + +/** + * Async initialization for the SQLite WASM database. + * Must be called (and awaited) before using any other provider methods. + */ +// eslint-disable-next-line @lwc/lwc/no-async-await +async function initAsync(): Promise { + // Dynamic import of the SQLite WASM module + const sqlite3InitModule = (await import('@sqlite.org/sqlite-wasm')).default; + const sqlite3 = await sqlite3InitModule(); + + // Try to install opfs-sahpool VFS + try { + const poolUtil = await sqlite3.installOpfsSAHPoolVfs({ + name: 'opfs-sahpool', + directory: '/onyx-opfs', + initialCapacity: 6, + }); + + // Open the database using the opfs-sahpool VFS + db = new poolUtil.OpfsSAHPoolDb('/OnyxDB'); + } catch (opfsError) { + // If opfs-sahpool is not available, fall back to in-memory + // (the main thread will handle the full IDB fallback) + console.error('[Onyx] opfs-sahpool VFS not available, using in-memory SQLite:', opfsError); + db = new sqlite3.oo1.DB(':memory:'); + } + + // Initialize the schema and pragmas + db.exec(Queries.CREATE_TABLE); + db.exec(Queries.PRAGMA_CACHE_SIZE); + db.exec(Queries.PRAGMA_SYNCHRONOUS); + db.exec(Queries.PRAGMA_JOURNAL_MODE); + + // Prepare reusable statements using shared SQL query constants + stmtGetItem = db.prepare(Queries.GET_ITEM); + stmtSetItem = db.prepare(Queries.SET_ITEM); + stmtSetItemJson = db.prepare(Queries.MULTI_SET_ITEM); + stmtMergePatch = db.prepare(Queries.MERGE_ITEM_PATCH); + stmtMergeReplace = db.prepare(Queries.MERGE_ITEM_REPLACE); + stmtRemoveItem = db.prepare(Queries.REMOVE_ITEM); + stmtGetAllKeys = db.prepare(Queries.GET_ALL_KEYS); + stmtGetAll = db.prepare(Queries.GET_ALL); + stmtClear = db.prepare(Queries.CLEAR); + + provider.store = db; +} + +export default provider; +export {initAsync}; diff --git a/lib/storage/providers/SQLiteQueries.ts b/lib/storage/providers/SQLiteQueries.ts new file mode 100644 index 000000000..b7c3ce312 --- /dev/null +++ b/lib/storage/providers/SQLiteQueries.ts @@ -0,0 +1,112 @@ +/** + * Shared SQL query constants used by both native and web SQLite providers. + * + * These strings are consumed by react-native-nitro-sqlite on iOS/Android and + * by @sqlite.org/sqlite-wasm on web so they must be plain SQL with `?` or + * named-parameter placeholders. + */ + +// --------------------------------------------------------------------------- +// Initialization +// --------------------------------------------------------------------------- + +const CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS keyvaluepairs (record_key TEXT NOT NULL PRIMARY KEY, valueJSON JSON NOT NULL) WITHOUT ROWID;'; +const PRAGMA_CACHE_SIZE = 'PRAGMA CACHE_SIZE=-20000;'; +const PRAGMA_SYNCHRONOUS = 'PRAGMA synchronous=NORMAL;'; +const PRAGMA_JOURNAL_MODE = 'PRAGMA journal_mode=WAL;'; + +// --------------------------------------------------------------------------- +// Read operations +// --------------------------------------------------------------------------- + +const GET_ITEM = 'SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key = ?;'; + +/** + * Builds a SELECT ... WHERE record_key IN (...) query for a given number of keys. + */ +function buildMultiGetQuery(count: number): string { + const placeholders = new Array(count).fill('?').join(','); + return `SELECT record_key, valueJSON FROM keyvaluepairs WHERE record_key IN (${placeholders});`; +} + +const GET_ALL_KEYS = 'SELECT record_key FROM keyvaluepairs;'; + +const GET_ALL = 'SELECT record_key, valueJSON FROM keyvaluepairs;'; + +// --------------------------------------------------------------------------- +// Write operations +// --------------------------------------------------------------------------- + +const SET_ITEM = 'REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, ?);'; +const MULTI_SET_ITEM = 'REPLACE INTO keyvaluepairs (record_key, valueJSON) VALUES (?, ?);'; + +// --------------------------------------------------------------------------- +// Merge operations +// --------------------------------------------------------------------------- + +/** + * INSERT-or-PATCH: inserts if the key doesn't exist, otherwise applies + * JSON_PATCH to merge the new value into the existing one. + */ +const MERGE_ITEM_PATCH = `INSERT INTO keyvaluepairs (record_key, valueJSON) + VALUES (:key, :value) + ON CONFLICT DO UPDATE + SET valueJSON = JSON_PATCH(valueJSON, :value); +`; + +/** + * Replaces a specific JSON path inside an existing value. + * Used to apply FastMergeReplaceNullPatch entries after the JSON_PATCH merge. + * + * NOTE: The JSON() wrapper around the replacement value is required here. Unlike JSON_PATCH (which + * parses both arguments as JSON internally), JSON_REPLACE treats a plain TEXT binding as a quoted + * JSON string. Without JSON(), objects would be stored as string values (e.g. "{...}") instead of + * actual JSON objects, corrupting the stored data. + */ +const MERGE_ITEM_REPLACE = `UPDATE keyvaluepairs + SET valueJSON = JSON_REPLACE(valueJSON, ?, JSON(?)) + WHERE record_key = ?; +`; + +// --------------------------------------------------------------------------- +// Delete operations +// --------------------------------------------------------------------------- + +const REMOVE_ITEM = 'DELETE FROM keyvaluepairs WHERE record_key = ?;'; + +/** + * Builds a DELETE ... WHERE record_key IN (...) query for a given number of keys. + */ +function buildRemoveItemsQuery(count: number): string { + const placeholders = new Array(count).fill('?').join(','); + return `DELETE FROM keyvaluepairs WHERE record_key IN (${placeholders});`; +} + +const CLEAR = 'DELETE FROM keyvaluepairs;'; + +// --------------------------------------------------------------------------- +// Size / diagnostics +// --------------------------------------------------------------------------- + +const PRAGMA_PAGE_SIZE = 'PRAGMA page_size;'; +const PRAGMA_PAGE_COUNT = 'PRAGMA page_count;'; + +export { + CREATE_TABLE, + PRAGMA_CACHE_SIZE, + PRAGMA_SYNCHRONOUS, + PRAGMA_JOURNAL_MODE, + GET_ITEM, + buildMultiGetQuery, + GET_ALL_KEYS, + GET_ALL, + SET_ITEM, + MULTI_SET_ITEM, + MERGE_ITEM_PATCH, + MERGE_ITEM_REPLACE, + REMOVE_ITEM, + buildRemoveItemsQuery, + CLEAR, + PRAGMA_PAGE_SIZE, + PRAGMA_PAGE_COUNT, +}; diff --git a/lib/storage/providers/types.ts b/lib/storage/providers/types.ts index 8bd4e17e2..bef57a586 100644 --- a/lib/storage/providers/types.ts +++ b/lib/storage/providers/types.ts @@ -20,9 +20,10 @@ type StorageProvider = { name: string; /** - * Initializes the storage provider + * Initializes the storage provider. + * May return a Promise if initialization is asynchronous (e.g. spawning a worker). */ - init: () => void; + init: () => void | Promise; /** * Gets the value of a given key or return `null` if it's not available in storage diff --git a/lib/storage/worker.ts b/lib/storage/worker.ts new file mode 100644 index 000000000..b8ac891aa --- /dev/null +++ b/lib/storage/worker.ts @@ -0,0 +1,287 @@ +/** + * Unified Storage Web Worker + * + * Provider-agnostic worker that handles all database operations off the main + * thread. On init, it receives a backend choice ('sqlite' or 'idb') and + * dynamically imports the appropriate StorageProvider implementation. + * + * Messages are processed **serially** via a queue to ensure that the init + * message completes before any data operations begin, and that concurrent + * messages never race against each other. + * + * After each write operation, changed keys are broadcast to other tabs via + * BroadcastChannel so they can update their caches. + */ + +import type StorageProvider from './providers/types'; +import type {StorageKeyValuePair} from './providers/types'; + +// --------------------------------------------------------------------------- +// Message types for main-thread <-> worker communication +// --------------------------------------------------------------------------- + +type InitMessage = {type: 'init'; id: string; backend: 'sqlite' | 'idb'}; +type GetItemMessage = {type: 'getItem'; id: string; key: string}; +type MultiGetMessage = {type: 'multiGet'; id: string; keys: string[]}; +type SetItemMessage = {type: 'setItem'; id: string; key: string; value: unknown}; +type MultiSetMessage = {type: 'multiSet'; id: string; pairs: StorageKeyValuePair[]}; +type MultiMergeMessage = {type: 'multiMerge'; id: string; pairs: StorageKeyValuePair[]}; +type GetAllKeysMessage = {type: 'getAllKeys'; id: string}; +type GetAllMessage = {type: 'getAll'; id: string}; +type RemoveItemMessage = {type: 'removeItem'; id: string; key: string}; +type RemoveItemsMessage = {type: 'removeItems'; id: string; keys: string[]}; +type ClearMessage = {type: 'clear'; id: string}; +type GetDatabaseSizeMessage = {type: 'getDatabaseSize'; id: string}; + +type WorkerMessage = + | InitMessage + | GetItemMessage + | MultiGetMessage + | SetItemMessage + | MultiSetMessage + | MultiMergeMessage + | GetAllKeysMessage + | GetAllMessage + | RemoveItemMessage + | RemoveItemsMessage + | ClearMessage + | GetDatabaseSizeMessage; + +type ResultMessage = {type: 'result'; id: string; data?: unknown; error?: string}; + +// --------------------------------------------------------------------------- +// State +// --------------------------------------------------------------------------- + +let provider: StorageProvider | null = null; +let broadcastChannel: BroadcastChannel | null = null; + +const BROADCAST_CHANNEL_NAME = 'onyx-sync'; + +// --------------------------------------------------------------------------- +// Serial message processing queue +// +// Each incoming message is pushed into `messageQueue`. A single `processQueue` +// loop pops one message at a time, awaits its async handler, then moves to the +// next. This guarantees: +// 1. `init` completes before any data operation touches `provider` +// 2. No two messages run concurrently (avoiding IDB transaction races) +// --------------------------------------------------------------------------- + +const messageQueue: WorkerMessage[] = []; +let processing = false; + +// eslint-disable-next-line @lwc/lwc/no-async-await +async function processQueue(): Promise { + if (processing) { + return; // another processQueue loop is already active + } + processing = true; + + while (messageQueue.length > 0) { + const msg = messageQueue.shift()!; + try { + // eslint-disable-next-line no-await-in-loop + await handleMessage(msg); + } catch (error) { + sendResult(msg.id, undefined, error instanceof Error ? error.message : String(error)); + } + } + + processing = false; +} + +// --------------------------------------------------------------------------- +// Broadcasting (value-bearing messages for cross-tab sync) +// --------------------------------------------------------------------------- + +/** + * Broadcast SET operations with full values to other tabs. + * Receiving tabs can update their caches directly without re-reading from storage. + */ +function broadcastSet(pairs: StorageKeyValuePair[]): void { + if (!broadcastChannel || pairs.length === 0) { + return; + } + + broadcastChannel.postMessage({type: 'set', pairs}); +} + +/** + * Broadcast MERGE operations with raw patches to other tabs. + * Receiving tabs apply fastMerge against their cached values. + */ +function broadcastMerge(pairs: StorageKeyValuePair[]): void { + if (!broadcastChannel || pairs.length === 0) { + return; + } + + broadcastChannel.postMessage({type: 'merge', pairs}); +} + +/** + * Broadcast REMOVE operations to other tabs. + */ +function broadcastRemove(keys: string[]): void { + if (!broadcastChannel || keys.length === 0) { + return; + } + + broadcastChannel.postMessage({type: 'remove', keys}); +} + +/** + * Broadcast CLEAR operation to other tabs. + */ +function broadcastClear(): void { + if (!broadcastChannel) { + return; + } + + broadcastChannel.postMessage({type: 'clear'}); +} + +// --------------------------------------------------------------------------- +// Result helper +// --------------------------------------------------------------------------- + +function sendResult(id: string, data?: unknown, error?: string): void { + const msg: ResultMessage = {type: 'result', id}; + if (data !== undefined) { + msg.data = data; + } + if (error !== undefined) { + msg.error = error; + } + // eslint-disable-next-line no-restricted-globals + self.postMessage(msg); +} + +// --------------------------------------------------------------------------- +// Message handler (processes a single message; called serially by the queue) +// --------------------------------------------------------------------------- + +// eslint-disable-next-line @lwc/lwc/no-async-await +async function handleMessage(msg: WorkerMessage): Promise { + switch (msg.type) { + case 'init': { + // Dynamically import and initialize the chosen backend. + // If SQLite WASM fails (missing WASM binary, no OPFS, etc.) + // we automatically fall back to IndexedDB so operations never hang. + if (msg.backend === 'sqlite') { + try { + const sqliteModule = await import('./providers/SQLiteProvider/index.web'); + const sqliteProvider = sqliteModule.default; + + // SQLite needs async init (dynamic WASM import) + await sqliteModule.initAsync(); + provider = sqliteProvider; + } catch (sqliteError) { + console.error('[Onyx] SQLite WASM init failed, falling back to IDB:', sqliteError); + const idbModule = await import('./providers/IDBKeyValProvider'); + provider = idbModule.default; + provider.init(); + } + } else { + const idbModule = await import('./providers/IDBKeyValProvider'); + provider = idbModule.default; + provider.init(); + } + + // Initialize BroadcastChannel for cross-tab sync + broadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME); + sendResult(msg.id); + break; + } + + case 'getItem': { + const result = await provider!.getItem(msg.key); + sendResult(msg.id, result); + break; + } + + case 'multiGet': { + const results = await provider!.multiGet(msg.keys); + sendResult(msg.id, results); + break; + } + + case 'setItem': { + await provider!.setItem(msg.key, msg.value); + broadcastSet([[msg.key, msg.value]]); + sendResult(msg.id); + break; + } + + case 'multiSet': { + const pairs = msg.pairs; + await provider!.multiSet(pairs); + broadcastSet(pairs); + sendResult(msg.id); + break; + } + + case 'multiMerge': { + const mergePairs = msg.pairs; + await provider!.multiMerge(mergePairs); + // Broadcast raw patches (key + change value) so receiving tabs can fastMerge + broadcastMerge(mergePairs.map(([key, value]) => [key, value])); + sendResult(msg.id); + break; + } + + case 'getAllKeys': { + const keys = await provider!.getAllKeys(); + sendResult(msg.id, keys); + break; + } + + case 'getAll': { + const data = await provider!.getAll(); + sendResult(msg.id, data); + break; + } + + case 'removeItem': { + await provider!.removeItem(msg.key); + broadcastRemove([msg.key]); + sendResult(msg.id); + break; + } + + case 'removeItems': { + await provider!.removeItems(msg.keys); + broadcastRemove(msg.keys); + sendResult(msg.id); + break; + } + + case 'clear': { + await provider!.clear(); + broadcastClear(); + sendResult(msg.id); + break; + } + + case 'getDatabaseSize': { + const size = await provider!.getDatabaseSize(); + sendResult(msg.id, size); + break; + } + + default: + sendResult((msg as {id: string}).id, undefined, `Unknown message type: ${(msg as {type: string}).type}`); + } +} + +// --------------------------------------------------------------------------- +// Entry point: enqueue every incoming message and kick the serial processor +// --------------------------------------------------------------------------- + +// eslint-disable-next-line no-restricted-globals +self.onmessage = (event: MessageEvent) => { + messageQueue.push(event.data); + processQueue(); +}; + +export type {WorkerMessage, ResultMessage}; diff --git a/package-lock.json b/package-lock.json index 7f7511b4e..0df1a6111 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "3.0.68", "license": "MIT", "dependencies": { + "@sqlite.org/sqlite-wasm": "^3.51.2-build6", "ascii-table": "0.0.9", "fast-equals": "^4.0.3", "lodash.bindall": "^4.4.0", @@ -75,7 +76,8 @@ "react-native": ">=0.75.0", "react-native-device-info": "^10.3.0", "react-native-nitro-modules": ">=0.35.0", - "react-native-nitro-sqlite": "^9.6.0" + "react-native-nitro-sqlite": "^9.6.0", + "react-native-worklets-core": "^1.6.2" }, "peerDependenciesMeta": { "idb-keyval": { @@ -151,7 +153,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -165,7 +166,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -180,7 +180,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -190,7 +189,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -241,7 +239,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.28.5", @@ -258,7 +255,6 @@ "version": "7.27.3", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.27.3" @@ -271,7 +267,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.2", @@ -288,7 +283,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -310,7 +304,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", @@ -328,7 +321,6 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", @@ -345,7 +337,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -355,7 +346,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.28.5", @@ -369,7 +359,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -383,7 +372,6 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -401,7 +389,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.27.1" @@ -414,7 +401,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -424,7 +410,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", @@ -442,7 +427,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-member-expression-to-functions": "^7.27.1", @@ -460,7 +444,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -474,7 +457,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -484,7 +466,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -494,7 +475,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -504,7 +484,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.1", @@ -519,7 +498,6 @@ "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", @@ -533,7 +511,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.28.5" @@ -549,7 +526,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -566,7 +542,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -582,7 +557,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -598,7 +572,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -616,7 +589,6 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -634,7 +606,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", @@ -651,7 +622,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.27.1.tgz", "integrity": "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -668,7 +638,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6", @@ -686,7 +655,6 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.20.2", @@ -704,7 +672,6 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -717,7 +684,6 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -730,7 +696,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -743,7 +708,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" @@ -756,7 +720,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -772,7 +735,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -785,7 +747,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.27.1.tgz", "integrity": "sha512-eBC/3KSekshx19+N40MzjWqJd7KTEdOoLesAfa4IDFI8eRz5a47i5Oszus6zG/cwIXN63YhgLOMSSNJx49sENg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -801,7 +762,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz", "integrity": "sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -817,7 +777,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -833,7 +792,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -849,7 +807,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" @@ -862,7 +819,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -875,7 +831,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -891,7 +846,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" @@ -904,7 +858,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -917,7 +870,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" @@ -930,7 +882,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -943,7 +894,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -956,7 +906,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" @@ -969,7 +918,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -985,7 +933,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" @@ -1001,7 +948,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1017,7 +963,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -1034,7 +979,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1050,7 +994,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1068,7 +1011,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -1086,7 +1028,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1102,7 +1043,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1118,7 +1058,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", @@ -1135,7 +1074,6 @@ "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.3", @@ -1152,7 +1090,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -1173,7 +1110,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1190,7 +1126,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1207,7 +1142,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1224,7 +1158,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1240,7 +1173,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1257,7 +1189,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1273,7 +1204,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1290,7 +1220,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1306,7 +1235,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1322,7 +1250,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1339,7 +1266,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1356,7 +1282,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", @@ -1374,7 +1299,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1390,7 +1314,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1406,7 +1329,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1422,7 +1344,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1438,7 +1359,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -1455,7 +1375,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -1472,7 +1391,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.28.3", @@ -1491,7 +1409,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.27.1", @@ -1508,7 +1425,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1525,7 +1441,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1541,7 +1456,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1557,7 +1471,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1573,7 +1486,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", @@ -1593,7 +1505,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1610,7 +1521,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1626,7 +1536,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1643,7 +1552,6 @@ "version": "7.27.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1659,7 +1567,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", @@ -1676,7 +1583,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", @@ -1694,7 +1600,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1710,7 +1615,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1726,7 +1630,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", @@ -1746,7 +1649,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1762,7 +1664,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1778,7 +1679,6 @@ "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1794,7 +1694,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1811,7 +1710,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1827,7 +1725,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.0.tgz", "integrity": "sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -1848,7 +1745,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1864,7 +1760,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -1881,7 +1776,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1897,7 +1791,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1913,7 +1806,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1929,7 +1821,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -1949,7 +1840,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" @@ -1965,7 +1855,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1982,7 +1871,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -1999,7 +1887,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", @@ -2016,7 +1903,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz", "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -2102,7 +1988,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.27.1.tgz", "integrity": "sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -2120,7 +2005,6 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -2135,7 +2019,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", @@ -2155,7 +2038,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.27.1.tgz", "integrity": "sha512-K13lQpoV54LATKkzBpBAEu1GGSIRzxR9f4IN4V8DCDgiUMo2UDGagEZr3lPeVNJPLkWUi5JE4hCHKneVTwQlYQ==", - "dev": true, "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", @@ -2175,7 +2057,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^4.0.1", @@ -2189,7 +2070,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -2199,7 +2079,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -2210,7 +2089,6 @@ "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -2220,7 +2098,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -2235,7 +2112,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -2255,7 +2131,6 @@ "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -2274,7 +2149,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -2795,7 +2669,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -2805,7 +2678,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, "license": "ISC", "dependencies": { "camelcase": "^5.3.1", @@ -2822,7 +2694,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -2832,7 +2703,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -2846,7 +2716,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -2860,7 +2729,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -2873,7 +2741,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -2889,7 +2756,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -2902,7 +2768,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2912,7 +2777,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2988,7 +2852,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", - "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3" @@ -3001,7 +2864,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.7.0", @@ -3044,7 +2906,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -3122,7 +2983,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.27.8" @@ -3182,7 +3042,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.11.6", @@ -3209,7 +3068,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", @@ -3227,7 +3085,6 @@ "version": "0.3.12", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -3238,7 +3095,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -3248,7 +3104,6 @@ "version": "0.3.10", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -3259,14 +3114,12 @@ "version": "1.5.4", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.29", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -3877,7 +3730,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.76.3.tgz", "integrity": "sha512-7Fnc3lzCFFpnoyL1egua6d/qUp0KiIpeSLbfOMln4nI2g2BMzyFHdPjJnpLV2NehmS0omOOkrfRqK5u1F/MXzA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -3887,7 +3739,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.3.tgz", "integrity": "sha512-mZ7jmIIg4bUnxCqY3yTOkoHvvzsDyrZgfnIKiTGm5QACrsIGa5eT3pMFpMm2OpxGXRDrTMsYdPXE2rCyDX52VQ==", - "dev": true, "license": "MIT", "dependencies": { "@react-native/codegen": "0.76.3" @@ -3900,7 +3751,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.3.tgz", "integrity": "sha512-zi2nPlQf9q2fmfPyzwWEj6DU96v8ziWtEfG7CTAX2PG/Vjfsr94vn/wWrCdhBVvLRQ6Kvd/MFAuDYpxmQwIiVQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -3960,7 +3810,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.3.tgz", "integrity": "sha512-oJCH/jbYeGmFJql8/y76gqWCCd74pyug41yzYAjREso1Z7xL88JhDyKMvxEnfhSdMOZYVl479N80xFiXPy3ZYA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.25.3", @@ -3983,7 +3832,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.76.3.tgz", "integrity": "sha512-vgsLixHS24jR0d0QqPykBWFaC+V8x9cM3cs4oYXw3W199jgBNGP9MWcUJLazD2vzrT/lUTVBVg0rBeB+4XR6fg==", - "dev": true, "license": "MIT", "dependencies": { "@react-native/dev-middleware": "0.76.3", @@ -4014,7 +3862,6 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4027,7 +3874,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.76.3.tgz", "integrity": "sha512-pMHQ3NpPB28RxXciSvm2yD+uDx3pkhzfuWkc7VFgOduyzPSIr0zotUiOJzsAtrj8++bPbOsAraCeQhCqoOTWQw==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=18" @@ -4037,7 +3883,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.76.3.tgz", "integrity": "sha512-b+2IpW40z1/S5Jo5JKrWPmucYU/PzeGyGBZZ/SJvmRnBDaP3txb9yIqNZAII1EWsKNhedh8vyRO5PSuJ9Juqzw==", - "dev": true, "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", @@ -4060,7 +3905,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -4070,14 +3914,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/@react-native/dev-middleware/node_modules/ws": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "dev": true, "license": "MIT", "dependencies": { "async-limiter": "~1.0.0" @@ -4087,7 +3929,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.76.3.tgz", "integrity": "sha512-t0aYZ8ND7+yc+yIm6Yp52bInneYpki6RSIFZ9/LMUzgMKvEB62ptt/7sfho9QkKHCNxE1DJSWIqLIGi/iHHkyg==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -4097,7 +3938,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.76.3.tgz", "integrity": "sha512-pubJFArMMrdZiytH+W95KngcSQs+LsxOBsVHkwgMnpBfRUxXPMK4fudtBwWvhnwN76Oe+WhxSq7vOS5XgoPhmw==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -4107,7 +3947,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.76.3.tgz", "integrity": "sha512-b2zQPXmW7avw/7zewc9nzMULPIAjsTwN03hskhxHUJH5pzUf7pIklB3FrgYPZrRhJgzHiNl3tOPu7vqiKzBYPg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -4126,7 +3965,6 @@ "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.76.3.tgz", "integrity": "sha512-Yrpmrh4IDEupUUM/dqVxhAN8QW1VEUR3Qrk2lzJC1jB2s46hDe0hrMP2vs12YJqlzshteOthjwXQlY0TgIzgbg==", - "dev": true, "license": "MIT" }, "node_modules/@react-native/polyfills": { @@ -4147,14 +3985,12 @@ "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, "license": "MIT" }, "node_modules/@sinonjs/commons": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" @@ -4164,12 +4000,20 @@ "version": "10.3.0", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@sqlite.org/sqlite-wasm": { + "version": "3.51.2-build9", + "resolved": "https://registry.npmjs.org/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.51.2-build9.tgz", + "integrity": "sha512-tj2Sa6X4gVZqS9SiT2xlEeChSUklSGq8Hz6zKNbHW6NRiGyrSXiFcspnrWru1wPBT76RX/VxweESKxawCxfDxg==", + "license": "Apache-2.0", + "engines": { + "node": ">=22" + } + }, "node_modules/@sqltools/formatter": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", @@ -4257,7 +4101,6 @@ "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", @@ -4271,7 +4114,6 @@ "version": "7.27.0", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" @@ -4281,7 +4123,6 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", @@ -4292,7 +4133,6 @@ "version": "7.20.7", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" @@ -4309,7 +4149,6 @@ "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -4319,14 +4158,12 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, "license": "MIT" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, "license": "MIT", "dependencies": { "@types/istanbul-lib-coverage": "*" @@ -4336,7 +4173,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/istanbul-lib-report": "*" @@ -4423,7 +4259,6 @@ "version": "20.19.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.4.tgz", "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -4434,7 +4269,6 @@ "version": "1.3.12", "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.12.tgz", "integrity": "sha512-a0ToKlRVnUw3aXKQq2F+krxZKq7B8LEQijzPn5RdFAMatARD2JX9o8FBpMXOOrjob0uc13aN+V/AXniOXW4d9A==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -4444,14 +4278,14 @@ "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.23", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -4479,7 +4313,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, "license": "MIT" }, "node_modules/@types/tough-cookie": { @@ -4500,7 +4333,6 @@ "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, "license": "MIT", "dependencies": { "@types/yargs-parser": "*" @@ -4510,7 +4342,6 @@ "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -5061,7 +4892,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" @@ -5074,7 +4904,6 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, "license": "MIT", "dependencies": { "mime-types": "~2.1.34", @@ -5088,7 +4917,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "peer": true, "bin": { @@ -5166,7 +4994,6 @@ "version": "1.4.10", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", - "dev": true, "license": "MIT" }, "node_modules/ansi-escape-sequences": { @@ -5225,7 +5052,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5235,7 +5061,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -5261,7 +5086,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -5275,7 +5099,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -5512,7 +5335,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true, "license": "MIT" }, "node_modules/ascii-table": { @@ -5525,7 +5347,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", - "dev": true, "license": "MIT", "dependencies": { "tslib": "^2.0.1" @@ -5555,7 +5376,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true, "license": "MIT" }, "node_modules/asynckit": { @@ -5605,7 +5425,6 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, "license": "MIT", "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -5615,7 +5434,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, "license": "MIT", "dependencies": { "@jest/transform": "^29.7.0", @@ -5637,7 +5455,6 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -5654,7 +5471,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@babel/core": "^7.12.3", @@ -5671,7 +5487,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.3.3", @@ -5687,7 +5502,6 @@ "version": "0.4.14", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.7", @@ -5702,7 +5516,6 @@ "version": "0.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5", @@ -5716,7 +5529,6 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5" @@ -5729,7 +5541,6 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", - "dev": true, "license": "MIT", "dependencies": { "hermes-parser": "0.25.1" @@ -5739,14 +5550,12 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, "license": "MIT" }, "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, "license": "MIT", "dependencies": { "hermes-estree": "0.25.1" @@ -5756,7 +5565,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/plugin-syntax-flow": "^7.12.1" @@ -5766,7 +5574,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", @@ -5793,7 +5600,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, "license": "MIT", "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", @@ -5810,14 +5616,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -5875,7 +5679,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -5888,7 +5691,6 @@ "version": "4.25.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5922,7 +5724,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" @@ -5957,7 +5758,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, "license": "MIT" }, "node_modules/builtin-modules": { @@ -6052,7 +5852,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "dev": true, "license": "MIT", "dependencies": { "callsites": "^2.0.0" @@ -6065,7 +5864,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -6075,7 +5873,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "dev": true, "license": "MIT", "dependencies": { "caller-callsite": "^2.0.0" @@ -6098,7 +5895,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -6108,7 +5904,6 @@ "version": "1.0.30001727", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6142,7 +5937,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -6214,7 +6008,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@types/node": "*", @@ -6233,7 +6026,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz", "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@types/node": "*", @@ -6248,7 +6040,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" @@ -6261,7 +6052,6 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, "funding": [ { "type": "github", @@ -6307,7 +6097,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -6322,7 +6111,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", @@ -6369,7 +6157,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -6382,7 +6169,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -6497,7 +6283,6 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -6527,7 +6312,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, "license": "MIT" }, "node_modules/complex.js": { @@ -6548,7 +6332,6 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, "license": "MIT" }, "node_modules/config-master": { @@ -6582,7 +6365,6 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -6598,7 +6380,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -6608,21 +6389,18 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, "node_modules/core-js-compat": { "version": "3.44.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", - "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.25.1" @@ -6636,7 +6414,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, "license": "MIT", "dependencies": { "import-fresh": "^2.0.0", @@ -6652,7 +6429,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" @@ -6662,7 +6438,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "dev": true, "license": "MIT", "dependencies": { "caller-path": "^2.0.0", @@ -6676,7 +6451,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -6690,7 +6464,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, "license": "MIT", "dependencies": { "error-ex": "^1.3.1", @@ -6704,7 +6477,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -6743,7 +6515,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -6785,7 +6556,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -6886,7 +6657,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6999,7 +6769,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -7016,7 +6785,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8", @@ -7143,14 +6911,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.5.180", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.180.tgz", "integrity": "sha512-ED+GEyEh3kYMwt2faNmgMB0b8O5qtATGgR4RmRsIp4T6p7B8vdMbIedYndnvZfsaXvSzegtpfqRMDNCjjiSduA==", - "dev": true, "license": "ISC" }, "node_modules/emittery": { @@ -7177,7 +6943,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -7200,7 +6965,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" @@ -7210,7 +6974,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "dev": true, "license": "MIT", "dependencies": { "stackframe": "^1.3.4" @@ -7397,7 +7160,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7407,7 +7169,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, "license": "MIT" }, "node_modules/escape-latex": { @@ -7421,7 +7182,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -8375,7 +8135,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", @@ -8425,7 +8184,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -8435,7 +8193,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -8445,7 +8202,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8455,7 +8211,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", @@ -8505,7 +8260,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", - "dev": true, "license": "Apache-2.0" }, "node_modules/fake-indexeddb": { @@ -8572,7 +8326,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -8615,7 +8368,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" @@ -8680,7 +8432,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -8693,7 +8444,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -8712,7 +8462,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -8722,14 +8471,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, "license": "MIT", "dependencies": { "commondir": "^1.0.1", @@ -8744,7 +8491,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^3.0.0" @@ -8757,7 +8503,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^3.0.0", @@ -8771,7 +8516,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^4.0.1", @@ -8785,7 +8529,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -8801,7 +8544,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.0.0" @@ -8814,7 +8556,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -8824,7 +8565,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "license": "MIT", "dependencies": { "find-up": "^3.0.0" @@ -8837,7 +8577,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver" @@ -8921,14 +8660,12 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", - "dev": true, "license": "MIT" }, "node_modules/flow-parser": { "version": "0.275.0", "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.275.0.tgz", "integrity": "sha512-fHNwawoA2LM7FsxhU/1lTRGq9n6/Q8k861eHgN7GKtamYt9Qrxpg/ZSrev8o1WX7fQ2D3Gg3+uvYN15PmsG7Yw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -9015,7 +8752,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -9035,14 +8771,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -9057,7 +8791,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9098,7 +8831,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -9108,7 +8840,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -9143,7 +8874,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.0.0" @@ -9167,7 +8897,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -9212,7 +8941,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", @@ -9246,7 +8974,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -9257,7 +8984,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -9334,7 +9060,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -9383,7 +9108,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9451,7 +9175,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9464,14 +9187,12 @@ "version": "0.23.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", - "dev": true, "license": "MIT" }, "node_modules/hermes-parser": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", - "dev": true, "license": "MIT", "dependencies": { "hermes-estree": "0.23.1" @@ -9518,7 +9239,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, "license": "MIT", "dependencies": { "depd": "2.0.0", @@ -9535,7 +9255,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -9574,7 +9293,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=10.17.0" @@ -9642,7 +9360,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", - "dev": true, "license": "MIT", "dependencies": { "queue": "6.0.2" @@ -9695,7 +9412,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -9716,7 +9432,6 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -9727,7 +9442,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/internal-slot": { @@ -9749,7 +9463,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" @@ -9777,7 +9490,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, "license": "MIT" }, "node_modules/is-async-function": { @@ -9902,7 +9614,6 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -9953,7 +9664,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9963,7 +9673,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" @@ -10005,7 +9714,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10083,7 +9791,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -10110,7 +9817,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "license": "MIT", "dependencies": { "isobject": "^3.0.1" @@ -10178,7 +9884,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10288,7 +9993,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "license": "MIT", "dependencies": { "is-docker": "^2.0.0" @@ -10308,14 +10012,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -10325,7 +10027,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=8" @@ -10679,7 +10380,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, "license": "MIT", "dependencies": { "@jest/environment": "^29.7.0", @@ -10697,7 +10397,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -10707,7 +10406,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -10763,7 +10461,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", @@ -10784,7 +10481,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -10817,7 +10513,6 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -10974,7 +10669,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -10992,7 +10686,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -11005,7 +10698,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^29.6.3", @@ -11023,7 +10715,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -11056,7 +10747,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -11072,7 +10762,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -11088,7 +10777,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -11118,21 +10806,18 @@ "version": "250231.0.0", "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/jsc-safe-url": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", - "dev": true, "license": "0BSD" }, "node_modules/jscodeshift": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.13.16", @@ -11166,7 +10851,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, "license": "ISC", "dependencies": { "graceful-fs": "^4.1.11", @@ -11364,7 +11048,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -11384,7 +11067,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { @@ -11412,7 +11094,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -11451,7 +11132,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11501,7 +11181,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -11525,7 +11204,6 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", - "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^2.6.9", @@ -11536,7 +11214,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -11546,7 +11223,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/lines-and-columns": { @@ -11613,7 +11289,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, "license": "MIT" }, "node_modules/lodash.merge": { @@ -11649,7 +11324,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "dev": true, "license": "MIT" }, "node_modules/lodash.transform": { @@ -11662,7 +11336,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -11675,7 +11348,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -11721,7 +11393,6 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "tmpl": "1.0.5" @@ -11774,7 +11445,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", - "dev": true, "license": "Apache-2.0" }, "node_modules/math-intrinsics": { @@ -11822,14 +11492,12 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "dev": true, "license": "MIT" }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, "license": "MIT" }, "node_modules/merge2": { @@ -11846,7 +11514,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro/-/metro-0.81.5.tgz", "integrity": "sha512-YpFF0DDDpDVygeca2mAn7K0+us+XKmiGk4rIYMz/CRdjFoCGqAei/IQSpV0UrGfQbToSugpMQeQJveaWSH88Hg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", @@ -11901,7 +11568,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.81.5.tgz", "integrity": "sha512-oKCQuajU5srm+ZdDcFg86pG/U8hkSjBlkyFjz380SZ4TTIiI5F+OQB830i53D8hmqmcosa4wR/pnKv8y4Q3dLw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -11917,14 +11583,12 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, "license": "MIT" }, "node_modules/metro-babel-transformer/node_modules/hermes-parser": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, "license": "MIT", "dependencies": { "hermes-estree": "0.25.1" @@ -11934,7 +11598,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.81.5.tgz", "integrity": "sha512-wOsXuEgmZMZ5DMPoz1pEDerjJ11AuMy9JifH4yNW7NmWS0ghCRqvDxk13LsElzLshey8C+my/tmXauXZ3OqZgg==", - "dev": true, "license": "MIT", "dependencies": { "exponential-backoff": "^3.1.1", @@ -11949,7 +11612,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.81.5.tgz", "integrity": "sha512-lGWnGVm1UwO8faRZ+LXQUesZSmP1LOg14OVR+KNPBip8kbMECbQJ8c10nGesw28uQT7AE0lwQThZPXlxDyCLKQ==", - "dev": true, "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6" @@ -11962,7 +11624,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.81.5.tgz", "integrity": "sha512-oDRAzUvj6RNRxratFdcVAqtAsg+T3qcKrGdqGZFUdwzlFJdHGR9Z413sW583uD2ynsuOjA2QB6US8FdwiBdNKg==", - "dev": true, "license": "MIT", "dependencies": { "connect": "^3.6.5", @@ -11982,7 +11643,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.81.5.tgz", "integrity": "sha512-+2R0c8ByfV2N7CH5wpdIajCWa8escUFd8TukfoXyBq/vb6yTCsznoA25FhNXJ+MC/cz1L447Zj3vdUfCXIZBwg==", - "dev": true, "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6", @@ -11997,7 +11657,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.81.5.tgz", "integrity": "sha512-mW1PKyiO3qZvjeeVjj1brhkmIotObA3/9jdbY1fQQYvEWM6Ml7bN/oJCRDGn2+bJRlG+J8pwyJ+DgdrM4BsKyg==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^2.2.0", @@ -12018,7 +11677,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -12028,14 +11686,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/metro-minify-terser": { "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.81.5.tgz", "integrity": "sha512-/mn4AxjANnsSS3/Bb+zA1G5yIS5xygbbz/OuPaJYs0CPcZCaWt66D+65j4Ft/nJkffUxcwE9mk4ubpkl3rjgtw==", - "dev": true, "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6", @@ -12049,7 +11705,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.81.5.tgz", "integrity": "sha512-6BX8Nq3g3go3FxcyXkVbWe7IgctjDTk6D9flq+P201DfHHQ28J+DWFpVelFcrNTn4tIfbP/Bw7u/0g2BGmeXfQ==", - "dev": true, "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6" @@ -12062,7 +11717,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.81.5.tgz", "integrity": "sha512-M/Gf71ictUKP9+77dV/y8XlAWg7xl76uhU7ggYFUwEdOHHWPG6gLBr1iiK0BmTjPFH8yRo/xyqMli4s3oGorPQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.0", @@ -12076,7 +11730,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.81.5.tgz", "integrity": "sha512-Jz+CjvCKLNbJZYJTBeN3Kq9kIJf6b61MoLBdaOQZJ5Ajhw6Pf95Nn21XwA8BwfUYgajsi6IXsp/dTZsYJbN00Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.3", @@ -12098,7 +11751,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -12108,7 +11760,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.81.5.tgz", "integrity": "sha512-X3HV3n3D6FuTE11UWFICqHbFMdTavfO48nXsSpnNGFkUZBexffu0Xd+fYKp+DJLNaQr3S+lAs8q9CgtDTlRRuA==", - "dev": true, "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6", @@ -12129,7 +11780,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -12139,7 +11789,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.81.5.tgz", "integrity": "sha512-MmHhVx/1dJC94FN7m3oHgv5uOjKH8EX8pBeu1pnPMxbJrx6ZuIejO0k84zTSaQTZ8RxX1wqwzWBpXAWPjEX8mA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -12157,7 +11806,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.81.5.tgz", "integrity": "sha512-lUFyWVHa7lZFRSLJEv+m4jH8WrR5gU7VIjUlg4XmxQfV8ngY4V10ARKynLhMYPeQGl7Qvf+Ayg0eCZ272YZ4Mg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -12182,14 +11830,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true, "license": "MIT" }, "node_modules/metro/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -12199,14 +11845,12 @@ "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, "license": "MIT" }, "node_modules/metro/node_modules/hermes-parser": { "version": "0.25.1", "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, "license": "MIT", "dependencies": { "hermes-estree": "0.25.1" @@ -12216,14 +11860,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/metro/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -12233,7 +11875,6 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.3.0" @@ -12255,7 +11896,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -12269,7 +11909,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -12282,7 +11921,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -12295,7 +11933,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -12305,7 +11942,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -12318,7 +11954,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -12354,7 +11989,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12374,7 +12008,6 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -12394,7 +12027,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/napi-postinstall": { @@ -12431,7 +12063,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -12441,14 +12072,12 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, "license": "MIT" }, "node_modules/node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, "license": "MIT", "dependencies": { "minimatch": "^3.0.2" @@ -12461,7 +12090,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -12472,7 +12100,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -12485,7 +12112,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -12506,21 +12132,18 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, "license": "MIT" }, "node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -12531,7 +12154,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -12541,14 +12163,12 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, "license": "MIT" }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, "license": "MIT" }, "node_modules/nodemon": { @@ -12644,7 +12264,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12654,7 +12273,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.0.0" @@ -12667,7 +12285,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "dev": true, "license": "MIT" }, "node_modules/nwsapi": { @@ -12681,7 +12298,6 @@ "version": "0.81.5", "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.81.5.tgz", "integrity": "sha512-iNpbeXPLmaiT9I5g16gFFFjsF3sGxLpYG2EGP3dfFB4z+l9X60mp/yRzStHhMtuNt8qmf7Ww80nOPQHngHhnIQ==", - "dev": true, "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6" @@ -12857,7 +12473,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -12870,7 +12485,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -12880,7 +12494,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" @@ -12896,7 +12509,6 @@ "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, "license": "MIT", "dependencies": { "is-docker": "^2.0.0", @@ -12981,7 +12593,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -13073,7 +12684,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -13083,7 +12693,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13093,7 +12702,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13103,7 +12711,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13113,7 +12720,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -13154,7 +12760,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -13175,7 +12780,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -13185,7 +12789,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -13324,7 +12927,6 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, "license": "MIT", "dependencies": { "@jest/schemas": "^29.6.3", @@ -13339,7 +12941,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -13352,7 +12953,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "dev": true, "license": "MIT", "dependencies": { "asap": "~2.0.6" @@ -13459,7 +13059,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dev": true, "license": "MIT", "dependencies": { "inherits": "~2.0.3" @@ -13490,7 +13089,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -13500,7 +13098,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -13514,7 +13111,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.3.2.tgz", "integrity": "sha512-crr9HkVrDiJ0A4zot89oS0Cgv0Oa4OG1Em4jit3P3ZxZSKPMYyMjfwMqgcJna9o625g8oN87rBm8SWWrSTBZxg==", - "dev": true, "license": "MIT", "dependencies": { "shell-quote": "^1.6.1", @@ -13525,7 +13121,6 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.3.0" @@ -13547,14 +13142,12 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, "license": "MIT" }, "node_modules/react-native": { "version": "0.76.3", "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.76.3.tgz", "integrity": "sha512-0TUhgmlouRNf6yuDIIAdbQl0g1VsONgCMsLs7Et64hjj5VLMCA7np+4dMrZvGZ3wRNqzgeyT9oWJsUm49AcwSQ==", - "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -13650,11 +13243,24 @@ "react-native-nitro-modules": ">=0.35.0" } }, + "node_modules/react-native-worklets-core": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/react-native-worklets-core/-/react-native-worklets-core-1.6.3.tgz", + "integrity": "sha512-r3Q40XQBccx/iAI5tlyiua+micvO1UGzzUOskNweZUXyfrrE+rb5aqxqruBPqXf90rO+bBiplylLMEAXCLTyGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "string-hash-64": "^1.0.3" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native/node_modules/@react-native/virtualized-lists": { "version": "0.76.3", "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.76.3.tgz", "integrity": "sha512-wTGv9pVh3vAOWb29xFm+J9VRe9dUcUcb9FyaMLT/Hxa88W4wqa5ZMe1V9UvrrBiA1G5DKjv8/1ZcDsJhyugVKA==", - "dev": true, "license": "MIT", "dependencies": { "invariant": "^2.2.4", @@ -13678,7 +13284,6 @@ "version": "0.23.1", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.23.1.tgz", "integrity": "sha512-uNLD0tk2tLUjGFdmCk+u/3FEw2o+BAwW4g+z2QVlxJrzZYOOPADroEcNtTPt5lNiScctaUmnsTkVEnOwZUOLhA==", - "dev": true, "license": "MIT", "dependencies": { "hermes-parser": "0.23.1" @@ -13688,7 +13293,6 @@ "version": "0.24.0-canary-efb381bbf-20230505", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -13698,7 +13302,6 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13711,7 +13314,6 @@ "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "dev": true, "license": "MIT", "dependencies": { "async-limiter": "~1.0.0" @@ -13721,7 +13323,6 @@ "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13787,7 +13388,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", - "dev": true, "license": "BSD" }, "node_modules/reassure": { @@ -13811,7 +13411,6 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", - "dev": true, "license": "MIT", "dependencies": { "ast-types": "0.15.2", @@ -13932,14 +13531,12 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2" @@ -13952,7 +13549,6 @@ "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true, "license": "MIT" }, "node_modules/regexp-tree": { @@ -14003,7 +13599,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", @@ -14021,14 +13616,12 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, "license": "MIT" }, "node_modules/regjsparser": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.0.2" @@ -14041,7 +13634,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -14054,7 +13646,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -14081,7 +13672,6 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -14167,7 +13757,6 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -14320,7 +13909,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/node-forge": "^1.3.0", @@ -14334,7 +13922,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -14344,7 +13931,6 @@ "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -14369,7 +13955,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -14379,14 +13964,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/send/node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -14399,7 +13982,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -14409,7 +13991,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -14419,7 +14000,6 @@ "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", @@ -14435,7 +14015,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -14494,7 +14073,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, "license": "ISC" }, "node_modules/sha.js": { @@ -14522,7 +14100,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "license": "MIT", "dependencies": { "kind-of": "^6.0.2" @@ -14535,7 +14112,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -14548,7 +14124,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14558,7 +14133,6 @@ "version": "1.8.3", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -14647,7 +14221,6 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, "license": "ISC" }, "node_modules/simple-git": { @@ -14703,7 +14276,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14745,7 +14317,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -14791,7 +14362,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/sql-highlight": { @@ -14825,7 +14395,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^2.0.0" @@ -14838,7 +14407,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14848,14 +14416,12 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", - "dev": true, "license": "MIT" }, "node_modules/stacktrace-parser": { "version": "0.1.11", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", - "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.7.1" @@ -14868,7 +14434,6 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" @@ -14878,7 +14443,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -14935,6 +14499,12 @@ "node": ">=0.10.0" } }, + "node_modules/string-hash-64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string-hash-64/-/string-hash-64-1.0.3.tgz", + "integrity": "sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==", + "license": "MIT" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -14960,7 +14530,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -14998,7 +14567,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/string.prototype.includes": { @@ -15118,7 +14686,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -15155,7 +14722,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -15204,7 +14770,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -15217,7 +14782,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -15267,7 +14831,6 @@ "version": "0.8.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "dev": true, "license": "MIT", "dependencies": { "rimraf": "~2.6.2" @@ -15288,7 +14851,6 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" @@ -15301,7 +14863,6 @@ "version": "5.43.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -15320,14 +14881,12 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, "node_modules/terser/node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -15338,7 +14897,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, "license": "ISC", "dependencies": { "@istanbuljs/schema": "^0.1.2", @@ -15353,7 +14911,6 @@ "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -15364,7 +14921,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -15404,7 +14960,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", - "dev": true, "license": "MIT" }, "node_modules/tiny-emitter": { @@ -15435,7 +14990,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/to-buffer": { @@ -15457,7 +15011,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -15470,7 +15023,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.6" @@ -15633,7 +15185,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, "license": "0BSD" }, "node_modules/tsutils": { @@ -15686,7 +15237,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -16024,14 +15574,12 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -16041,7 +15589,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", @@ -16055,7 +15602,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -16065,7 +15611,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -16092,7 +15637,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -16138,7 +15682,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -16190,7 +15733,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -16232,7 +15774,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", - "dev": true, "license": "MIT" }, "node_modules/w3c-xmlserializer": { @@ -16262,7 +15803,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, "license": "Apache-2.0", "dependencies": { "makeerror": "1.0.12" @@ -16295,7 +15835,6 @@ "version": "3.6.20", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", - "dev": true, "license": "MIT" }, "node_modules/whatwg-mimetype": { @@ -16326,7 +15865,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -16472,7 +16010,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -16509,14 +16046,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", @@ -16576,7 +16111,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -16586,14 +16120,12 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, "license": "ISC" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -16612,7 +16144,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" diff --git a/package.json b/package.json index 343fbff03..a8a7a2bd5 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "gh-actions-build": "./.github/scripts/buildActions.sh" }, "dependencies": { + "@sqlite.org/sqlite-wasm": "^3.51.2-build6", "ascii-table": "0.0.9", "fast-equals": "^4.0.3", "lodash.bindall": "^4.4.0", @@ -105,7 +106,8 @@ "react-native": ">=0.75.0", "react-native-device-info": "^10.3.0", "react-native-nitro-modules": ">=0.35.0", - "react-native-nitro-sqlite": "^9.6.0" + "react-native-nitro-sqlite": "^9.6.0", + "react-native-worklets-core": "^1.6.2" }, "peerDependenciesMeta": { "idb-keyval": { @@ -126,4 +128,4 @@ "npm": ">=10.8.2" }, "sideEffects": false -} +} \ No newline at end of file diff --git a/tests/unit/storage/providers/StorageProviderTest.ts b/tests/unit/storage/providers/StorageProviderTest.ts index 90f82f3a9..7c67c389f 100644 --- a/tests/unit/storage/providers/StorageProviderTest.ts +++ b/tests/unit/storage/providers/StorageProviderTest.ts @@ -1,7 +1,6 @@ /* eslint-disable import/first */ jest.unmock('../../../../lib/storage/platforms/index.native'); jest.unmock('../../../../lib/storage/platforms/index'); -jest.unmock('../../../../lib/storage/providers/IDBKeyValProvider'); import NativeStorage from '../../../../lib/storage/platforms/index.native'; import WebStorage from '../../../../lib/storage/platforms/index';