@credo-ts/askar 0.6.1 → 0.6.2-alpha-20251211115250
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -82,7 +82,7 @@ let AskarStoreManager = class AskarStoreManager$1 {
|
|
|
82
82
|
const storeConfig = await this.getStoreConfig(agentContext);
|
|
83
83
|
const askarStoreConfig = this.getAskarStoreConfig(storeConfig);
|
|
84
84
|
agentContext.config.logger.debug(`Provisioning store '${storeConfig.id}`);
|
|
85
|
-
if (this.getStore(agentContext)) throw new
|
|
85
|
+
if (this.getStore(agentContext)) throw new AskarStoreDuplicateError("Store already provisioned");
|
|
86
86
|
try {
|
|
87
87
|
if (askarStoreConfig.path) {
|
|
88
88
|
if (await this.fileSystem.exists(askarStoreConfig.path)) throw new AskarStoreDuplicateError(`Store '${storeConfig.id}' at path ${askarStoreConfig.path} already exists.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AskarStoreManager.mjs","names":["AskarStoreManager","fileSystem: FileSystem","config: AskarModuleConfig","errorMessage","sourceWalletStore: Store | undefined","session: Session | undefined","AskarError","injectable"],"sources":["../src/AskarStoreManager.ts"],"sourcesContent":["import { AgentContext, type FileSystem, InjectionSymbols, JsonTransformer, StorageVersionRecord } from '@credo-ts/core'\nimport { KdfMethod, Session, Store, StoreKeyMethod } from '@openwallet-foundation/askar-shared'\nimport { inject, injectable } from 'tsyringe'\n\nimport type { AskarStoreExportOptions, AskarStoreImportOptions, AskarStoreRotateKeyOptions } from './AskarApiOptions'\nimport {\n AskarModuleConfig,\n type AskarModuleConfigStoreOptions,\n AskarMultiWalletDatabaseScheme,\n} from './AskarModuleConfig'\nimport {\n AskarError,\n AskarStoreDuplicateError,\n AskarStoreError,\n AskarStoreExportPathExistsError,\n AskarStoreImportPathExistsError,\n AskarStoreInvalidKeyError,\n AskarStoreNotFoundError,\n} from './error'\nimport { transformFromRecordTagValues } from './storage/utils'\nimport { getAskarStoreConfigForContextCorrelationId } from './tenants'\nimport {\n AskarErrorCode,\n isAskarError,\n isSqliteInMemoryUri,\n keyDerivationMethodFromStoreConfig,\n uriFromStoreConfig,\n} from './utils'\n\n@injectable()\nexport class AskarStoreManager {\n public constructor(\n @inject(InjectionSymbols.FileSystem) private fileSystem: FileSystem,\n private config: AskarModuleConfig\n ) {}\n\n public isStoreOpen(agentContext: AgentContext) {\n return !!this.getStore(agentContext)?.handle\n }\n\n private async getStoreConfig(agentContext: AgentContext): Promise<AskarModuleConfigStoreOptions> {\n if (\n agentContext.isRootAgentContext ||\n this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.ProfilePerWallet\n ) {\n return this.config.store\n }\n\n // Otherwise we need to get the wallet key from the tenant record\n const storeConfig = await getAskarStoreConfigForContextCorrelationId(agentContext)\n\n return {\n id: agentContext.contextCorrelationId,\n key: storeConfig.key,\n // we always use raw at the moment\n keyDerivationMethod: 'raw',\n database: this.config.store.database,\n }\n }\n\n /**\n * When we create storage for a context we need to store the version record\n */\n private async setCurrentFrameworkStorageVersionOnSession(session: Session) {\n const record = new StorageVersionRecord({\n storageVersion: StorageVersionRecord.frameworkStorageVersion,\n })\n\n await session.insert({\n value: JsonTransformer.serialize(record),\n name: record.id,\n category: record.type,\n tags: transformFromRecordTagValues(record.getTags()),\n })\n }\n\n /**\n * Deletes all storage related to a context. If on store level, meaning root agent\n * or when using database per wallet storage, the whole store will be deleted.\n * Otherwise only a profile within the store will be removed.\n */\n public async deleteContext(agentContext: AgentContext) {\n const { profile, store } = await this.getInitializedStoreWithProfile(agentContext)\n // Currently it will delete the whole store. We can delete only the root profile, BUT:\n // - all tenant records will be deleted\n // - the root agent is deleted, this is not a flow we support (there's no default profile anymore)\n if (this.isStoreLevel(agentContext)) {\n await this.deleteStore(agentContext)\n } else {\n if (!profile)\n throw new AskarStoreError(\n 'Unable to delete asksar data for context. No profile found and not on store level (so not deleting the whole store)'\n )\n\n await store.removeProfile(profile)\n }\n }\n\n /**\n * Closes an active context. If on store level, meaning root agent\n * or when using database per wallet storage, the whole store will be closed.\n * Otherwise nothing will be done as profiles are opened on a store from higher level.\n */\n public async closeContext(agentContext: AgentContext) {\n // TODO: we should maybe set some value on the agentContext indicating it is disposed so no new sessions can be opened\n // If not on store level we don't have to do anything.\n if (!this.isStoreLevel(agentContext)) return\n\n await this.closeStore(agentContext)\n }\n\n /**\n * @throws {AskarStoreDuplicateError} if the wallet already exists\n * @throws {AskarStoreError} if another error occurs\n */\n public async provisionStore(agentContext: AgentContext): Promise<Store> {\n this.ensureStoreLevel(agentContext)\n\n const storeConfig = await this.getStoreConfig(agentContext)\n const askarStoreConfig = this.getAskarStoreConfig(storeConfig)\n\n agentContext.config.logger.debug(`Provisioning store '${storeConfig.id}`)\n\n if (this.getStore(agentContext)) {\n throw new AskarStoreError('Store already provisioned')\n }\n\n try {\n if (askarStoreConfig.path) {\n if (await this.fileSystem.exists(askarStoreConfig.path)) {\n throw new AskarStoreDuplicateError(\n `Store '${storeConfig.id}' at path ${askarStoreConfig.path} already exists.`\n )\n }\n\n // Make sure path exists before creating the wallet\n await this.fileSystem.createDirectory(askarStoreConfig.path)\n }\n\n const store = await Store.provision({\n recreate: false,\n uri: askarStoreConfig.uri,\n profile: askarStoreConfig.profile,\n keyMethod: askarStoreConfig.keyMethod,\n passKey: askarStoreConfig.passKey,\n })\n agentContext.dependencyManager.registerInstance(Store, store)\n\n // For new stores we need to set the framework storage version\n await this.withSession(agentContext, (session) => this.setCurrentFrameworkStorageVersionOnSession(session))\n\n return store\n } catch (error) {\n if (error instanceof AskarStoreDuplicateError) throw error\n\n // FIXME: Askar should throw a Duplicate error code, but is currently returning Encryption\n // And if we provide the very same wallet key, it will open it without any error\n if (\n isAskarError(error) &&\n (error.code === AskarErrorCode.Encryption || error.code === AskarErrorCode.Duplicate)\n ) {\n const errorMessage = `Store '${storeConfig.id}' already exists`\n agentContext.config.logger.debug(errorMessage)\n\n throw new AskarStoreDuplicateError(errorMessage, {\n cause: error,\n })\n }\n\n const errorMessage = `Error creating store '${storeConfig.id}'`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * @throws {AskarStoreNotFoundError} if the wallet does not exist\n * @throws {AskarStoreError} if another error occurs\n */\n public async openStore(agentContext: AgentContext): Promise<Store> {\n this.ensureStoreLevel(agentContext)\n\n if (this.getStore(agentContext)) {\n throw new AskarStoreError('Store already opened. Close the currently opened store before re-opening the store')\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n const askarStoreConfig = this.getAskarStoreConfig(storeConfig)\n\n try {\n const store = await Store.open({\n uri: askarStoreConfig.uri,\n keyMethod: askarStoreConfig.keyMethod,\n passKey: askarStoreConfig.passKey,\n })\n agentContext.dependencyManager.registerInstance(Store, store)\n return store\n } catch (error) {\n if (\n isAskarError(error) &&\n (error.code === AskarErrorCode.NotFound ||\n (error.code === AskarErrorCode.Backend && isSqliteInMemoryUri(askarStoreConfig.uri)))\n ) {\n const errorMessage = `Store '${storeConfig.id}' not found`\n agentContext.config.logger.debug(errorMessage)\n\n throw new AskarStoreNotFoundError(errorMessage, {\n cause: error,\n })\n }\n\n if (isAskarError(error) && error.code === AskarErrorCode.Encryption) {\n const errorMessage = `Incorrect key for store '${storeConfig.id}'`\n agentContext.config.logger.debug(errorMessage)\n throw new AskarStoreInvalidKeyError(errorMessage, {\n cause: error,\n })\n }\n throw new AskarStoreError(`Error opening store ${storeConfig.id}: ${error.message}`, { cause: error })\n }\n }\n\n /**\n * Rotate the key of the current askar store.\n *\n * NOTE: multiple agent contexts (tenants) can use the same store. This method rotates the key for the whole store,\n * it is advised to only run this method on the root tenant agent when using profile per wallet database strategy.\n * After running this method you should change the store configuration in the Askar module.\n *\n * @throws {AskarStoreNotFoundError} if the wallet does not exist\n * @throws {AskarStoreError} if another error occurs\n */\n public async rotateStoreKey(agentContext: AgentContext, options: AskarStoreRotateKeyOptions): Promise<void> {\n this.ensureStoreLevel(agentContext)\n\n const store = this.getStore(agentContext)\n if (!store) {\n throw new AskarStoreError('Store needs to be open to rotate the wallet key')\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n\n try {\n await store.rekey({\n passKey: options.newKey,\n keyMethod: keyDerivationMethodFromStoreConfig(\n options.newKeyDerivationMethod ?? storeConfig.keyDerivationMethod\n ),\n })\n } catch (error) {\n const errorMessage = `Error rotating key for store '${storeConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Exports the current askar store.\n *\n * NOTE: a store can contain profiles for multiple tenants. When you export a store\n * all profiles will be exported with it.\n */\n public async exportStore(agentContext: AgentContext, options: AskarStoreExportOptions) {\n this.ensureStoreLevel(agentContext)\n\n const store = this.getStore(agentContext)\n if (!store) {\n throw new AskarStoreError('Unable to export store. No store available on agent context')\n }\n\n const currentStoreConfig = await this.getStoreConfig(agentContext)\n try {\n const newAskarStoreConfig = this.getAskarStoreConfig(options.exportToStore)\n\n // If path based store, ensure path does not exist yet, and create new store path\n if (newAskarStoreConfig.path) {\n // Export path already exists\n if (await this.fileSystem.exists(newAskarStoreConfig.path)) {\n throw new AskarStoreExportPathExistsError(\n `Unable to create export, wallet export at path '${newAskarStoreConfig.path}' already exists`\n )\n }\n\n // Make sure destination path exists\n await this.fileSystem.createDirectory(newAskarStoreConfig.path)\n }\n\n await store.copyTo({\n recreate: false,\n uri: newAskarStoreConfig.uri,\n keyMethod: newAskarStoreConfig.keyMethod,\n passKey: newAskarStoreConfig.passKey,\n })\n } catch (error) {\n const errorMessage = `Error exporting store '${currentStoreConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n if (error instanceof AskarStoreExportPathExistsError) throw error\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Imports from an external store config into the current askar store config.\n */\n public async importStore(agentContext: AgentContext, options: AskarStoreImportOptions) {\n this.ensureStoreLevel(agentContext)\n\n if (this.getStore(agentContext)) {\n throw new AskarStoreError('To import a store the current store needs to be closed first')\n }\n\n const destinationStoreConfig = await this.getStoreConfig(agentContext)\n\n const sourceAskarStoreConfig = this.getAskarStoreConfig(options.importFromStore)\n const destinationAskarStoreConfig = this.getAskarStoreConfig(destinationStoreConfig)\n\n let sourceWalletStore: Store | undefined\n try {\n if (destinationAskarStoreConfig.path) {\n // Import path already exists\n if (await this.fileSystem.exists(destinationAskarStoreConfig.path)) {\n throw new AskarStoreImportPathExistsError(\n `Unable to import store. Path '${destinationAskarStoreConfig.path}' already exists`\n )\n }\n\n await this.fileSystem.createDirectory(destinationAskarStoreConfig.path)\n }\n\n // Open imported wallet and copy to destination\n sourceWalletStore = await Store.open({\n uri: sourceAskarStoreConfig.uri,\n keyMethod: sourceAskarStoreConfig.keyMethod,\n passKey: sourceAskarStoreConfig.passKey,\n })\n\n await sourceWalletStore.copyTo({\n recreate: false,\n uri: destinationAskarStoreConfig.uri,\n keyMethod: destinationAskarStoreConfig.keyMethod,\n passKey: destinationAskarStoreConfig.passKey,\n })\n\n await sourceWalletStore.close()\n } catch (error) {\n await sourceWalletStore?.close()\n const errorMessage = `Error importing store '${options.importFromStore.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n if (error instanceof AskarStoreImportPathExistsError) throw error\n\n // Cleanup any wallet file we could have created\n if (destinationAskarStoreConfig.path && (await this.fileSystem.exists(destinationAskarStoreConfig.path))) {\n await this.fileSystem.delete(destinationAskarStoreConfig.path)\n }\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Delete the current askar store.\n *\n * NOTE: multiple agent contexts (tenants) can use the same store. This method deletes the whole store,\n * and if you're using multi-tenancy with profile per wallet it is advised to only run this method on the root tenant agent.\n *\n * @throws {AskarStoreNotFoundError} if the wallet does not exist\n * @throws {AskarStoreError} if another error occurs\n */\n public async deleteStore(agentContext: AgentContext): Promise<void> {\n this.ensureStoreLevel(agentContext)\n\n if (this.getStore(agentContext)) {\n await this.closeStore(agentContext)\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n const askarStoreConfig = this.getAskarStoreConfig(storeConfig)\n\n agentContext.config.logger.info(`Deleting store '${storeConfig.id}'`)\n try {\n await Store.remove(askarStoreConfig.uri)\n // Clear the store instance\n agentContext.dependencyManager.registerInstance(Store, undefined)\n } catch (error) {\n const errorMessage = `Error deleting store '${storeConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Close the current askar store\n */\n public async closeStore(agentContext: AgentContext) {\n this.ensureStoreLevel(agentContext)\n\n const store = this.getStore(agentContext)\n if (!store) {\n throw new AskarStoreError('There is no open store.')\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n\n try {\n agentContext.config.logger.debug(`Closing store '${storeConfig.id}'`)\n await store.close()\n // Unregister the store from the context\n agentContext.dependencyManager.registerInstance(Store, undefined)\n } catch (error) {\n const errorMessage = `Error closing store '${storeConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n private getAskarStoreConfig(storeConfig: AskarModuleConfigStoreOptions) {\n const { uri, path } = uriFromStoreConfig(storeConfig, this.fileSystem.dataPath)\n\n return {\n uri,\n path,\n profile: storeConfig.id,\n keyMethod: new StoreKeyMethod(\n (storeConfig.keyDerivationMethod ?? KdfMethod.Argon2IMod) satisfies `${KdfMethod}` | KdfMethod as KdfMethod\n ),\n passKey: storeConfig.key,\n }\n }\n\n /**\n * Run callback with a transaction. If the callback resolves the transaction\n * will be committed if the transaction is not closed yet. If the callback rejects\n * the transaction will be rolled back if the transaction is not closed yet.\n *\n * TODO: update to new `using` syntax so we don't have to use a callback\n */\n public async withTransaction<Return>(\n agentContext: AgentContext,\n callback: (session: Session) => Return\n ): Promise<Awaited<Return>> {\n return this._withSession(agentContext, callback, true)\n }\n\n /**\n * Run callback with the session provided, the session will\n * be closed once the callback resolves or rejects if it is not closed yet.\n *\n * TODO: update to new `using` syntax so we don't have to use a callback\n */\n public async withSession<Return>(\n agentContext: AgentContext,\n callback: (session: Session) => Return\n ): Promise<Awaited<Return>> {\n return this._withSession(agentContext, callback, false)\n }\n\n private getStore(agentContext: AgentContext, { recursive = false }: { recursive?: boolean } = {}) {\n const isRegistered = agentContext.dependencyManager.isRegistered(Store, recursive)\n if (!isRegistered) return null\n\n // We set the store value to undefined in the dependency manager\n // when closing it, but TSyringe still marks is as registered, but\n // will throw an error when resolved. Since there is no unregister method\n // we wrap it with a try-catch\n try {\n return agentContext.dependencyManager.resolve(Store)\n } catch {\n return null\n }\n }\n\n private async _withSession<Return>(\n agentContext: AgentContext,\n callback: (session: Session) => Return,\n transaction = false\n ): Promise<Awaited<Return>> {\n let session: Session | undefined\n try {\n const { store, profile } = await this.getInitializedStoreWithProfile(agentContext)\n\n session = await (transaction ? store.transaction(profile) : store.session(profile)).open()\n\n const result = await callback(session)\n if (transaction && session.handle) {\n await session.commit()\n }\n\n return result\n } catch (error) {\n agentContext.config.logger.error('Error occurred during transaction, rollback', {\n error,\n })\n if (transaction && session?.handle) {\n await session.rollback()\n }\n throw error\n } finally {\n if (session?.handle) {\n await session.close()\n }\n }\n }\n\n public async getInitializedStoreWithProfile(agentContext: AgentContext) {\n let store = this.getStore(agentContext, {\n // In case we use a profile per wallet, we want to use the parent store, otherwise we only\n // want to use a store that is directly registered on this context.\n recursive: this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.ProfilePerWallet,\n })\n\n if (!store) {\n try {\n store = await this.openStore(agentContext)\n } catch (error) {\n if (error instanceof AskarStoreNotFoundError) {\n store = await this.provisionStore(agentContext)\n } else {\n throw error\n }\n }\n }\n\n return {\n // If we're on store level the default profile can be used automatically\n // otherwise we need to set the profile, which we do based on the context correlation id\n profile: this.isStoreLevel(agentContext) ? undefined : agentContext.contextCorrelationId,\n store,\n }\n }\n\n /**\n * Ensures a command is ran on a store level, preventing a tenant instance from\n * removing a whole store (and potentially other tennats).\n */\n private ensureStoreLevel(agentContext: AgentContext) {\n if (this.isStoreLevel(agentContext)) return\n\n throw new AskarError(\n `Agent context ${agentContext.contextCorrelationId} is not on store level. Make sure to only perform askar store operations in the agent context managing the askar store`\n )\n }\n\n /**\n * Checks whether the current agent context is on store level\n */\n private isStoreLevel(agentContext: AgentContext) {\n if (agentContext.isRootAgentContext) return true\n return this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.DatabasePerWallet\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BO,8BAAMA,oBAAkB;CAC7B,AAAO,YACL,AAA6CC,YAC7C,AAAQC,QACR;EAF6C;EACrC;;CAGV,AAAO,YAAY,cAA4B;AAC7C,SAAO,CAAC,CAAC,KAAK,SAAS,aAAa,EAAE;;CAGxC,MAAc,eAAe,cAAoE;AAC/F,MACE,aAAa,sBACb,KAAK,OAAO,8BAA8B,+BAA+B,iBAEzE,QAAO,KAAK,OAAO;EAIrB,MAAM,cAAc,MAAM,2CAA2C,aAAa;AAElF,SAAO;GACL,IAAI,aAAa;GACjB,KAAK,YAAY;GAEjB,qBAAqB;GACrB,UAAU,KAAK,OAAO,MAAM;GAC7B;;;;;CAMH,MAAc,2CAA2C,SAAkB;EACzE,MAAM,SAAS,IAAI,qBAAqB,EACtC,gBAAgB,qBAAqB,yBACtC,CAAC;AAEF,QAAM,QAAQ,OAAO;GACnB,OAAO,gBAAgB,UAAU,OAAO;GACxC,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,MAAM,6BAA6B,OAAO,SAAS,CAAC;GACrD,CAAC;;;;;;;CAQJ,MAAa,cAAc,cAA4B;EACrD,MAAM,EAAE,SAAS,UAAU,MAAM,KAAK,+BAA+B,aAAa;AAIlF,MAAI,KAAK,aAAa,aAAa,CACjC,OAAM,KAAK,YAAY,aAAa;OAC/B;AACL,OAAI,CAAC,QACH,OAAM,IAAI,gBACR,sHACD;AAEH,SAAM,MAAM,cAAc,QAAQ;;;;;;;;CAStC,MAAa,aAAa,cAA4B;AAGpD,MAAI,CAAC,KAAK,aAAa,aAAa,CAAE;AAEtC,QAAM,KAAK,WAAW,aAAa;;;;;;CAOrC,MAAa,eAAe,cAA4C;AACtE,OAAK,iBAAiB,aAAa;EAEnC,MAAM,cAAc,MAAM,KAAK,eAAe,aAAa;EAC3D,MAAM,mBAAmB,KAAK,oBAAoB,YAAY;AAE9D,eAAa,OAAO,OAAO,MAAM,uBAAuB,YAAY,KAAK;AAEzE,MAAI,KAAK,SAAS,aAAa,CAC7B,OAAM,IAAI,gBAAgB,4BAA4B;AAGxD,MAAI;AACF,OAAI,iBAAiB,MAAM;AACzB,QAAI,MAAM,KAAK,WAAW,OAAO,iBAAiB,KAAK,CACrD,OAAM,IAAI,yBACR,UAAU,YAAY,GAAG,YAAY,iBAAiB,KAAK,kBAC5D;AAIH,UAAM,KAAK,WAAW,gBAAgB,iBAAiB,KAAK;;GAG9D,MAAM,QAAQ,MAAM,MAAM,UAAU;IAClC,UAAU;IACV,KAAK,iBAAiB;IACtB,SAAS,iBAAiB;IAC1B,WAAW,iBAAiB;IAC5B,SAAS,iBAAiB;IAC3B,CAAC;AACF,gBAAa,kBAAkB,iBAAiB,OAAO,MAAM;AAG7D,SAAM,KAAK,YAAY,eAAe,YAAY,KAAK,2CAA2C,QAAQ,CAAC;AAE3G,UAAO;WACA,OAAO;AACd,OAAI,iBAAiB,yBAA0B,OAAM;AAIrD,OACE,aAAa,MAAM,KAClB,MAAM,SAAS,eAAe,cAAc,MAAM,SAAS,eAAe,YAC3E;IACA,MAAMC,iBAAe,UAAU,YAAY,GAAG;AAC9C,iBAAa,OAAO,OAAO,MAAMA,eAAa;AAE9C,UAAM,IAAI,yBAAyBA,gBAAc,EAC/C,OAAO,OACR,CAAC;;GAGJ,MAAM,eAAe,yBAAyB,YAAY,GAAG;AAC7D,gBAAa,OAAO,OAAO,MAAM,cAAc;IAC7C;IACA,cAAc,MAAM;IACrB,CAAC;AAEF,SAAM,IAAI,gBAAgB,cAAc,EAAE,OAAO,OAAO,CAAC;;;;;;;CAQ7D,MAAa,UAAU,cAA4C;AACjE,OAAK,iBAAiB,aAAa;AAEnC,MAAI,KAAK,SAAS,aAAa,CAC7B,OAAM,IAAI,gBAAgB,qFAAqF;EAGjH,MAAM,cAAc,MAAM,KAAK,eAAe,aAAa;EAC3D,MAAM,mBAAmB,KAAK,oBAAoB,YAAY;AAE9D,MAAI;GACF,MAAM,QAAQ,MAAM,MAAM,KAAK;IAC7B,KAAK,iBAAiB;IACtB,WAAW,iBAAiB;IAC5B,SAAS,iBAAiB;IAC3B,CAAC;AACF,gBAAa,kBAAkB,iBAAiB,OAAO,MAAM;AAC7D,UAAO;WACA,OAAO;AACd,OACE,aAAa,MAAM,KAClB,MAAM,SAAS,eAAe,YAC5B,MAAM,SAAS,eAAe,WAAW,oBAAoB,iBAAiB,IAAI,GACrF;IACA,MAAM,eAAe,UAAU,YAAY,GAAG;AAC9C,iBAAa,OAAO,OAAO,MAAM,aAAa;AAE9C,UAAM,IAAI,wBAAwB,cAAc,EAC9C,OAAO,OACR,CAAC;;AAGJ,OAAI,aAAa,MAAM,IAAI,MAAM,SAAS,eAAe,YAAY;IACnE,MAAM,eAAe,4BAA4B,YAAY,GAAG;AAChE,iBAAa,OAAO,OAAO,MAAM,aAAa;AAC9C,UAAM,IAAI,0BAA0B,cAAc,EAChD,OAAO,OACR,CAAC;;AAEJ,SAAM,IAAI,gBAAgB,uBAAuB,YAAY,GAAG,IAAI,MAAM,WAAW,EAAE,OAAO,OAAO,CAAC;;;;;;;;;;;;;CAc1G,MAAa,eAAe,cAA4B,SAAoD;AAC1G,OAAK,iBAAiB,aAAa;EAEnC,MAAM,QAAQ,KAAK,SAAS,aAAa;AACzC,MAAI,CAAC,MACH,OAAM,IAAI,gBAAgB,kDAAkD;EAG9E,MAAM,cAAc,MAAM,KAAK,eAAe,aAAa;AAE3D,MAAI;AACF,SAAM,MAAM,MAAM;IAChB,SAAS,QAAQ;IACjB,WAAW,mCACT,QAAQ,0BAA0B,YAAY,oBAC/C;IACF,CAAC;WACK,OAAO;GACd,MAAM,eAAe,iCAAiC,YAAY,GAAG,KAAK,MAAM;AAChF,gBAAa,OAAO,OAAO,MAAM,cAAc;IAC7C;IACA,cAAc,MAAM;IACrB,CAAC;AAEF,SAAM,IAAI,gBAAgB,cAAc,EAAE,OAAO,OAAO,CAAC;;;;;;;;;CAU7D,MAAa,YAAY,cAA4B,SAAkC;AACrF,OAAK,iBAAiB,aAAa;EAEnC,MAAM,QAAQ,KAAK,SAAS,aAAa;AACzC,MAAI,CAAC,MACH,OAAM,IAAI,gBAAgB,8DAA8D;EAG1F,MAAM,qBAAqB,MAAM,KAAK,eAAe,aAAa;AAClE,MAAI;GACF,MAAM,sBAAsB,KAAK,oBAAoB,QAAQ,cAAc;AAG3E,OAAI,oBAAoB,MAAM;AAE5B,QAAI,MAAM,KAAK,WAAW,OAAO,oBAAoB,KAAK,CACxD,OAAM,IAAI,gCACR,mDAAmD,oBAAoB,KAAK,kBAC7E;AAIH,UAAM,KAAK,WAAW,gBAAgB,oBAAoB,KAAK;;AAGjE,SAAM,MAAM,OAAO;IACjB,UAAU;IACV,KAAK,oBAAoB;IACzB,WAAW,oBAAoB;IAC/B,SAAS,oBAAoB;IAC9B,CAAC;WACK,OAAO;GACd,MAAM,eAAe,0BAA0B,mBAAmB,GAAG,KAAK,MAAM;AAChF,gBAAa,OAAO,OAAO,MAAM,cAAc;IAC7C;IACA,cAAc,MAAM;IACrB,CAAC;AAEF,OAAI,iBAAiB,gCAAiC,OAAM;AAC5D,SAAM,IAAI,gBAAgB,cAAc,EAAE,OAAO,OAAO,CAAC;;;;;;CAO7D,MAAa,YAAY,cAA4B,SAAkC;AACrF,OAAK,iBAAiB,aAAa;AAEnC,MAAI,KAAK,SAAS,aAAa,CAC7B,OAAM,IAAI,gBAAgB,+DAA+D;EAG3F,MAAM,yBAAyB,MAAM,KAAK,eAAe,aAAa;EAEtE,MAAM,yBAAyB,KAAK,oBAAoB,QAAQ,gBAAgB;EAChF,MAAM,8BAA8B,KAAK,oBAAoB,uBAAuB;EAEpF,IAAIC;AACJ,MAAI;AACF,OAAI,4BAA4B,MAAM;AAEpC,QAAI,MAAM,KAAK,WAAW,OAAO,4BAA4B,KAAK,CAChE,OAAM,IAAI,gCACR,iCAAiC,4BAA4B,KAAK,kBACnE;AAGH,UAAM,KAAK,WAAW,gBAAgB,4BAA4B,KAAK;;AAIzE,uBAAoB,MAAM,MAAM,KAAK;IACnC,KAAK,uBAAuB;IAC5B,WAAW,uBAAuB;IAClC,SAAS,uBAAuB;IACjC,CAAC;AAEF,SAAM,kBAAkB,OAAO;IAC7B,UAAU;IACV,KAAK,4BAA4B;IACjC,WAAW,4BAA4B;IACvC,SAAS,4BAA4B;IACtC,CAAC;AAEF,SAAM,kBAAkB,OAAO;WACxB,OAAO;AACd,SAAM,mBAAmB,OAAO;GAChC,MAAM,eAAe,0BAA0B,QAAQ,gBAAgB,GAAG,KAAK,MAAM;AACrF,gBAAa,OAAO,OAAO,MAAM,cAAc;IAC7C;IACA,cAAc,MAAM;IACrB,CAAC;AAEF,OAAI,iBAAiB,gCAAiC,OAAM;AAG5D,OAAI,4BAA4B,QAAS,MAAM,KAAK,WAAW,OAAO,4BAA4B,KAAK,CACrG,OAAM,KAAK,WAAW,OAAO,4BAA4B,KAAK;AAGhE,SAAM,IAAI,gBAAgB,cAAc,EAAE,OAAO,OAAO,CAAC;;;;;;;;;;;;CAa7D,MAAa,YAAY,cAA2C;AAClE,OAAK,iBAAiB,aAAa;AAEnC,MAAI,KAAK,SAAS,aAAa,CAC7B,OAAM,KAAK,WAAW,aAAa;EAGrC,MAAM,cAAc,MAAM,KAAK,eAAe,aAAa;EAC3D,MAAM,mBAAmB,KAAK,oBAAoB,YAAY;AAE9D,eAAa,OAAO,OAAO,KAAK,mBAAmB,YAAY,GAAG,GAAG;AACrE,MAAI;AACF,SAAM,MAAM,OAAO,iBAAiB,IAAI;AAExC,gBAAa,kBAAkB,iBAAiB,OAAO,OAAU;WAC1D,OAAO;GACd,MAAM,eAAe,yBAAyB,YAAY,GAAG,KAAK,MAAM;AACxE,gBAAa,OAAO,OAAO,MAAM,cAAc;IAC7C;IACA,cAAc,MAAM;IACrB,CAAC;AAEF,SAAM,IAAI,gBAAgB,cAAc,EAAE,OAAO,OAAO,CAAC;;;;;;CAO7D,MAAa,WAAW,cAA4B;AAClD,OAAK,iBAAiB,aAAa;EAEnC,MAAM,QAAQ,KAAK,SAAS,aAAa;AACzC,MAAI,CAAC,MACH,OAAM,IAAI,gBAAgB,0BAA0B;EAGtD,MAAM,cAAc,MAAM,KAAK,eAAe,aAAa;AAE3D,MAAI;AACF,gBAAa,OAAO,OAAO,MAAM,kBAAkB,YAAY,GAAG,GAAG;AACrE,SAAM,MAAM,OAAO;AAEnB,gBAAa,kBAAkB,iBAAiB,OAAO,OAAU;WAC1D,OAAO;GACd,MAAM,eAAe,wBAAwB,YAAY,GAAG,KAAK,MAAM;AACvE,gBAAa,OAAO,OAAO,MAAM,cAAc;IAC7C;IACA,cAAc,MAAM;IACrB,CAAC;AAEF,SAAM,IAAI,gBAAgB,cAAc,EAAE,OAAO,OAAO,CAAC;;;CAI7D,AAAQ,oBAAoB,aAA4C;EACtE,MAAM,EAAE,KAAK,SAAS,mBAAmB,aAAa,KAAK,WAAW,SAAS;AAE/E,SAAO;GACL;GACA;GACA,SAAS,YAAY;GACrB,WAAW,IAAI,eACZ,YAAY,uBAAuB,UAAU,WAC/C;GACD,SAAS,YAAY;GACtB;;;;;;;;;CAUH,MAAa,gBACX,cACA,UAC0B;AAC1B,SAAO,KAAK,aAAa,cAAc,UAAU,KAAK;;;;;;;;CASxD,MAAa,YACX,cACA,UAC0B;AAC1B,SAAO,KAAK,aAAa,cAAc,UAAU,MAAM;;CAGzD,AAAQ,SAAS,cAA4B,EAAE,YAAY,UAAmC,EAAE,EAAE;AAEhG,MAAI,CADiB,aAAa,kBAAkB,aAAa,OAAO,UAAU,CAC/D,QAAO;AAM1B,MAAI;AACF,UAAO,aAAa,kBAAkB,QAAQ,MAAM;UAC9C;AACN,UAAO;;;CAIX,MAAc,aACZ,cACA,UACA,cAAc,OACY;EAC1B,IAAIC;AACJ,MAAI;GACF,MAAM,EAAE,OAAO,YAAY,MAAM,KAAK,+BAA+B,aAAa;AAElF,aAAU,OAAO,cAAc,MAAM,YAAY,QAAQ,GAAG,MAAM,QAAQ,QAAQ,EAAE,MAAM;GAE1F,MAAM,SAAS,MAAM,SAAS,QAAQ;AACtC,OAAI,eAAe,QAAQ,OACzB,OAAM,QAAQ,QAAQ;AAGxB,UAAO;WACA,OAAO;AACd,gBAAa,OAAO,OAAO,MAAM,+CAA+C,EAC9E,OACD,CAAC;AACF,OAAI,eAAe,SAAS,OAC1B,OAAM,QAAQ,UAAU;AAE1B,SAAM;YACE;AACR,OAAI,SAAS,OACX,OAAM,QAAQ,OAAO;;;CAK3B,MAAa,+BAA+B,cAA4B;EACtE,IAAI,QAAQ,KAAK,SAAS,cAAc,EAGtC,WAAW,KAAK,OAAO,8BAA8B,+BAA+B,kBACrF,CAAC;AAEF,MAAI,CAAC,MACH,KAAI;AACF,WAAQ,MAAM,KAAK,UAAU,aAAa;WACnC,OAAO;AACd,OAAI,iBAAiB,wBACnB,SAAQ,MAAM,KAAK,eAAe,aAAa;OAE/C,OAAM;;AAKZ,SAAO;GAGL,SAAS,KAAK,aAAa,aAAa,GAAG,SAAY,aAAa;GACpE;GACD;;;;;;CAOH,AAAQ,iBAAiB,cAA4B;AACnD,MAAI,KAAK,aAAa,aAAa,CAAE;AAErC,QAAM,IAAIC,aACR,iBAAiB,aAAa,qBAAqB,wHACpD;;;;;CAMH,AAAQ,aAAa,cAA4B;AAC/C,MAAI,aAAa,mBAAoB,QAAO;AAC5C,SAAO,KAAK,OAAO,8BAA8B,+BAA+B;;;;CA9hBnFC,cAAY;oBAGR,OAAO,iBAAiB,WAAW"}
|
|
1
|
+
{"version":3,"file":"AskarStoreManager.mjs","names":["AskarStoreManager","fileSystem: FileSystem","config: AskarModuleConfig","errorMessage","sourceWalletStore: Store | undefined","session: Session | undefined","AskarError","injectable"],"sources":["../src/AskarStoreManager.ts"],"sourcesContent":["import { AgentContext, type FileSystem, InjectionSymbols, JsonTransformer, StorageVersionRecord } from '@credo-ts/core'\nimport { KdfMethod, Session, Store, StoreKeyMethod } from '@openwallet-foundation/askar-shared'\nimport { inject, injectable } from 'tsyringe'\n\nimport type { AskarStoreExportOptions, AskarStoreImportOptions, AskarStoreRotateKeyOptions } from './AskarApiOptions'\nimport {\n AskarModuleConfig,\n type AskarModuleConfigStoreOptions,\n AskarMultiWalletDatabaseScheme,\n} from './AskarModuleConfig'\nimport {\n AskarError,\n AskarStoreDuplicateError,\n AskarStoreError,\n AskarStoreExportPathExistsError,\n AskarStoreImportPathExistsError,\n AskarStoreInvalidKeyError,\n AskarStoreNotFoundError,\n} from './error'\nimport { transformFromRecordTagValues } from './storage/utils'\nimport { getAskarStoreConfigForContextCorrelationId } from './tenants'\nimport {\n AskarErrorCode,\n isAskarError,\n isSqliteInMemoryUri,\n keyDerivationMethodFromStoreConfig,\n uriFromStoreConfig,\n} from './utils'\n\n@injectable()\nexport class AskarStoreManager {\n public constructor(\n @inject(InjectionSymbols.FileSystem) private fileSystem: FileSystem,\n private config: AskarModuleConfig\n ) {}\n\n public isStoreOpen(agentContext: AgentContext) {\n return !!this.getStore(agentContext)?.handle\n }\n\n private async getStoreConfig(agentContext: AgentContext): Promise<AskarModuleConfigStoreOptions> {\n if (\n agentContext.isRootAgentContext ||\n this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.ProfilePerWallet\n ) {\n return this.config.store\n }\n\n // Otherwise we need to get the wallet key from the tenant record\n const storeConfig = await getAskarStoreConfigForContextCorrelationId(agentContext)\n\n return {\n id: agentContext.contextCorrelationId,\n key: storeConfig.key,\n // we always use raw at the moment\n keyDerivationMethod: 'raw',\n database: this.config.store.database,\n }\n }\n\n /**\n * When we create storage for a context we need to store the version record\n */\n private async setCurrentFrameworkStorageVersionOnSession(session: Session) {\n const record = new StorageVersionRecord({\n storageVersion: StorageVersionRecord.frameworkStorageVersion,\n })\n\n await session.insert({\n value: JsonTransformer.serialize(record),\n name: record.id,\n category: record.type,\n tags: transformFromRecordTagValues(record.getTags()),\n })\n }\n\n /**\n * Deletes all storage related to a context. If on store level, meaning root agent\n * or when using database per wallet storage, the whole store will be deleted.\n * Otherwise only a profile within the store will be removed.\n */\n public async deleteContext(agentContext: AgentContext) {\n const { profile, store } = await this.getInitializedStoreWithProfile(agentContext)\n // Currently it will delete the whole store. We can delete only the root profile, BUT:\n // - all tenant records will be deleted\n // - the root agent is deleted, this is not a flow we support (there's no default profile anymore)\n if (this.isStoreLevel(agentContext)) {\n await this.deleteStore(agentContext)\n } else {\n if (!profile)\n throw new AskarStoreError(\n 'Unable to delete asksar data for context. No profile found and not on store level (so not deleting the whole store)'\n )\n\n await store.removeProfile(profile)\n }\n }\n\n /**\n * Closes an active context. If on store level, meaning root agent\n * or when using database per wallet storage, the whole store will be closed.\n * Otherwise nothing will be done as profiles are opened on a store from higher level.\n */\n public async closeContext(agentContext: AgentContext) {\n // TODO: we should maybe set some value on the agentContext indicating it is disposed so no new sessions can be opened\n // If not on store level we don't have to do anything.\n if (!this.isStoreLevel(agentContext)) return\n\n await this.closeStore(agentContext)\n }\n\n /**\n * @throws {AskarStoreDuplicateError} if the wallet already exists\n * @throws {AskarStoreError} if another error occurs\n */\n public async provisionStore(agentContext: AgentContext): Promise<Store> {\n this.ensureStoreLevel(agentContext)\n\n const storeConfig = await this.getStoreConfig(agentContext)\n const askarStoreConfig = this.getAskarStoreConfig(storeConfig)\n\n agentContext.config.logger.debug(`Provisioning store '${storeConfig.id}`)\n\n if (this.getStore(agentContext)) {\n throw new AskarStoreDuplicateError('Store already provisioned')\n }\n\n try {\n if (askarStoreConfig.path) {\n if (await this.fileSystem.exists(askarStoreConfig.path)) {\n throw new AskarStoreDuplicateError(\n `Store '${storeConfig.id}' at path ${askarStoreConfig.path} already exists.`\n )\n }\n\n // Make sure path exists before creating the wallet\n await this.fileSystem.createDirectory(askarStoreConfig.path)\n }\n\n const store = await Store.provision({\n recreate: false,\n uri: askarStoreConfig.uri,\n profile: askarStoreConfig.profile,\n keyMethod: askarStoreConfig.keyMethod,\n passKey: askarStoreConfig.passKey,\n })\n agentContext.dependencyManager.registerInstance(Store, store)\n\n // For new stores we need to set the framework storage version\n await this.withSession(agentContext, (session) => this.setCurrentFrameworkStorageVersionOnSession(session))\n\n return store\n } catch (error) {\n if (error instanceof AskarStoreDuplicateError) throw error\n\n // FIXME: Askar should throw a Duplicate error code, but is currently returning Encryption\n // And if we provide the very same wallet key, it will open it without any error\n if (\n isAskarError(error) &&\n (error.code === AskarErrorCode.Encryption || error.code === AskarErrorCode.Duplicate)\n ) {\n const errorMessage = `Store '${storeConfig.id}' already exists`\n agentContext.config.logger.debug(errorMessage)\n\n throw new AskarStoreDuplicateError(errorMessage, {\n cause: error,\n })\n }\n\n const errorMessage = `Error creating store '${storeConfig.id}'`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * @throws {AskarStoreNotFoundError} if the wallet does not exist\n * @throws {AskarStoreError} if another error occurs\n */\n public async openStore(agentContext: AgentContext): Promise<Store> {\n this.ensureStoreLevel(agentContext)\n\n if (this.getStore(agentContext)) {\n throw new AskarStoreError('Store already opened. Close the currently opened store before re-opening the store')\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n const askarStoreConfig = this.getAskarStoreConfig(storeConfig)\n\n try {\n const store = await Store.open({\n uri: askarStoreConfig.uri,\n keyMethod: askarStoreConfig.keyMethod,\n passKey: askarStoreConfig.passKey,\n })\n agentContext.dependencyManager.registerInstance(Store, store)\n return store\n } catch (error) {\n if (\n isAskarError(error) &&\n (error.code === AskarErrorCode.NotFound ||\n (error.code === AskarErrorCode.Backend && isSqliteInMemoryUri(askarStoreConfig.uri)))\n ) {\n const errorMessage = `Store '${storeConfig.id}' not found`\n agentContext.config.logger.debug(errorMessage)\n\n throw new AskarStoreNotFoundError(errorMessage, {\n cause: error,\n })\n }\n\n if (isAskarError(error) && error.code === AskarErrorCode.Encryption) {\n const errorMessage = `Incorrect key for store '${storeConfig.id}'`\n agentContext.config.logger.debug(errorMessage)\n throw new AskarStoreInvalidKeyError(errorMessage, {\n cause: error,\n })\n }\n throw new AskarStoreError(`Error opening store ${storeConfig.id}: ${error.message}`, { cause: error })\n }\n }\n\n /**\n * Rotate the key of the current askar store.\n *\n * NOTE: multiple agent contexts (tenants) can use the same store. This method rotates the key for the whole store,\n * it is advised to only run this method on the root tenant agent when using profile per wallet database strategy.\n * After running this method you should change the store configuration in the Askar module.\n *\n * @throws {AskarStoreNotFoundError} if the wallet does not exist\n * @throws {AskarStoreError} if another error occurs\n */\n public async rotateStoreKey(agentContext: AgentContext, options: AskarStoreRotateKeyOptions): Promise<void> {\n this.ensureStoreLevel(agentContext)\n\n const store = this.getStore(agentContext)\n if (!store) {\n throw new AskarStoreError('Store needs to be open to rotate the wallet key')\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n\n try {\n await store.rekey({\n passKey: options.newKey,\n keyMethod: keyDerivationMethodFromStoreConfig(\n options.newKeyDerivationMethod ?? storeConfig.keyDerivationMethod\n ),\n })\n } catch (error) {\n const errorMessage = `Error rotating key for store '${storeConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Exports the current askar store.\n *\n * NOTE: a store can contain profiles for multiple tenants. When you export a store\n * all profiles will be exported with it.\n */\n public async exportStore(agentContext: AgentContext, options: AskarStoreExportOptions) {\n this.ensureStoreLevel(agentContext)\n\n const store = this.getStore(agentContext)\n if (!store) {\n throw new AskarStoreError('Unable to export store. No store available on agent context')\n }\n\n const currentStoreConfig = await this.getStoreConfig(agentContext)\n try {\n const newAskarStoreConfig = this.getAskarStoreConfig(options.exportToStore)\n\n // If path based store, ensure path does not exist yet, and create new store path\n if (newAskarStoreConfig.path) {\n // Export path already exists\n if (await this.fileSystem.exists(newAskarStoreConfig.path)) {\n throw new AskarStoreExportPathExistsError(\n `Unable to create export, wallet export at path '${newAskarStoreConfig.path}' already exists`\n )\n }\n\n // Make sure destination path exists\n await this.fileSystem.createDirectory(newAskarStoreConfig.path)\n }\n\n await store.copyTo({\n recreate: false,\n uri: newAskarStoreConfig.uri,\n keyMethod: newAskarStoreConfig.keyMethod,\n passKey: newAskarStoreConfig.passKey,\n })\n } catch (error) {\n const errorMessage = `Error exporting store '${currentStoreConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n if (error instanceof AskarStoreExportPathExistsError) throw error\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Imports from an external store config into the current askar store config.\n */\n public async importStore(agentContext: AgentContext, options: AskarStoreImportOptions) {\n this.ensureStoreLevel(agentContext)\n\n if (this.getStore(agentContext)) {\n throw new AskarStoreError('To import a store the current store needs to be closed first')\n }\n\n const destinationStoreConfig = await this.getStoreConfig(agentContext)\n\n const sourceAskarStoreConfig = this.getAskarStoreConfig(options.importFromStore)\n const destinationAskarStoreConfig = this.getAskarStoreConfig(destinationStoreConfig)\n\n let sourceWalletStore: Store | undefined\n try {\n if (destinationAskarStoreConfig.path) {\n // Import path already exists\n if (await this.fileSystem.exists(destinationAskarStoreConfig.path)) {\n throw new AskarStoreImportPathExistsError(\n `Unable to import store. Path '${destinationAskarStoreConfig.path}' already exists`\n )\n }\n\n await this.fileSystem.createDirectory(destinationAskarStoreConfig.path)\n }\n\n // Open imported wallet and copy to destination\n sourceWalletStore = await Store.open({\n uri: sourceAskarStoreConfig.uri,\n keyMethod: sourceAskarStoreConfig.keyMethod,\n passKey: sourceAskarStoreConfig.passKey,\n })\n\n await sourceWalletStore.copyTo({\n recreate: false,\n uri: destinationAskarStoreConfig.uri,\n keyMethod: destinationAskarStoreConfig.keyMethod,\n passKey: destinationAskarStoreConfig.passKey,\n })\n\n await sourceWalletStore.close()\n } catch (error) {\n await sourceWalletStore?.close()\n const errorMessage = `Error importing store '${options.importFromStore.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n if (error instanceof AskarStoreImportPathExistsError) throw error\n\n // Cleanup any wallet file we could have created\n if (destinationAskarStoreConfig.path && (await this.fileSystem.exists(destinationAskarStoreConfig.path))) {\n await this.fileSystem.delete(destinationAskarStoreConfig.path)\n }\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Delete the current askar store.\n *\n * NOTE: multiple agent contexts (tenants) can use the same store. This method deletes the whole store,\n * and if you're using multi-tenancy with profile per wallet it is advised to only run this method on the root tenant agent.\n *\n * @throws {AskarStoreNotFoundError} if the wallet does not exist\n * @throws {AskarStoreError} if another error occurs\n */\n public async deleteStore(agentContext: AgentContext): Promise<void> {\n this.ensureStoreLevel(agentContext)\n\n if (this.getStore(agentContext)) {\n await this.closeStore(agentContext)\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n const askarStoreConfig = this.getAskarStoreConfig(storeConfig)\n\n agentContext.config.logger.info(`Deleting store '${storeConfig.id}'`)\n try {\n await Store.remove(askarStoreConfig.uri)\n // Clear the store instance\n agentContext.dependencyManager.registerInstance(Store, undefined)\n } catch (error) {\n const errorMessage = `Error deleting store '${storeConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n /**\n * Close the current askar store\n */\n public async closeStore(agentContext: AgentContext) {\n this.ensureStoreLevel(agentContext)\n\n const store = this.getStore(agentContext)\n if (!store) {\n throw new AskarStoreError('There is no open store.')\n }\n\n const storeConfig = await this.getStoreConfig(agentContext)\n\n try {\n agentContext.config.logger.debug(`Closing store '${storeConfig.id}'`)\n await store.close()\n // Unregister the store from the context\n agentContext.dependencyManager.registerInstance(Store, undefined)\n } catch (error) {\n const errorMessage = `Error closing store '${storeConfig.id}': ${error.message}`\n agentContext.config.logger.error(errorMessage, {\n error,\n errorMessage: error.message,\n })\n\n throw new AskarStoreError(errorMessage, { cause: error })\n }\n }\n\n private getAskarStoreConfig(storeConfig: AskarModuleConfigStoreOptions) {\n const { uri, path } = uriFromStoreConfig(storeConfig, this.fileSystem.dataPath)\n\n return {\n uri,\n path,\n profile: storeConfig.id,\n keyMethod: new StoreKeyMethod(\n (storeConfig.keyDerivationMethod ?? KdfMethod.Argon2IMod) satisfies `${KdfMethod}` | KdfMethod as KdfMethod\n ),\n passKey: storeConfig.key,\n }\n }\n\n /**\n * Run callback with a transaction. If the callback resolves the transaction\n * will be committed if the transaction is not closed yet. If the callback rejects\n * the transaction will be rolled back if the transaction is not closed yet.\n *\n * TODO: update to new `using` syntax so we don't have to use a callback\n */\n public async withTransaction<Return>(\n agentContext: AgentContext,\n callback: (session: Session) => Return\n ): Promise<Awaited<Return>> {\n return this._withSession(agentContext, callback, true)\n }\n\n /**\n * Run callback with the session provided, the session will\n * be closed once the callback resolves or rejects if it is not closed yet.\n *\n * TODO: update to new `using` syntax so we don't have to use a callback\n */\n public async withSession<Return>(\n agentContext: AgentContext,\n callback: (session: Session) => Return\n ): Promise<Awaited<Return>> {\n return this._withSession(agentContext, callback, false)\n }\n\n private getStore(agentContext: AgentContext, { recursive = false }: { recursive?: boolean } = {}) {\n const isRegistered = agentContext.dependencyManager.isRegistered(Store, recursive)\n if (!isRegistered) return null\n\n // We set the store value to undefined in the dependency manager\n // when closing it, but TSyringe still marks is as registered, but\n // will throw an error when resolved. Since there is no unregister method\n // we wrap it with a try-catch\n try {\n return agentContext.dependencyManager.resolve(Store)\n } catch {\n return null\n }\n }\n\n private async _withSession<Return>(\n agentContext: AgentContext,\n callback: (session: Session) => Return,\n transaction = false\n ): Promise<Awaited<Return>> {\n let session: Session | undefined\n try {\n const { store, profile } = await this.getInitializedStoreWithProfile(agentContext)\n\n session = await (transaction ? store.transaction(profile) : store.session(profile)).open()\n\n const result = await callback(session)\n if (transaction && session.handle) {\n await session.commit()\n }\n\n return result\n } catch (error) {\n agentContext.config.logger.error('Error occurred during transaction, rollback', {\n error,\n })\n if (transaction && session?.handle) {\n await session.rollback()\n }\n throw error\n } finally {\n if (session?.handle) {\n await session.close()\n }\n }\n }\n\n public async getInitializedStoreWithProfile(agentContext: AgentContext) {\n let store = this.getStore(agentContext, {\n // In case we use a profile per wallet, we want to use the parent store, otherwise we only\n // want to use a store that is directly registered on this context.\n recursive: this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.ProfilePerWallet,\n })\n\n if (!store) {\n try {\n store = await this.openStore(agentContext)\n } catch (error) {\n if (error instanceof AskarStoreNotFoundError) {\n store = await this.provisionStore(agentContext)\n } else {\n throw error\n }\n }\n }\n\n return {\n // If we're on store level the default profile can be used automatically\n // otherwise we need to set the profile, which we do based on the context correlation id\n profile: this.isStoreLevel(agentContext) ? undefined : agentContext.contextCorrelationId,\n store,\n }\n }\n\n /**\n * Ensures a command is ran on a store level, preventing a tenant instance from\n * removing a whole store (and potentially other tennats).\n */\n private ensureStoreLevel(agentContext: AgentContext) {\n if (this.isStoreLevel(agentContext)) return\n\n throw new AskarError(\n `Agent context ${agentContext.contextCorrelationId} is not on store level. Make sure to only perform askar store operations in the agent context managing the askar store`\n )\n }\n\n /**\n * Checks whether the current agent context is on store level\n */\n private isStoreLevel(agentContext: AgentContext) {\n if (agentContext.isRootAgentContext) return true\n return this.config.multiWalletDatabaseScheme === AskarMultiWalletDatabaseScheme.DatabasePerWallet\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
".": "./build/index.mjs",
|
|
5
5
|
"./package.json": "./package.json"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.6.
|
|
7
|
+
"version": "0.6.2-alpha-20251211115250",
|
|
8
8
|
"files": [
|
|
9
9
|
"build"
|
|
10
10
|
],
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"class-validator": "^0.14.1",
|
|
24
24
|
"rxjs": "^7.8.2",
|
|
25
25
|
"tsyringe": "^4.10.0",
|
|
26
|
-
"@credo-ts/core": "0.6.
|
|
26
|
+
"@credo-ts/core": "0.6.2-alpha-20251211115250"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@openwallet-foundation/askar-nodejs": "^0.4.3",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@types/ref-struct-di": "^1.1.12",
|
|
33
33
|
"reflect-metadata": "0.2.2",
|
|
34
34
|
"typescript": "~5.9.3",
|
|
35
|
-
"@credo-ts/tenants": "0.6.
|
|
35
|
+
"@credo-ts/tenants": "0.6.2-alpha-20251211115250"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@openwallet-foundation/askar-shared": "^0.4.3"
|