fix: migrate driver modules to DriverFactoryBase lazy-loading pattern (#18731)

## Summary

- Migrates `LogicFunctionModule`, `CodeInterpreterModule`, and
`CaptchaModule` from the `forRootAsync` + injection token pattern to the
`DriverFactoryBase` lazy-loading pattern (matching `EmailModule` and
`FileStorageModule`)
- Fixes #18724 where `LOGIC_FUNCTION_TYPE` was not respected in worker
processes because the driver was created at module boot time before the
DB config cache was loaded
- Removes `isEnvOnly` from `LOGIC_FUNCTION_TYPE`,
`CODE_INTERPRETER_TYPE`, `CAPTCHA_DRIVER`, `IS_MULTIWORKSPACE_ENABLED`,
and `FRONTEND_URL` — these can now be safely configured via the database
at runtime

## How it works

Each migrated module now uses a `DriverFactory` (extending
`DriverFactoryBase`) instead of a module-level async factory + Symbol
injection token:

1. **Lazy creation**: `getCurrentDriver()` creates the driver on first
call, after `DatabaseConfigDriver.onModuleInit()` has loaded the DB
cache
2. **Auto-recreation**: If config changes in the DB, the next
`getCurrentDriver()` call detects the key mismatch and creates a new
driver instance
3. **Unified config**: Both server and worker read from the same
database — driver config only needs to be set once

### Files deleted (old pattern)
- `logic-function-module.factory.ts`,
`logic-function-drivers.module.ts`, `logic-function-driver.constants.ts`
- `code-interpreter-module.factory.ts`
- `captcha.module-factory.ts`, `captcha-driver.constants.ts`

### Files created (new pattern)
- `logic-function-driver.factory.ts`
- `code-interpreter-driver.factory.ts`
- `captcha-driver.factory.ts`

Net: **-150 lines**

## Test plan

- [x] `npx nx typecheck twenty-server` passes
- [x] `npx nx lint:diff-with-main twenty-server` passes
- [ ] Integration tests pass (`npx nx run
twenty-server:test:integration:with-db-reset`)
- [ ] Verify logic functions execute in workflow runs (the original bug)
- [ ] Verify code interpreter works in workflow code steps
- [ ] Verify captcha validation works on sign-up (when captcha is
configured)


Made with [Cursor](https://cursor.com)
This commit is contained in:
Félix Malfait
2026-03-18 16:00:45 +01:00
committed by GitHub
parent fe4512f80c
commit c6f11d8adb
49 changed files with 420 additions and 769 deletions
@@ -84,7 +84,6 @@ describe('ClientConfigController', () => {
provider: undefined,
siteKey: undefined,
},
chromeExtensionId: undefined,
api: {
mutationMaximumAffectedRecords: 100,
},
@@ -213,9 +213,6 @@ export class ClientConfig {
@Field(() => Captcha)
captcha: Captcha;
@Field(() => String, { nullable: true })
chromeExtensionId: string | undefined;
@Field(() => ApiConfig)
api: ApiConfig;
@@ -77,7 +77,6 @@ describe('ClientConfigService', () => {
SENTRY_FRONT_DSN: 'https://sentry.example.com',
CAPTCHA_DRIVER: CaptchaDriverType.GOOGLE_RECAPTCHA,
CAPTCHA_SITE_KEY: 'site-key-123',
CHROME_EXTENSION_ID: 'extension-123',
MUTATION_MAXIMUM_AFFECTED_RECORDS: 1000,
IS_ATTACHMENT_PREVIEW_ENABLED: true,
ANALYTICS_ENABLED: true,
@@ -145,7 +144,6 @@ describe('ClientConfigService', () => {
provider: 'GOOGLE_RECAPTCHA',
siteKey: 'site-key-123',
},
chromeExtensionId: 'extension-123',
api: {
mutationMaximumAffectedRecords: 1000,
},
@@ -165,7 +165,6 @@ export class ClientConfigService {
provider: captchaProvider ? captchaProvider : undefined,
siteKey: this.twentyConfigService.get('CAPTCHA_SITE_KEY'),
},
chromeExtensionId: this.twentyConfigService.get('CHROME_EXTENSION_ID'),
api: {
mutationMaximumAffectedRecords: this.twentyConfigService.get(
'MUTATION_MAXIMUM_AFFECTED_RECORDS',