diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index d7966a9ca..9652f84f3 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -883,6 +883,16 @@ backupCli.subcommand("exportDb", "export-db").action(async (args) => { }); }); +backupCli.subcommand("importDb", "import-db").action(async (args) => { + await withWallet(args, async (wallet) => { + const dumpRaw = await read(process.stdin); + const dump = JSON.parse(dumpRaw); + await wallet.client.call(WalletApiOperation.ImportDb, { + dump, + }); + }); +}); + const depositCli = walletCli.subcommand("depositArgs", "deposit", { help: "Subcommands for depositing money to payto:// accounts", }); @@ -1600,6 +1610,3 @@ async function read(stream: NodeJS.ReadStream) { export function main() { walletCli.run(); } -function classifyTalerUri(uri: string) { - throw new Error("Function not implemented."); -} diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index efc0333f4..e68385267 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -2890,15 +2890,9 @@ export async function exportDb(idb: IDBFactory): Promise { return dbDump; } -export interface DatabaseDump { - name: string; - stores: { [s: string]: any }; - version: string; -} - async function recoverFromDump( db: IDBDatabase, - dump: DatabaseDump, + dbDump: DbDumpDatabase, ): Promise { return new Promise((resolve, reject) => { const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite"); @@ -2907,67 +2901,33 @@ async function recoverFromDump( }); for (let i = 0; i < db.objectStoreNames.length; i++) { const name = db.objectStoreNames[i]; - const storeDump = dump.stores[name]; + const storeDump = dbDump.stores[name]; if (!storeDump) continue; - Object.keys(storeDump).forEach(async (key) => { - const value = storeDump[key]; - if (!value) return; - tx.objectStore(name).put(value); - }); + for (let rec of storeDump.records) { + tx.objectStore(name).put(rec.value, rec.key); + } } tx.commit(); }); } -export async function importDb(db: IDBDatabase, object: any): Promise { - if ("name" in object && "stores" in object && "version" in object) { - // looks like a database dump - const dump = object as DatabaseDump; - return recoverFromDump(db, dump); - } +function checkDbDump(x: any): x is DbDump { + return "databases" in x; +} - if ("databases" in object && "$types" in object) { - // looks like a IDBDatabase - const someDatabase = object.databases; - - if (TALER_WALLET_META_DB_NAME in someDatabase) { - //looks like a taler database - const currentMainDbValue = - someDatabase[TALER_WALLET_META_DB_NAME].objectStores.metaConfig - .records[0].value.value; - - if (currentMainDbValue !== TALER_WALLET_MAIN_DB_NAME) { - console.log("not the current database version"); - } - - const talerDb = someDatabase[currentMainDbValue]; - - const objectStoreNames = Object.keys(talerDb.objectStores); - - const dump: DatabaseDump = { - name: talerDb.schema.databaseName, - version: talerDb.schema.databaseVersion, - stores: {}, - }; - - for (let i = 0; i < objectStoreNames.length; i++) { - const name = objectStoreNames[i]; - const storeDump = {} as { [s: string]: any }; - dump.stores[name] = storeDump; - talerDb.objectStores[name].records.map((r: any) => { - const pkey = r.primaryKey; - const key = - typeof pkey === "string" || typeof pkey === "number" - ? pkey - : pkey.join(","); - storeDump[key] = r.value; - }); - } - - return recoverFromDump(db, dump); +export async function importDb(db: IDBDatabase, dumpJson: any): Promise { + const d = dumpJson; + if (checkDbDump(d)) { + const walletDb = d.databases[TALER_WALLET_MAIN_DB_NAME]; + if (!walletDb) { + throw Error( + `unable to import, main wallet database (${TALER_WALLET_MAIN_DB_NAME}) not found`, + ); } + await recoverFromDump(db, walletDb); + } else { + throw Error("unable to import, doesn't look like a valid DB dump"); } - throw Error("could not import database"); } export interface FixupDescription {