{"version":3,"file":"UpdateAssistant.mjs","names":[],"sources":["../../../src/storage/migration/UpdateAssistant.ts"],"sourcesContent":["import type { BaseAgent } from '../../agent/BaseAgent'\nimport { CredoError } from '../../error'\nimport type { Module } from '../../plugins'\nimport { isFirstVersionEqualToSecond, isFirstVersionHigherThanSecond, parseVersionString } from '../../utils/version'\nimport { StorageUpdateError } from './error/StorageUpdateError'\n\nimport { StorageUpdateService } from './StorageUpdateService'\nimport type { Update, UpdateConfig, UpdateToVersion } from './updates'\nimport { CURRENT_FRAMEWORK_STORAGE_VERSION, DEFAULT_UPDATE_CONFIG, supportedUpdates } from './updates'\n\nexport interface UpdateAssistantUpdateOptions {\n  updateToVersion?: UpdateToVersion\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: no explanation\nexport class UpdateAssistant<Agent extends BaseAgent<any> = BaseAgent> {\n  private agent: Agent\n  private storageUpdateService: StorageUpdateService\n  private updateConfig: UpdateConfig\n\n  public constructor(agent: Agent, updateConfig: UpdateConfig = DEFAULT_UPDATE_CONFIG) {\n    this.agent = agent\n    this.updateConfig = updateConfig\n\n    this.storageUpdateService = this.agent.dependencyManager.resolve(StorageUpdateService)\n  }\n\n  public async initialize() {\n    if (this.agent.isInitialized) {\n      throw new CredoError(\"Can't initialize UpdateAssistant after agent is initialized\")\n    }\n  }\n\n  public async isUpToDate(updateToVersion?: UpdateToVersion) {\n    return this.storageUpdateService.isUpToDate(this.agent.context, updateToVersion)\n  }\n\n  public async getCurrentAgentStorageVersion() {\n    return this.storageUpdateService.getCurrentStorageVersion(this.agent.context)\n  }\n\n  public static get frameworkStorageVersion() {\n    return CURRENT_FRAMEWORK_STORAGE_VERSION\n  }\n\n  public async getNeededUpdates(toVersion?: UpdateToVersion) {\n    const currentStorageVersion = parseVersionString(\n      await this.storageUpdateService.getCurrentStorageVersion(this.agent.context)\n    )\n\n    const parsedToVersion = toVersion ? parseVersionString(toVersion) : undefined\n\n    // If the current storage version is higher or equal to the toVersion, we can't update, so return empty array\n    if (\n      parsedToVersion &&\n      (isFirstVersionHigherThanSecond(currentStorageVersion, parsedToVersion) ||\n        isFirstVersionEqualToSecond(currentStorageVersion, parsedToVersion))\n    ) {\n      return []\n    }\n\n    // Filter updates. We don't want older updates we already applied\n    // or aren't needed because the wallet was created after the update script was made\n    const neededUpdates = supportedUpdates.filter((update) => {\n      const updateToVersion = parseVersionString(update.toVersion)\n\n      // If the update toVersion is higher than the wanted toVersion, we skip the update\n      if (parsedToVersion && isFirstVersionHigherThanSecond(updateToVersion, parsedToVersion)) {\n        return false\n      }\n\n      // if an update toVersion is higher than currentStorageVersion we want to to include the update\n      return isFirstVersionHigherThanSecond(updateToVersion, currentStorageVersion)\n    })\n\n    // The current storage version is too old to update\n    if (\n      neededUpdates.length > 0 &&\n      isFirstVersionHigherThanSecond(parseVersionString(neededUpdates[0].fromVersion), currentStorageVersion)\n    ) {\n      throw new CredoError(\n        `First fromVersion is higher than current storage version. You need to use an older version of the framework to update to at least version ${neededUpdates[0].fromVersion}`\n      )\n    }\n\n    const lastUpdateToVersion = neededUpdates.length > 0 ? neededUpdates[neededUpdates.length - 1].toVersion : undefined\n    if (toVersion && lastUpdateToVersion && lastUpdateToVersion !== toVersion) {\n      throw new CredoError(\n        `No update found for toVersion ${toVersion}. Make sure the toVersion is a valid version you can update to`\n      )\n    }\n\n    return neededUpdates\n  }\n\n  public async update(options?: UpdateAssistantUpdateOptions) {\n    const updateIdentifier = Date.now().toString()\n    const updateToVersion = options?.updateToVersion\n\n    try {\n      this.agent.config.logger.info(`Starting update of agent storage with updateIdentifier ${updateIdentifier}`)\n      const neededUpdates = await this.getNeededUpdates(updateToVersion)\n\n      const currentStorageVersion = parseVersionString(\n        await this.storageUpdateService.getCurrentStorageVersion(this.agent.context)\n      )\n      const parsedToVersion = updateToVersion ? parseVersionString(updateToVersion) : undefined\n\n      // If the current storage version is higher or equal to the toVersion, we can't update.\n      if (\n        parsedToVersion &&\n        (isFirstVersionHigherThanSecond(currentStorageVersion, parsedToVersion) ||\n          isFirstVersionEqualToSecond(currentStorageVersion, parsedToVersion))\n      ) {\n        throw new StorageUpdateError(\n          `Can't update to version ${updateToVersion} because it is lower or equal to the current agent storage version ${currentStorageVersion[0]}.${currentStorageVersion[1]}}`\n        )\n      }\n\n      if (neededUpdates.length === 0) {\n        this.agent.config.logger.info('No update needed. Agent storage is up to date.')\n        return\n      }\n\n      const fromVersion = neededUpdates[0].fromVersion\n      const toVersion = neededUpdates[neededUpdates.length - 1].toVersion\n\n      this.agent.config.logger.info(\n        `Starting update process. Total of ${neededUpdates.length} update(s) will be applied to update the agent storage from version ${fromVersion} to version ${toVersion}`\n      )\n\n      try {\n        for (const update of neededUpdates) {\n          const registeredModules = Object.values(this.agent.dependencyManager.registeredModules)\n          const modulesWithUpdate: Array<{ module: Module; update: Update }> = []\n\n          // Filter modules that have an update script for the current update\n          for (const registeredModule of registeredModules) {\n            const moduleUpdate = registeredModule.updates?.find(\n              (module) => module.fromVersion === update.fromVersion && module.toVersion === update.toVersion\n            )\n\n            if (moduleUpdate) {\n              modulesWithUpdate.push({\n                module: registeredModule,\n                update: moduleUpdate,\n              })\n            }\n          }\n\n          this.agent.config.logger.info(\n            `Starting update of agent storage from version ${update.fromVersion} to version ${update.toVersion}. Found ${modulesWithUpdate.length} extension module(s) with update scripts`\n          )\n          await update.doUpdate(this.agent)\n\n          this.agent.config.logger.info(\n            `Finished update of core agent storage from version ${update.fromVersion} to version ${update.toVersion}. Starting update of extension modules`\n          )\n\n          for (const moduleWithUpdate of modulesWithUpdate) {\n            this.agent.config.logger.info(\n              `Starting update of extension module ${moduleWithUpdate.module.constructor.name} from version ${moduleWithUpdate.update.fromVersion} to version ${moduleWithUpdate.update.toVersion}`\n            )\n            await moduleWithUpdate.update.doUpdate(this.agent, this.updateConfig)\n            this.agent.config.logger.info(\n              `Finished update of extension module ${moduleWithUpdate.module.constructor.name} from version ${moduleWithUpdate.update.fromVersion} to version ${moduleWithUpdate.update.toVersion}`\n            )\n          }\n\n          // Update the framework version in storage\n          await this.storageUpdateService.setCurrentStorageVersion(this.agent.context, update.toVersion)\n          this.agent.config.logger.info(\n            `Successfully updated agent storage from version ${update.fromVersion} to version ${update.toVersion}`\n          )\n        }\n      } catch (error) {\n        this.agent.config.logger.fatal('An error occurred while updating the wallet.', {\n          error,\n        })\n\n        throw error\n      }\n    } catch (error) {\n      this.agent.config.logger.error(`Error updating storage (updateIdentifier: ${updateIdentifier})`, {\n        cause: error,\n      })\n\n      throw new StorageUpdateError(`Error updating storage (updateIdentifier: ${updateIdentifier}): ${error.message}`, {\n        cause: error,\n      })\n    }\n\n    return updateIdentifier\n  }\n}\n"],"mappings":"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"}