@web5/agent
Version:
109 lines (87 loc) • 4.22 kB
text/typescript
import { Convert } from '@web5/common';
import type { Web5PlatformAgent } from './types/agent.js';
import type { IdentityMetadata } from './types/identity.js';
import type { AgentDataStore, DataStoreDeleteParams, DataStoreGetParams, DataStoreListParams, DataStoreSetParams } from './store-data.js';
import { DwnInterface } from './types/dwn.js';
import { IdentityProtocolDefinition } from './store-data-protocols.js';
import { TENANT_SEPARATOR } from './utils-internal.js';
import { DwnDataStore, InMemoryDataStore } from './store-data.js';
export function isIdentityMetadata(obj: unknown): obj is IdentityMetadata {
// Validate that the given value is an object that has the necessary properties of IdentityMetadata.
return !(!obj || typeof obj !== 'object' || obj === null)
&& 'name' in obj;
}
export class DwnIdentityStore extends DwnDataStore<IdentityMetadata> implements AgentDataStore<IdentityMetadata> {
protected name = 'DwnIdentityStore';
protected _recordProtocolDefinition = IdentityProtocolDefinition;
/**
* Properties to use when writing and querying Identity records with the DWN store.
*/
protected _recordProperties = {
dataFormat : 'application/json',
protocol : this._recordProtocolDefinition.protocol,
protocolPath : 'identityMetadata',
schema : this._recordProtocolDefinition.types.identityMetadata.schema,
};
public async delete(params: DataStoreDeleteParams): Promise<boolean> {
return await super.delete(params);
}
public async get(params: DataStoreGetParams): Promise<IdentityMetadata | undefined> {
return await super.get(params);
}
public async set(params: DataStoreSetParams<IdentityMetadata>): Promise<void> {
return await super.set(params);
}
public async list(params: DataStoreListParams): Promise<IdentityMetadata[]> {
return await super.list(params);
}
protected async getAllRecords({ agent, tenantDid }: {
agent: Web5PlatformAgent;
tenantDid: string;
}): Promise<IdentityMetadata[]> {
// Clear the index since it will be rebuilt from the query results.
this._index.clear();
// Query the DWN for all stored IdentityMetadata objects.
const { reply: queryReply } = await agent.dwn.processRequest({
author : tenantDid,
target : tenantDid,
messageType : DwnInterface.RecordsQuery,
messageParams : { filter: { ...this._recordProperties } }
});
// Loop through all of the stored IdentityMetadata records and accumulate the objects.
let storedIdentities: IdentityMetadata[] = [];
for (const record of queryReply.entries ?? []) {
// All IdentityMetadata records are expected to be small enough such that the data is returned
// with the query results. If a record is returned without `encodedData` this is unexpected so
// throw an error.
if (!record.encodedData) {
throw new Error(`${this.name}: Expected 'encodedData' to be present in the DWN query result entry`);
}
const storedIdentity = Convert.base64Url(record.encodedData).toObject() as IdentityMetadata;
if (isIdentityMetadata(storedIdentity)) {
// Update the index with the matching record ID.
const indexKey = `${tenantDid}${TENANT_SEPARATOR}${storedIdentity.uri}`;
this._index.set(indexKey, record.recordId);
// Add the stored Identity to the cache.
this._cache.set(record.recordId, storedIdentity);
storedIdentities.push(storedIdentity);
}
}
return storedIdentities;
}
}
export class InMemoryIdentityStore extends InMemoryDataStore<IdentityMetadata> implements AgentDataStore<IdentityMetadata> {
protected name = 'InMemoryIdentityStore';
public async delete(params: DataStoreDeleteParams): Promise<boolean> {
return await super.delete(params);
}
public async get(params: DataStoreGetParams): Promise<IdentityMetadata | undefined> {
return await super.get(params);
}
public async list(params: DataStoreListParams): Promise<IdentityMetadata[]> {
return await super.list(params);
}
public async set(params: DataStoreSetParams<IdentityMetadata>): Promise<void> {
return await super.set(params);
}
}