git » sdk » commit 3c345fe

Implement get/storeOmemoId

author Eric Roberts
2026-08-26 18:14:46 UTC
committer Stephen Paul Weber
2026-08-26 18:16:17 UTC
parent e44e4ea0d87b04714eb3feee07c54b49ec7780ec

Implement get/storeOmemoId

I changed the interface for storeOmemoId to return a Promise. This is primarily
so that I don't have to use timers in my tests to wait for the right, I can
await the Promise.

I chose to return the ID as that seemed like the most logical choice. Maybe
Promise<Void> would be nice but this won't produce compilable C++.
Promise<Bool> could be done instead but it just always returns true. At least
the id is the value actually written to the db. Though at the time of writing
nothing here actually cares about the return value. Definitely open to
reconsidering or changing in the future.

Updated IDB.js to match.

For getOmemoId the signature in Persistence.hx says it's nullable but IDB
returns undefined. When I wrote the test in persistence-tests.ts I asserted it
would be null and this failed, so I fixed it in IDB to coerce the value to
null. While null and undefined can often be used in interchangeably, sometimes
people implement things to explicitly expect one or the other, so I think our
implementations should be consistent.

borogove/Persistence.hx +4 -1
borogove/persistence/Dummy.hx +3 -1
borogove/persistence/IDB.js +7 -3
borogove/persistence/Sqlite.hx +6 -3
test/TestSqlite.hx +30 -0
test/persistence-tests.ts +30 -0

diff --git a/borogove/Persistence.hx b/borogove/Persistence.hx
index 4b79c98..c1722c2 100644
--- a/borogove/Persistence.hx
+++ b/borogove/Persistence.hx
@@ -341,8 +341,11 @@ interface Persistence {
 
 	/**
 		Store the local OMEMO device ID for an account
+		@param accountId the account to store omemo id for
+		@param omemoId the OMEMO device ID
+		@returns Promise resolving to the stored device ID
 	**/
-	public function storeOmemoId(login:String, omemoId:Int):Void;
+	public function storeOmemoId(login:String, omemoId:Int):Promise<Int>;
 
 	/**
 		Store the local OMEMO identity key pair for an account
diff --git a/borogove/persistence/Dummy.hx b/borogove/persistence/Dummy.hx
index 2f94855..fe93725 100644
--- a/borogove/persistence/Dummy.hx
+++ b/borogove/persistence/Dummy.hx
@@ -189,7 +189,9 @@ class Dummy implements Persistence {
 	}
 
 	@HaxeCBridge.noemit
-	public function storeOmemoId(login:String, omemoId:Int):Void { }
+	public function storeOmemoId(login:String, omemoId:Int):Promise<Int> {
+		return Promise.resolve(omemoId);
+	}
 
 	@HaxeCBridge.noemit
 	public function storeOmemoIdentityKey(login:String, keypair:IdentityKeyPair):Void { }
diff --git a/borogove/persistence/IDB.js b/borogove/persistence/IDB.js
index 9bdedb4..2b686ca 100644
--- a/borogove/persistence/IDB.js
+++ b/borogove/persistence/IDB.js
@@ -1141,10 +1141,12 @@ tx.onerror = console.error;
 			return true;
 		},
 
-		storeOmemoId(account, omemoId) {
+		async storeOmemoId(account, omemoId) {
 			const tx = db.transaction(["keyvaluepairs"], "readwrite");
 			const store = tx.objectStore("keyvaluepairs");
-			store.put(omemoId, "omemo:id:" + account).onerror = console.error;
+			await promisifyRequest(store.put(omemoId, "omemo:id:" + account));
+
+			return omemoId;
 		},
 
 		storeOmemoIdentityKey(account, keypair) {
@@ -1283,7 +1285,9 @@ tx.onerror = console.error;
 		getOmemoId(account) {
 			const tx = db.transaction(["keyvaluepairs"], "readonly");
 			const store = tx.objectStore("keyvaluepairs");
-			return promisifyRequest(store.get("omemo:id:"+account));
+			return promisifyRequest(store.get("omemo:id:"+account)).then(
+				(result) => result ?? null,
+			);
 		},
 
 		getOmemoIdentityKey(account) {
diff --git a/borogove/persistence/Sqlite.hx b/borogove/persistence/Sqlite.hx
index 017465c..164953d 100644
--- a/borogove/persistence/Sqlite.hx
+++ b/borogove/persistence/Sqlite.hx
@@ -1373,14 +1373,17 @@ class Sqlite implements Persistence implements KeyValueStore {
 
 #if !NO_OMEMO
 	// OMEMO
-	// TODO
 	@HaxeCBridge.noemit
 	public function getOmemoId(login:String): Promise<Null<Int>> {
-		return Promise.resolve(null);
+		return get("omemo:id:" + login).then(omemoId ->
+			omemoId == null ? null : Std.parseInt(omemoId)
+		);
 	}
 
 	@HaxeCBridge.noemit
-	public function storeOmemoId(login:String, omemoId:Int):Void { }
+	public function storeOmemoId(login:String, omemoId:Int):Promise<Int> {
+		return set("omemo:id:" + login, Std.string(omemoId)).then(_ -> omemoId);
+	}
 
 	@HaxeCBridge.noemit
 	public function storeOmemoIdentityKey(login:String, keypair:IdentityKeyPair):Void { }
diff --git a/test/TestSqlite.hx b/test/TestSqlite.hx
index cc59750..28f5e55 100644
--- a/test/TestSqlite.hx
+++ b/test/TestSqlite.hx
@@ -1301,4 +1301,34 @@ class TestSqlite extends utest.Test {
 			async.done();
 		});
 	}
+
+	public function testGetOmemoIdNotFound(async: Async) {
+		persistence
+			.getOmemoId('notfound@example.com')
+			.then(result -> {
+				Assert.equals(null, result);
+				async.done();
+			})
+			.catchError(e -> {
+				Assert.fail(Std.string(e));
+				async.done();
+			});
+	}
+
+	public function testGetOmemoIdExisting(async: Async) {
+		final login = "existing@example.com";
+		final omemoId = 12345;
+
+		persistence
+			.storeOmemoId(login, omemoId)
+			.then(_ -> persistence.getOmemoId(login))
+			.then(result -> {
+				Assert.equals(omemoId, result);
+				async.done();
+			})
+			.catchError(e -> {
+				Assert.fail(Std.string(e));
+				async.done();
+			});
+	}
 }
diff --git a/test/persistence-tests.ts b/test/persistence-tests.ts
index 0e00dac..7185789 100644
--- a/test/persistence-tests.ts
+++ b/test/persistence-tests.ts
@@ -1463,4 +1463,34 @@ export function sharedPersistenceTests(test: PersistenceTest) {
 		expect(result.requests1).toEqual(["Bob", "Charlie"]);
 		expect(result.requests2).toEqual(["Charlie"]);
 	});
+
+	test("getOmemoId returns no ID when none is stored", async ({
+		page,
+		persistence,
+	}) => {
+		const result = await page.evaluate(
+			async (persistence) =>
+				persistence.getOmemoId("omemo-not-found@example.com"),
+			persistence,
+		);
+
+		expect(result).toBeNull();
+	});
+
+	test("storeOmemoId stores the ID", async ({
+		page,
+		persistence,
+	}) => {
+		const account = "omemo-existing@example.com";
+		const omemoId = 12345;
+		const result = await page.evaluate(
+			async ({ persistence, account, omemoId }) => {
+				await persistence.storeOmemoId(account, omemoId);
+				return persistence.getOmemoId(account);
+			},
+			{ persistence, account, omemoId },
+		);
+
+		expect(result).toBe(omemoId);
+	});
 }