diff --git a/apps/tlon-mobile/ios/Podfile.lock b/apps/tlon-mobile/ios/Podfile.lock index 118028b13b..a07aa06a5a 100644 --- a/apps/tlon-mobile/ios/Podfile.lock +++ b/apps/tlon-mobile/ios/Podfile.lock @@ -1757,39 +1757,39 @@ SPEC CHECKSUMS: boost: d3f49c53809116a5d38da093a8aa78bf551aed09 BranchSDK: cb046c2714b03e573484ce9e349e2ddbad7016e8 DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953 - EASClient: a42ee8bf36c93b3128352faf2ae49405ab4f80bd - EXApplication: 137189a3f149b4e8e546884629392c3efc94cbd3 - EXAV: e4f6137431ddc4cb025895046bfefa9612025c35 - EXConstants: 988aa430ca0f76b43cd46b66e7fae3287f9cc2fc - EXFont: 21b9c760abd593ce8f0d5386b558ced76018506f - EXImageLoader: 55080616b2fe9da19ef8c7f706afd9814e279b6b + EASClient: 45d2459af3eb8a0283b50d3de38af7ac9930d747 + EXApplication: 45ce4be704dbde177c98e2e0e38c3aae3bb92535 + EXAV: e160fec51bf6bc41c3b6f7e4c72ea9fd36860cd6 + EXConstants: 348adb88fb0d65892f16732ec5e02e1365c31588 + EXFont: db0560db6676fce70dcc7656483d6560be02cbf0 + EXImageLoader: ba2506b443b9656e93167c104406a2c265924823 EXJSONUtils: 5c42959e87be238b045ef37cc5268b16a6c0ad4a - EXManifests: 5e8c29f36c716af768a4ea47ec05e1b89ab93091 - EXMediaLibrary: 70cf1fb7028fda2d682090c9fe57568674e4abab - EXNotifications: e11f0e9a5b657c064a481a5d522f3bc5a07bf7cd - Expo: fb745b3074989670b6641f9f20463e8ee56a69ca - expo-dev-client: dbc8e8a81d17a9d92e083a2856d056ba9a58984d - expo-dev-launcher: 346abfe8bd102bdcf6605dee01380a97635b63dc - expo-dev-menu: 166fc9c7b82641cdead1dc26d958d20a127ee97b - expo-dev-menu-interface: 7ba029c9d1a82ac22b9b584c00514860b060553e - ExpoBattery: 60bf880aea8f769fe39f709a920442542c1bfd62 - ExpoBlur: e832d874bd94afc0645daddbd3162ec1ce172080 - ExpoClipboard: b597982124f067ff9f5b89093eb3d97898d5d877 - ExpoDevice: d204395e17fffdcefa7470bdef33b07719ac41b1 - ExpoFileSystem: 74cc0fae916f9f044248433971dcfc8c3befd057 - ExpoHaptics: 28a771b630353cd6e8dcf1b1e3e693e38ad7c3c3 - ExpoImage: 8cf2d51de3d03b7e984e9b0ba8f19c0c22057001 - ExpoImageManipulator: c1d7cb865eacd620a35659f3da34c70531f10b59 - ExpoImagePicker: 66970181d1c838f444e5e1f81b804ab2d5ff49bd - ExpoKeepAwake: 0f5cad99603a3268e50af9a6eb8b76d0d9ac956c - ExpoLinearGradient: 4ad1449a2408e0435ac959076562b3921f2e32a1 - ExpoLocalization: f5f5d71dc0c9514d3d77b2771144f6fed6398d04 - ExpoModulesCore: 2346e83abf90c2b2c16a54c3fc4a1169ae12816c - ExpoSecureStore: c84ae37d1c36f38524d289c67c3a2e3fc56f1108 - EXSplashScreen: 6bd596128cd52fac91997ebc64f3d394c843a8f9 + EXManifests: 429136cffa3ae82d1ba3b60b7243fb186615562e + EXMediaLibrary: d3bf5c458643f9821b96af328d399ef3f44de7db + EXNotifications: 0df7db27e8cc862e37a30a56775ab883642f2872 + Expo: 72deced93cbf0d42e434764bb432e010ff4d8bdb + expo-dev-client: 90dd9b69d09a3a3788746df8713252f65125a18b + expo-dev-launcher: 0a8a761b63f1702cb513939198f1be0bcebdb235 + expo-dev-menu: 81becfb05d38e4bdcd50bfeec31617ee08567d5e + expo-dev-menu-interface: 44e69ddff62bbc6c5418c200e657635720b5a480 + ExpoBattery: 6cdcb673b99f53b3e9955b03268fd571cff68f51 + ExpoBlur: 3a9548a738624968836926f4aa1e18fa22155640 + ExpoClipboard: 24cc2b881ab6ca2e5b431b1f6d9d4a302adbf9d0 + ExpoDevice: a9a3955ece7cffe8ee98869d01018e4d6ca91bc7 + ExpoFileSystem: df58e1eb2a4d6f1006a1ca70bddfbbf63e52fa4f + ExpoHaptics: c91902e436f3fb0e07aa19acc118018089fa90de + ExpoImage: a70db90f39a7af98930cef91c84e877b1131f3dd + ExpoImageManipulator: 0c2ada7a028619ea1cc0c670bfa90c8ebeaa4af4 + ExpoImagePicker: d06822d74f1f0e7fe7cb070ece0fff6e678fa3eb + ExpoKeepAwake: 3b8cf8533b9212500565a1e41fb080fc5af29918 + ExpoLinearGradient: 501f9bbd83f3ec1d0e0425862b9ef4693605fc1c + ExpoLocalization: bee500d73d9bd5694c70d1e09d62f15d96cd0977 + ExpoModulesCore: 29b3765cf833c60c0a742e8b0693316105af81df + ExpoSecureStore: 4cec57fd2c40dcff05ce2186c39afc1af39d213c + EXSplashScreen: 7bbe853200d944b7266b53d5c79499b0d1fdcb19 EXStructuredHeaders: 5b0f47259db047dc1fdfa84752e292c2bfa68ecd - EXTaskManager: 3e446dbf75cd662aa6e7d6828be5bc26265241c3 - EXUpdates: 40e069f2987861a6d39101c4496e816561f3e167 + EXTaskManager: c3da046549b52b572a9bddb140e2b3d0e28b2ece + EXUpdates: 8cc7407328c3852e3ce890a381fe0022ae71902b EXUpdatesInterface: 3e444e2093e25b7ca0999a7d8c16e8392dee70c3 FBLazyVector: 98c189b92292d4bfeac13ffa8df3ce3d84e2fc5b FBReactNativeSpec: f40d89f4be3e854b08cf9b66cba9e9d6c68d863d @@ -1816,81 +1816,81 @@ SPEC CHECKSUMS: libvmaf: 27f523f1e63c694d14d534cd0fddd2fab0ae8711 libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 nanopb: 438bc412db1928dac798aa6fd75726007be04262 - op-sqlite: 12039198fdf455a3af0e18420b656c23cf8ecc01 + op-sqlite: b0c2f06e0660235bc3dca10714b0498fdbb811bb PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 - RCT-Folly: 7169b2b1c44399c76a47b5deaaba715eeeb476c0 + RCT-Folly: cd21f1661364f975ae76b3308167ad66b09f53f5 RCTRequired: d362a61864a64315aee00faea8dee6cf5b3f4aad RCTTypeSafety: 09baf60faeab02492dc8bf04ce5af1dda645b86d ReachabilitySwift: 7f151ff156cea1481a8411701195ac6a984f4979 React: b87c7c7c12f8232bd7cfdc4a00bf687144c17e30 React-callinvoker: 67de0bc05ecb7e690345a53a1661cea9b24670b0 - React-Codegen: dd60c11cfeb20cdd8b5a787603346d4e04f95499 - React-Core: 4c87a1873c6d11c6d3843582fbc266ba9ea304ce - React-CoreModules: 29ad1cbe757a70575913457bb7c646b7f4d4edf0 - React-cxxreact: 08ffaf2def6fe1ec8ef7f16e208587c96a87978e + React-Codegen: e81f008b53f3db74336a4324ea2b1ca15d7fe2da + React-Core: 4cb660fe310d6ee6d1e87308c2bec1541e1a40b4 + React-CoreModules: 12f9b33b8e1c67324be550e3c2ef1a03fa1aa473 + React-cxxreact: 4abb46b2ce1fa4eabe1105be8df331fc2dca9706 React-debug: 30d97e8abfec9b6ba0ad111b92ac749d3ace2dd5 - React-Fabric: 8da8e4c0ed603fbed5208f5045cd1582a96ffa3d - React-FabricImage: f0cf2b8a823e98dae20013910bbdd0889bc719c2 - React-graphics: 6dc8dba8a095a962204dd8bd4ca8264a1ed718db - React-hermes: fdaab14cc289d8d9cd45ffd9a3f8aa11157d4c7e - React-ImageManager: 4a39d60f9163fce83474c2b79acec8336742983d - React-jserrorhandler: 81e19a227a75741456c8f7b1240fc8926fb48c7e - React-jsi: 2253621cb2fb5d43a78fec4db8989cf9711039df - React-jsiexecutor: 5e4620a87fbc4ab174d75220f06ba8b53ae8317b + React-Fabric: 93d15dfd53ea0a8ece4d4bc399924571c1ab2d1c + React-FabricImage: 3e7fa7e5bd260008741e60f7ca4f8d5417b5fa7f + React-graphics: fe19a38958a23f951ef36613a34a6e867a6ef8f9 + React-hermes: 1f47d1f8b218565fd980eb00121d40e0ba2edcea + React-ImageManager: 941a294408b8a35cf929cf38d74deb83522c4556 + React-jserrorhandler: c06aabbbcd49aad9ddaa360b1fedaa7a4a0e820e + React-jsi: 0422dc0b680234b3eabee952c20e23ca63e10b3d + React-jsiexecutor: a61443a46b9616f17142d8f63d2e788f9b634be6 React-jsinspector: aee04d04ef553d5e30e52a4de2af958cb060069f - React-logger: 87a4232dd55485435edfa6803ff0de0b5c9eea1a - React-Mapbuffer: 94db5977cd64330f9e715c19026c9a267d8358a5 - react-native-branch: 021b9c261f732d0950e9a304284779d48bf81109 - react-native-context-menu-view: dcec18eb8882e20596dbb75802e7d19cb87dac02 - react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06 - react-native-netinfo: 3aa5637c18834966e0c932de8ae1ae56fea20a97 - react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b - react-native-webview: ad868affda04ff2b204de83546193bc0325a8280 + React-logger: ef76a6d8e04672f19be9b3a49f6ecc4c7141399b + React-Mapbuffer: 30deaceab523707646f5f35efad961133e4e1f25 + react-native-branch: 5d4ecda7bae040542f6c9f651a05d3df23d8b35a + react-native-context-menu-view: c7477ad2a9b5005eb45dd168c2dcdd64526dba77 + react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba + react-native-netinfo: 5364263f903da576bdef9c84a76fe243ab06812c + react-native-safe-area-context: 435f4c13ac75ceed6135382ee77d57d1a5b5b2d6 + react-native-webview: dc76301066fed23a66b1198f990056d2f8c67d20 React-nativeconfig: 44cd3076b158c39cb6758f238cd3e65953e989c0 - React-NativeModulesApple: af58ca346cf42c3bb4dab9173b6edd0c83c2a21c + React-NativeModulesApple: d8f0d34218e897ff56525e4446ba4d5e8f74f9c8 React-perflogger: c93b6a895eca3f9196656bb20ce0e15ad597a4e9 React-RCTActionSheet: 258842f426709dccbc2af31ca42b0a1807d76ad7 - React-RCTAnimation: 78c40269e35864f541b7486d17bd82a353c99fbc - React-RCTAppDelegate: d98ec2cdfb161d7a8496990e9649f94018025922 - React-RCTBlob: 593a5dbc58c45e3cccc37ad4498b10766ace26e6 - React-RCTFabric: c589babe0224cb137f64bfa4770e92d752c18012 - React-RCTImage: a0cdbb81db012ebc42c7dbaabdcb15f488c7c391 - React-RCTLinking: 82b6b0a5b2d5c8d3a28997e70bda46bac4be4c6e - React-RCTNetwork: 45e30079bcb987724028c9a93c0110b6d82e4a1f - React-RCTSettings: e67cbe694fe45b080b96b1394d4e45dff1b3ae04 - React-RCTText: 14a54686a1fa0b51b76660c7700980fdec6c3093 - React-RCTVibration: 00561f3d12dca44ed55af9060752bf8cf3fb0bfc - React-rendererdebug: 9e62f84756f080d88ed01b8063355c3a042934ed + React-RCTAnimation: e173f27b6e20108354df11ee0ae5a9f7fe09930f + React-RCTAppDelegate: 8c1e725f4be6d5fb55e7ea62b76c929eddcb859e + React-RCTBlob: 2135cb24f3fa9f4617d7cae03aee10724d5122bb + React-RCTFabric: 51dbbcfa09f76183d2fe9d305eedf0f4f7343333 + React-RCTImage: 345d59868e372e90a40f30f9775c8f34c50b5ebb + React-RCTLinking: d9623fb24075a5a7b9d5f263297135c5128ea37c + React-RCTNetwork: 4dfc12857609eae588c212268656bf0ff3ebe1f3 + React-RCTSettings: 5fa0803b17f29d87dc8d4649a1e5a32d4d081237 + React-RCTText: f23cca90ce571720460ee8e3525ff7e5f1af5ad0 + React-RCTVibration: efd2a82f8ecac6e7b363689322215735d1cbcf9e + React-rendererdebug: ea0f77385485b5251a0e61133e3b5f709ef02e9b React-rncore: e7f10bc6dbd75fa137583bd3b2bc4880203dbc1d React-runtimeexecutor: bf98e8973ed4c45139fbbaf2c34af44053acc9a9 - React-runtimescheduler: 7a4ccc1854c5918dee508536fad93172b4c49629 - React-utils: 59bbef368c9ba8b6e27416b46933cd03a35f2841 - ReactCommon: 656e520d76937c8d781ef82a7186a4af7160d814 - recaptcha-enterprise-react-native: 7d63c5bdde3b48996b984a86ac2b536a1d8f5f16 + React-runtimescheduler: e6288bce4309ba16280ce54690b4d7109091ff43 + React-utils: 28bc17e3e21dc06646b45a003718e0fe6034c66f + ReactCommon: e7f772a7660fc683a6ba0a0e0bebd45f4977ee57 + recaptcha-enterprise-react-native: 82f186a0ab29c91c4d4bd08f7758f849e91b4558 RecaptchaEnterprise: dc302910b77963a0cc6f6908407e30b35268a755 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 - RNCAsyncStorage: 618d03a5f52fbccb3d7010076bc54712844c18ef - RNCClipboard: 090462274cc05b02628bd158baf6d73c3abe8441 - RNDeviceInfo: db5c64a060e66e5db3102d041ebe3ef307a85120 - RNFBApp: 91311b27bc9a33e23b76a62825afd1635501018a - RNFBCrashlytics: c3219ef7a0c779f2428236215781c38e7892f6f9 - RNFBPerf: 2c926ff255c704a644dd53572008cba47c67ada0 - RNFlashList: 4b4b6b093afc0df60ae08f9cbf6ccd4c836c667a - RNGestureHandler: 79c035e2243d3b7f4f353e7eb32869eace6b596c - RNReanimated: 4b1bce37b188450e3a2d03c925edd5fb11d4bb2d - RNScreens: a4d9ce8f68f833f4e42410140eafd88e38bba163 - RNSVG: 3f65a03e0c61a8495dee92bf82545ed9041cbf3b + RNCAsyncStorage: a03b770a50541a761447cea9c24536047832124d + RNCClipboard: c20b93d3a1b47ce86dcffa5c0af5dd59938e47e1 + RNDeviceInfo: addb9b427c2822a2d8e94c87a136a224e0af738c + RNFBApp: e905ce948d9290555d9ab1303449827eb5119b5c + RNFBCrashlytics: e9459c8656ccbbb53d12afe47b4a96194c858745 + RNFBPerf: ae6cfdac3e06eab3d4d092944e979e95a69b0179 + RNFlashList: 1076a3fb7c4608a8cdf265f0783592b8fc41b6a7 + RNGestureHandler: 9852b7617e28551f5d339309c73ebf221ba1013d + RNReanimated: 1b07d2def747e4e5510ecd8460b2862029ee3df2 + RNScreens: 1174f55dd2f72abe45a4e48bf20e552feb051600 + RNSVG: a9e095acf2e207f2ef491870523ed455636cf3b8 SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9 SDWebImageAVIFCoder: 8348fef6d0ec69e129c66c9fe4d74fbfbf366112 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c SDWebImageWebPCoder: af09429398d99d524cae2fe00f6f0f6e491ed102 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 sqlite3: f163dbbb7aa3339ad8fc622782c2d9d7b72f7e9c - tentap: 2cf2e387dd284bf867010eb7d0f91618fb35b673 + tentap: 2a4256b6641a27d72d2b5fe2eb94cd1a203e4975 UMAppLoader: 5df85360d65cabaef544be5424ac64672e648482 Yoga: fb61b2337c7688c81a137e5560b3cbb515289f91 PODFILE CHECKSUM: 0cb7a78e5777e69c86c1bf4bb5135fd660376dbe -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/apps/tlon-mobile/package.json b/apps/tlon-mobile/package.json index 49c6c1ae95..3c4615c436 100644 --- a/apps/tlon-mobile/package.json +++ b/apps/tlon-mobile/package.json @@ -44,7 +44,7 @@ "@dev-plugins/react-query": "^0.0.6", "@google-cloud/recaptcha-enterprise-react-native": "^18.3.0", "@gorhom/bottom-sheet": "^4.5.1", - "@op-engineering/op-sqlite": "11.2.4", + "@op-engineering/op-sqlite": "5.0.5", "@react-native-async-storage/async-storage": "1.21.0", "@react-native-clipboard/clipboard": "^1.14.0", "@react-native-community/netinfo": "11.1.0", diff --git a/packages/app/features/top/ChannelScreen.tsx b/packages/app/features/top/ChannelScreen.tsx index 682fdddecd..8d3c768143 100644 --- a/packages/app/features/top/ChannelScreen.tsx +++ b/packages/app/features/top/ChannelScreen.tsx @@ -64,6 +64,11 @@ export default function ChannelScreen(props: Props) { const channelIsPending = !channel || channel.isPendingChannel; useFocusEffect( useCallback(() => { + if (!channelIsPending) { + store.syncChannelThreadUnreads(channelId, { + priority: store.SyncPriority.High, + }); + } // Mark the channel as visited when we unfocus/leave this screen () => { if (!channelIsPending) { @@ -96,14 +101,6 @@ export default function ChannelScreen(props: Props) { }, [groupId, channelId]) ); - useEffect(() => { - if (!channelIsPending) { - store.syncChannelThreadUnreads(channelId, { - priority: store.SyncPriority.High, - }); - } - }, [channelIsPending, channelId]); - const [channelNavOpen, setChannelNavOpen] = React.useState(false); const [inviteSheetGroup, setInviteSheetGroup] = React.useState(); diff --git a/packages/app/lib/baseDb.ts b/packages/app/lib/baseDb.ts deleted file mode 100644 index e49bba330b..0000000000 --- a/packages/app/lib/baseDb.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { createDevLogger } from '@tloncorp/shared'; -import { handleChange } from '@tloncorp/shared/db'; -import { sql } from 'drizzle-orm'; -import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; -import { useEffect, useMemo, useState } from 'react'; - -export const enableLogger = false; -export const logger = createDevLogger('db', enableLogger); - -export const changeLogTable = sqliteTable('__change_log', { - id: integer('id').primaryKey(), - table_name: text('table_name').notNull(), - operation: text('operation').notNull(), - row_id: integer('row_id'), - row_data: text('row_data'), - timestamp: integer('timestamp').default(sql`(strftime('%s', 'now'))`), -}); - -export function useMigrations(db: BaseDb) { - const [hasSucceeded, setHasSucceeded] = useState(false); - const [error, setError] = useState(null); - - useEffect(() => { - logger.log('running migrations'); - const startTime = Date.now(); - db.runMigrations() - .then(() => setHasSucceeded(true)) - .catch((e) => { - logger.log('failed to migrate database', e); - setError(e); - }) - .finally(() => - logger.log('migrations complete in', Date.now() - startTime + 'ms') - ); - }, [db]); - - return useMemo( - () => ({ - success: hasSucceeded, - error: error, - }), - [hasSucceeded, error] - ); -} - -export abstract class BaseDb { - protected client: any = null; - protected isPolling = false; - - abstract setupDb(): Promise; - abstract purgeDb(): Promise; - abstract getDbPath(): Promise; - abstract runMigrations(): Promise; - - protected async processChanges() { - if (!this.client) return; - - try { - const changes = await this.client.select().from(changeLogTable).all(); - for (const change of changes) { - handleChange({ - table: change.table_name, - operation: change.operation as 'INSERT' | 'UPDATE' | 'DELETE', - row: JSON.parse(change.row_data ?? ''), - }); - } - await this.client.delete(changeLogTable).run(); - } catch (e) { - logger.error('failed to process changes:', e); - } - } - - async resetDb() { - await this.purgeDb(); - await this.runMigrations(); - } -} diff --git a/packages/app/lib/nativeDb.ts b/packages/app/lib/nativeDb.ts index 82fea91cfe..c8ca44d71f 100644 --- a/packages/app/lib/nativeDb.ts +++ b/packages/app/lib/nativeDb.ts @@ -1,90 +1,108 @@ import { open } from '@op-engineering/op-sqlite'; -import { escapeLog } from '@tloncorp/shared'; -import { schema, setClient } from '@tloncorp/shared/db'; +import { createDevLogger, escapeLog } from '@tloncorp/shared'; +import { handleChange, schema, setClient } from '@tloncorp/shared/db'; +import { AnySqliteDatabase } from '@tloncorp/shared/db'; +import { useEffect, useMemo, useState } from 'react'; -import { - BaseDb, - enableLogger, - logger, - useMigrations as useMigrationsBase, -} from './baseDb'; import { OPSQLite$SQLiteConnection } from './opsqliteConnection'; import { SQLiteConnection } from './sqliteConnection'; -import { TRIGGER_SETUP } from './triggers'; -export class NativeDb extends BaseDb { - private connection: SQLiteConnection | null = null; +let connection: SQLiteConnection | null = null; +let client: AnySqliteDatabase | null = null; - async setupDb() { - if (this.connection || this.client) { - logger.warn('setupDb called multiple times, ignoring'); - return; - } - this.connection = new OPSQLite$SQLiteConnection( - // NB: the iOS code in SQLiteDB.swift relies on this path - if you change - // this, you should change that too. - open({ location: 'default', name: 'tlon.sqlite' }) - ); - // Experimental SQLite settings. May cause crashes. More here: - // https://ospfranco.notion.site/Configuration-6b8b9564afcc4ac6b6b377fe34475090 - this.connection.execute('PRAGMA mmap_size=268435456'); - this.connection.execute('PRAGMA journal_mode=MEMORY'); - this.connection.execute('PRAGMA synchronous=OFF'); +const enableLogger = false; +const logger = createDevLogger('db', enableLogger); - this.connection.updateHook(() => { - this.processChanges(); - }); - - this.client = this.connection.createClient({ - schema, - logger: enableLogger - ? { - logQuery(query, params) { - logger.log(escapeLog(query), params); - }, - } - : undefined, - }); - setClient(this.client); - logger.log('SQLite database opened at', this.connection.getDbPath()); +export function setupDb() { + if (connection || client) { + logger.warn('setupDb called multiple times, ignoring'); + return; } + connection = new OPSQLite$SQLiteConnection( + // NB: the iOS code in SQLiteDB.swift relies on this path - if you change + // this, you should change that too. + open({ location: 'default', name: 'tlon.sqlite' }) + ); + // Experimental SQLite settings. May cause crashes. More here: + // https://ospfranco.notion.site/Configuration-6b8b9564afcc4ac6b6b377fe34475090 + connection.execute('PRAGMA mmap_size=268435456'); + connection.execute('PRAGMA journal_mode=MEMORY'); + connection.execute('PRAGMA synchronous=OFF'); - async purgeDb() { - if (!this.connection) { - logger.warn('purgeDb called before setupDb, ignoring'); - return; - } - logger.log('purging sqlite database'); - this.connection.close(); - this.connection.delete(); - this.connection = null; - this.client = null; - logger.log('purged sqlite database, recreating'); - await this.setupDb(); - } + connection.updateHook(handleChange); + + client = connection.createClient({ + schema, + logger: enableLogger + ? { + logQuery(query, params) { + logger.log(escapeLog(query), params); + }, + } + : undefined, + }); + setClient(client); + logger.log('SQLite database opened at', connection.getDbPath()); +} - async getDbPath(): Promise { - return this.connection?.getDbPath(); +export async function purgeDb() { + if (!connection) { + logger.warn('purgeDb called before setupDb, ignoring'); + return; } + logger.log('purging sqlite database'); + connection.close(); + connection.delete(); + connection = null; + client = null; + logger.log('purged sqlite database, recreating'); + setupDb(); +} + +export function getDbPath() { + return connection?.getDbPath(); +} + +export function useMigrations() { + const [hasSucceeded, setHasSucceeded] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + logger.log('running migrations'); + const startTime = Date.now(); + runMigrations() + .then(() => setHasSucceeded(true)) + .catch((e) => { + logger.log('failed to migrate database', e); + setError(e); + }) + .finally(() => + logger.log('migrations complete in', Date.now() - startTime + 'ms') + ); + }, []); - async runMigrations() { - try { - await this.connection?.migrateClient(this.client!); - this.connection?.execute(TRIGGER_SETUP); - return; - } catch (e) { - logger.log('migrations failed, purging db and retrying', e); - } - await this.purgeDb(); - await this.connection?.migrateClient(this.client!); - logger.log("migrations succeeded after purge, shouldn't happen often"); + return useMemo( + () => ({ + success: hasSucceeded, + error: error, + }), + [hasSucceeded, error] + ); +} + +async function runMigrations() { + try { + await connection?.migrateClient(client!); + return; + } catch (e) { + logger.log('migrations failed, purging db and retrying', e); } + await purgeDb(); + await connection?.migrateClient(client!); + logger.log("migrations succeeded after purge, shouldn't happen often"); } -// Create singleton instance -const nativeDb = new NativeDb(); -export const setupDb = () => nativeDb.setupDb(); -export const purgeDb = () => nativeDb.purgeDb(); -export const getDbPath = () => nativeDb.getDbPath(); -export const resetDb = () => nativeDb.resetDb(); -export const useMigrations = () => useMigrationsBase(nativeDb); +export async function resetDb() { + await purgeDb(); + await connection?.migrateClient(client!); +} diff --git a/packages/app/lib/opsqliteConnection.ts b/packages/app/lib/opsqliteConnection.ts index c0333f72c1..8c8232afac 100644 --- a/packages/app/lib/opsqliteConnection.ts +++ b/packages/app/lib/opsqliteConnection.ts @@ -1,4 +1,4 @@ -import { DB } from '@op-engineering/op-sqlite'; +import { OPSQLiteConnection } from '@op-engineering/op-sqlite'; import { migrations } from '@tloncorp/shared/db/migrations'; import { Schema } from '@tloncorp/shared/db/types'; import { DrizzleConfig } from 'drizzle-orm'; @@ -11,7 +11,7 @@ import { SQLiteConnection } from './sqliteConnection'; export class OPSQLite$SQLiteConnection implements SQLiteConnection> { - constructor(private connection: DB) {} + constructor(private connection: OPSQLiteConnection) {} execute(query: string): void { this.connection.execute(query); diff --git a/packages/app/lib/webDb.ts b/packages/app/lib/webDb.ts index 81d300865f..44b86f0cf1 100644 --- a/packages/app/lib/webDb.ts +++ b/packages/app/lib/webDb.ts @@ -1,113 +1,186 @@ +import { createDevLogger } from '@tloncorp/shared'; import type { Schema } from '@tloncorp/shared/db'; -import { schema, setClient } from '@tloncorp/shared/db'; +import { handleChange, schema, setClient } from '@tloncorp/shared/db'; import { migrations } from '@tloncorp/shared/db/migrations'; +import { sql } from 'drizzle-orm'; +import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; import { drizzle } from 'drizzle-orm/sqlite-proxy'; +import { useEffect, useMemo, useState } from 'react'; import { SQLocalDrizzle } from 'sqlocal/drizzle'; -import { BaseDb, logger, useMigrations as useMigrationsBase } from './baseDb'; -import { TRIGGER_SETUP } from './triggers'; import migrate from './webMigrator'; +import { TRIGGER_SETUP } from './webTriggers'; -export class WebDb extends BaseDb { - private sqlocal: SQLocalDrizzle | null = null; +const POLL_INTERVAL = 100; - async setupDb() { - if (this.sqlocal || this.client) { - logger.warn('setupDb called multiple times, ignoring'); - return; - } - try { - this.sqlocal = new SQLocalDrizzle({ - databasePath: 'tlon.sqlite', - verbose: false, - }); +let sqlocal: SQLocalDrizzle | null = null; +let client: ReturnType> | null = null; - logger.log('sqlocal instance created', { sqlocal: this.sqlocal }); - // Experimental SQLite settings. May cause crashes. More here: - // https://ospfranco.notion.site/Configuration-6b8b9564afcc4ac6b6b377fe34475090 - await this.sqlocal.sql('PRAGMA mmap_size=268435456'); - // await this.sqlocal.sql('PRAGMA journal_mode=MEMORY'); - await this.sqlocal.sql('PRAGMA synchronous=OFF'); - await this.sqlocal.sql('PRAGMA journal_mode=WAL'); +const enableLogger = false; +const logger = createDevLogger('db', enableLogger); - await this.sqlocal.createCallbackFunction('processChanges', async () => - this.processChanges() - ); +export async function setupDb() { + if (sqlocal || client) { + logger.warn('setupDb called multiple times, ignoring'); + return; + } + try { + sqlocal = new SQLocalDrizzle({ + databasePath: 'tlon.sqlite', + verbose: enableLogger, + }); + + logger.log('sqlocal instance created', { sqlocal }); + // Experimental SQLite settings. May cause crashes. More here: + // https://ospfranco.notion.site/Configuration-6b8b9564afcc4ac6b6b377fe34475090 + await sqlocal.sql('PRAGMA mmap_size=268435456'); + // await sqlocal.sql('PRAGMA journal_mode=MEMORY'); + await sqlocal.sql('PRAGMA synchronous=OFF'); + await sqlocal.sql('PRAGMA journal_mode=WAL'); + + const { driver } = sqlocal; + + client = drizzle(driver, { + schema, + logger: enableLogger + ? { + logQuery(query, params) { + logger.log(query, params); + }, + } + : undefined, + }); + + const dbInfo = await sqlocal.getDatabaseInfo(); + logger.log('SQLite database opened:', dbInfo); + + setClient(client); + } catch (e) { + logger.error('Failed to setup SQLite db', e); + } +} - const { driver } = this.sqlocal; +export async function checkDb() { + if (!sqlocal) { + logger.warn('checkDb called before setupDb, ignoring'); + return; + } + const dbInfo = await sqlocal.getDatabaseInfo(); + logger.log('SQLite database info:', dbInfo); + return dbInfo; +} - this.client = drizzle(driver, { schema }); - setClient(this.client); +let isPolling = false; - const dbInfo = await this.sqlocal.getDatabaseInfo(); - logger.log('SQLite database opened:', dbInfo); - } catch (e) { - logger.error('Failed to setup SQLite db', e); - } - } +function startChangePolling() { + if (isPolling) return; + isPolling = true; + pollChanges(); +} - async checkDb() { - if (!this.sqlocal) { - logger.warn('checkDb called before setupDb, ignoring'); - return; +const changeLogTable = sqliteTable('__change_log', { + id: integer('id').primaryKey(), + table_name: text('table_name').notNull(), + operation: text('operation').notNull(), + row_id: integer('row_id'), + row_data: text('row_data'), + timestamp: integer('timestamp').default(sql`(strftime('%s', 'now'))`), +}); + +async function pollChanges() { + if (!client) return; + + try { + const changes = await client.select().from(changeLogTable).all(); + + for (const change of changes) { + handleChange({ + table: change.table_name, + operation: change.operation as 'INSERT' | 'UPDATE' | 'DELETE', + row: JSON.parse(change.row_data ?? ''), + }); } - const dbInfo = await this.sqlocal.getDatabaseInfo(); - logger.log('SQLite database info:', dbInfo); - return dbInfo; - } - async purgeDb() { - if (!this.sqlocal) { - logger.warn('purgeDb called before setupDb, ignoring'); - return; - } - logger.log('purging sqlite database'); - this.sqlocal.destroy(); - this.sqlocal = null; - this.client = null; - logger.log('purged sqlite database, recreating'); - await this.setupDb(); + // Clear processed changes + await client.delete(changeLogTable).run(); + } catch (error) { + console.error('Error polling changes:', error); + } finally { + // Schedule next poll + setTimeout(pollChanges, POLL_INTERVAL); // Poll every second } +} - async getDbPath() { - return this.sqlocal?.getDatabaseInfo().then((info) => info.databasePath); +export async function purgeDb() { + if (!sqlocal) { + logger.warn('purgeDb called before setupDb, ignoring'); + return; } + logger.log('purging sqlite database'); + sqlocal.destroy(); + sqlocal = null; + client = null; + logger.log('purged sqlite database, recreating'); + await setupDb(); +} - async runMigrations() { - if (!this.client || !this.sqlocal) { - logger.warn('runMigrations called before setupDb, ignoring'); - return; - } +export async function getDbPath() { + return sqlocal?.getDatabaseInfo().then((info) => info.databasePath); +} - try { - logger.log('runMigrations: starting migration'); - await migrate(this.client, migrations, this.sqlocal); - logger.log('runMigrations: migrations succeeded'); - await this.sqlocal.sql(TRIGGER_SETUP); - - await this.sqlocal.sql(` - CREATE TRIGGER IF NOT EXISTS after_changes_insert - AFTER INSERT ON __change_log - BEGIN - SELECT processChanges(); - END; - `); - - return; - } catch (e) { - logger.log('migrations failed, purging db and retrying', e); +export function useMigrations() { + const [hasSucceeded, setHasSucceeded] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + async function performMigrations() { + logger.log('running migrations'); + const startTime = Date.now(); + + try { + await runMigrations(); + setHasSucceeded(true); + logger.log('migrations complete in', Date.now() - startTime + 'ms'); + } catch (e) { + logger.log('failed to migrate database', e); + setError(e); + } } - await this.purgeDb(); - await migrate(this.client, migrations, this.sqlocal); - logger.log("migrations succeeded after purge, shouldn't happen often"); + + performMigrations(); + }, []); + + return useMemo( + () => ({ + success: hasSucceeded, + error: error, + }), + [hasSucceeded, error] + ); +} + +async function runMigrations() { + if (!client || !sqlocal) { + logger.warn('runMigrations called before setupDb, ignoring'); + return; } + + try { + logger.log('runMigrations: starting migration'); + await migrate(client, migrations, sqlocal); + logger.log('runMigrations: migrations succeeded'); + await sqlocal.sql(TRIGGER_SETUP); + startChangePolling(); + return; + } catch (e) { + logger.log('migrations failed, purging db and retrying', e); + } + await purgeDb(); + await migrate(client, migrations, sqlocal); + logger.log("migrations succeeded after purge, shouldn't happen often"); } -// Create singleton instance -const webDb = new WebDb(); -export const setupDb = () => webDb.setupDb(); -export const checkDb = () => webDb.checkDb(); -export const purgeDb = () => webDb.purgeDb(); -export const getDbPath = () => webDb.getDbPath(); -export const resetDb = () => webDb.resetDb(); -export const useMigrations = () => useMigrationsBase(webDb); +export async function resetDb() { + await purgeDb(); + await migrate(client!, migrations, sqlocal!); +} diff --git a/packages/app/lib/triggers.ts b/packages/app/lib/webTriggers.ts similarity index 97% rename from packages/app/lib/triggers.ts rename to packages/app/lib/webTriggers.ts index b54ec525ae..91dad7acfb 100644 --- a/packages/app/lib/triggers.ts +++ b/packages/app/lib/webTriggers.ts @@ -78,8 +78,8 @@ BEGIN VALUES ( 'post_reactions', 'DELETE', - OLD.value, - json_object('value', OLD.value, 'post_id', OLD.post_id) + OLD.id, + json_object('id', OLD.id, 'post_id', OLD.post_id) ); END; diff --git a/patches/drizzle-orm@0.36.1.patch b/patches/drizzle-orm@0.36.1.patch index c32bb66088..93e826c369 100644 --- a/patches/drizzle-orm@0.36.1.patch +++ b/patches/drizzle-orm@0.36.1.patch @@ -220,7 +220,7 @@ index 07cae6b6cb6c0c1a11d283ae26aad1c1c1d7cd4d..021c904e0b9d22fad58853669c341b51 } export {}; diff --git a/op-sqlite/session.js b/op-sqlite/session.js -index ff84604e7998182ef78fbffc8d20019aaf76755e..b924059196f0bc7f368bebd920aa0cbca89f65eb 100644 +index ff84604e7998182ef78fbffc8d20019aaf76755e..454f154677b6761798419b9196b1ba5674cbb5c6 100644 --- a/op-sqlite/session.js +++ b/op-sqlite/session.js @@ -1,6 +1,6 @@ @@ -285,12 +285,8 @@ index ff84604e7998182ef78fbffc8d20019aaf76755e..b924059196f0bc7f368bebd920aa0cbc } } class OPSQLitePreparedQuery extends SQLitePreparedQuery { -@@ -69,10 +66,17 @@ class OPSQLitePreparedQuery extends SQLitePreparedQuery { - run(placeholderValues) { - const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); - this.logger.logQuery(this.query.sql, params); -- return this.client.executeAsync(this.query.sql, params); -+ return this.client.execute(this.query.sql, params); +@@ -72,7 +69,14 @@ class OPSQLitePreparedQuery extends SQLitePreparedQuery { + return this.client.executeAsync(this.query.sql, params); } async all(placeholderValues) { - const { fields, joinsNotNullableMap, query, logger, customResultMapper, client } = this; @@ -321,15 +317,6 @@ index ff84604e7998182ef78fbffc8d20019aaf76755e..b924059196f0bc7f368bebd920aa0cbc const params = fillPlaceholders(query.params, placeholderValues ?? {}); logger.logQuery(query.sql, params); if (!fields && !customResultMapper) { -@@ -105,7 +116,7 @@ class OPSQLitePreparedQuery extends SQLitePreparedQuery { - values(placeholderValues) { - const params = fillPlaceholders(this.query.params, placeholderValues ?? {}); - this.logger.logQuery(this.query.sql, params); -- return this.client.executeRawAsync(this.query.sql, params); -+ return this.client.executeRaw(this.query.sql, params); - } - /** @internal */ - isResponseInArrayMode() { diff --git a/op-sqlite/session.js.map b/op-sqlite/session.js.map index e9d9ca06b6bed8fa265438fc41fe35e20723f61a..ebfae284accc68b35aae9d8dc8e61fdbe07f8f15 100644 --- a/op-sqlite/session.js.map diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea70e29713..d5887b0d85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ patchedDependencies: hash: 5ofxtlxe6za2xqrbq5pqbz7wb4 path: patches/any-ascii@0.3.2.patch drizzle-orm@0.36.1: - hash: emfaialij3z7aqdjf53okvbhey + hash: 7epepcnfyprhmo2nsyfz6xaw3i path: patches/drizzle-orm@0.36.1.patch react-cosmos@6.1.1: hash: y5kop5rmmd7jprmzzewk4whiie @@ -127,8 +127,8 @@ importers: specifier: ^4.5.1 version: 4.6.0(@types/react-native@0.73.0(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(@types/react@18.2.55)(react-native-gesture-handler@2.20.0(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.8.1(patch_hash=iololnqcieadxwydikuxdlowf4)(@babel/core@7.25.2)(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@op-engineering/op-sqlite': - specifier: 11.2.4 - version: 11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + specifier: 5.0.5 + version: 5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-native-async-storage/async-storage': specifier: 1.21.0 version: 1.21.0(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0)) @@ -1180,7 +1180,7 @@ importers: version: 0.19.12(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) sqlocal: specifier: ^0.11.1 - version: 0.11.1(drizzle-orm@0.36.1(patch_hash=emfaialij3z7aqdjf53okvbhey)(@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0)) + version: 0.11.1(drizzle-orm@0.36.1(patch_hash=7epepcnfyprhmo2nsyfz6xaw3i)(@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0)) tailwindcss-opentype: specifier: ^1.1.0 version: 1.1.0(tailwindcss@3.4.1) @@ -1403,7 +1403,7 @@ importers: version: 3.1.0(base-64@1.0.0)(react-native-fetch-api@3.0.0)(react-native-get-random-values@1.11.0(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0)))(react-native-url-polyfill@2.0.0(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0)))(text-encoding@0.7.0)(web-streams-polyfill@3.3.3) sqlocal: specifier: ^0.11.1 - version: 0.11.1(drizzle-orm@0.36.1(patch_hash=emfaialij3z7aqdjf53okvbhey)(@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0)) + version: 0.11.1(drizzle-orm@0.36.1(patch_hash=7epepcnfyprhmo2nsyfz6xaw3i)(@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0)) zustand: specifier: ^3.7.2 version: 3.7.2(react@18.2.0) @@ -1498,7 +1498,7 @@ importers: version: 3.0.0 drizzle-orm: specifier: 0.36.1 - version: 0.36.1(patch_hash=emfaialij3z7aqdjf53okvbhey)(@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0) + version: 0.36.1(patch_hash=7epepcnfyprhmo2nsyfz6xaw3i)(@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0) exponential-backoff: specifier: ^3.1.1 version: 3.1.1 @@ -4443,11 +4443,11 @@ packages: engines: {node: '>=10'} deprecated: This functionality has been moved to @npmcli/fs - '@op-engineering/op-sqlite@11.2.4': - resolution: {integrity: sha512-YL3n2zxbv+VrEgFw3JYdhGbwhs4Gqt5/ofcyx3F4Bd+cI37lmhbGxTPNnJZvFo4fGFMpEfnNVgz2hOPKR8EpNg==} + '@op-engineering/op-sqlite@5.0.5': + resolution: {integrity: sha512-7BK+U2EY4S8ZUc0zKuRQkDiadP3lyhSimspu74GQsjzT3tjmbcrJ19rg7+D0T1bAAOJNbyHQhWZvcKtkHiBRRg==} peerDependencies: react: '*' - react-native: '>0.73.0' + react-native: '*' '@open-draft/until@1.0.3': resolution: {integrity: sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==} @@ -14298,16 +14298,16 @@ snapshots: '@aws-sdk/abort-controller@3.190.0': dependencies: '@aws-sdk/types': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/chunked-blob-reader-native@3.188.0': dependencies: '@aws-sdk/util-base64-browser': 3.188.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/chunked-blob-reader@3.188.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/client-s3@3.190.0': dependencies: @@ -14464,7 +14464,7 @@ snapshots: '@aws-sdk/property-provider': 3.190.0 '@aws-sdk/types': 3.190.0 '@aws-sdk/url-parser': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/credential-provider-ini@3.190.0': dependencies: @@ -14545,7 +14545,7 @@ snapshots: dependencies: '@aws-sdk/eventstream-codec': 3.190.0 '@aws-sdk/types': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/fetch-http-handler@3.190.0': dependencies: @@ -14580,7 +14580,7 @@ snapshots: '@aws-sdk/is-array-buffer@3.188.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/md5-js@3.190.0': dependencies: @@ -14675,7 +14675,7 @@ snapshots: '@aws-sdk/protocol-http': 3.190.0 '@aws-sdk/signature-v4': 3.190.0 '@aws-sdk/types': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/middleware-serde@3.190.0': dependencies: @@ -14724,7 +14724,7 @@ snapshots: '@aws-sdk/property-provider@3.190.0': dependencies: '@aws-sdk/types': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/protocol-http@3.190.0': dependencies: @@ -14735,12 +14735,12 @@ snapshots: dependencies: '@aws-sdk/types': 3.190.0 '@aws-sdk/util-uri-escape': 3.188.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/querystring-parser@3.190.0': dependencies: '@aws-sdk/types': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/s3-request-presigner@3.190.0': dependencies: @@ -14761,7 +14761,7 @@ snapshots: '@aws-sdk/shared-ini-file-loader@3.190.0': dependencies: '@aws-sdk/types': 3.190.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/signature-v4-multi-region@3.190.0': dependencies: @@ -14778,7 +14778,7 @@ snapshots: '@aws-sdk/util-hex-encoding': 3.188.0 '@aws-sdk/util-middleware': 3.190.0 '@aws-sdk/util-uri-escape': 3.188.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/smithy-client@3.190.0': dependencies: @@ -14796,7 +14796,7 @@ snapshots: '@aws-sdk/util-arn-parser@3.188.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/util-base64-browser@3.188.0': dependencies: @@ -14818,11 +14818,11 @@ snapshots: '@aws-sdk/util-buffer-from@3.188.0': dependencies: '@aws-sdk/is-array-buffer': 3.188.0 - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/util-config-provider@3.188.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/util-create-request@3.190.0': dependencies: @@ -14855,15 +14855,15 @@ snapshots: '@aws-sdk/util-hex-encoding@3.188.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/util-locate-window@3.188.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/util-middleware@3.190.0': dependencies: - tslib: 2.8.1 + tslib: 2.6.2 '@aws-sdk/util-stream-browser@3.190.0': dependencies: @@ -18802,12 +18802,12 @@ snapshots: mkdirp: 1.0.4 rimraf: 3.0.2 - '@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0)': + '@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0)': dependencies: react: 18.2.0 react-native: 0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.23.7(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0) - '@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0)': + '@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0)': dependencies: react: 18.2.0 react-native: 0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0) @@ -24439,9 +24439,9 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.36.1(patch_hash=emfaialij3z7aqdjf53okvbhey)(@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0): + drizzle-orm@0.36.1(patch_hash=7epepcnfyprhmo2nsyfz6xaw3i)(@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0): optionalDependencies: - '@op-engineering/op-sqlite': 11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0) + '@op-engineering/op-sqlite': 5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@opentelemetry/api': 1.9.0 '@types/better-sqlite3': 7.6.9 '@types/react': 18.2.55 @@ -30342,13 +30342,13 @@ snapshots: sprintf-js@1.0.3: {} - sqlocal@0.11.1(drizzle-orm@0.36.1(patch_hash=emfaialij3z7aqdjf53okvbhey)(@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0)): + sqlocal@0.11.1(drizzle-orm@0.36.1(patch_hash=7epepcnfyprhmo2nsyfz6xaw3i)(@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0)): dependencies: '@sqlite.org/sqlite-wasm': 3.46.0-build2 coincident: 1.2.3 nanoid: 5.0.7 optionalDependencies: - drizzle-orm: 0.36.1(patch_hash=emfaialij3z7aqdjf53okvbhey)(@op-engineering/op-sqlite@11.2.4(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0) + drizzle-orm: 0.36.1(patch_hash=7epepcnfyprhmo2nsyfz6xaw3i)(@op-engineering/op-sqlite@5.0.5(react-native@0.73.9(@babel/core@7.25.2)(@babel/preset-env@7.26.0(@babel/core@7.25.2))(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.9)(@types/react@18.2.55)(better-sqlite3@9.4.5)(react@18.2.0) transitivePeerDependencies: - bufferutil - utf-8-validate