From adb68668fbeee20ef727b461c2059f854943d079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Wed, 22 Apr 2026 16:32:49 +0200 Subject: [PATCH] refactor(pre-installed-apps): extract parsePreInstalledApps util MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `@ValidateIf` callback on EXA_API_KEY in config-variables.ts (added in the stacked PR) reimplements the same comma-split-trim-filter logic as PreInstalledAppsService.getPreInstalledPackageNames. Extract the pure parser once so the startup-validator and the runtime service can share the invariant (whitespace, empty handling) — if the parsing rule ever changes, both sites update together. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../pre-installed-apps/pre-installed-apps.service.ts | 10 ++++------ .../utils/parse-pre-installed-apps.util.ts | 9 +++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/utils/parse-pre-installed-apps.util.ts diff --git a/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/pre-installed-apps.service.ts b/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/pre-installed-apps.service.ts index 83c7b65af7a..a0cdd18936a 100644 --- a/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/pre-installed-apps.service.ts +++ b/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/pre-installed-apps.service.ts @@ -10,6 +10,7 @@ import { ApplicationRegistrationVariableEntity } from 'src/engine/core-modules/a import { ApplicationRegistrationEntity } from 'src/engine/core-modules/application/application-registration/application-registration.entity'; import { ApplicationRegistrationSourceType } from 'src/engine/core-modules/application/application-registration/enums/application-registration-source-type.enum'; import { ApplicationRegistrationService } from 'src/engine/core-modules/application/application-registration/application-registration.service'; +import { parsePreInstalledApps } from 'src/engine/core-modules/application/pre-installed-apps/utils/parse-pre-installed-apps.util'; import { SecretEncryptionService } from 'src/engine/core-modules/secret-encryption/secret-encryption.service'; import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; @@ -49,12 +50,9 @@ export class PreInstalledAppsService implements OnApplicationBootstrap { } getPreInstalledPackageNames(): string[] { - const raw = this.twentyConfigService.get('PRE_INSTALLED_APPS') ?? ''; - - return raw - .split(',') - .map((name) => name.trim()) - .filter((name) => name.length > 0); + return parsePreInstalledApps( + this.twentyConfigService.get('PRE_INSTALLED_APPS'), + ); } // Idempotent: fetches each pre-installed package's manifest from the diff --git a/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/utils/parse-pre-installed-apps.util.ts b/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/utils/parse-pre-installed-apps.util.ts new file mode 100644 index 00000000000..274d1a244d8 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/application/pre-installed-apps/utils/parse-pre-installed-apps.util.ts @@ -0,0 +1,9 @@ +// Parses the `PRE_INSTALLED_APPS` env string into a list of npm package +// names. Shared between the config validator (at startup-time) and +// PreInstalledAppsService (at runtime) so the two code paths can't drift +// on whitespace/empty handling. +export const parsePreInstalledApps = (raw: string | undefined): string[] => + (raw ?? '') + .split(',') + .map((name) => name.trim()) + .filter((name) => name.length > 0);