Skip to content

Commit 57803fa

Browse files
authored
Ability to update SyncOptions for an identity (#895)
Added the ability to get/update the sync options for a given identity. Additionally calling `registerIdentity` will fail if an identity is already registered instead of over-writing the options. Ability to `unregister` an identity, which will stop it from syncing further the next interval.
1 parent 43a5078 commit 57803fa

File tree

5 files changed

+1679
-1490
lines changed

5 files changed

+1679
-1490
lines changed

.changeset/lovely-eyes-tell.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@web5/agent": patch
3+
"@web5/identity-agent": patch
4+
"@web5/proxy-agent": patch
5+
"@web5/user-agent": patch
6+
---
7+
8+
Add additionaly Sync Identity Management capabilities

packages/agent/src/sync-api.ts

+12
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ export class AgentSyncApi implements SyncEngine {
4545
await this._syncEngine.registerIdentity(params);
4646
}
4747

48+
public async unregisterIdentity(did: string): Promise<void> {
49+
await this._syncEngine.unregisterIdentity(did);
50+
}
51+
52+
public async getIdentityOptions(did: string): Promise<SyncIdentityOptions | undefined> {
53+
return await this._syncEngine.getIdentityOptions(did);
54+
}
55+
56+
public async updateIdentityOptions(params: { did: string, options: SyncIdentityOptions }): Promise<void> {
57+
await this._syncEngine.updateIdentityOptions(params);
58+
}
59+
4860
public sync(direction?: 'push' | 'pull'): Promise<void> {
4961
return this._syncEngine.sync(direction);
5062
}

packages/agent/src/sync-engine-level.ts

+43
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,56 @@ export class SyncEngineLevel implements SyncEngine {
257257
// Get a reference to the `registeredIdentities` sublevel.
258258
const registeredIdentities = this._db.sublevel('registeredIdentities');
259259

260+
const existing = await this.getIdentityOptions(did);
261+
if (existing) {
262+
throw new Error(`SyncEngineLevel: Identity with DID ${did} is already registered.`);
263+
}
264+
260265
// if no options are provided, we default to no delegateDid and all protocols (empty array)
261266
options ??= { protocols: [] };
262267

263268
// Add (or overwrite, if present) the Identity's DID as a registered identity.
264269
await registeredIdentities.put(did, JSON.stringify(options));
265270
}
266271

272+
public async unregisterIdentity(did: string): Promise<void> {
273+
const registeredIdentities = this._db.sublevel('registeredIdentities');
274+
const existing = await this.getIdentityOptions(did);
275+
if (!existing) {
276+
throw new Error(`SyncEngineLevel: Identity with DID ${did} is not registered.`);
277+
}
278+
279+
await registeredIdentities.del(did);
280+
}
281+
282+
public async getIdentityOptions(did: string): Promise<SyncIdentityOptions | undefined> {
283+
const registeredIdentities = this._db.sublevel('registeredIdentities');
284+
try {
285+
const options = await registeredIdentities.get(did);
286+
if (options) {
287+
return JSON.parse(options) as SyncIdentityOptions;
288+
}
289+
} catch(error) {
290+
const e = error as { code: string };
291+
// `Level`` throws an error if the key is not present. Return `undefined` in this case.
292+
if (e.code === 'LEVEL_NOT_FOUND') {
293+
return;
294+
} else {
295+
throw new Error(`SyncEngineLevel: Error reading level: ${e.code}.`);
296+
}
297+
}
298+
}
299+
300+
public async updateIdentityOptions({ did, options }: { did: string, options: SyncIdentityOptions }): Promise<void> {
301+
const registeredIdentities = this._db.sublevel('registeredIdentities');
302+
const existingOptions = await this.getIdentityOptions(did);
303+
if (!existingOptions) {
304+
throw new Error(`SyncEngineLevel: Identity with DID ${did} is not registered.`);
305+
}
306+
307+
await registeredIdentities.put(did, JSON.stringify(options));
308+
}
309+
267310
public async sync(direction?: 'push' | 'pull'): Promise<void> {
268311
if (this._syncLock) {
269312
throw new Error('SyncEngineLevel: Sync operation is already in progress.');

packages/agent/src/types/sync.ts

+12
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ export interface SyncEngine {
2323
* The options can define specific protocols that should only be synced, or a delegate DID that should be used to sign the sync messages.
2424
*/
2525
registerIdentity(params: { did: string, options?: SyncIdentityOptions }): Promise<void>;
26+
/**
27+
* Unregister an identity from the SyncEngine, this will stop syncing messages for this identity.
28+
*/
29+
unregisterIdentity(did: string): Promise<void>;
30+
/**
31+
* Get the Sync Options for a specific identity.
32+
*/
33+
getIdentityOptions(did: string): Promise<SyncIdentityOptions | undefined>;
34+
/**
35+
* Update the Sync Options for a specific identity, replaces the existing options.
36+
*/
37+
updateIdentityOptions(params: { did: string, options: SyncIdentityOptions }): Promise<void>;
2638
/**
2739
* Preforms a one-shot sync operation. If no direction is provided, it will perform both push and pull.
2840
* @param direction which direction you'd like to perform the sync operation.

0 commit comments

Comments
 (0)