wallet-core: make primitive backup import work
This commit is contained in:
parent
183aed4ba5
commit
0a4782a0da
@ -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", {
|
const depositCli = walletCli.subcommand("depositArgs", "deposit", {
|
||||||
help: "Subcommands for depositing money to payto:// accounts",
|
help: "Subcommands for depositing money to payto:// accounts",
|
||||||
});
|
});
|
||||||
@ -1600,6 +1610,3 @@ async function read(stream: NodeJS.ReadStream) {
|
|||||||
export function main() {
|
export function main() {
|
||||||
walletCli.run();
|
walletCli.run();
|
||||||
}
|
}
|
||||||
function classifyTalerUri(uri: string) {
|
|
||||||
throw new Error("Function not implemented.");
|
|
||||||
}
|
|
||||||
|
@ -2890,15 +2890,9 @@ export async function exportDb(idb: IDBFactory): Promise<DbDump> {
|
|||||||
return dbDump;
|
return dbDump;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DatabaseDump {
|
|
||||||
name: string;
|
|
||||||
stores: { [s: string]: any };
|
|
||||||
version: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function recoverFromDump(
|
async function recoverFromDump(
|
||||||
db: IDBDatabase,
|
db: IDBDatabase,
|
||||||
dump: DatabaseDump,
|
dbDump: DbDumpDatabase,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
|
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++) {
|
for (let i = 0; i < db.objectStoreNames.length; i++) {
|
||||||
const name = db.objectStoreNames[i];
|
const name = db.objectStoreNames[i];
|
||||||
const storeDump = dump.stores[name];
|
const storeDump = dbDump.stores[name];
|
||||||
if (!storeDump) continue;
|
if (!storeDump) continue;
|
||||||
Object.keys(storeDump).forEach(async (key) => {
|
for (let rec of storeDump.records) {
|
||||||
const value = storeDump[key];
|
tx.objectStore(name).put(rec.value, rec.key);
|
||||||
if (!value) return;
|
}
|
||||||
tx.objectStore(name).put(value);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
tx.commit();
|
tx.commit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function importDb(db: IDBDatabase, object: any): Promise<void> {
|
function checkDbDump(x: any): x is DbDump {
|
||||||
if ("name" in object && "stores" in object && "version" in object) {
|
return "databases" in x;
|
||||||
// looks like a database dump
|
}
|
||||||
const dump = object as DatabaseDump;
|
|
||||||
return recoverFromDump(db, dump);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("databases" in object && "$types" in object) {
|
export async function importDb(db: IDBDatabase, dumpJson: any): Promise<void> {
|
||||||
// looks like a IDBDatabase
|
const d = dumpJson;
|
||||||
const someDatabase = object.databases;
|
if (checkDbDump(d)) {
|
||||||
|
const walletDb = d.databases[TALER_WALLET_MAIN_DB_NAME];
|
||||||
if (TALER_WALLET_META_DB_NAME in someDatabase) {
|
if (!walletDb) {
|
||||||
//looks like a taler database
|
throw Error(
|
||||||
const currentMainDbValue =
|
`unable to import, main wallet database (${TALER_WALLET_MAIN_DB_NAME}) not found`,
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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 {
|
export interface FixupDescription {
|
||||||
|
Loading…
Reference in New Issue
Block a user