diff --git a/lib/shared/redux/client-db-utils.js b/lib/shared/redux/client-db-utils.js --- a/lib/shared/redux/client-db-utils.js +++ b/lib/shared/redux/client-db-utils.js @@ -11,8 +11,8 @@ import { reportStoreOpsHandlers } from '../../ops/report-store-ops.js'; import { syncedMetadataStoreOpsHandlers } from '../../ops/synced-metadata-store-ops.js'; import { threadActivityStoreOpsHandlers } from '../../ops/thread-activity-store-ops.js'; -import type { ClientDBThreadStoreOperation } from '../../ops/thread-store-ops.js'; import { threadStoreOpsHandlers } from '../../ops/thread-store-ops.js'; +import type { ThreadStoreOperation } from '../../ops/thread-store-ops.js'; import { userStoreOpsHandlers } from '../../ops/user-store-ops.js'; import type { ClientDBStoreOperations, @@ -23,15 +23,12 @@ ClientDBThreadInfo, } from '../../types/thread-types.js'; import { values } from '../../utils/objects.js'; -import { - convertClientDBThreadInfoToRawThreadInfo, - convertRawThreadInfoToClientDBThreadInfo, -} from '../../utils/thread-ops-utils.js'; +import { convertClientDBThreadInfoToRawThreadInfo } from '../../utils/thread-ops-utils.js'; function createUpdateDBOpsForThreadStoreThreadInfos( clientDBThreadInfos: $ReadOnlyArray, migrationFunc: RawThreadInfos => RawThreadInfos, -): $ReadOnlyArray { +): $ReadOnlyArray { // 1. Translate `ClientDBThreadInfo`s to `RawThreadInfo`s. const rawThreadInfos = clientDBThreadInfos.map( convertClientDBThreadInfoToRawThreadInfo, @@ -46,18 +43,18 @@ // 4. Convert the updated `RawThreadInfos` back into an array. const updatedKeyedRawThreadInfosArray = values(updatedKeyedRawThreadInfos); - // 5. Translate `RawThreadInfo`s back to `ClientDBThreadInfo`s. - const updatedClientDBThreadInfos = updatedKeyedRawThreadInfosArray.map( - convertRawThreadInfoToClientDBThreadInfo, + // 5. Construct `replace` `ThreadStoreOperation`s. + const replaceThreadOperations = updatedKeyedRawThreadInfosArray.map( + thread => ({ + type: 'replace', + payload: { + id: thread.id, + threadInfo: thread, + }, + }), ); - // 6. Construct `replace` `ClientDBThreadStoreOperation`s. - const replaceThreadOperations = updatedClientDBThreadInfos.map(thread => ({ - type: 'replace', - payload: thread, - })); - - // 7. Prepend `replaceThreadOperations` with `remove_all` op and return. + // 6. Prepend `replaceThreadOperations` with `remove_all` op and return. return [{ type: 'remove_all' }, ...replaceThreadOperations]; } diff --git a/lib/utils/migration-utils.js b/lib/utils/migration-utils.js --- a/lib/utils/migration-utils.js +++ b/lib/utils/migration-utils.js @@ -204,18 +204,23 @@ debug: boolean, ) => Promise>; -export type MigrationManifest> = { - +[number | string]: (PersistedState) => Promise<{ - +state: T, - +ops: StoreOperations, - +changesSchema?: boolean, - }>, +export type MigrationManifest< + N: BaseNavInfo, + T: BaseAppState, +> = T => Promise<{ + +state: T, + +ops: StoreOperations, + +changesSchema?: boolean, +}>; + +export type MigrationsManifest> = { + +[number | string]: MigrationManifest, }; function createAsyncMigrate>( legacyMigrations: LegacyMigrationManifest, config: ConfigType, - migrations: MigrationManifest, + migrations: MigrationsManifest, handleException: (error: Error, state: T) => T, storageMigration: ?StorageMigrationFunction, ): ( @@ -268,7 +273,7 @@ async function runMigrations>( legacyMigrations: LegacyMigrationManifest, - migrations: MigrationManifest, + migrations: MigrationsManifest, state: T, inboundVersion: number, currentVersion: number, diff --git a/native/redux/client-db-utils.js b/native/redux/client-db-utils.js --- a/native/redux/client-db-utils.js +++ b/native/redux/client-db-utils.js @@ -1,6 +1,7 @@ // @flow import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js'; +import { threadStoreOpsHandlers } from 'lib/ops/thread-store-ops.js'; import { createUpdateDBOpsForThreadStoreThreadInfos } from 'lib/shared/redux/client-db-utils.js'; import type { RawMessageInfo, @@ -30,9 +31,11 @@ clientDBThreadInfos, migrationFunc, ); + const dbOperations = + threadStoreOpsHandlers.convertOpsToClientDBOps(operations); try { - commCoreModule.processThreadStoreOperationsSync(operations); + commCoreModule.processThreadStoreOperationsSync(dbOperations); } catch (exception) { console.log(exception); if (handleMigrationFailure) { diff --git a/native/redux/persist.js b/native/redux/persist.js --- a/native/redux/persist.js +++ b/native/redux/persist.js @@ -121,6 +121,10 @@ convertThreadStoreThreadInfosToNewIDSchema, createAsyncMigrate, } from 'lib/utils/migration-utils.js'; +import type { + MigrationManifest, + MigrationsManifest, +} from 'lib/utils/migration-utils.js'; import { entries } from 'lib/utils/objects.js'; import { deprecatedConvertClientDBThreadInfoToRawThreadInfo, @@ -149,6 +153,7 @@ import { unshimClientDB } from './unshim-utils.js'; import { authoritativeKeyserverID } from '../authoritative-keyserver.js'; import { commCoreModule } from '../native-modules.js'; +import type { NavInfo } from '../navigation/default-state.js'; import { defaultDeviceCameraInfo } from '../types/camera.js'; import { isTaskCancelledError } from '../utils/error-handling.js'; import { defaultURLPrefix } from '../utils/url-utils.js'; @@ -1363,14 +1368,14 @@ { whitelist: ['entryStore'] }, ); -const migrations = { +const migrations: MigrationsManifest = Object.freeze({ // This migration doesn't change the store but sets a persisted version // in the DB - [75]: (state: AppState) => ({ + [75]: (async (state: AppState) => ({ state, - ops: [], - }), - [76]: (state: AppState) => { + ops: {}, + }): MigrationManifest), + [76]: (async (state: AppState) => { const localMessageInfos = state.messageStore.local; const replaceOps: $ReadOnlyArray = @@ -1394,35 +1399,36 @@ operations, ); - const dbOperations: $ReadOnlyArray = - messageStoreOpsHandlers.convertOpsToClientDBOps(operations); - return { state: { ...state, messageStore: newMessageStore, }, - ops: dbOperations, + ops: { + messageStoreOperations: operations, + }, }; - }, - [77]: (state: AppState) => ({ + }: MigrationManifest), + [77]: (async (state: AppState) => ({ state, - ops: [], - }), - [78]: (state: AppState) => { + ops: {}, + }): MigrationManifest), + [78]: (async (state: AppState) => { const clientDBThreadInfos = commCoreModule.getAllThreadsSync(); - const dbOperations = createUpdateDBOpsForThreadStoreThreadInfos( + const operations = createUpdateDBOpsForThreadStoreThreadInfos( clientDBThreadInfos, deprecatedUpdateRolesAndPermissions, ); return { state, - ops: dbOperations, + ops: { + threadStoreOperations: operations, + }, }; - }, - [79]: (state: AppState) => { + }: MigrationManifest), + [79]: (async (state: AppState) => { return { state: { ...state, @@ -1431,10 +1437,10 @@ tunnelbrokerToken: null, }, }, - ops: [], + ops: {}, }; - }, - [80]: (state: AppState) => { + }: MigrationManifest), + [80]: (async (state: AppState) => { const clientDBThreadInfos = commCoreModule.getAllThreadsSync(); // This isn't actually accurate, but we force this cast here because the @@ -1444,26 +1450,28 @@ const stripMemberPermissions: RawThreadInfos => RawThreadInfos = (stripMemberPermissionsFromRawThreadInfos: any); - const dbOperations = createUpdateDBOpsForThreadStoreThreadInfos( + const operations = createUpdateDBOpsForThreadStoreThreadInfos( clientDBThreadInfos, stripMemberPermissions, ); return { state, - ops: dbOperations, + ops: { + threadStoreOperations: operations, + }, }; - }, - [81]: (state: AppState) => ({ + }: MigrationManifest), + [81]: (async (state: any) => ({ state: { ...state, queuedDMOperations: { operations: {}, }, }, - ops: [], - }), - [82]: (state: any) => ({ + ops: {}, + }): MigrationManifest), + [82]: (async (state: any) => ({ state: { ...state, queuedDMOperations: { @@ -1473,18 +1481,18 @@ membershipQueue: {}, }, }, - ops: [], - }), - [83]: (state: AppState) => ({ + ops: {}, + }): MigrationManifest), + [83]: (async (state: AppState) => ({ state: { ...state, holderStore: { storedHolders: {}, }, }, - ops: [], - }), -}; + ops: {}, + }): MigrationManifest), +}); // NOTE: renaming this object, and especially the `version` property // requires updating `native/native_rust_library/build.rs` to correctly diff --git a/web/redux/persist.js b/web/redux/persist.js --- a/web/redux/persist.js +++ b/web/redux/persist.js @@ -40,6 +40,8 @@ convertDraftStoreToNewIDSchema, createAsyncMigrate, type StorageMigrationFunction, + type MigrationManifest, + type MigrationsManifest, } from 'lib/utils/migration-utils.js'; import { entries } from 'lib/utils/objects.js'; import { @@ -512,14 +514,14 @@ return newStorage; }; -const migrations = { +const migrations: MigrationsManifest = { // This migration doesn't change the store but sets a persisted version // in the DB - [75]: (state: AppState) => ({ + [75]: (async (state: AppState) => ({ state, - ops: [], - }), - [76]: async (state: AppState) => { + ops: {}, + }): MigrationManifest), + [76]: (async (state: AppState) => { const localMessageInfos = state.messageStore.local; const replaceOps: $ReadOnlyArray = @@ -543,22 +545,21 @@ operations, ); - const dbOperations: $ReadOnlyArray = - messageStoreOpsHandlers.convertOpsToClientDBOps(operations); - return { state: { ...state, messageStore: newMessageStore, }, - ops: dbOperations, + ops: { + messageStoreOperations: operations, + }, }; - }, - [77]: (state: AppState) => ({ + }: MigrationManifest), + [77]: (async (state: AppState) => ({ state, - ops: [], - }), - [78]: async (state: AppState) => { + ops: {}, + }): MigrationManifest), + [78]: (async (state: AppState) => { // 1. Check if `databaseModule` is supported and early-exit if not. const sharedWorker = await getCommSharedWorker(); const isDatabaseSupported = await sharedWorker.isSupported(); @@ -566,7 +567,7 @@ if (!isDatabaseSupported) { return { state, - ops: [], + ops: {}, }; } @@ -585,21 +586,23 @@ ) { return { state, - ops: [], + ops: {}, }; } - const dbOperations = createUpdateDBOpsForThreadStoreThreadInfos( + const operations = createUpdateDBOpsForThreadStoreThreadInfos( clientDBThreadInfos, deprecatedUpdateRolesAndPermissions, ); return { state, - ops: dbOperations, + ops: { + threadStoreOperations: operations, + }, }; - }, - [79]: (state: AppState) => { + }: MigrationManifest), + [79]: (async (state: AppState) => { return { state: { ...state, @@ -608,19 +611,19 @@ tunnelbrokerToken: null, }, }, - ops: [], + ops: {}, }; - }, - [81]: (state: AppState) => ({ + }: MigrationManifest), + [81]: (async (state: any) => ({ state: { ...state, queuedDMOperations: { operations: {}, }, }, - ops: [], - }), - [82]: (state: any) => ({ + ops: {}, + }): MigrationManifest), + [82]: (async (state: any) => ({ state: { ...state, queuedDMOperations: { @@ -630,17 +633,17 @@ membershipQueue: {}, }, }, - ops: [], - }), - [83]: (state: AppState) => ({ + ops: {}, + }): MigrationManifest), + [83]: (async (state: AppState) => ({ state: { ...state, holderStore: { storedHolders: {}, }, }, - ops: [], - }), + ops: {}, + }): MigrationManifest), }; const persistConfig: PersistConfig = {