Fix pre post logic function not executed (#19462)
- removes pre-install function
- execute **asyncrhonously** post-install function at application
installation
- add optional `shouldRunOnVersionUpgrade` boolean value on post-install
function definition default false
- update PostInstallPayload to
```
export type PostInstallPayload = {
previousVersion?: string;
newVersion: string;
};
```
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+2
@@ -33,6 +33,8 @@ export class ApplicationExceptionFilter implements ExceptionFilter {
|
||||
case ApplicationExceptionCode.CANNOT_DOWNGRADE_APPLICATION:
|
||||
throw new UserInputError(exception);
|
||||
case ApplicationExceptionCode.PACKAGE_RESOLUTION_FAILED:
|
||||
case ApplicationExceptionCode.POST_INSTALL_ERROR:
|
||||
case ApplicationExceptionCode.PRE_INSTALL_ERROR:
|
||||
case ApplicationExceptionCode.TARBALL_EXTRACTION_FAILED:
|
||||
case ApplicationExceptionCode.UPGRADE_FAILED:
|
||||
throw new InternalServerError(exception);
|
||||
|
||||
+4
@@ -10,8 +10,10 @@ import { ApplicationPackageModule } from 'src/engine/core-modules/application/ap
|
||||
import { ApplicationInstallResolver } from 'src/engine/core-modules/application/application-install/application-install.resolver';
|
||||
import { ApplicationInstallService } from 'src/engine/core-modules/application/application-install/application-install.service';
|
||||
import { FileStorageModule } from 'src/engine/core-modules/file-storage/file-storage.module';
|
||||
import { LogicFunctionModule } from 'src/engine/core-modules/logic-function/logic-function.module';
|
||||
import { SdkClientModule } from 'src/engine/core-modules/sdk-client/sdk-client.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -21,9 +23,11 @@ import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permi
|
||||
ApplicationPackageModule,
|
||||
CacheLockModule,
|
||||
FeatureFlagModule,
|
||||
LogicFunctionModule,
|
||||
SdkClientModule,
|
||||
PermissionsModule,
|
||||
FileStorageModule,
|
||||
WorkspaceCacheModule,
|
||||
],
|
||||
providers: [ApplicationInstallResolver, ApplicationInstallService],
|
||||
exports: [ApplicationInstallService],
|
||||
|
||||
+235
-7
@@ -25,7 +25,17 @@ import {
|
||||
import { ApplicationSyncService } from 'src/engine/core-modules/application/application-manifest/application-sync.service';
|
||||
import { CacheLockService } from 'src/engine/core-modules/cache-lock/cache-lock.service';
|
||||
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
|
||||
import {
|
||||
LogicFunctionTriggerJob,
|
||||
type LogicFunctionTriggerJobData,
|
||||
} from 'src/engine/core-modules/logic-function/logic-function-trigger/jobs/logic-function-trigger.job';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { SdkClientGenerationService } from 'src/engine/core-modules/sdk-client/sdk-client-generation.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { LogicFunctionExecutorService } from 'src/engine/core-modules/logic-function/logic-function-executor/logic-function-executor.service';
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationInstallService {
|
||||
private readonly logger = new Logger(ApplicationInstallService.name);
|
||||
@@ -37,8 +47,12 @@ export class ApplicationInstallService {
|
||||
private readonly applicationPackageFetcherService: ApplicationPackageFetcherService,
|
||||
private readonly applicationSyncService: ApplicationSyncService,
|
||||
private readonly fileStorageService: FileStorageService,
|
||||
private readonly logicFunctionExecutorService: LogicFunctionExecutorService,
|
||||
private readonly cacheLockService: CacheLockService,
|
||||
private readonly sdkClientGenerationService: SdkClientGenerationService,
|
||||
@InjectMessageQueue(MessageQueue.logicFunctionQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {}
|
||||
|
||||
async installApplication(params: {
|
||||
@@ -110,7 +124,27 @@ export class ApplicationInstallService {
|
||||
|
||||
const universalIdentifier = appRegistration.universalIdentifier;
|
||||
|
||||
const existingApplication =
|
||||
await this.applicationService.findByUniversalIdentifier({
|
||||
universalIdentifier,
|
||||
workspaceId: params.workspaceId,
|
||||
});
|
||||
|
||||
const previousVersion = existingApplication?.version ?? undefined;
|
||||
|
||||
const newVersion = resolvedPackage.packageJson.version;
|
||||
|
||||
if (!isDefined(newVersion)) {
|
||||
throw new ApplicationException(
|
||||
`Package ${universalIdentifier} has no version`,
|
||||
ApplicationExceptionCode.PACKAGE_RESOLUTION_FAILED,
|
||||
);
|
||||
}
|
||||
|
||||
const isVersionUpgrade = isDefined(existingApplication);
|
||||
|
||||
const { application, wasCreated } = await this.ensureApplicationExists({
|
||||
existingApplication,
|
||||
universalIdentifier,
|
||||
name: resolvedPackage.manifest.application.displayName,
|
||||
workspaceId: params.workspaceId,
|
||||
@@ -156,6 +190,16 @@ export class ApplicationInstallService {
|
||||
params.workspaceId,
|
||||
);
|
||||
|
||||
await this.runPreInstallHook({
|
||||
manifest: resolvedPackage.manifest,
|
||||
workspaceId: params.workspaceId,
|
||||
applicationRegistrationId: appRegistration.id,
|
||||
previousVersion,
|
||||
newVersion,
|
||||
isVersionUpgrade,
|
||||
universalIdentifier,
|
||||
});
|
||||
|
||||
const { hasSchemaMetadataChanged } =
|
||||
await this.applicationSyncService.synchronizeFromManifest({
|
||||
workspaceId: params.workspaceId,
|
||||
@@ -171,6 +215,15 @@ export class ApplicationInstallService {
|
||||
});
|
||||
}
|
||||
|
||||
await this.runPostInstallHook({
|
||||
manifest: resolvedPackage.manifest,
|
||||
workspaceId: params.workspaceId,
|
||||
previousVersion,
|
||||
newVersion,
|
||||
isVersionUpgrade,
|
||||
universalIdentifier,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Successfully installed app ${universalIdentifier} v${resolvedPackage.packageJson.version ?? 'unknown'}`,
|
||||
);
|
||||
@@ -191,6 +244,185 @@ export class ApplicationInstallService {
|
||||
}
|
||||
}
|
||||
|
||||
private async runPreInstallHook(params: {
|
||||
manifest: Manifest;
|
||||
workspaceId: string;
|
||||
applicationRegistrationId?: string;
|
||||
previousVersion?: string;
|
||||
newVersion: string;
|
||||
isVersionUpgrade: boolean;
|
||||
universalIdentifier: string;
|
||||
}): Promise<void> {
|
||||
const {
|
||||
manifest,
|
||||
workspaceId,
|
||||
applicationRegistrationId,
|
||||
previousVersion,
|
||||
newVersion,
|
||||
isVersionUpgrade,
|
||||
universalIdentifier,
|
||||
} = params;
|
||||
|
||||
if (!isDefined(manifest.application.preInstallLogicFunction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.applicationSyncService.preInstallSynchronizeFromManifest({
|
||||
workspaceId: params.workspaceId,
|
||||
manifest,
|
||||
applicationRegistrationId,
|
||||
});
|
||||
|
||||
const {
|
||||
universalIdentifier: preInstallLogicFunctionUniversalIdentifier,
|
||||
shouldRunOnVersionUpgrade,
|
||||
} = manifest.application.preInstallLogicFunction;
|
||||
|
||||
if (isVersionUpgrade && !shouldRunOnVersionUpgrade) {
|
||||
this.logger.log(
|
||||
`Skipping pre-install hook for app ${universalIdentifier}: version upgrade and shouldRunOnVersionUpgrade is false`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { flatLogicFunctionMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatLogicFunctionMaps',
|
||||
]);
|
||||
|
||||
const flatLogicFunction =
|
||||
flatLogicFunctionMaps.byUniversalIdentifier[
|
||||
preInstallLogicFunctionUniversalIdentifier
|
||||
];
|
||||
|
||||
// preInstallSynchronizeFromManifest should have registered this function
|
||||
// moments ago — a miss here means the pared-down sync did not persist the
|
||||
// entry, which is a real failure and should abort the install.
|
||||
if (!isDefined(flatLogicFunction)) {
|
||||
throw new ApplicationException(
|
||||
`Pre-install logic function "${preInstallLogicFunctionUniversalIdentifier}" not found for application "${universalIdentifier}" after pre-install sync. The pared-down sync did not register the function as expected.`,
|
||||
ApplicationExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const payload = { previousVersion, newVersion };
|
||||
|
||||
this.logger.log(
|
||||
`Executing pre-install hook for app ${universalIdentifier} with payload:`,
|
||||
JSON.stringify(payload),
|
||||
);
|
||||
|
||||
const result = await this.logicFunctionExecutorService.execute({
|
||||
logicFunctionId: flatLogicFunction.id,
|
||||
workspaceId,
|
||||
payload,
|
||||
});
|
||||
|
||||
if (!isDefined(result)) {
|
||||
this.logger.log('Pre-install hook executed successfully');
|
||||
}
|
||||
|
||||
if (result.error) {
|
||||
throw new ApplicationException(
|
||||
result.error.errorMessage,
|
||||
ApplicationExceptionCode.PRE_INSTALL_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async runPostInstallHook(params: {
|
||||
manifest: Manifest;
|
||||
workspaceId: string;
|
||||
previousVersion?: string;
|
||||
newVersion: string;
|
||||
isVersionUpgrade: boolean;
|
||||
universalIdentifier: string;
|
||||
}): Promise<void> {
|
||||
const {
|
||||
manifest,
|
||||
workspaceId,
|
||||
previousVersion,
|
||||
newVersion,
|
||||
isVersionUpgrade,
|
||||
universalIdentifier,
|
||||
} = params;
|
||||
|
||||
if (!isDefined(manifest.application.postInstallLogicFunction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
universalIdentifier: postInstallLogicFunctionUniversalIdentifier,
|
||||
shouldRunOnVersionUpgrade,
|
||||
shouldRunSynchronously,
|
||||
} = manifest.application.postInstallLogicFunction;
|
||||
|
||||
if (isVersionUpgrade && !shouldRunOnVersionUpgrade) {
|
||||
this.logger.log(
|
||||
`Skipping post-install hook for app ${universalIdentifier}: version upgrade and shouldRunOnVersionUpgrade is false`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const { flatLogicFunctionMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatLogicFunctionMaps',
|
||||
]);
|
||||
|
||||
const flatLogicFunction =
|
||||
flatLogicFunctionMaps.byUniversalIdentifier[
|
||||
postInstallLogicFunctionUniversalIdentifier
|
||||
];
|
||||
|
||||
if (!isDefined(flatLogicFunction)) {
|
||||
throw new ApplicationException(
|
||||
`Post-install logic function "${postInstallLogicFunctionUniversalIdentifier}" not found for application "${universalIdentifier}" after sync. Manifest may reference a stale identifier.`,
|
||||
ApplicationExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const payload = { previousVersion, newVersion };
|
||||
|
||||
this.logger.log(
|
||||
`Enqueuing post-install hook for app ${universalIdentifier} with payload:`,
|
||||
JSON.stringify(payload),
|
||||
);
|
||||
|
||||
if (!shouldRunSynchronously) {
|
||||
await this.messageQueueService.add<LogicFunctionTriggerJobData[]>(
|
||||
LogicFunctionTriggerJob.name,
|
||||
[
|
||||
{
|
||||
logicFunctionId: flatLogicFunction.id,
|
||||
workspaceId,
|
||||
payload,
|
||||
},
|
||||
],
|
||||
{ retryLimit: 3 },
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.logicFunctionExecutorService.execute({
|
||||
logicFunctionId: flatLogicFunction.id,
|
||||
workspaceId,
|
||||
payload,
|
||||
});
|
||||
|
||||
if (!isDefined(result)) {
|
||||
this.logger.log('Post-install hook executed successfully');
|
||||
}
|
||||
|
||||
if (result.error) {
|
||||
throw new ApplicationException(
|
||||
result.error.errorMessage,
|
||||
ApplicationExceptionCode.POST_INSTALL_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async writeFilesToStorage(
|
||||
extractedDir: string,
|
||||
manifest: Manifest,
|
||||
@@ -269,19 +501,15 @@ export class ApplicationInstallService {
|
||||
}
|
||||
|
||||
private async ensureApplicationExists(params: {
|
||||
existingApplication: ApplicationEntity | null;
|
||||
universalIdentifier: string;
|
||||
name: string;
|
||||
workspaceId: string;
|
||||
applicationRegistrationId: string;
|
||||
sourceType: ApplicationRegistrationSourceType;
|
||||
}): Promise<{ application: ApplicationEntity; wasCreated: boolean }> {
|
||||
const existing = await this.applicationService.findByUniversalIdentifier({
|
||||
universalIdentifier: params.universalIdentifier,
|
||||
workspaceId: params.workspaceId,
|
||||
});
|
||||
|
||||
if (isDefined(existing)) {
|
||||
return { application: existing, wasCreated: false };
|
||||
if (isDefined(params.existingApplication)) {
|
||||
return { application: params.existingApplication, wasCreated: false };
|
||||
}
|
||||
|
||||
const application = await this.applicationService.create({
|
||||
|
||||
+146
-3
@@ -4,15 +4,15 @@ import { type Manifest } from 'twenty-shared/application';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { buildFromToAllUniversalFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/build-from-to-all-universal-flat-entity-maps.util';
|
||||
import { computeApplicationManifestAllUniversalFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/compute-application-manifest-all-universal-flat-entity-maps.util';
|
||||
import { getApplicationSubAllFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/get-application-sub-all-flat-entity-maps.util';
|
||||
import {
|
||||
ApplicationException,
|
||||
ApplicationExceptionCode,
|
||||
} from 'src/engine/core-modules/application/application.exception';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { buildFromToAllUniversalFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/build-from-to-all-universal-flat-entity-maps.util';
|
||||
import { computeApplicationManifestAllUniversalFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/compute-application-manifest-all-universal-flat-entity-maps.util';
|
||||
import { getApplicationSubAllFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/get-application-sub-all-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
@@ -33,6 +33,149 @@ export class ApplicationManifestMigrationService {
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async syncPreInstallLogicFunctionFromManifest({
|
||||
manifest,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
}: {
|
||||
manifest: Manifest;
|
||||
workspaceId: string;
|
||||
ownerFlatApplication: FlatApplication;
|
||||
}): Promise<void> {
|
||||
const preInstallLogicFunction =
|
||||
manifest.application.preInstallLogicFunction;
|
||||
|
||||
if (!isDefined(preInstallLogicFunction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const preInstallLogicFunctionManifest = manifest.logicFunctions.find(
|
||||
(logicFunction) =>
|
||||
logicFunction.universalIdentifier ===
|
||||
preInstallLogicFunction.universalIdentifier,
|
||||
);
|
||||
|
||||
if (!isDefined(preInstallLogicFunctionManifest)) {
|
||||
throw new ApplicationException(
|
||||
`Pre-install logic function "${preInstallLogicFunction.universalIdentifier}" is declared on the application manifest but not present in manifest.logicFunctions`,
|
||||
ApplicationExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const defaultRoleManifest = manifest.roles.find(
|
||||
(role) =>
|
||||
role.universalIdentifier ===
|
||||
manifest.application.defaultRoleUniversalIdentifier,
|
||||
);
|
||||
|
||||
// Pared-down manifest: only the pre-install logic function, every other
|
||||
// entity array intentionally empty. Combined with
|
||||
// inferDeletionFromMissingEntities: false below, this produces a purely
|
||||
// additive migration that registers the pre-install logic function without
|
||||
// touching any previously-synced metadata (important on upgrades).
|
||||
const strippedDefaultRoleManifest = isDefined(defaultRoleManifest)
|
||||
? {
|
||||
...defaultRoleManifest,
|
||||
objectPermissions: [],
|
||||
fieldPermissions: [],
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const preInstallOnlyManifest: Manifest = {
|
||||
application: manifest.application,
|
||||
objects: [],
|
||||
fields: [],
|
||||
logicFunctions: [preInstallLogicFunctionManifest],
|
||||
frontComponents: [],
|
||||
roles: isDefined(strippedDefaultRoleManifest)
|
||||
? [strippedDefaultRoleManifest]
|
||||
: [],
|
||||
skills: [],
|
||||
agents: [],
|
||||
publicAssets: [],
|
||||
views: [],
|
||||
navigationMenuItems: [],
|
||||
pageLayouts: [],
|
||||
};
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const cacheResult = await this.workspaceCacheService.getOrRecompute(
|
||||
workspaceId,
|
||||
[
|
||||
...Object.values(ALL_METADATA_NAME).map(getMetadataFlatEntityMapsKey),
|
||||
'featureFlagsMap',
|
||||
],
|
||||
);
|
||||
|
||||
const { featureFlagsMap, ...existingAllFlatEntityMaps } = cacheResult;
|
||||
|
||||
const fromAllFlatEntityMaps = getApplicationSubAllFlatEntityMaps({
|
||||
applicationIds: [ownerFlatApplication.id],
|
||||
fromAllFlatEntityMaps: existingAllFlatEntityMaps,
|
||||
});
|
||||
|
||||
const toAllUniversalFlatEntityMaps =
|
||||
computeApplicationManifestAllUniversalFlatEntityMaps({
|
||||
manifest: preInstallOnlyManifest,
|
||||
ownerFlatApplication,
|
||||
now,
|
||||
});
|
||||
|
||||
const dependencyAllFlatEntityMaps = getApplicationSubAllFlatEntityMaps({
|
||||
applicationIds:
|
||||
ownerFlatApplication.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier
|
||||
? [twentyStandardFlatApplication.id]
|
||||
: [ownerFlatApplication.id, twentyStandardFlatApplication.id],
|
||||
fromAllFlatEntityMaps: existingAllFlatEntityMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigrationFromTo(
|
||||
{
|
||||
// inferDeletionFromMissingEntities is intentionally omitted (undefined)
|
||||
// so this pared-down sync is purely additive — existing metadata for
|
||||
// objects/fields/other logic functions that are absent from
|
||||
// preInstallOnlyManifest are left untouched on upgrades.
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
ownerFlatApplication.universalIdentifier,
|
||||
},
|
||||
fromToAllFlatEntityMaps: buildFromToAllUniversalFlatEntityMaps({
|
||||
fromAllFlatEntityMaps,
|
||||
toAllUniversalFlatEntityMaps,
|
||||
}),
|
||||
workspaceId,
|
||||
dependencyAllFlatEntityMaps,
|
||||
additionalCacheDataMaps: { featureFlagsMap },
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
throw new WorkspaceMigrationBuilderException(
|
||||
validateAndBuildResult,
|
||||
'Validation errors occurred while syncing pre-install logic function',
|
||||
);
|
||||
}
|
||||
|
||||
await this.syncDefaultRoleAndSettingsCustomTab({
|
||||
manifest,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Pre-install logic function synced for application ${ownerFlatApplication.universalIdentifier}`,
|
||||
);
|
||||
}
|
||||
|
||||
async syncMetadataFromManifest({
|
||||
manifest,
|
||||
workspaceId,
|
||||
|
||||
+36
@@ -71,6 +71,42 @@ export class ApplicationSyncService {
|
||||
return syncResult;
|
||||
}
|
||||
|
||||
// Registers the application + only the pre-install logic function in
|
||||
// workspace metadata so the pre-install hook can resolve and execute it
|
||||
// before the main synchronizeFromManifest runs the full migrations.
|
||||
// No-op when the manifest does not declare a pre-install logic function.
|
||||
public async preInstallSynchronizeFromManifest({
|
||||
workspaceId,
|
||||
manifest,
|
||||
applicationRegistrationId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
manifest: Manifest;
|
||||
applicationRegistrationId?: string;
|
||||
}): Promise<void> {
|
||||
if (!isDefined(manifest.application.preInstallLogicFunction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const application = await this.syncApplication({
|
||||
workspaceId,
|
||||
manifest,
|
||||
applicationRegistrationId,
|
||||
});
|
||||
|
||||
const ownerFlatApplication: FlatApplication = application;
|
||||
|
||||
await this.applicationManifestMigrationService.syncPreInstallLogicFunctionFromManifest(
|
||||
{
|
||||
manifest,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
},
|
||||
);
|
||||
|
||||
this.logger.log('Pre-install sync from manifest completed');
|
||||
}
|
||||
|
||||
private async syncApplication({
|
||||
workspaceId,
|
||||
manifest,
|
||||
|
||||
@@ -18,6 +18,8 @@ export enum ApplicationExceptionCode {
|
||||
PACKAGE_RESOLUTION_FAILED = 'PACKAGE_RESOLUTION_FAILED',
|
||||
TARBALL_EXTRACTION_FAILED = 'TARBALL_EXTRACTION_FAILED',
|
||||
UPGRADE_FAILED = 'UPGRADE_FAILED',
|
||||
PRE_INSTALL_ERROR = 'PRE_INSTALL_ERROR',
|
||||
POST_INSTALL_ERROR = 'POST_INSTALL_ERROR',
|
||||
APP_ALREADY_INSTALLED = 'APP_ALREADY_INSTALLED',
|
||||
CANNOT_DOWNGRADE_APPLICATION = 'CANNOT_DOWNGRADE_APPLICATION',
|
||||
}
|
||||
@@ -52,6 +54,10 @@ const getApplicationExceptionUserFriendlyMessage = (
|
||||
return msg`Failed to extract tarball.`;
|
||||
case ApplicationExceptionCode.UPGRADE_FAILED:
|
||||
return msg`Application upgrade failed.`;
|
||||
case ApplicationExceptionCode.PRE_INSTALL_ERROR:
|
||||
return msg`Application pre-install logic function failed.`;
|
||||
case ApplicationExceptionCode.POST_INSTALL_ERROR:
|
||||
return msg`Application post-install logic function failed.`;
|
||||
case ApplicationExceptionCode.APP_ALREADY_INSTALLED:
|
||||
return msg`This version of the application is already installed in this workspace.`;
|
||||
case ApplicationExceptionCode.CANNOT_DOWNGRADE_APPLICATION:
|
||||
|
||||
Reference in New Issue
Block a user