taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 51d902402de1356a9089d9ab867d340dcaf83315
parent 5ea6298d9cb9945ed23a9b856e69fca839bc48a0
Author: Florian Dold <florian@dold.me>
Date:   Thu, 19 Jun 2025 23:30:43 +0200

implement JSON file export for qtart platform

Diffstat:
Mpackages/taler-util/src/qtart.ts | 33++++++++++++++++++++++++++++++---
Mpackages/taler-util/src/types-taler-wallet.ts | 9+++++++++
Mpackages/taler-wallet-core/src/host-impl.qtart.ts | 30++++++++++++++++++++++++------
Mpackages/taler-wallet-core/src/wallet.ts | 7++++++-
Mpackages/taler-wallet-embedded/src/wallet-qjs.ts | 11+++++++++++
5 files changed, 80 insertions(+), 10 deletions(-)

diff --git a/packages/taler-util/src/qtart.ts b/packages/taler-util/src/qtart.ts @@ -16,20 +16,47 @@ export interface QjsHttpOptions { headers?: string[]; } +export interface ErrReceiver { + errno?: number; +} + +export interface QjsFile { + /** + * Close the file. Return 0 if OK or -errno in case of I/O error. + */ + close(): number; + /** + * Outputs the string with UTF-8 encoding. + */ + puts(str: string): void; +} + export interface QjsOsLib { - fetchHttp(url: string, options?: QjsHttpOptions): { - promise: Promise<QjsHttpResp>, - cancelFn: () => number, + fetchHttp( + url: string, + options?: QjsHttpOptions, + ): { + promise: Promise<QjsHttpResp>; + cancelFn: () => number; }; postMessageToHost(s: string): void; setMessageFromHostHandler(h: (s: string) => void): void; rename(oldPath: string, newPath: string): number; remove(path: string): number; + + readonly O_RDONLY: number; + readonly O_WRONLY: number; + readonly O_RDWR: number; + readonly O_APPEND: number; + readonly O_CREAT: number; + readonly O_EXCL: number; + readonly O_TRUNC: number; } export interface QjsStdLib { writeFile(filename: string, contents: string): void; loadFile(filename: string): string; + open(filename: string, mode: string, errorObj?: ErrReceiver): QjsFile | null; } // This is not the nodejs "os" module, but the qjs "os" module. diff --git a/packages/taler-util/src/types-taler-wallet.ts b/packages/taler-util/src/types-taler-wallet.ts @@ -4112,12 +4112,21 @@ export interface ExportDbToFileRequest { * where the extension depends on the used DB backend. */ stem: string; + + /** + * Force the format of the export. + * + * Currently only "json" is supported as a forced + * export format. + */ + forceFormat?: string; } export const codecForExportDbToFileRequest = (): Codec<ExportDbToFileRequest> => buildCodecForObject<ExportDbToFileRequest>() .property("directory", codecForString()) .property("stem", codecForString()) + .property("forceFormat", codecOptional(codecForString())) .build("ExportDbToFileRequest"); export interface ExportDbToFileResponse { diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts b/packages/taler-wallet-core/src/host-impl.qtart.ts @@ -49,6 +49,7 @@ import { getSqlite3FilenameFromStoragePath, makeTempfileId, } from "./host-common.js"; +import { exportDb } from "./index.js"; import { Wallet, WalletDatabaseImplementation } from "./wallet.js"; const logger = new Logger("host-impl.qtart.ts"); @@ -122,12 +123,29 @@ async function makeSqliteDb( primitiveStatements: numStmt, }; }, - async exportToFile(directory, stem) { - const path = `${directory}/${stem}.sqlite3`; - await myBackend.backupToFile(path); - return { - path, - }; + async exportToFile(directory, stem, forceFormat) { + if (forceFormat === "json") { + const path = `${directory}/${stem}.json`; + const dbDump = await exportDb(myBridgeIdbFactory); + const errObj = { errno: undefined }; + const file = qjsStd.open(path, "w+", errObj); + if (!file) { + throw Error(`could not create file (errno=${errObj.errno})`); + } + file.puts(JSON.stringify(dbDump)); + file.close(); + return { + path, + }; + } else if (forceFormat === "sqlite3" || forceFormat == null) { + const path = `${directory}/${stem}.sqlite3`; + await myBackend.backupToFile(path); + return { + path, + }; + } else { + throw Error(`forcing format ${forceFormat} not supported`); + } }, idbFactory: myBridgeIdbFactory, }; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts @@ -1670,6 +1670,7 @@ async function handleExportDbToFile( const res = await wex.ws.dbImplementation.exportToFile( req.directory, req.stem, + req.forceFormat, ); return { path: res.path, @@ -2557,7 +2558,11 @@ export type HttpFactory = (config: WalletRunConfig) => HttpRequestLibrary; export interface WalletDatabaseImplementation { idbFactory: BridgeIDBFactory; getStats: () => AccessStats; - exportToFile: (directory: string, stem: string) => Promise<{ path: string }>; + exportToFile: ( + directory: string, + stem: string, + forceFormat?: string, + ) => Promise<{ path: string }>; } /** diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts b/packages/taler-wallet-embedded/src/wallet-qjs.ts @@ -51,6 +51,10 @@ import { testWithLocal, } from "./wallet-qjs-tests.js"; +import * as talerUtil from "@gnu-taler/taler-util"; +import * as talerUtilHttp from "@gnu-taler/taler-util/http"; +import * as talerWalletCore from "@gnu-taler/taler-wallet-core"; + setGlobalLogLevelFromString("trace"); const logger = new Logger("taler-wallet-embedded/index.ts"); @@ -261,3 +265,10 @@ globalThis.testReduceAction = reduceAction; globalThis.testDiscoverPolicies = discoverPolicies; // @ts-ignore globalThis.testWithFdold = testWithFdold; + +// @ts-ignore +globalThis.talerModules = { + talerUtil, + talerWalletCore, + talerUtilHttp, +};