@credo-ts/core
Version:
<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1
1 lines • 11.2 kB
Source Map (JSON)
{"version":3,"file":"Repository.mjs","names":[],"sources":["../../src/storage/Repository.ts"],"sourcesContent":["import type { AgentContext } from '../agent'\nimport type { EventEmitter } from '../agent/EventEmitter'\nimport { RecordDuplicateError, RecordNotFoundError } from '../error'\nimport { CachedStorageService } from '../modules/cache/CachedStorageService'\nimport { CacheModuleConfig } from '../modules/cache/CacheModuleConfig'\nimport { JsonTransformer } from '../utils'\nimport type { BaseRecord } from './BaseRecord'\nimport type { RecordDeletedEvent, RecordSavedEvent, RecordUpdatedEvent } from './RepositoryEvents'\nimport { RepositoryEventTypes } from './RepositoryEvents'\nimport type { BaseRecordConstructor, Query, QueryOptions, StorageService } from './StorageService'\n\n// biome-ignore lint/suspicious/noExplicitAny: no explanation\nexport class Repository<T extends BaseRecord<any, any, any>> {\n private storageService: StorageService<T>\n private recordClass: BaseRecordConstructor<T>\n private eventEmitter: EventEmitter\n\n public constructor(\n recordClass: BaseRecordConstructor<T>,\n storageService: StorageService<T>,\n eventEmitter: EventEmitter\n ) {\n this.recordClass = recordClass\n this.storageService = storageService\n this.eventEmitter = eventEmitter\n }\n\n private getStorageService(agentContext: AgentContext): StorageService<T> {\n try {\n if (agentContext.dependencyManager.isRegistered(CachedStorageService, true)) {\n return agentContext.resolve(CachedStorageService<T>)\n }\n\n return this.storageService\n } catch {\n return this.storageService\n }\n }\n\n public supportsLocking(agentContext: AgentContext): boolean {\n return this.getStorageService(agentContext).supportsLocking?.(agentContext) ?? false\n }\n\n /** @inheritDoc {StorageService#save} */\n public async save(agentContext: AgentContext, record: T): Promise<void> {\n await this.getStorageService(agentContext).save(agentContext, record)\n\n this.eventEmitter.emit<RecordSavedEvent<T>>(agentContext, {\n type: RepositoryEventTypes.RecordSaved,\n payload: {\n // Record in event should be static\n record: record.clone(),\n },\n })\n }\n\n /** @inheritDoc {StorageService#update} */\n public async update(agentContext: AgentContext, record: T): Promise<void> {\n await this.getStorageService(agentContext).update(agentContext, record)\n\n this.eventEmitter.emit<RecordUpdatedEvent<T>>(agentContext, {\n type: RepositoryEventTypes.RecordUpdated,\n payload: {\n // Record in event should be static\n record: record.clone(),\n },\n })\n }\n\n /** @inheritDoc {StorageService#updateByIdWithLock} */\n public async updateByIdWithLock(\n agentContext: AgentContext,\n id: string,\n updateCallback: (record: T) => Promise<T>\n ): Promise<T> {\n const storageService = this.getStorageService(agentContext)\n\n // NOTE: we might want to not do this, to allow the caller to handle it, (e.g. they might already\n // have the record and this would just re-fetch it again). Then we could just return null?\n // If a backend does not implement this method, we fall back to two separate calls to\n // getById and update\n if (!storageService.updateByIdWithLock) {\n const record = await this.getById(agentContext, id)\n const updatedRecord = await updateCallback(record)\n await this.update(agentContext, record)\n return updatedRecord\n }\n\n const updatedRecord = await storageService.updateByIdWithLock(agentContext, this.recordClass, id, updateCallback)\n this.eventEmitter.emit<RecordUpdatedEvent<T>>(agentContext, {\n type: RepositoryEventTypes.RecordUpdated,\n payload: {\n // Record in event should be static\n record: updatedRecord.clone(),\n },\n })\n\n return updatedRecord\n }\n\n /** @inheritDoc {StorageService#delete} */\n public async delete(agentContext: AgentContext, record: T): Promise<void> {\n await this.getStorageService(agentContext).delete(agentContext, record)\n\n this.eventEmitter.emit<RecordDeletedEvent<T>>(agentContext, {\n type: RepositoryEventTypes.RecordDeleted,\n payload: {\n // Record in event should be static\n record: record.clone(),\n },\n })\n }\n\n /**\n * Delete record by id. Throws {RecordNotFoundError} if no record is found\n * @param id the id of the record to delete\n * @returns\n */\n public async deleteById(agentContext: AgentContext, id: string): Promise<void> {\n await this.getStorageService(agentContext).deleteById(agentContext, this.recordClass, id)\n\n this.eventEmitter.emit<RecordDeletedEvent<T>>(agentContext, {\n type: RepositoryEventTypes.RecordDeleted,\n payload: {\n record: { id, type: this.recordClass.type },\n },\n })\n }\n\n /** @inheritDoc {StorageService#getById} */\n public async getById(agentContext: AgentContext, id: string): Promise<T> {\n return this.getStorageService(agentContext).getById(agentContext, this.recordClass, id)\n }\n\n /**\n * Find record by id. Returns null if no record is found\n * @param id the id of the record to retrieve\n * @returns\n */\n public async findById(agentContext: AgentContext, id: string): Promise<T | null> {\n try {\n return await this.getStorageService(agentContext).getById(agentContext, this.recordClass, id)\n } catch (error) {\n if (error instanceof RecordNotFoundError) return null\n\n throw error\n }\n }\n\n /** @inheritDoc {StorageService#getAll} */\n public async getAll(agentContext: AgentContext): Promise<T[]> {\n return this.getStorageService(agentContext).getAll(agentContext, this.recordClass)\n }\n\n /** @inheritDoc {StorageService#findByQuery} */\n public async findByQuery(agentContext: AgentContext, query: Query<T>, queryOptions?: QueryOptions): Promise<T[]> {\n return this.getStorageService(agentContext).findByQuery(agentContext, this.recordClass, query, queryOptions)\n }\n\n /**\n * Find a single record by query. Returns null if not found.\n * @param query the query\n * @param cacheKey optional cache key to use for caching. By default query results are not cached, but if a cache key is provided\n * as well as the record allows caching and the agent has a cached storage service enabled it will use the cache.\n * @returns the record, or null if not found\n * @throws {RecordDuplicateError} if multiple records are found for the given query\n */\n public async findSingleByQuery(\n agentContext: AgentContext,\n query: Query<T>,\n { cacheKey }: { cacheKey?: string } = {}\n ): Promise<T | null> {\n const cache = agentContext.resolve(CacheModuleConfig)\n const useCacheStorage = cache.useCachedStorageService ?? false\n\n if (useCacheStorage && cacheKey) {\n const recordId = (await cache?.cache.get<string>(agentContext, cacheKey)) ?? null\n if (recordId !== null) {\n const recordJson = await cache?.cache.get<T>(agentContext, recordId)\n if (recordJson) return JsonTransformer.fromJSON(recordJson, this.recordClass)\n }\n }\n\n const records = await this.findByQuery(agentContext, query)\n if (records.length > 1) {\n throw new RecordDuplicateError(`Multiple records found for given query '${JSON.stringify(query)}'`, {\n recordType: this.recordClass.type,\n })\n }\n\n if (records.length < 1) {\n return null\n }\n\n if (useCacheStorage && cacheKey) {\n await cache?.cache.set(agentContext, cacheKey, records[0].id)\n await cache?.cache.set(agentContext, records[0].id, records[0].toJSON())\n }\n\n return records[0]\n }\n\n /**\n * Find a single record by query. Throws if not found\n * @param query the query\n * @returns the record\n * @throws {RecordDuplicateError} if multiple records are found for the given query\n * @throws {RecordNotFoundError} if no record is found for the given query\n */\n public async getSingleByQuery(agentContext: AgentContext, query: Query<T>): Promise<T> {\n const record = await this.findSingleByQuery(agentContext, query)\n\n if (!record) {\n throw new RecordNotFoundError(`No record found for given query '${JSON.stringify(query)}'`, {\n recordType: this.recordClass.type,\n })\n }\n\n return record\n }\n}\n"],"mappings":";;;;;;;;;;;;AAYA,IAAa,aAAb,MAA6D;CAK3D,AAAO,YACL,aACA,gBACA,cACA;AACA,OAAK,cAAc;AACnB,OAAK,iBAAiB;AACtB,OAAK,eAAe;;CAGtB,AAAQ,kBAAkB,cAA+C;AACvE,MAAI;AACF,OAAI,aAAa,kBAAkB,aAAa,sBAAsB,KAAK,CACzE,QAAO,aAAa,QAAQ,qBAAwB;AAGtD,UAAO,KAAK;UACN;AACN,UAAO,KAAK;;;CAIhB,AAAO,gBAAgB,cAAqC;AAC1D,SAAO,KAAK,kBAAkB,aAAa,CAAC,kBAAkB,aAAa,IAAI;;;CAIjF,MAAa,KAAK,cAA4B,QAA0B;AACtE,QAAM,KAAK,kBAAkB,aAAa,CAAC,KAAK,cAAc,OAAO;AAErE,OAAK,aAAa,KAA0B,cAAc;GACxD,MAAM,qBAAqB;GAC3B,SAAS,EAEP,QAAQ,OAAO,OAAO,EACvB;GACF,CAAC;;;CAIJ,MAAa,OAAO,cAA4B,QAA0B;AACxE,QAAM,KAAK,kBAAkB,aAAa,CAAC,OAAO,cAAc,OAAO;AAEvE,OAAK,aAAa,KAA4B,cAAc;GAC1D,MAAM,qBAAqB;GAC3B,SAAS,EAEP,QAAQ,OAAO,OAAO,EACvB;GACF,CAAC;;;CAIJ,MAAa,mBACX,cACA,IACA,gBACY;EACZ,MAAM,iBAAiB,KAAK,kBAAkB,aAAa;AAM3D,MAAI,CAAC,eAAe,oBAAoB;GACtC,MAAM,SAAS,MAAM,KAAK,QAAQ,cAAc,GAAG;GACnD,MAAM,gBAAgB,MAAM,eAAe,OAAO;AAClD,SAAM,KAAK,OAAO,cAAc,OAAO;AACvC,UAAO;;EAGT,MAAM,gBAAgB,MAAM,eAAe,mBAAmB,cAAc,KAAK,aAAa,IAAI,eAAe;AACjH,OAAK,aAAa,KAA4B,cAAc;GAC1D,MAAM,qBAAqB;GAC3B,SAAS,EAEP,QAAQ,cAAc,OAAO,EAC9B;GACF,CAAC;AAEF,SAAO;;;CAIT,MAAa,OAAO,cAA4B,QAA0B;AACxE,QAAM,KAAK,kBAAkB,aAAa,CAAC,OAAO,cAAc,OAAO;AAEvE,OAAK,aAAa,KAA4B,cAAc;GAC1D,MAAM,qBAAqB;GAC3B,SAAS,EAEP,QAAQ,OAAO,OAAO,EACvB;GACF,CAAC;;;;;;;CAQJ,MAAa,WAAW,cAA4B,IAA2B;AAC7E,QAAM,KAAK,kBAAkB,aAAa,CAAC,WAAW,cAAc,KAAK,aAAa,GAAG;AAEzF,OAAK,aAAa,KAA4B,cAAc;GAC1D,MAAM,qBAAqB;GAC3B,SAAS,EACP,QAAQ;IAAE;IAAI,MAAM,KAAK,YAAY;IAAM,EAC5C;GACF,CAAC;;;CAIJ,MAAa,QAAQ,cAA4B,IAAwB;AACvE,SAAO,KAAK,kBAAkB,aAAa,CAAC,QAAQ,cAAc,KAAK,aAAa,GAAG;;;;;;;CAQzF,MAAa,SAAS,cAA4B,IAA+B;AAC/E,MAAI;AACF,UAAO,MAAM,KAAK,kBAAkB,aAAa,CAAC,QAAQ,cAAc,KAAK,aAAa,GAAG;WACtF,OAAO;AACd,OAAI,iBAAiB,oBAAqB,QAAO;AAEjD,SAAM;;;;CAKV,MAAa,OAAO,cAA0C;AAC5D,SAAO,KAAK,kBAAkB,aAAa,CAAC,OAAO,cAAc,KAAK,YAAY;;;CAIpF,MAAa,YAAY,cAA4B,OAAiB,cAA2C;AAC/G,SAAO,KAAK,kBAAkB,aAAa,CAAC,YAAY,cAAc,KAAK,aAAa,OAAO,aAAa;;;;;;;;;;CAW9G,MAAa,kBACX,cACA,OACA,EAAE,aAAoC,EAAE,EACrB;EACnB,MAAM,QAAQ,aAAa,QAAQ,kBAAkB;EACrD,MAAM,kBAAkB,MAAM,2BAA2B;AAEzD,MAAI,mBAAmB,UAAU;GAC/B,MAAM,WAAY,MAAM,OAAO,MAAM,IAAY,cAAc,SAAS,IAAK;AAC7E,OAAI,aAAa,MAAM;IACrB,MAAM,aAAa,MAAM,OAAO,MAAM,IAAO,cAAc,SAAS;AACpE,QAAI,WAAY,QAAO,gBAAgB,SAAS,YAAY,KAAK,YAAY;;;EAIjF,MAAM,UAAU,MAAM,KAAK,YAAY,cAAc,MAAM;AAC3D,MAAI,QAAQ,SAAS,EACnB,OAAM,IAAI,qBAAqB,2CAA2C,KAAK,UAAU,MAAM,CAAC,IAAI,EAClG,YAAY,KAAK,YAAY,MAC9B,CAAC;AAGJ,MAAI,QAAQ,SAAS,EACnB,QAAO;AAGT,MAAI,mBAAmB,UAAU;AAC/B,SAAM,OAAO,MAAM,IAAI,cAAc,UAAU,QAAQ,GAAG,GAAG;AAC7D,SAAM,OAAO,MAAM,IAAI,cAAc,QAAQ,GAAG,IAAI,QAAQ,GAAG,QAAQ,CAAC;;AAG1E,SAAO,QAAQ;;;;;;;;;CAUjB,MAAa,iBAAiB,cAA4B,OAA6B;EACrF,MAAM,SAAS,MAAM,KAAK,kBAAkB,cAAc,MAAM;AAEhE,MAAI,CAAC,OACH,OAAM,IAAI,oBAAoB,oCAAoC,KAAK,UAAU,MAAM,CAAC,IAAI,EAC1F,YAAY,KAAK,YAAY,MAC9B,CAAC;AAGJ,SAAO"}