diff --git a/packages/contentstack-import/src/import/modules/marketplace-apps.ts b/packages/contentstack-import/src/import/modules/marketplace-apps.ts index cb150583a..e418a4256 100644 --- a/packages/contentstack-import/src/import/modules/marketplace-apps.ts +++ b/packages/contentstack-import/src/import/modules/marketplace-apps.ts @@ -697,46 +697,84 @@ export default class ImportMarketplaceApps extends BaseClass { if (!isEmpty(configuration)) { log.debug(`Updating app configuration for: ${appName}`, this.importConfig.context); - await this.appSdk - .marketplace(this.importConfig.org_uid) - .installation(installation_uid) - .setConfiguration(this.nodeCrypto.decrypt(configuration)) - .then(({ data }: any) => { - if (data?.message) { - log.debug(data, this.importConfig.context); - log.info(formatError(data.message), this.importConfig.context); - } else { - log.success(`${appName} app config updated successfully.!`, this.importConfig.context); - log.debug(`Configuration update successful for: ${appName}`, this.importConfig.context); - } - }) - .catch((error: any) => { - log.debug(error, this.importConfig.context); - log.error(formatError(error), this.importConfig.context); - log.debug(`Configuration update failed for: ${appName}`, this.importConfig.context); - }); + // NOTE: decrypt synchronously in a guard. A bad-decrypt (e.g. ERR_OSSL_BAD_DECRYPT when the + // export was encrypted with a different key) would otherwise throw here — outside the promise + // chain's .catch — abort the whole marketplace-apps module, and skip writing the + // marketplace_apps uid-mapping, which starves the downstream GF/CT/entry extension remap. + // Instead: warn and skip only this app's configuration; the app stays installed and its + // extension mappings are still recorded. + let decryptedConfiguration: any; + try { + decryptedConfiguration = this.nodeCrypto.decrypt(configuration); + } catch (error: any) { + log.warn( + `Failed to decrypt configuration for '${appName}'; skipping its configuration update. The app is installed and its extension mappings are preserved. (${ + error?.message || error + })`, + this.importConfig.context, + ); + decryptedConfiguration = undefined; + } + + if (decryptedConfiguration !== undefined) { + await this.appSdk + .marketplace(this.importConfig.org_uid) + .installation(installation_uid) + .setConfiguration(decryptedConfiguration) + .then(({ data }: any) => { + if (data?.message) { + log.debug(data, this.importConfig.context); + log.info(formatError(data.message), this.importConfig.context); + } else { + log.success(`${appName} app config updated successfully.!`, this.importConfig.context); + log.debug(`Configuration update successful for: ${appName}`, this.importConfig.context); + } + }) + .catch((error: any) => { + log.debug(error, this.importConfig.context); + log.error(formatError(error), this.importConfig.context); + log.debug(`Configuration update failed for: ${appName}`, this.importConfig.context); + }); + } } if (!isEmpty(server_configuration)) { log.debug(`Updating server configuration for: ${appName}`, this.importConfig.context); - await this.appSdk - .marketplace(this.importConfig.org_uid) - .installation(installation_uid) - .setServerConfig(this.nodeCrypto.decrypt(server_configuration)) - .then(({ data }: any) => { - if (data?.message) { - log.debug(data, this.importConfig.context); - log.error(formatError(data.message), this.importConfig.context); - } else { - log.success(`${appName} app server config updated successfully.!`, this.importConfig.context); - log.debug(`Server configuration update successful for: ${appName}`, this.importConfig.context); - } - }) - .catch((error: any) => { - log.debug(error, this.importConfig.context); - log.error(formatError(error), this.importConfig.context); - log.debug(`Server configuration update failed for: ${appName}`, this.importConfig.context); - }); + // NOTE: guard the decrypt for the same reason as `configuration` above — a bad-decrypt must + // not abort the module or skip the uid-mapping write. + let decryptedServerConfiguration: any; + try { + decryptedServerConfiguration = this.nodeCrypto.decrypt(server_configuration); + } catch (error: any) { + log.warn( + `Failed to decrypt server configuration for '${appName}'; skipping its server configuration update. The app is installed and its extension mappings are preserved. (${ + error?.message || error + })`, + this.importConfig.context, + ); + decryptedServerConfiguration = undefined; + } + + if (decryptedServerConfiguration !== undefined) { + await this.appSdk + .marketplace(this.importConfig.org_uid) + .installation(installation_uid) + .setServerConfig(decryptedServerConfiguration) + .then(({ data }: any) => { + if (data?.message) { + log.debug(data, this.importConfig.context); + log.error(formatError(data.message), this.importConfig.context); + } else { + log.success(`${appName} app server config updated successfully.!`, this.importConfig.context); + log.debug(`Server configuration update successful for: ${appName}`, this.importConfig.context); + } + }) + .catch((error: any) => { + log.debug(error, this.importConfig.context); + log.error(formatError(error), this.importConfig.context); + log.debug(`Server configuration update failed for: ${appName}`, this.importConfig.context); + }); + } } }