diff --git a/.changeset/loud-mangos-kick.md b/.changeset/loud-mangos-kick.md new file mode 100644 index 000000000..e910f23a7 --- /dev/null +++ b/.changeset/loud-mangos-kick.md @@ -0,0 +1,6 @@ +--- +'@powersync/common': patch +'@powersync/web': patch +--- + +Fixed race condition in async closing of databases diff --git a/package.json b/package.json index f90f90f41..0f6357519 100644 --- a/package.json +++ b/package.json @@ -33,12 +33,12 @@ "@actions/core": "^1.10.1", "@changesets/cli": "2.27.2", "@pnpm/workspace.find-packages": "^4.0.2", - "@vitest/browser": "^3.0.5", + "@vitest/browser": "^3.0.8", "husky": "^9.0.11", "lint-staged": "^15.2.2", - "playwright": "^1.50.1", + "playwright": "^1.51.0", "prettier": "^3.2.5", "typescript": "^5.7.2", - "vitest": "^3.0.5" + "vitest": "^3.0.8" } } diff --git a/packages/common/src/client/AbstractPowerSyncDatabase.ts b/packages/common/src/client/AbstractPowerSyncDatabase.ts index 24b35a123..375ea2ee9 100644 --- a/packages/common/src/client/AbstractPowerSyncDatabase.ts +++ b/packages/common/src/client/AbstractPowerSyncDatabase.ts @@ -18,20 +18,20 @@ import { mutexRunExclusive } from '../utils/mutex.js'; import { throttleTrailing } from '../utils/throttle.js'; import { SQLOpenFactory, SQLOpenOptions, isDBAdapter, isSQLOpenFactory, isSQLOpenOptions } from './SQLOpenFactory.js'; import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector.js'; +import { runOnSchemaChange } from './runOnSchemaChange.js'; import { BucketStorageAdapter, PSInternalTable } from './sync/bucket/BucketStorageAdapter.js'; import { CrudBatch } from './sync/bucket/CrudBatch.js'; import { CrudEntry, CrudEntryJSON } from './sync/bucket/CrudEntry.js'; import { CrudTransaction } from './sync/bucket/CrudTransaction.js'; import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS, - type AdditionalConnectionOptions, - type PowerSyncConnectionOptions, + DEFAULT_RETRY_DELAY_MS, StreamingSyncImplementation, StreamingSyncImplementationListener, - DEFAULT_RETRY_DELAY_MS, + type AdditionalConnectionOptions, + type PowerSyncConnectionOptions, type RequiredAdditionalConnectionOptions } from './sync/stream/AbstractStreamingSyncImplementation.js'; -import { runOnSchemaChange } from './runOnSchemaChange.js'; export interface DisconnectAndClearOptions { /** When set to false, data in local-only tables is preserved. */ @@ -505,13 +505,17 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver, DBGetUtils { - close: () => void; + close: () => void | Promise; execute: (query: string, params?: any[]) => Promise; executeBatch: (query: string, params?: any[][]) => Promise; name: string; diff --git a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts index fe68b44eb..f3893ffbe 100644 --- a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts +++ b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts @@ -147,9 +147,9 @@ export class LockedAsyncDatabaseAdapter * Shared workers might not actually close the connection if other * tabs are still using it. */ - close() { + async close() { this._disposeTableChangeListener?.(); - this.baseDB?.close?.(); + await this.baseDB?.close?.(); } async getAll(sql: string, parameters?: any[] | undefined): Promise { diff --git a/packages/web/tests/bucket_storage.test.ts b/packages/web/tests/bucket_storage.test.ts index ae7e0cb44..70f9e6a10 100644 --- a/packages/web/tests/bucket_storage.test.ts +++ b/packages/web/tests/bucket_storage.test.ts @@ -1,5 +1,7 @@ import { + AbstractPowerSyncDatabase, BucketStorageAdapter, + Checkpoint, OpType, OpTypeEnum, OplogEntry, @@ -8,10 +10,9 @@ import { SyncDataBatch, SyncDataBucket } from '@powersync/common'; -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -import { AbstractPowerSyncDatabase, Checkpoint } from '@powersync/common'; import { PowerSyncDatabase, WASQLitePowerSyncDatabaseOpenFactory } from '@powersync/web'; import { Mutex } from 'async-mutex'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { testSchema } from './utils/testDb'; const putAsset1_1 = OplogEntry.fromRow({ @@ -57,7 +58,7 @@ const removeAsset1_5 = OplogEntry.fromRow({ checksum: 5 }); -describe('Bucket Storage', () => { +describe('Bucket Storage', { sequential: true }, () => { let db: AbstractPowerSyncDatabase; let bucketStorage: BucketStorageAdapter; diff --git a/packages/web/tests/crud.test.ts b/packages/web/tests/crud.test.ts index e2342f0a5..036f8cbf5 100644 --- a/packages/web/tests/crud.test.ts +++ b/packages/web/tests/crud.test.ts @@ -1,25 +1,15 @@ -import { AbstractPowerSyncDatabase, Column, ColumnType, CrudEntry, Schema, Table, UpdateType } from '@powersync/common'; -import { PowerSyncDatabase } from '@powersync/web'; +import { Column, ColumnType, CrudEntry, Schema, Table, UpdateType } from '@powersync/common'; import pDefer from 'p-defer'; import { v4 as uuid } from 'uuid'; -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { generateTestDb } from './utils/testDb'; const testId = '2290de4f-0488-4e50-abed-f8e8eb1d0b42'; -describe('CRUD Tests', () => { - let powersync: AbstractPowerSyncDatabase; - - beforeEach(async () => { - powersync = generateTestDb(); - }); - - afterEach(async () => { - await powersync.disconnectAndClear(); - await powersync.close(); - }); - +describe('CRUD Tests', { sequential: true }, () => { it('INSERT', async () => { + const powersync = generateTestDb(); + expect(await powersync.getAll('SELECT * FROM ps_crud')).empty; await powersync.execute('INSERT INTO assets(id, description) VALUES(?, ?)', [testId, 'test']); @@ -37,6 +27,8 @@ describe('CRUD Tests', () => { }); it('BATCH INSERT', async () => { + const powersync = generateTestDb(); + expect(await powersync.getAll('SELECT * FROM ps_crud')).empty; const query = `INSERT INTO assets(id, description) VALUES(?, ?)`; @@ -63,6 +55,8 @@ describe('CRUD Tests', () => { }); it('INSERT OR REPLACE', async () => { + const powersync = generateTestDb(); + await powersync.execute('INSERT INTO assets(id, description) VALUES(?, ?)', [testId, 'test']); await powersync.execute('DELETE FROM ps_crud WHERE 1'); @@ -85,6 +79,8 @@ describe('CRUD Tests', () => { }); it('UPDATE', async () => { + const powersync = generateTestDb(); + await powersync.execute('INSERT INTO assets(id, description, make) VALUES(?, ?, ?)', [testId, 'test', 'test']); await powersync.execute('DELETE FROM ps_crud WHERE 1'); @@ -105,6 +101,8 @@ describe('CRUD Tests', () => { }); it('BATCH UPDATE', async () => { + const powersync = generateTestDb(); + await powersync.executeBatch('INSERT INTO assets(id, description, make) VALUES(?, ?, ?)', [ [testId, 'test', 'test'], ['mockId', 'test', 'test'] @@ -137,6 +135,8 @@ describe('CRUD Tests', () => { }); it('DELETE', async () => { + const powersync = generateTestDb(); + await powersync.execute('INSERT INTO assets(id, description, make) VALUES(?, ?, ?)', [testId, 'test', 'test']); await powersync.execute('DELETE FROM ps_crud WHERE 1'); @@ -153,6 +153,8 @@ describe('CRUD Tests', () => { }); it('UPSERT not supported', async () => { + const powersync = generateTestDb(); + // Just shows that we cannot currently do this await expect( powersync.execute('INSERT INTO assets(id, description) VALUES(?, ?) ON CONFLICT DO UPDATE SET description = ?', [ @@ -164,9 +166,7 @@ describe('CRUD Tests', () => { }); it('INSERT-only tables', async () => { - await powersync.disconnectAndClear(); - - powersync = new PowerSyncDatabase({ + const powersync = generateTestDb({ /** * Deleting the IndexDB seems to freeze the test. * Use a new DB for each run to keep CRUD counters @@ -212,6 +212,8 @@ describe('CRUD Tests', () => { }); it('big numbers - integer', async () => { + const powersync = generateTestDb(); + const bigNumber = 1 << 62; await powersync.execute('INSERT INTO assets(id, quantity) VALUES(?, ?)', [testId, bigNumber]); @@ -233,6 +235,8 @@ describe('CRUD Tests', () => { }); it('big numbers - text', async () => { + const powersync = generateTestDb(); + const bigNumber = 1 << 62; await powersync.execute('INSERT INTO assets(id, quantity) VALUES(?, ?)', [testId, `${bigNumber}`]); @@ -263,6 +267,8 @@ describe('CRUD Tests', () => { }); it('Transaction grouping', async () => { + const powersync = generateTestDb(); + expect(await powersync.getAll('SELECT * FROM ps_crud')).empty; await powersync.writeTransaction(async (tx) => { await tx.execute('INSERT INTO assets(id, description) VALUES(?, ?)', [testId, 'test1']); @@ -292,6 +298,8 @@ describe('CRUD Tests', () => { }); it('Transaction exclusivity', async () => { + const powersync = generateTestDb(); + const outside = pDefer(); const inTx = pDefer(); @@ -313,6 +321,8 @@ describe('CRUD Tests', () => { }); it('CRUD Batch Limits', async () => { + const powersync = generateTestDb(); + const initialBatch = await powersync.getCrudBatch(); expect(initialBatch, 'Initial CRUD batch should be null').null; diff --git a/packages/web/tests/main.test.ts b/packages/web/tests/main.test.ts index 6a7adb1f6..539907882 100644 --- a/packages/web/tests/main.test.ts +++ b/packages/web/tests/main.test.ts @@ -1,64 +1,74 @@ -import { AbstractPowerSyncDatabase } from '@powersync/common'; import { PowerSyncDatabase, WASQLiteOpenFactory, WASQLiteVFS } from '@powersync/web'; import { v4 as uuid } from 'uuid'; -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { TestDatabase, generateTestDb, testSchema } from './utils/testDb'; // TODO import tests from a common package -describe('Basic', () => { - let dbWithoutWebWorker: AbstractPowerSyncDatabase; - let dbWithWebWorker: AbstractPowerSyncDatabase; - let dbWithOPFS: AbstractPowerSyncDatabase; +describe( + 'Basic - With Web Workers', + { sequential: true }, + describeBasicTests(() => generateTestDb()) +); - beforeEach(() => { - dbWithoutWebWorker = generateTestDb({ useWebWorker: false }); - dbWithWebWorker = generateTestDb(); - dbWithOPFS = new PowerSyncDatabase({ - database: new WASQLiteOpenFactory({ dbFilename: 'basic.sqlite', vfs: WASQLiteVFS.OPFSCoopSyncVFS }), +describe( + 'Basic - Without Web Workers', + { sequential: true }, + describeBasicTests(() => + generateTestDb({ + database: { + dbFilename: 'basic-no-worker.sqlite' + }, + flags: { + useWebWorker: false + }, schema: testSchema - }); - }); + }) + ) +); - /** - * Declares a test to be executed with multiple DB connections - */ - const itWithDBs = (name: string, test: (db: AbstractPowerSyncDatabase) => Promise) => { - it(`${name} - with web worker`, () => test(dbWithWebWorker)); - it(`${name} - without web worker`, () => test(dbWithoutWebWorker)); - it(`${name} - with OPFS`, () => test(dbWithOPFS)); - }; +describe( + 'Basic - With OPFS', + { sequential: true }, + describeBasicTests(() => + generateTestDb({ + database: new WASQLiteOpenFactory({ + dbFilename: 'basic-opfs.sqlite', + vfs: WASQLiteVFS.OPFSCoopSyncVFS + }), + schema: testSchema + }) + ) +); - afterEach(async () => { - await dbWithWebWorker.disconnectAndClear(); - await dbWithWebWorker.close(); - await dbWithoutWebWorker.disconnectAndClear(); - await dbWithoutWebWorker.close(); - await dbWithOPFS.disconnectAndClear(); - await dbWithOPFS.close(); - }); +function describeBasicTests(generateDB: () => PowerSyncDatabase) { + return () => { + it('should execute a select query using getAll', async () => { + const db = generateDB(); - describe('executeQuery', () => { - itWithDBs('should execute a select query using getAll', async (db) => { const result = await db.getAll('SELECT * FROM customers'); expect(result.length).toEqual(0); }); - itWithDBs('should allow inserts', async (db) => { + it('should allow inserts', async () => { + const db = generateDB(); + const testName = 'Steven'; await db.execute('INSERT INTO customers (id, name) VALUES(?, ?)', [uuid(), testName]); const result = await db.get('SELECT * FROM customers'); expect(result.name).equals(testName); }); - }); - describe('executeBatchQuery', () => { - itWithDBs('should execute a select query using getAll', async (db) => { + it('should execute a select query using getAll', async () => { + const db = generateDB(); + const result = await db.getAll('SELECT * FROM customers'); expect(result.length).toEqual(0); }); - itWithDBs('should allow batch inserts', async (db) => { + it('should allow batch inserts', async () => { + const db = generateDB(); + const testName = 'Mugi'; await db.executeBatch('INSERT INTO customers (id, name) VALUES(?, ?)', [ [uuid(), testName], @@ -72,5 +82,5 @@ describe('Basic', () => { expect(result[1].name).equals('Steven'); expect(result[2].name).equals('Chris'); }); - }); -}); + }; +} diff --git a/packages/web/tests/multiple_instances.test.ts b/packages/web/tests/multiple_instances.test.ts index 466a8f679..87c8dceb9 100644 --- a/packages/web/tests/multiple_instances.test.ts +++ b/packages/web/tests/multiple_instances.test.ts @@ -1,70 +1,57 @@ import { AbstractPowerSyncDatabase, SqliteBucketStorage, SyncStatus } from '@powersync/common'; import { - PowerSyncDatabase, SharedWebStreamingSyncImplementation, SharedWebStreamingSyncImplementationOptions, WebRemote } from '@powersync/web'; import { Mutex } from 'async-mutex'; import Logger from 'js-logger'; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import { beforeAll, describe, expect, it, vi } from 'vitest'; import { WebDBAdapter } from '../src/db/adapters/WebDBAdapter'; import { TestConnector } from './utils/MockStreamOpenFactory'; -import { testSchema } from './utils/testDb'; - -describe('Multiple Instances', () => { - const dbFilename = 'test-multiple-instances.db'; - let db: AbstractPowerSyncDatabase; +import { generateTestDb, testSchema } from './utils/testDb'; +describe('Multiple Instances', { sequential: true }, () => { const openDatabase = () => - new PowerSyncDatabase({ + generateTestDb({ database: { - dbFilename + dbFilename: `test-multiple-instances.db` }, schema: testSchema }); beforeAll(() => Logger.useDefaults()); - beforeEach(async () => { - db = openDatabase(); - await db.init(); - }); - - afterEach(async () => { - await db.disconnectAndClear(); - await db.close(); - }); - - function createAsset(powersync: AbstractPowerSyncDatabase = db) { + function createAsset(powersync: AbstractPowerSyncDatabase) { return powersync.execute('INSERT INTO assets(id, description) VALUES(uuid(), ?)', ['test']); } it('should share data between instances', async () => { + const powersync = openDatabase(); + // Create an asset on the first connection - await createAsset(); + await createAsset(powersync); // Create a new connection and verify it can read existing assets const db2 = openDatabase(); const assets = await db2.getAll('SELECT * FROM assets'); expect(assets.length).equals(1); - - await db2.close(); }); it('should broadcast logs from shared sync worker', { timeout: 20000 }, async () => { const logger = Logger.get('test-logger'); const spiedErrorLogger = vi.spyOn(logger, 'error'); const spiedDebugLogger = vi.spyOn(logger, 'debug'); - const db = new PowerSyncDatabase({ - schema: testSchema, + + const powersync = generateTestDb({ + logger, database: { - dbFilename: 'log-test.sqlite' + dbFilename: 'broadcast-logger-test.sqlite' }, - logger + schema: testSchema }); - db.connect({ + powersync.connect({ fetchCredentials: async () => { return { endpoint: 'http://localhost/does-not-exist', @@ -89,8 +76,6 @@ describe('Multiple Instances', () => { // The connection should fail with an error await vi.waitFor(() => expect(spiedErrorLogger.mock.calls.length).gt(0), { timeout: 2000 }); // This test seems to take quite long while waiting for this disconnect call - await db.disconnectAndClear(); - await db.close(); }); it('should maintain DB connections if instances call close', async () => { @@ -99,32 +84,38 @@ describe('Multiple Instances', () => { * The shared connection should only be closed if all PowerSync clients * close themselves. */ - const db2 = openDatabase(); - await db2.close(); + const powersync1 = openDatabase(); + const powersync2 = openDatabase(); + await powersync1.close(); // Create an asset on the first connection - await createAsset(); + await createAsset(powersync2); }); it('should watch table changes between instances', async () => { + const db1 = openDatabase(); const db2 = openDatabase(); const watchedPromise = new Promise(async (resolve) => { const controller = new AbortController(); - for await (const result of db2.watch('SELECT * FROM assets')) { - resolve(); - controller.abort(); + for await (const result of db2.watch('SELECT * FROM assets', [], { signal: controller.signal })) { + if (result.rows?.length) { + resolve(); + controller.abort(); + } } }); - await createAsset(); + await createAsset(db1); - expect(watchedPromise).rejects; + await watchedPromise; }); it('should share sync updates', async () => { // Generate the first streaming sync implementation const connector1 = new TestConnector(); + const db = openDatabase(); + await db.init(); // They need to use the same identifier to use the same shared worker. const identifier = 'streaming-sync-shared'; @@ -180,8 +171,10 @@ describe('Multiple Instances', () => { const connector1 = new TestConnector(); const spy1 = vi.spyOn(connector1, 'uploadData'); + const db = openDatabase(); + await db.init(); // They need to use the same identifier to use the same shared worker. - const identifier = dbFilename; + const identifier = db.database.name; // Resolves once the first connector has been called to upload data let triggerUpload1: () => void; diff --git a/packages/web/tests/offline.test.ts b/packages/web/tests/offline.test.ts index 65f894e58..55d493b58 100644 --- a/packages/web/tests/offline.test.ts +++ b/packages/web/tests/offline.test.ts @@ -1,4 +1,4 @@ -import { AbstractPowerSyncDatabase, column, Schema, Table } from '@powersync/common'; +import { AbstractPowerSyncDatabase } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { makeOptionalSyncSchema } from './utils/optionalSyncTestSchema'; @@ -7,7 +7,7 @@ const assetId = '2290de4f-0488-4e50-abed-f8e8eb1d0b42'; const userId = '3390de4f-0488-4e50-abed-f8e8eb1d0b42'; const customerId = '4490de4f-0488-4e50-abed-f8e8eb1d0b42'; -describe('Schema Tests', () => { +describe('Schema Tests', { sequential: true }, () => { let db: AbstractPowerSyncDatabase; beforeEach(async () => { diff --git a/packages/web/tests/on_change.test.ts b/packages/web/tests/on_change.test.ts index 676866df2..f026cde72 100644 --- a/packages/web/tests/on_change.test.ts +++ b/packages/web/tests/on_change.test.ts @@ -6,7 +6,7 @@ import { testSchema } from './utils/testDb'; const UPLOAD_TIMEOUT_MS = 3000; -describe('OnChange Tests', () => { +describe('OnChange Tests', { sequential: true }, () => { let powersync: AbstractPowerSyncDatabase; beforeEach(async () => { diff --git a/packages/web/tests/open.test.ts b/packages/web/tests/open.test.ts index 7ab900781..1faf76507 100644 --- a/packages/web/tests/open.test.ts +++ b/packages/web/tests/open.test.ts @@ -55,7 +55,7 @@ const proxyWorkers = () => { }; }; -describe('Open Methods', () => { +describe('Open Methods', { sequential: true }, () => { let mocks: ReturnType; beforeEach(() => { diff --git a/packages/web/tests/performance.test.ts b/packages/web/tests/performance.test.ts index 9ae959501..ad3d53532 100644 --- a/packages/web/tests/performance.test.ts +++ b/packages/web/tests/performance.test.ts @@ -1,8 +1,8 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { AbstractPowerSyncDatabase, Schema, Table, column } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -describe('Basic', () => { +describe('Basic', { sequential: true }, () => { const users = new Table({ name: column.text, email: column.text diff --git a/packages/web/tests/schema.test.ts b/packages/web/tests/schema.test.ts index 11b8b43d5..9c96053fd 100644 --- a/packages/web/tests/schema.test.ts +++ b/packages/web/tests/schema.test.ts @@ -1,6 +1,6 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { AbstractPowerSyncDatabase, Column, ColumnType, Index, IndexedColumn, Schema, Table } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; type SchemaVersionResult = { schema_version: number; @@ -74,7 +74,7 @@ const generateSchemaTables = (assetsTableGenerator: () => Table = generateAssets */ const schema = new Schema(generateSchemaTables()); -describe('Schema Tests', () => { +describe('Schema Tests', { sequential: true }, () => { let powersync: AbstractPowerSyncDatabase; beforeEach(async () => { diff --git a/packages/web/tests/schemav2.test.ts b/packages/web/tests/schemav2.test.ts index 9d83163f4..1fc54b6aa 100644 --- a/packages/web/tests/schemav2.test.ts +++ b/packages/web/tests/schemav2.test.ts @@ -1,6 +1,6 @@ -import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { AbstractPowerSyncDatabase, Schema, TableV2, column } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; type SchemaVersionResult = { schema_version: number; @@ -56,7 +56,7 @@ const aliased = new TableV2({ name: column.text }, { viewName: 'test1' }); */ const schema = new Schema({ assets, customers, logs, credentials, aliased }); -describe('Schema Tests', () => { +describe('Schema Tests', { sequential: true }, () => { let powersync: AbstractPowerSyncDatabase; beforeEach(async () => { diff --git a/packages/web/tests/stream.test.ts b/packages/web/tests/stream.test.ts index 52989c7e7..1e564950d 100644 --- a/packages/web/tests/stream.test.ts +++ b/packages/web/tests/stream.test.ts @@ -1,59 +1,56 @@ import { BucketChecksum, WASQLiteOpenFactory, WASQLiteVFS } from '@powersync/web'; -import Logger from 'js-logger'; -import { afterEach, beforeAll, describe, expect, it, onTestFinished, vi } from 'vitest'; +import { describe, expect, it, onTestFinished, vi } from 'vitest'; import { TestConnector } from './utils/MockStreamOpenFactory'; import { ConnectedDatabaseUtils, generateConnectedDatabase } from './utils/generateConnectedDatabase'; const UPLOAD_TIMEOUT_MS = 3000; -describe( - 'Streaming', - { - sequential: true - }, - () => { - /** - * Declares a test to be executed with different generated db functions - */ - const itWithGenerators = ( - name: string, - test: (createConnectedDatabase: () => ReturnType) => Promise - ) => { - const funcWithWebWorker = () => - generateConnectedDatabase({ - powerSyncOptions: { - dbFilename: `test-stream-connection-worker.db` +describe('Streaming', { sequential: true }, () => { + describe( + 'Streaming - With Web Workers', + { + sequential: true + }, + describeStreamingTests(() => generateConnectedDatabase()) + ); + + describe( + 'Streaming - Without Web Workers', + { + sequential: true + }, + describeStreamingTests(() => + generateConnectedDatabase({ + powerSyncOptions: { + flags: { + useWebWorker: false } - }); - const funcWithoutWebWorker = () => - generateConnectedDatabase({ - powerSyncOptions: { - dbFilename: `test-stream-connection-no-worker.db`, - flags: { - useWebWorker: false - } - } - }); - - it.sequential(`${name} - with web worker`, () => test(funcWithWebWorker)); - it.sequential(`${name} - without web worker`, () => test(funcWithoutWebWorker)); - it.sequential(`${name} - with OPFS`, () => - test(() => - generateConnectedDatabase({ - powerSyncOptions: { - database: new WASQLiteOpenFactory({ - dbFilename: `test-stream-connection-opfs.db`, - vfs: WASQLiteVFS.OPFSCoopSyncVFS - }) - } + } + }) + ) + ); + + describe( + 'Streaming - With OPFS', + { + sequential: true + }, + describeStreamingTests(() => + generateConnectedDatabase({ + powerSyncOptions: { + database: new WASQLiteOpenFactory({ + dbFilename: 'streaming-opfs.sqlite', + vfs: WASQLiteVFS.OPFSCoopSyncVFS }) - ) - ); - }; - - beforeAll(() => Logger.useDefaults()); - - itWithGenerators('PowerSync reconnect on closed stream', async (createConnectedDatabase) => { + } + }) + ) + ); +}); + +function describeStreamingTests(createConnectedDatabase: () => Promise) { + return () => { + it('PowerSync reconnect on closed stream', async () => { const { powersync, waitForStream, remote } = await createConnectedDatabase(); expect(powersync.connected).toBe(true); @@ -66,7 +63,7 @@ describe( await newStream; }); - itWithGenerators('PowerSync reconnect multiple connect calls', async (createConnectedDatabase) => { + it('PowerSync reconnect multiple connect calls', async () => { // This initially performs a connect call const { powersync, waitForStream } = await createConnectedDatabase(); expect(powersync.connected).toBe(true); @@ -79,7 +76,7 @@ describe( await newStream; }); - itWithGenerators('Should trigger upload connector when connected', async (createConnectedDatabase) => { + it('Should trigger upload connector when connected', async () => { const { powersync, uploadSpy } = await createConnectedDatabase(); expect(powersync.connected).toBe(true); @@ -98,9 +95,8 @@ describe( ); }); - itWithGenerators('Should retry failed uploads when connected', async (createConnectedDatabase) => { + it('Should retry failed uploads when connected', async () => { const { powersync, uploadSpy } = await createConnectedDatabase(); - expect(powersync.connected).toBe(true); let uploadCounter = 0; @@ -131,7 +127,7 @@ describe( ); }); - itWithGenerators('Should upload after reconnecting', async (createConnectedDatabase) => { + it('Should upload after reconnecting', async () => { const { powersync, connect, uploadSpy } = await createConnectedDatabase(); expect(powersync.connected).toBe(true); @@ -149,110 +145,108 @@ describe( ); }); - describe('Partial', () => { - itWithGenerators('Should update sync state incrementally', async (createConnectedDatabase) => { - const { powersync, remote } = await createConnectedDatabase(); - expect(powersync.currentStatus.dataFlowStatus.downloading).toBe(false); - - const buckets: BucketChecksum[] = []; - for (let prio = 0; prio <= 3; prio++) { - buckets.push({ bucket: `prio${prio}`, priority: prio, checksum: 10 + prio }); + it('Should update sync state incrementally', async () => { + const { powersync, remote } = await createConnectedDatabase(); + expect(powersync.currentStatus.dataFlowStatus.downloading).toBe(false); + + const buckets: BucketChecksum[] = []; + for (let prio = 0; prio <= 3; prio++) { + buckets.push({ bucket: `prio${prio}`, priority: prio, checksum: 10 + prio }); + } + remote.enqueueLine({ + checkpoint: { + last_op_id: '4', + buckets } + }); + + let operationId = 1; + const addRow = (prio: number) => { remote.enqueueLine({ - checkpoint: { - last_op_id: '4', - buckets + data: { + bucket: `prio${prio}`, + data: [ + { + checksum: prio + 10, + data: JSON.stringify({ name: 'row' }), + op: 'PUT', + op_id: (operationId++).toString(), + object_id: `prio${prio}`, + object_type: 'users' + } + ] } }); + }; - let operationId = 1; - const addRow = (prio: number) => { - remote.enqueueLine({ - data: { - bucket: `prio${prio}`, - data: [ - { - checksum: prio + 10, - data: JSON.stringify({ name: 'row' }), - op: 'PUT', - op_id: (operationId++).toString(), - object_id: `prio${prio}`, - object_type: 'users' - } - ] - } - }); - }; - - const syncCompleted = vi.fn(); - powersync.waitForFirstSync().then(syncCompleted); - - // Emit partial sync complete for each priority but the last. - for (var prio = 0; prio < 3; prio++) { - const partialSyncCompleted = vi.fn(); - powersync.waitForFirstSync({ priority: prio }).then(partialSyncCompleted); - expect(powersync.currentStatus.statusForPriority(prio).hasSynced).toBe(false); - expect(partialSyncCompleted).not.toHaveBeenCalled(); - expect(syncCompleted).not.toHaveBeenCalled(); - - addRow(prio); - remote.enqueueLine({ - partial_checkpoint_complete: { - last_op_id: operationId.toString(), - priority: prio - } - }); - - await powersync.syncStreamImplementation!.waitUntilStatusMatches((status) => { - return status.statusForPriority(prio).hasSynced === true; - }); - await new Promise((r) => setTimeout(r)); - expect(partialSyncCompleted).toHaveBeenCalledOnce(); - - expect(await powersync.getAll('select * from users')).toHaveLength(prio + 1); - } - - // Then, complete the sync. - addRow(3); - remote.enqueueLine({ checkpoint_complete: { last_op_id: operationId.toString() } }); - await vi.waitFor(() => expect(syncCompleted).toHaveBeenCalledOnce(), 500); - expect(await powersync.getAll('select * from users')).toHaveLength(4); - }); + const syncCompleted = vi.fn(); + powersync.waitForFirstSync().then(syncCompleted); - itWithGenerators('Should remember sync state', async (createConnectedDatabase) => { - const { powersync, remote, openAnother } = await createConnectedDatabase(); - expect(powersync.currentStatus.dataFlowStatus.downloading).toBe(false); + // Emit partial sync complete for each priority but the last. + for (var prio = 0; prio < 3; prio++) { + const partialSyncCompleted = vi.fn(); + powersync.waitForFirstSync({ priority: prio }).then(partialSyncCompleted); + expect(powersync.currentStatus.statusForPriority(prio).hasSynced).toBe(false); + expect(partialSyncCompleted).not.toHaveBeenCalled(); + expect(syncCompleted).not.toHaveBeenCalled(); - const buckets: BucketChecksum[] = []; - for (let prio = 0; prio <= 3; prio++) { - buckets.push({ bucket: `prio${prio}`, priority: prio, checksum: 0 }); - } - remote.enqueueLine({ - checkpoint: { - last_op_id: '0', - buckets - } - }); + addRow(prio); remote.enqueueLine({ partial_checkpoint_complete: { - last_op_id: '0', - priority: 0 + last_op_id: operationId.toString(), + priority: prio } }); - await powersync.waitForFirstSync({ priority: 0 }); - - // Open another database instance. - const another = openAnother(); - onTestFinished(async () => { - await another.close(); + await powersync.syncStreamImplementation!.waitUntilStatusMatches((status) => { + return status.statusForPriority(prio).hasSynced === true; }); - await another.init(); + await new Promise((r) => setTimeout(r)); + expect(partialSyncCompleted).toHaveBeenCalledOnce(); + + expect(await powersync.getAll('select * from users')).toHaveLength(prio + 1); + } + + // Then, complete the sync. + addRow(3); + remote.enqueueLine({ checkpoint_complete: { last_op_id: operationId.toString() } }); + await vi.waitFor(() => expect(syncCompleted).toHaveBeenCalledOnce(), 500); + expect(await powersync.getAll('select * from users')).toHaveLength(4); + }); - expect(another.currentStatus.priorityStatusEntries).toHaveLength(1); - expect(another.currentStatus.statusForPriority(0).hasSynced).toBeTruthy(); - await another.waitForFirstSync({ priority: 0 }); + it('Should remember sync state', async () => { + const { powersync, remote, openAnother } = await createConnectedDatabase(); + expect(powersync.currentStatus.dataFlowStatus.downloading).toBe(false); + + const buckets: BucketChecksum[] = []; + for (let prio = 0; prio <= 3; prio++) { + buckets.push({ bucket: `prio${prio}`, priority: prio, checksum: 0 }); + } + remote.enqueueLine({ + checkpoint: { + last_op_id: '0', + buckets + } + }); + remote.enqueueLine({ + partial_checkpoint_complete: { + last_op_id: '0', + priority: 0 + } }); + + await powersync.waitForFirstSync({ priority: 0 }); + + // Open another database instance. + const another = openAnother(); + onTestFinished(async () => { + await another.close(); + }); + await another.init(); + + expect(another.currentStatus.priorityStatusEntries).toHaveLength(1); + expect(another.currentStatus.statusForPriority(0).hasSynced).toBeTruthy(); + await another.waitForFirstSync({ priority: 0 }); }); - } -); + }; +} diff --git a/packages/web/tests/uploads.test.ts b/packages/web/tests/uploads.test.ts index 2a88ad99c..c853c90a3 100644 --- a/packages/web/tests/uploads.test.ts +++ b/packages/web/tests/uploads.test.ts @@ -1,113 +1,147 @@ +import { WebPowerSyncDatabaseOptions } from '@powersync/web'; import Logger from 'js-logger'; import p from 'p-defer'; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; -import { ConnectedDatabaseUtils, generateConnectedDatabase } from './utils/generateConnectedDatabase'; +import { v4 } from 'uuid'; +import { beforeAll, describe, expect, it, vi } from 'vitest'; +import { DEFAULT_CONNECTED_POWERSYNC_OPTIONS, generateConnectedDatabase } from './utils/generateConnectedDatabase'; // Don't want to actually export the warning string from the package const PARTIAL_WARNING = 'Potentially previously uploaded CRUD entries are still present'; -describe('CRUD Uploads', () => { - let connectedUtils: ConnectedDatabaseUtils; - const logger = Logger.get('crud-logger'); +describe( + 'CRUD Uploads - With Web Workers', + { sequential: true }, + describeCrudUploadTests(() => ({ + database: { + dbFilename: `${v4()}.db` + }, + schema: DEFAULT_CONNECTED_POWERSYNC_OPTIONS.powerSyncOptions.schema, + crudUploadThrottleMs: 1_000, + flags: { + enableMultiTabs: false + } + })) +); + +describe( + 'CRUD Uploads - Without Web Workers', + { sequential: true }, + describeCrudUploadTests(() => ({ + database: { + dbFilename: `crud-uploads-test-${v4()}.db` + }, + schema: DEFAULT_CONNECTED_POWERSYNC_OPTIONS.powerSyncOptions.schema, + crudUploadThrottleMs: 1_000, + flags: { + useWebWorker: false + } + })) +); + +function describeCrudUploadTests(getDatabaseOptions: () => WebPowerSyncDatabaseOptions) { + return () => { + beforeAll(() => Logger.useDefaults()); + + it('should warn for missing upload operations in uploadData', async () => { + const logger = Logger.get('crud-logger'); + + const options = getDatabaseOptions(); + + const { powersync, uploadSpy } = await generateConnectedDatabase({ + powerSyncOptions: { + ...options, + logger + } + }); + + const loggerSpy = vi.spyOn(logger, 'warn'); + + const deferred = p(); + + uploadSpy.mockImplementation(async (db) => { + // This upload method does not perform an upload + deferred.resolve(); + }); - beforeAll(() => Logger.useDefaults()); + // Create something with CRUD in it. + await powersync.execute('INSERT into users (id, name) VALUES (uuid(), ?)', ['steven']); - beforeEach(async () => { - connectedUtils = await generateConnectedDatabase({ - powerSyncOptions: { - dbFilename: 'crud-uploads-test.db', - logger, - crudUploadThrottleMs: 1_000, - flags: { - enableMultiTabs: false + // The empty upload handler should have been called + // Timeouts seem to be weird in Vitest Browser mode. + // This makes the check below more stable. + await deferred.promise; + + await vi.waitFor( + () => { + expect(loggerSpy.mock.calls.find((logArgs) => logArgs[0].includes(PARTIAL_WARNING))).exist; + }, + { + timeout: 500, + interval: 100 } - } + ); }); - }); - afterEach(async () => { - connectedUtils.remote.streamController?.close(); - }); + it('should immediately upload sequential transactions', async () => { + const logger = Logger.get('crud-logger'); - it('should warn for missing upload operations in uploadData', async () => { - const { powersync, uploadSpy } = connectedUtils; - const loggerSpy = vi.spyOn(logger, 'warn'); + const options = getDatabaseOptions(); - const deferred = p(); + const { powersync, uploadSpy } = await generateConnectedDatabase({ + powerSyncOptions: { + ...options, + logger + } + }); - uploadSpy.mockImplementation(async (db) => { - // This upload method does not perform an upload - deferred.resolve(); - }); + const loggerSpy = vi.spyOn(logger, 'warn'); - // Create something with CRUD in it. - await powersync.execute('INSERT into users (id, name) VALUES (uuid(), ?)', ['steven']); - - // The empty upload handler should have been called - // Timeouts seem to be weird in Vitest Browser mode. - // This makes the check below more stable. - await deferred.promise; - - await vi.waitFor( - () => { - expect(loggerSpy.mock.calls.find((logArgs) => logArgs[0].includes(PARTIAL_WARNING))).exist; - }, - { - timeout: 500, - interval: 100 - } - ); - }); - - it('should immediately upload sequential transactions', async () => { - const { powersync, uploadSpy } = connectedUtils; - const loggerSpy = vi.spyOn(logger, 'warn'); - - const deferred = p(); - - uploadSpy.mockImplementation(async (db) => { - const nextTransaction = await db.getNextCrudTransaction(); - if (!nextTransaction) { - return; - } - // Mockingly delete the crud op in order to progress through the CRUD queue - for (const op of nextTransaction.crud) { - await db.execute(`DELETE FROM ps_crud WHERE id = ?`, [op.clientId]); - } - - deferred.resolve(); - }); + const deferred = p(); + + uploadSpy.mockImplementation(async (db) => { + const nextTransaction = await db.getNextCrudTransaction(); + if (!nextTransaction) { + return; + } + // Mockingly delete the crud op in order to progress through the CRUD queue + for (const op of nextTransaction.crud) { + await db.execute(`DELETE FROM ps_crud WHERE id = ?`, [op.clientId]); + } - // Create the first item - await powersync.execute('INSERT into users (id, name) VALUES (uuid(), ?)', ['steven']); - - // Modify the first item in a new transaction - await powersync.execute(` - UPDATE - users - SET - name = 'Mugi' - WHERE - name = 'steven'`); - - // Create a second item - await powersync.execute('INSERT into users (id, name) VALUES (uuid(), ?)', ['steven2']); - - // The empty upload handler should have been called. - // Timeouts seem to be weird in Vitest Browser mode. - // This makes the check below more stable. - await deferred.promise; - - await vi.waitFor( - () => { - expect(uploadSpy.mock.calls.length).eq(3); - }, - { - timeout: 5_000, - interval: 300 - } - ); - - expect(loggerSpy.mock.calls.find((logArgs) => logArgs[0].includes(PARTIAL_WARNING))).toBeUndefined; - }); -}); + deferred.resolve(); + }); + + // Create the first item + await powersync.execute('INSERT into users (id, name) VALUES (uuid(), ?)', ['steven']); + + // Modify the first item in a new transaction + await powersync.execute(` + UPDATE + users + SET + name = 'Mugi' + WHERE + name = 'steven'`); + + // Create a second item + await powersync.execute('INSERT into users (id, name) VALUES (uuid(), ?)', ['steven2']); + + // The empty upload handler should have been called. + // Timeouts seem to be weird in Vitest Browser mode. + // This makes the check below more stable. + await deferred.promise; + + await vi.waitFor( + () => { + expect(uploadSpy.mock.calls.length).eq(3); + }, + { + timeout: 5_000, + interval: 300 + } + ); + + expect(loggerSpy.mock.calls.find((logArgs) => logArgs[0].includes(PARTIAL_WARNING))).toBeUndefined; + }); + }; +} diff --git a/packages/web/tests/utils/generateConnectedDatabase.ts b/packages/web/tests/utils/generateConnectedDatabase.ts index 87f7430e0..260fb5e7e 100644 --- a/packages/web/tests/utils/generateConnectedDatabase.ts +++ b/packages/web/tests/utils/generateConnectedDatabase.ts @@ -1,6 +1,6 @@ import { Schema, Table, column } from '@powersync/common'; import { WebPowerSyncOpenFactoryOptions } from '@powersync/web'; -import { v4 as uuid } from 'uuid'; +import { v4 as uuid, v4 } from 'uuid'; import { onTestFinished, vi } from 'vitest'; import { MockRemote, MockStreamOpenFactory, TestConnector } from './MockStreamOpenFactory'; @@ -11,24 +11,28 @@ export type GenerateConnectedDatabaseOptions = { powerSyncOptions: Partial; }; -export const DEFAULT_CONNECTED_POWERSYNC_OPTIONS = { - powerSyncOptions: { - dbFilename: 'test-stream-connection.db', - flags: { - enableMultiTabs: false, - useWebWorker: true - }, - // Makes tests faster - crudUploadThrottleMs: 0, - schema: new Schema({ - users: new Table({ name: column.text }) - }) - } -}; +export type ConnectedDBGenerator = typeof generateConnectedDatabase; + +export const DEFAULT_CONNECTED_POWERSYNC_OPTIONS = generateDefaultOptions(); + +function generateDefaultOptions() { + return { + powerSyncOptions: { + dbFilename: `${v4()}.db`, + flags: { + enableMultiTabs: false, + useWebWorker: true + }, + // Makes tests faster + crudUploadThrottleMs: 0, + schema: new Schema({ + users: new Table({ name: column.text }) + }) + } + }; +} -export async function generateConnectedDatabase( - options: GenerateConnectedDatabaseOptions = DEFAULT_CONNECTED_POWERSYNC_OPTIONS -) { +export async function generateConnectedDatabase(options: GenerateConnectedDatabaseOptions = generateDefaultOptions()) { const { powerSyncOptions } = options; const { powerSyncOptions: defaultPowerSyncOptions } = DEFAULT_CONNECTED_POWERSYNC_OPTIONS; /** @@ -80,6 +84,9 @@ export async function generateConnectedDatabase( await connect(); onTestFinished(async () => { + if (powersync.closed) { + return; + } await powersync.disconnectAndClear(); await powersync.close(); }); diff --git a/packages/web/tests/utils/testDb.ts b/packages/web/tests/utils/testDb.ts index 132f00a63..108081df8 100644 --- a/packages/web/tests/utils/testDb.ts +++ b/packages/web/tests/utils/testDb.ts @@ -1,5 +1,6 @@ -import { column, PowerSyncDatabase, Schema, TableV2 } from '@powersync/web'; +import { column, PowerSyncDatabase, Schema, TableV2, WebPowerSyncDatabaseOptions } from '@powersync/web'; import { v4 as uuid } from 'uuid'; +import { onTestFinished } from 'vitest'; const assets = new TableV2( { @@ -22,16 +23,25 @@ const customers = new TableV2({ export const testSchema = new Schema({ assets, customers }); -export const generateTestDb = ({ useWebWorker } = { useWebWorker: true }) => { - const db = new PowerSyncDatabase({ +export const generateTestDb = (options?: WebPowerSyncDatabaseOptions) => { + const resolvedOptions = options ?? { database: { - dbFilename: `test-crud-${uuid()}.db` + dbFilename: `${uuid()}.db` }, schema: testSchema, flags: { - enableMultiTabs: false, - useWebWorker + enableMultiTabs: false } + }; + + const db = new PowerSyncDatabase(resolvedOptions); + + onTestFinished(async () => { + if (db.closed) { + return; + } + await db.disconnectAndClear(); + await db.close(); }); return db; diff --git a/packages/web/tests/watch.test.ts b/packages/web/tests/watch.test.ts index 0320debf9..6aea2211d 100644 --- a/packages/web/tests/watch.test.ts +++ b/packages/web/tests/watch.test.ts @@ -1,9 +1,8 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { v4 as uuid } from 'uuid'; -import { AbstractPowerSyncDatabase, QueryResult } from '@powersync/common'; +import { AbstractPowerSyncDatabase } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; +import { v4 as uuid } from 'uuid'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { testSchema } from './utils/testDb'; -import { makeOptionalSyncSchema } from './utils/optionalSyncTestSchema'; vi.useRealTimers(); /** @@ -16,7 +15,7 @@ vi.useRealTimers(); */ const throttleDuration = 1000; -describe('Watch Tests', () => { +describe('Watch Tests', { sequential: true }, () => { let powersync: AbstractPowerSyncDatabase; beforeEach(async () => { diff --git a/packages/web/tests/watchSchemaChange.test.ts b/packages/web/tests/watchSchemaChange.test.ts index a9c0e5f62..e2ed3e2eb 100644 --- a/packages/web/tests/watchSchemaChange.test.ts +++ b/packages/web/tests/watchSchemaChange.test.ts @@ -1,7 +1,7 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { v4 as uuid } from 'uuid'; import { AbstractPowerSyncDatabase, QueryResult } from '@powersync/common'; import { PowerSyncDatabase } from '@powersync/web'; +import { v4 as uuid } from 'uuid'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { makeOptionalSyncSchema } from './utils/optionalSyncTestSchema'; vi.useRealTimers(); @@ -15,7 +15,7 @@ vi.useRealTimers(); */ const throttleDuration = 1000; -describe('Watch With Schema Change Tests', () => { +describe('Watch With Schema Change Tests', { sequential: true }, () => { let powersync: AbstractPowerSyncDatabase; beforeEach(async () => { diff --git a/packages/web/vitest.config.ts b/packages/web/vitest.config.ts index 741140011..42f7d5e3c 100644 --- a/packages/web/vitest.config.ts +++ b/packages/web/vitest.config.ts @@ -35,12 +35,20 @@ const config: UserConfigExport = { }, plugins: [wasm(), topLevelAwait()], test: { - isolate: false, globals: true, include: ['tests/**/*.test.ts'], maxConcurrency: 1, + // This doesn't currently seem to work in browser mode, but setting this for one day when it does + sequence: { + shuffle: false, // Disable shuffling of test files + concurrent: false // Run test files sequentially + }, browser: { enabled: true, + /** + * Starts each test in a new iFrame + */ + isolate: true, provider: 'playwright', headless: true, instances: [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3cf1344b9..2698631a7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^4.0.2 version: 4.0.11(@pnpm/logger@5.2.0) '@vitest/browser': - specifier: ^3.0.5 - version: 3.0.5(@types/node@22.7.4)(playwright@1.50.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.5)(webdriverio@9.8.0) + specifier: ^3.0.8 + version: 3.0.8(@testing-library/dom@10.4.0)(@types/node@22.7.4)(playwright@1.51.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.8)(webdriverio@9.8.0) husky: specifier: ^9.0.11 version: 9.1.6 @@ -27,8 +27,8 @@ importers: specifier: ^15.2.2 version: 15.2.10 playwright: - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.51.0 + version: 1.51.0 prettier: specifier: ^3.2.5 version: 3.3.3 @@ -36,8 +36,8 @@ importers: specifier: ^5.7.2 version: 5.7.2 vitest: - specifier: ^3.0.5 - version: 3.0.5(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.5)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1) + specifier: ^3.0.8 + version: 3.0.8(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.8)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1) demos/angular-supabase-todolist: dependencies: @@ -137,7 +137,7 @@ importers: version: 0.1.11(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/drawer': specifier: ^6.6.15 - version: 6.7.2(de9b7caae7cef38a32afa5b76a3c9d54) + version: 6.7.2(yaao3llbshooz2bjipuf6mkduy) '@react-navigation/native': specifier: ^6.1.17 version: 6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -161,7 +161,7 @@ importers: version: 1.11.3 expo-router: specifier: 3.5.21 - version: 3.5.21(49b2fd6c45ca81e2d20f2f5a4be05a3e) + version: 3.5.21(gtohwu5bdvnl7tvlmjhokmubum) expo-splash-screen: specifier: ~0.27.4 version: 0.27.6(encoding@0.1.13)(expo-modules-autolinking@1.11.3)(expo@51.0.27(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(encoding@0.1.13)) @@ -215,7 +215,7 @@ importers: version: 10.2.0 react-navigation-stack: specifier: ^2.10.4 - version: 2.10.4(b5d6035dfb87b14e0677db2e89c1e7ef) + version: 2.10.4(ei6zhj5w65kzzp3jt27w3zu7ea) typed-async-storage: specifier: ^3.1.2 version: 3.1.2 @@ -702,7 +702,7 @@ importers: version: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(encoding@0.1.13)) expo-router: specifier: ^3.5.15 - version: 3.5.21(988d822f9e58e176bb73f45e8e45eb4a) + version: 3.5.21(j6qjh2jsuy2ozdtd6girxrw3ky) expo-splash-screen: specifier: ~0.27.4 version: 0.27.6(encoding@0.1.13)(expo-modules-autolinking@1.11.1)(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(encoding@0.1.13)) @@ -799,7 +799,7 @@ importers: version: 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/drawer': specifier: ^6.6.3 - version: 6.7.2(fe8cd8328c484d4e3eaed8eea351852b) + version: 6.7.2(f5uupuoecme7pb3346nlwm73my) '@react-navigation/native': specifier: ^6.0.0 version: 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -838,7 +838,7 @@ importers: version: 6.3.1(expo@51.0.37(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) expo-router: specifier: 3.5.23 - version: 3.5.23(2f86f7434a59b644ba234fab7be01c9e) + version: 3.5.23(x45f6tg66eoafhyrv4brrngbdm) expo-secure-store: specifier: ~13.0.1 version: 13.0.2(expo@51.0.37(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) @@ -886,7 +886,7 @@ importers: version: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) react-navigation-stack: specifier: ^2.10.4 - version: 2.10.4(cf0911ea264205029347060226fe0d29) + version: 2.10.4(b23yjknfeew5kcy4o5zrlfz5ae) devDependencies: '@babel/core': specifier: ^7.24.5 @@ -950,7 +950,7 @@ importers: version: 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/drawer': specifier: ^6.6.3 - version: 6.7.2(fe8cd8328c484d4e3eaed8eea351852b) + version: 6.7.2(f5uupuoecme7pb3346nlwm73my) '@react-navigation/native': specifier: ^6.0.0 version: 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -983,7 +983,7 @@ importers: version: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) expo-router: specifier: 3.5.21 - version: 3.5.21(43cc03a7fb538f7aef105856925492f6) + version: 3.5.21(qrxjjyxvihi5xb6jovt7bb6fjy) expo-secure-store: specifier: ~13.0.1 version: 13.0.2(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) @@ -1043,7 +1043,7 @@ importers: version: 0.19.12(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react-navigation-stack: specifier: ^2.10.4 - version: 2.10.4(cf0911ea264205029347060226fe0d29) + version: 2.10.4(b23yjknfeew5kcy4o5zrlfz5ae) devDependencies: '@babel/core': specifier: ^7.24.5 @@ -9001,13 +9001,13 @@ packages: vite: ^5.0.0 vue: ^3.2.25 - '@vitest/browser@3.0.5': - resolution: {integrity: sha512-5WAWJoucuWcGYU5t0HPBY03k9uogbUEIu4pDmZHoB4Dt+6pXqzDbzEmxGjejZSitSYA3k/udYfuotKNxETVA3A==} + '@vitest/browser@3.0.8': + resolution: {integrity: sha512-ARAGav2gJE/t+qF44fOwJlK0dK8ZJEYjZ725ewHzN6liBAJSCt9elqv/74iwjl5RJzel00k/wufJB7EEu+MJEw==} peerDependencies: playwright: '*' safaridriver: '*' - vitest: 3.0.5 - webdriverio: '*' + vitest: 3.0.8 + webdriverio: ^7.0.0 || ^8.0.0 || ^9.0.0 peerDependenciesMeta: playwright: optional: true @@ -9016,11 +9016,11 @@ packages: webdriverio: optional: true - '@vitest/expect@3.0.5': - resolution: {integrity: sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==} + '@vitest/expect@3.0.8': + resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} - '@vitest/mocker@3.0.5': - resolution: {integrity: sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==} + '@vitest/mocker@3.0.8': + resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 @@ -9030,20 +9030,20 @@ packages: vite: optional: true - '@vitest/pretty-format@3.0.5': - resolution: {integrity: sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==} + '@vitest/pretty-format@3.0.8': + resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==} - '@vitest/runner@3.0.5': - resolution: {integrity: sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==} + '@vitest/runner@3.0.8': + resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==} - '@vitest/snapshot@3.0.5': - resolution: {integrity: sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==} + '@vitest/snapshot@3.0.8': + resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==} - '@vitest/spy@3.0.5': - resolution: {integrity: sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==} + '@vitest/spy@3.0.8': + resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==} - '@vitest/utils@3.0.5': - resolution: {integrity: sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==} + '@vitest/utils@3.0.8': + resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==} '@volar/language-core@2.1.6': resolution: {integrity: sha512-pAlMCGX/HatBSiDFMdMyqUshkbwWbLxpN/RL7HCQDOo2gYBE+uS+nanosLc1qR6pTQ/U8q00xt8bdrrAFPSC0A==} @@ -9901,6 +9901,7 @@ packages: bson@6.8.0: resolution: {integrity: sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==} engines: {node: '>=16.20.1'} + deprecated: a critical bug affecting only useBigInt64=true deserialization usage is fixed in bson@6.10.3 buffer-alloc-unsafe@1.1.0: resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} @@ -10065,8 +10066,8 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chai@5.1.2: - resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} engines: {node: '>=12'} chalk-template@0.4.0: @@ -14158,6 +14159,9 @@ packages: loupe@3.1.2: resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -14897,8 +14901,8 @@ packages: msgpackr@1.11.0: resolution: {integrity: sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==} - msw@2.7.0: - resolution: {integrity: sha512-BIodwZ19RWfCbYTxWTUfTXc+sg4OwjCAgxU1ZsgmggX/7S3LdUifsbUPJs61j0rWb19CZRGY5if77duhc0uXzw==} + msw@2.7.3: + resolution: {integrity: sha512-+mycXv8l2fEAjFZ5sjrtjJDmm2ceKGjrNbBr1durRg6VkU9fNUE/gsmQ51hWbHqs+l35W1iM+ZsmOD9Fd6lspw==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -15641,8 +15645,8 @@ packages: resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} engines: {node: '>=12'} - pathe@2.0.2: - resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pathval@2.0.0: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} @@ -15719,13 +15723,13 @@ packages: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} - playwright-core@1.50.1: - resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==} + playwright-core@1.51.0: + resolution: {integrity: sha512-x47yPE3Zwhlil7wlNU/iktF7t2r/URR3VLbH6EknJd/04Qc/PSJ0EY3CMXipmglLG+zyRxW6HNo2EGbKLHPWMg==} engines: {node: '>=18'} hasBin: true - playwright@1.50.1: - resolution: {integrity: sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==} + playwright@1.51.0: + resolution: {integrity: sha512-442pTfGM0xxfCYxuBa/Pu6B2OqxqqaYq39JS8QDMGThUvIOCd6s0ANDog3uwA0cHavVlnTQzGCN7Id2YekDSXA==} engines: {node: '>=18'} hasBin: true @@ -17610,8 +17614,8 @@ packages: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} engines: {node: '>= 10'} - sirv@3.0.0: - resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} engines: {node: '>=18'} sisteransi@1.0.5: @@ -18914,8 +18918,8 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite-node@3.0.5: - resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==} + vite-node@3.0.8: + resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -19088,16 +19092,16 @@ packages: yaml: optional: true - vitest@3.0.5: - resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} + vitest@3.0.8: + resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.0.5 - '@vitest/ui': 3.0.5 + '@vitest/browser': 3.0.8 + '@vitest/ui': 3.0.8 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -19613,6 +19617,18 @@ packages: utf-8-validate: optional: true + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xcode@3.0.1: resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==} engines: {node: '>=10.0.0'} @@ -20376,7 +20392,7 @@ snapshots: '@babel/traverse': 7.26.4 '@babel/types': 7.26.3 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -20601,7 +20617,7 @@ snapshots: '@babel/core': 7.24.5 '@babel/helper-compilation-targets': 7.25.7 '@babel/helper-plugin-utils': 7.25.7 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -20612,7 +20628,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.7 '@babel/helper-plugin-utils': 7.25.7 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -20623,7 +20639,7 @@ snapshots: '@babel/core': 7.25.7 '@babel/helper-compilation-targets': 7.25.7 '@babel/helper-plugin-utils': 7.25.7 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -20634,7 +20650,7 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-compilation-targets': 7.25.7 '@babel/helper-plugin-utils': 7.25.7 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -25305,7 +25321,7 @@ snapshots: '@babel/parser': 7.26.3 '@babel/template': 7.25.9 '@babel/types': 7.26.3 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -26867,7 +26883,7 @@ snapshots: '@electron/notarize@2.5.0': dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) fs-extra: 9.1.0 promise-retry: 2.0.1 transitivePeerDependencies: @@ -26876,7 +26892,7 @@ snapshots: '@electron/osx-sign@1.3.1': dependencies: compare-version: 0.1.2 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) fs-extra: 10.1.0 isbinaryfile: 4.0.10 minimist: 1.2.8 @@ -26932,7 +26948,7 @@ snapshots: dependencies: '@electron/asar': 3.2.13 '@malept/cross-spawn-promise': 2.0.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) dir-compare: 4.2.0 fs-extra: 11.2.0 minimatch: 9.0.5 @@ -27738,7 +27754,7 @@ snapshots: dependencies: '@expo/spawn-async': 1.7.0 chalk: 4.1.2 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) find-up: 5.0.0 minimatch: 3.1.2 p-limit: 3.1.0 @@ -27944,7 +27960,7 @@ snapshots: '@expo/image-utils': 0.5.1(encoding@0.1.13) '@expo/json-file': 8.3.3 '@react-native/normalize-colors': 0.74.84 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) expo-modules-autolinking: 1.11.1 fs-extra: 9.1.0 resolve-from: 5.0.0 @@ -27962,7 +27978,7 @@ snapshots: '@expo/image-utils': 0.5.1(encoding@0.1.13) '@expo/json-file': 8.3.3 '@react-native/normalize-colors': 0.74.84 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) expo-modules-autolinking: 1.11.3 fs-extra: 9.1.0 resolve-from: 5.0.0 @@ -28016,7 +28032,7 @@ snapshots: '@expo/image-utils': 0.5.1(encoding@0.1.13) '@expo/json-file': 8.3.3 '@react-native/normalize-colors': 0.74.85 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) expo-modules-autolinking: 1.11.3 fs-extra: 9.1.0 resolve-from: 5.0.0 @@ -28345,7 +28361,7 @@ snapshots: '@ionic/utils-object@2.1.5': dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) tslib: 2.7.0 transitivePeerDependencies: - supports-color @@ -29372,7 +29388,7 @@ snapshots: chalk: 4.1.2 clean-stack: 3.0.1 cli-progress: 3.12.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) ejs: 3.1.10 get-package-type: 0.1.0 globby: 11.1.0 @@ -29735,7 +29751,7 @@ snapshots: '@puppeteer/browsers@2.4.1': dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.4.0 @@ -31385,7 +31401,7 @@ snapshots: react-is: 16.13.1 use-latest-callback: 0.2.1(react@18.2.0) - '@react-navigation/drawer@6.7.2(038ae2d2ed70d2cde1afeae3252026e4)': + '@react-navigation/drawer@6.7.2(bmedeebhe3ixiqe753c2r26xfi)': dependencies: '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/native': 6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -31399,20 +31415,7 @@ snapshots: warn-once: 0.1.1 optional: true - '@react-navigation/drawer@6.7.2(de9b7caae7cef38a32afa5b76a3c9d54)': - dependencies: - '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - color: 4.2.3 - react: 18.2.0 - react-native: 0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0) - react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-native-reanimated: 3.10.1(@babel/core@7.26.0)(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - warn-once: 0.1.1 - - '@react-navigation/drawer@6.7.2(fe8cd8328c484d4e3eaed8eea351852b)': + '@react-navigation/drawer@6.7.2(f5uupuoecme7pb3346nlwm73my)': dependencies: '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -31425,6 +31428,19 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) warn-once: 0.1.1 + '@react-navigation/drawer@6.7.2(yaao3llbshooz2bjipuf6mkduy)': + dependencies: + '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + color: 4.2.3 + react: 18.2.0 + react-native: 0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0) + react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-native-reanimated: 3.10.1(@babel/core@7.26.0)(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + warn-once: 0.1.1 + '@react-navigation/elements@1.3.31(@react-navigation/native@6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)': dependencies: '@react-navigation/native': 6.1.18(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -34153,7 +34169,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.7.2) '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.7.2) - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) eslint: 8.57.1 tsutils: 3.21.0(typescript@5.7.2) optionalDependencies: @@ -34165,7 +34181,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) '@typescript-eslint/utils': 6.21.0(eslint@8.55.0)(typescript@5.3.3) - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) eslint: 8.55.0 ts-api-utils: 1.3.0(typescript@5.3.3) optionalDependencies: @@ -34181,7 +34197,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 @@ -34195,7 +34211,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -34210,7 +34226,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -34315,67 +34331,67 @@ snapshots: vite: 5.4.8(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1) vue: 3.4.21(typescript@5.5.4) - '@vitest/browser@3.0.5(@types/node@22.7.4)(playwright@1.50.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.5)(webdriverio@9.8.0)': + '@vitest/browser@3.0.8(@testing-library/dom@10.4.0)(@types/node@22.7.4)(playwright@1.51.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.8)(webdriverio@9.8.0)': dependencies: - '@testing-library/dom': 10.4.0 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) - '@vitest/mocker': 3.0.5(msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2))(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)) - '@vitest/utils': 3.0.5 + '@vitest/mocker': 3.0.8(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)) + '@vitest/utils': 3.0.8 magic-string: 0.30.17 - msw: 2.7.0(@types/node@22.7.4)(typescript@5.7.2) - sirv: 3.0.0 + msw: 2.7.3(@types/node@22.7.4)(typescript@5.7.2) + sirv: 3.0.1 tinyrainbow: 2.0.0 - vitest: 3.0.5(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.5)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1) - ws: 8.18.0 + vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.8)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1) + ws: 8.18.1 optionalDependencies: - playwright: 1.50.1 + playwright: 1.51.0 webdriverio: 9.8.0 transitivePeerDependencies: + - '@testing-library/dom' - '@types/node' - bufferutil - typescript - utf-8-validate - vite - '@vitest/expect@3.0.5': + '@vitest/expect@3.0.8': dependencies: - '@vitest/spy': 3.0.5 - '@vitest/utils': 3.0.5 - chai: 5.1.2 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.5(msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2))(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))': + '@vitest/mocker@3.0.8(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))': dependencies: - '@vitest/spy': 3.0.5 + '@vitest/spy': 3.0.8 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - msw: 2.7.0(@types/node@22.7.4)(typescript@5.7.2) + msw: 2.7.3(@types/node@22.7.4)(typescript@5.7.2) vite: 5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1) - '@vitest/pretty-format@3.0.5': + '@vitest/pretty-format@3.0.8': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.0.5': + '@vitest/runner@3.0.8': dependencies: - '@vitest/utils': 3.0.5 - pathe: 2.0.2 + '@vitest/utils': 3.0.8 + pathe: 2.0.3 - '@vitest/snapshot@3.0.5': + '@vitest/snapshot@3.0.8': dependencies: - '@vitest/pretty-format': 3.0.5 + '@vitest/pretty-format': 3.0.8 magic-string: 0.30.17 - pathe: 2.0.2 + pathe: 2.0.3 - '@vitest/spy@3.0.5': + '@vitest/spy@3.0.8': dependencies: tinyspy: 3.0.2 - '@vitest/utils@3.0.5': + '@vitest/utils@3.0.8': dependencies: - '@vitest/pretty-format': 3.0.5 - loupe: 3.1.2 + '@vitest/pretty-format': 3.0.8 + loupe: 3.1.3 tinyrainbow: 2.0.0 '@volar/language-core@2.1.6': @@ -34727,13 +34743,13 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color agent-base@7.1.1: dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -35912,7 +35928,7 @@ snapshots: ccount@2.0.1: {} - chai@5.1.2: + chai@5.2.0: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 @@ -36889,9 +36905,11 @@ snapshots: optionalDependencies: supports-color: 8.1.1 - debug@4.4.0: + debug@4.4.0(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 decamelize-keys@1.1.1: dependencies: @@ -37604,7 +37622,7 @@ snapshots: esbuild-register@3.6.0(esbuild@0.19.12): dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) esbuild: 0.19.12 transitivePeerDependencies: - supports-color @@ -38553,35 +38571,7 @@ snapshots: dependencies: invariant: 2.2.4 - expo-router@3.5.21(43cc03a7fb538f7aef105856925492f6): - dependencies: - '@expo/metro-runtime': 3.2.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) - '@expo/server': 0.4.4(typescript@5.5.4) - '@radix-ui/react-slot': 1.0.1(react@18.2.0) - '@react-navigation/bottom-tabs': 6.5.20(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - '@react-navigation/native-stack': 6.9.26(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - expo: 51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13) - expo-constants: 16.0.2(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) - expo-linking: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) - expo-splash-screen: 0.27.5(encoding@0.1.13)(expo-modules-autolinking@1.11.3)(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) - expo-status-bar: 1.12.1 - react-native-helmet-async: 2.0.4(react@18.2.0) - react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - schema-utils: 4.2.0 - optionalDependencies: - '@react-navigation/drawer': 6.7.2(fe8cd8328c484d4e3eaed8eea351852b) - react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - transitivePeerDependencies: - - encoding - - expo-modules-autolinking - - react - - react-native - - supports-color - - typescript - - expo-router@3.5.21(49b2fd6c45ca81e2d20f2f5a4be05a3e): + expo-router@3.5.21(gtohwu5bdvnl7tvlmjhokmubum): dependencies: '@expo/metro-runtime': 3.2.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) '@expo/server': 0.4.4(typescript@5.5.4) @@ -38599,7 +38589,7 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) schema-utils: 4.2.0 optionalDependencies: - '@react-navigation/drawer': 6.7.2(de9b7caae7cef38a32afa5b76a3c9d54) + '@react-navigation/drawer': 6.7.2(yaao3llbshooz2bjipuf6mkduy) react-native-reanimated: 3.10.1(@babel/core@7.26.0)(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) transitivePeerDependencies: - encoding @@ -38609,7 +38599,7 @@ snapshots: - supports-color - typescript - expo-router@3.5.21(988d822f9e58e176bb73f45e8e45eb4a): + expo-router@3.5.21(j6qjh2jsuy2ozdtd6girxrw3ky): dependencies: '@expo/metro-runtime': 3.2.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0)) '@expo/server': 0.4.4(typescript@5.3.3) @@ -38627,7 +38617,7 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) schema-utils: 4.2.0 optionalDependencies: - '@react-navigation/drawer': 6.7.2(038ae2d2ed70d2cde1afeae3252026e4) + '@react-navigation/drawer': 6.7.2(bmedeebhe3ixiqe753c2r26xfi) react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.26.0(@babel/core@7.24.5))(@types/react@18.3.11)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) transitivePeerDependencies: - encoding @@ -38637,7 +38627,35 @@ snapshots: - supports-color - typescript - expo-router@3.5.23(2f86f7434a59b644ba234fab7be01c9e): + expo-router@3.5.21(qrxjjyxvihi5xb6jovt7bb6fjy): + dependencies: + '@expo/metro-runtime': 3.2.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) + '@expo/server': 0.4.4(typescript@5.5.4) + '@radix-ui/react-slot': 1.0.1(react@18.2.0) + '@react-navigation/bottom-tabs': 6.5.20(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + '@react-navigation/native': 6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + '@react-navigation/native-stack': 6.9.26(@react-navigation/native@6.1.18(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + expo: 51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13) + expo-constants: 16.0.2(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) + expo-linking: 6.3.1(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) + expo-splash-screen: 0.27.5(encoding@0.1.13)(expo-modules-autolinking@1.11.3)(expo@51.0.27(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(encoding@0.1.13)) + expo-status-bar: 1.12.1 + react-native-helmet-async: 2.0.4(react@18.2.0) + react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + schema-utils: 4.2.0 + optionalDependencies: + '@react-navigation/drawer': 6.7.2(f5uupuoecme7pb3346nlwm73my) + react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + transitivePeerDependencies: + - encoding + - expo-modules-autolinking + - react + - react-native + - supports-color + - typescript + + expo-router@3.5.23(x45f6tg66eoafhyrv4brrngbdm): dependencies: '@expo/metro-runtime': 3.2.3(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) '@expo/server': 0.4.4(typescript@5.5.4) @@ -38655,7 +38673,7 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) schema-utils: 4.2.0 optionalDependencies: - '@react-navigation/drawer': 6.7.2(fe8cd8328c484d4e3eaed8eea351852b) + '@react-navigation/drawer': 6.7.2(f5uupuoecme7pb3346nlwm73my) react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) transitivePeerDependencies: - encoding @@ -39135,7 +39153,7 @@ snapshots: flora-colossus@2.0.0: dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) fs-extra: 10.1.0 transitivePeerDependencies: - supports-color @@ -39312,7 +39330,7 @@ snapshots: galactus@1.0.0: dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) flora-colossus: 2.0.0 fs-extra: 10.1.0 transitivePeerDependencies: @@ -39421,7 +39439,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) fs-extra: 11.2.0 transitivePeerDependencies: - supports-color @@ -39965,7 +39983,7 @@ snapshots: http-call@5.3.0: dependencies: content-type: 1.0.5 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.4.0(supports-color@8.1.1) is-retry-allowed: 1.2.0 is-stream: 2.0.1 parse-json: 4.0.0 @@ -39996,7 +40014,7 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -41299,6 +41317,8 @@ snapshots: loupe@3.1.2: {} + loupe@3.1.3: {} + lower-case@2.0.2: dependencies: tslib: 2.7.0 @@ -42452,7 +42472,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -42668,7 +42688,7 @@ snapshots: optionalDependencies: msgpackr-extract: 3.0.3 - msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2): + msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2): dependencies: '@bundled-es-modules/cookie': 2.0.1 '@bundled-es-modules/statuses': 1.0.1 @@ -43291,7 +43311,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.1 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) get-uri: 6.0.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.5 @@ -43487,7 +43507,7 @@ snapshots: path-type@5.0.0: {} - pathe@2.0.2: {} + pathe@2.0.3: {} pathval@2.0.0: {} @@ -43549,11 +43569,11 @@ snapshots: dependencies: find-up: 3.0.0 - playwright-core@1.50.1: {} + playwright-core@1.51.0: {} - playwright@1.50.1: + playwright@1.51.0: dependencies: - playwright-core: 1.50.1 + playwright-core: 1.51.0 optionalDependencies: fsevents: 2.3.2 @@ -44313,7 +44333,7 @@ snapshots: proxy-agent@6.4.0: dependencies: agent-base: 7.1.1 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.5 lru-cache: 7.18.3 @@ -45215,19 +45235,7 @@ snapshots: - utf-8-validate optional: true - react-navigation-stack@2.10.4(b5d6035dfb87b14e0677db2e89c1e7ef): - dependencies: - '@react-native-community/masked-view': 0.1.11(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - color: 3.2.1 - react: 18.2.0 - react-native: 0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0) - react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-native-iphone-x-helper: 1.3.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) - react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - react-navigation: 4.4.4(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) - - react-navigation-stack@2.10.4(cf0911ea264205029347060226fe0d29): + react-navigation-stack@2.10.4(b23yjknfeew5kcy4o5zrlfz5ae): dependencies: '@react-native-community/masked-view': 0.1.11(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) color: 3.2.1 @@ -45239,6 +45247,18 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) react-navigation: 4.4.4(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-navigation-stack@2.10.4(ei6zhj5w65kzzp3jt27w3zu7ea): + dependencies: + '@react-native-community/masked-view': 0.1.11(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + color: 3.2.1 + react: 18.2.0 + react-native: 0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0) + react-native-gesture-handler: 2.16.2(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-native-iphone-x-helper: 1.3.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) + react-native-safe-area-context: 4.10.5(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-native-screens: 3.31.1(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-navigation: 4.4.4(react-native@0.74.5(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + react-navigation@4.4.4(react-native@0.74.5(@babel/core@7.24.5)(@babel/preset-env@7.25.7(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0): dependencies: '@react-navigation/core': 3.7.9(react@18.2.0) @@ -45352,7 +45372,7 @@ snapshots: read-binary-file-arch@1.0.6: dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -46311,7 +46331,7 @@ snapshots: mrmime: 2.0.0 totalist: 3.0.1 - sirv@3.0.0: + sirv@3.0.1: dependencies: '@polka/url': 1.0.0-next.28 mrmime: 2.0.0 @@ -46393,7 +46413,7 @@ snapshots: socks-proxy-agent@7.0.0: dependencies: agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -46401,7 +46421,7 @@ snapshots: socks-proxy-agent@8.0.4: dependencies: agent-base: 7.1.1 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -46474,7 +46494,7 @@ snapshots: spdy-transport@3.0.0: dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -46485,7 +46505,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -47372,7 +47392,7 @@ snapshots: tuf-js@2.2.1: dependencies: '@tufjs/models': 2.0.1 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) make-fetch-happen: 13.0.1 transitivePeerDependencies: - supports-color @@ -47848,12 +47868,12 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-node@3.0.5(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1): + vite-node@3.0.8(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1): dependencies: cac: 6.7.14 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) es-module-lexer: 1.6.0 - pathe: 2.0.2 + pathe: 2.0.3 vite: 5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1) transitivePeerDependencies: - '@types/node' @@ -47986,8 +48006,8 @@ snapshots: vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.47 - rollup: 4.24.0 + postcss: 8.5.1 + rollup: 4.34.6 optionalDependencies: '@types/node': 22.7.4 fsevents: 2.3.3 @@ -48065,32 +48085,32 @@ snapshots: terser: 5.34.1 yaml: 2.6.1 - vitest@3.0.5(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.5)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1): - dependencies: - '@vitest/expect': 3.0.5 - '@vitest/mocker': 3.0.5(msw@2.7.0(@types/node@22.7.4)(typescript@5.7.2))(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)) - '@vitest/pretty-format': 3.0.5 - '@vitest/runner': 3.0.5 - '@vitest/snapshot': 3.0.5 - '@vitest/spy': 3.0.5 - '@vitest/utils': 3.0.5 - chai: 5.1.2 - debug: 4.4.0 + vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.7.4)(@vitest/browser@3.0.8)(jsdom@24.1.3)(less@4.2.0)(lightningcss@1.28.2)(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(sass@1.79.4)(terser@5.34.1): + dependencies: + '@vitest/expect': 3.0.8 + '@vitest/mocker': 3.0.8(msw@2.7.3(@types/node@22.7.4)(typescript@5.7.2))(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1)) + '@vitest/pretty-format': 3.0.8 + '@vitest/runner': 3.0.8 + '@vitest/snapshot': 3.0.8 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + debug: 4.4.0(supports-color@8.1.1) expect-type: 1.1.0 magic-string: 0.30.17 - pathe: 2.0.2 + pathe: 2.0.3 std-env: 3.8.0 tinybench: 2.9.0 tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 2.0.0 vite: 5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1) - vite-node: 3.0.5(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1) + vite-node: 3.0.8(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 '@types/node': 22.7.4 - '@vitest/browser': 3.0.5(@types/node@22.7.4)(playwright@1.50.1)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.5)(webdriverio@9.8.0) + '@vitest/browser': 3.0.8(@testing-library/dom@10.4.0)(@types/node@22.7.4)(playwright@1.51.0)(typescript@5.7.2)(vite@5.4.11(@types/node@22.7.4)(less@4.2.0)(lightningcss@1.28.2)(sass@1.79.4)(terser@5.34.1))(vitest@3.0.8)(webdriverio@9.8.0) jsdom: 24.1.3 transitivePeerDependencies: - less @@ -48183,7 +48203,7 @@ snapshots: dependencies: chalk: 4.1.2 commander: 9.5.0 - debug: 4.4.0 + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color optional: true @@ -48235,7 +48255,7 @@ snapshots: '@wdio/utils': 9.7.3 deepmerge-ts: 7.1.3 undici: 6.21.0 - ws: 8.18.0 + ws: 8.18.1 transitivePeerDependencies: - bufferutil - supports-color @@ -48880,6 +48900,8 @@ snapshots: ws@8.18.0: {} + ws@8.18.1: {} + xcode@3.0.1: dependencies: simple-plist: 1.3.1