From c171c620995c01c2e9f602b3bf10d4d75718696e Mon Sep 17 00:00:00 2001 From: "Abdullah." <125115953+mabdullahabaid@users.noreply.github.com> Date: Mon, 22 Jun 2026 19:08:09 +0500 Subject: [PATCH] chore(twenty-server): upgrade typeorm to 0.3.29 (#21957) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Upgrades **typeorm `0.3.26` → `0.3.29`** and adapts the twenty-orm `update`/`upsert` overrides to typeorm's newly-added `options.returning`. Upgrading to resolve [this](https://github.com/twentyhq/twenty/security/dependabot/1573) alert. ## Why `0.3.29` is the latest release compatible with `@ptc-org/nestjs-query-typeorm` (peers `typeorm@^0.3.15`; the `1.x` line has no compatible release, so it's blocked until that dependency moves). ## Changes **`chore` — bump** - `typeorm` patch descriptor `0.3.26 → 0.3.29` + `yarn.lock`. - Local patch carried over **unchanged** (pure rename) — both hunks (`PickKeysByType` nullable-awareness, `DeleteResult.generatedMaps`) are still absent upstream in `0.3.29`, so it remains load-bearing. **`refactor` — adapt overrides** - `0.3.29` adds `options?: UpdateOptions` (carrying `returning`) to `EntityManager`/`Repository` `update()`. The override must accept it at the base-mandated position, so it's added as its **own dedicated parameter** (not hidden inside `permissionOptions`), honoring `options.returning` with a fallback to Twenty's permission-aware `selectedColumns` (`'*'` default). - The same merge is applied to `upsert()`, which already received `UpsertOptions` but was dropping its `returning` field — so both write methods now treat the option identically. - Internal call sites + specs updated for the new parameter slot. ## Verification - `nx typecheck twenty-server` — **0 errors** - twenty-orm unit tests — **191 / 191 pass** - `oxlint` / `oxfmt` — clean --- packages/twenty-server/package.json | 2 +- ...eorm+0.3.26.patch => typeorm+0.3.29.patch} | 0 .../workspace-entity-manager.spec.ts | 8 +- .../workspace-entity-manager.ts | 10 +- .../__tests__/workspace.repository.spec.ts | 1 + .../repository/workspace.repository.ts | 3 + .../workflow-common.workspace-service.ts | 2 + .../workflow-run.workspace-service.ts | 1 + .../workflow-trigger.workspace-service.ts | 4 + yarn.lock | 95 +++++++++++-------- 10 files changed, 83 insertions(+), 43 deletions(-) rename packages/twenty-server/patches/{typeorm+0.3.26.patch => typeorm+0.3.29.patch} (100%) diff --git a/packages/twenty-server/package.json b/packages/twenty-server/package.json index ed0e3596a9..bd5cb66da0 100644 --- a/packages/twenty-server/package.json +++ b/packages/twenty-server/package.json @@ -166,7 +166,7 @@ "tsdav": "^2.2.0", "tslib": "2.8.1", "type-fest": "4.10.1", - "typeorm": "patch:typeorm@0.3.26#./patches/typeorm+0.3.26.patch", + "typeorm": "patch:typeorm@0.3.29#./patches/typeorm+0.3.29.patch", "unzipper": "^0.12.3", "uuid": "^11.1.1", "zod": "^4.1.11" diff --git a/packages/twenty-server/patches/typeorm+0.3.26.patch b/packages/twenty-server/patches/typeorm+0.3.29.patch similarity index 100% rename from packages/twenty-server/patches/typeorm+0.3.26.patch rename to packages/twenty-server/patches/typeorm+0.3.29.patch diff --git a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts index a1591b8a16..8bdd0d75c1 100644 --- a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts +++ b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts @@ -474,7 +474,13 @@ describe('WorkspaceEntityManager', () => { describe('Update Methods', () => { it('should call createQueryBuilder with permissionOptions for update', async () => { await withWorkspaceContext(mockWorkspaceContext, () => - entityManager.update('test-entity', {}, {}, mockPermissionOptions), + entityManager.update( + 'test-entity', + {}, + {}, + undefined, + mockPermissionOptions, + ), ); expect(entityManager['createQueryBuilder']).toHaveBeenCalledWith( 'test-entity', diff --git a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts index 9b11c62aa4..a815b8f665 100644 --- a/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts +++ b/packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.ts @@ -30,6 +30,7 @@ import { FindOptionsUtils } from 'typeorm/find-options/FindOptionsUtils'; import { EntityPersistExecutor } from 'typeorm/persistence/EntityPersistExecutor'; import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'; import { PlainObjectToDatabaseEntityTransformer } from 'typeorm/query-builder/transformer/PlainObjectToDatabaseEntityTransformer'; +import { type UpdateOptions } from 'typeorm/repository/UpdateOptions'; import { type UpsertOptions } from 'typeorm/repository/UpsertOptions'; import { InstanceChecker } from 'typeorm/util/InstanceChecker'; @@ -320,7 +321,7 @@ export class WorkspaceEntityManager extends EntityManager { .into(target) .values(entities) .orUpdate(overwrites, conflictTargets, upsertOptions) - .returning(selectedColumns); + .returning(options.returning ?? selectedColumns); return queryBuilder.execute(); } @@ -338,6 +339,7 @@ export class WorkspaceEntityManager extends EntityManager { | ObjectId[] | unknown, partialEntity: QueryDeepPartialEntity, + options?: UpdateOptions, permissionOptions?: PermissionOptions, selectedColumns: string[] | '*' = '*', ): Promise { @@ -370,7 +372,7 @@ export class WorkspaceEntityManager extends EntityManager { .update() .set(partialEntity) .whereInIds(criteria) - .returning(selectedColumns) + .returning(options?.returning ?? selectedColumns) .execute(); } else { return this.createQueryBuilder( @@ -382,7 +384,7 @@ export class WorkspaceEntityManager extends EntityManager { .update() .set(partialEntity) .where(criteria) - .returning(selectedColumns) + .returning(options?.returning ?? selectedColumns) .execute(); } } @@ -438,6 +440,7 @@ export class WorkspaceEntityManager extends EntityManager { target, criteria, values, + undefined, permissionOptions, selectedColumns, ); @@ -1050,6 +1053,7 @@ export class WorkspaceEntityManager extends EntityManager { target, criteria, values, + undefined, permissionOptions, selectedColumns, ); diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/__tests__/workspace.repository.spec.ts b/packages/twenty-server/src/engine/twenty-orm/repository/__tests__/workspace.repository.spec.ts index beee23a5e6..6043b62cd6 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/__tests__/workspace.repository.spec.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/__tests__/workspace.repository.spec.ts @@ -405,6 +405,7 @@ describe('WorkspaceRepository', () => { 'test-entity', { id: 'test-id' }, { name: 'test' }, + undefined, { shouldBypassPermissionChecks: false, objectRecordsPermissions: mockObjectRecordsPermissions, diff --git a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts index b6295f5d63..60c0c9668c 100644 --- a/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts +++ b/packages/twenty-server/src/engine/twenty-orm/repository/workspace.repository.ts @@ -17,6 +17,7 @@ import { } from 'typeorm'; import { type PickKeysByType } from 'typeorm/common/PickKeysByType'; import { type QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity'; +import { type UpdateOptions } from 'typeorm/repository/UpdateOptions'; import { type UpsertOptions } from 'typeorm/repository/UpsertOptions'; import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface'; @@ -592,6 +593,7 @@ export class WorkspaceRepository< | ObjectId[] | FindOptionsWhere, partialEntity: QueryDeepPartialEntity, + options?: UpdateOptions, entityManager?: WorkspaceEntityManager, selectedColumns?: string[], ): Promise { @@ -610,6 +612,7 @@ export class WorkspaceRepository< this.target, criteria, partialEntity, + options, permissionOptions, selectedColumns, ); diff --git a/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts index eb7a639a87..5d79fd5df0 100644 --- a/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/common/workspace-services/workflow-common.workspace-service.ts @@ -408,6 +408,7 @@ export class WorkflowCommonWorkspaceService { await workflowRepository.update( workflowId, { statuses: newStatuses }, + undefined, queryRunner.manager, ); } @@ -417,6 +418,7 @@ export class WorkflowCommonWorkspaceService { await workflowVersionRepository.update( workflowVersion.id, { status: WorkflowVersionStatus.DEACTIVATED }, + undefined, queryRunner.manager, ); } diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts index 3f726c4bea..b4bcdbe653 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service.ts @@ -438,6 +438,7 @@ export class WorkflowRunWorkspaceService { workflowRunToUpdate.id, partialUpdate, undefined, + undefined, ['id'], ); }, authContext); diff --git a/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts index 70343f23fa..dac5177802 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service.ts @@ -283,6 +283,7 @@ export class WorkflowTriggerWorkspaceService { await workflowVersionRepository.update( { id: workflow.lastPublishedVersionId }, { status: WorkflowVersionStatus.ARCHIVED }, + undefined, queryRunner.manager, ); } @@ -290,6 +291,7 @@ export class WorkflowTriggerWorkspaceService { await workflowRepository.update( { id: workflow.id }, { lastPublishedVersionId: workflowVersion.id }, + undefined, queryRunner.manager, ); } @@ -317,6 +319,7 @@ export class WorkflowTriggerWorkspaceService { await workflowVersionRepository.update( { id: workflowVersion.id }, { status: WorkflowVersionStatus.ACTIVE }, + undefined, queryRunner.manager, ); @@ -374,6 +377,7 @@ export class WorkflowTriggerWorkspaceService { await workflowVersionRepository.update( { id: workflowVersion.id }, { status: WorkflowVersionStatus.DEACTIVATED }, + undefined, queryRunner.manager, ); diff --git a/yarn.lock b/yarn.lock index 9c1aadfa46..b5810cd0b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26923,6 +26923,13 @@ __metadata: languageName: node linkType: hard +"ansis@npm:^4.2.0": + version: 4.3.1 + resolution: "ansis@npm:4.3.1" + checksum: 10c0/d1a48090f9c33b18f254a3496e5336a20391a51140b552a1c0bc38710ae7c8bc36a62658f28759797d7bce15e89b893e9ef1962ea1ea42a291d112263f6e593c + languageName: node + linkType: hard + "any-promise@npm:^1.0.0": version: 1.3.0 resolution: "any-promise@npm:1.3.0" @@ -31051,7 +31058,7 @@ __metadata: languageName: node linkType: hard -"dayjs@npm:^1.10.0, dayjs@npm:^1.11.13": +"dayjs@npm:^1.10.0, dayjs@npm:^1.11.20": version: 1.11.21 resolution: "dayjs@npm:1.11.21" checksum: 10c0/bd97dfdc4bfea3c66268635690313828b386faa040fbc1f829ff42a2bd748b72c9d9b3c8f9616ce9e61fcb78923f1461a462c969c54b1084458ae1b715898fb0 @@ -31228,6 +31235,18 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^1.7.2": + version: 1.7.2 + resolution: "dedent@npm:1.7.2" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: 10c0/acaff07cac355b93f17b1b17ebbb84d3cc55af6ab4b7814c3f505e061903e168bc6bf9ddce331552d64dee1525f0b4c549c9ade46aebfac6f69caaed74e90751 + languageName: node + linkType: hard + "deeks@npm:3.1.0": version: 3.1.0 resolution: "deeks@npm:3.1.0" @@ -31914,7 +31933,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.3.0, dotenv@npm:^16.4.5, dotenv@npm:^16.4.7, dotenv@npm:^16.5.0": +"dotenv@npm:^16.3.0, dotenv@npm:^16.4.5, dotenv@npm:^16.5.0, dotenv@npm:^16.6.1": version: 16.6.1 resolution: "dotenv@npm:16.6.1" checksum: 10c0/15ce56608326ea0d1d9414a5c8ee6dcf0fffc79d2c16422b4ac2268e7e2d76ff5a572d37ffe747c377de12005f14b3cc22361e79fc7f1061cce81f77d2c973dc @@ -35337,7 +35356,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.5": +"glob@npm:^10.0.0, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.5.0": version: 10.5.0 resolution: "glob@npm:10.5.0" dependencies: @@ -50682,7 +50701,7 @@ __metadata: languageName: node linkType: hard -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.11": +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12": version: 2.4.12 resolution: "sha.js@npm:2.4.12" dependencies: @@ -51596,7 +51615,7 @@ __metadata: languageName: node linkType: hard -"sql-highlight@npm:^6.0.0": +"sql-highlight@npm:^6.1.0": version: 6.1.0 resolution: "sql-highlight@npm:6.1.0" checksum: 10c0/9614f4608bfde8ea7bf9b2fe9233dcc99a619c91cbc3f5cd85a6fb5ad4b2177f4ac8ca4a0191f4243ff8aea3b6f2a1229efc88635298269e0049b2ac08bde263 @@ -54304,7 +54323,7 @@ __metadata: twenty-emails: "workspace:*" twenty-shared: "workspace:*" type-fest: "npm:4.10.1" - typeorm: "patch:typeorm@0.3.26#./patches/typeorm+0.3.26.patch" + typeorm: "patch:typeorm@0.3.29#./patches/typeorm+0.3.29.patch" unzipper: "npm:^0.12.3" uuid: "npm:^11.1.1" zod: "npm:^4.1.11" @@ -54705,38 +54724,38 @@ __metadata: languageName: node linkType: hard -"typeorm@npm:0.3.26": - version: 0.3.26 - resolution: "typeorm@npm:0.3.26" +"typeorm@npm:0.3.29": + version: 0.3.29 + resolution: "typeorm@npm:0.3.29" dependencies: "@sqltools/formatter": "npm:^1.2.5" - ansis: "npm:^3.17.0" + ansis: "npm:^4.2.0" app-root-path: "npm:^3.1.0" buffer: "npm:^6.0.3" - dayjs: "npm:^1.11.13" - debug: "npm:^4.4.0" - dedent: "npm:^1.6.0" - dotenv: "npm:^16.4.7" - glob: "npm:^10.4.5" - sha.js: "npm:^2.4.11" - sql-highlight: "npm:^6.0.0" + dayjs: "npm:^1.11.20" + debug: "npm:^4.4.3" + dedent: "npm:^1.7.2" + dotenv: "npm:^16.6.1" + glob: "npm:^10.5.0" + reflect-metadata: "npm:^0.2.2" + sha.js: "npm:^2.4.12" + sql-highlight: "npm:^6.1.0" tslib: "npm:^2.8.1" - uuid: "npm:^11.1.0" + uuid: "npm:^11.1.1" yargs: "npm:^17.7.2" peerDependencies: - "@google-cloud/spanner": ^5.18.0 || ^6.0.0 || ^7.0.0 + "@google-cloud/spanner": ^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 "@sap/hana-client": ^2.14.22 better-sqlite3: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 ioredis: ^5.0.4 mongodb: ^5.8.0 || ^6.0.0 - mssql: ^9.1.1 || ^10.0.1 || ^11.0.1 + mssql: ^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0 mysql2: ^2.2.5 || ^3.0.1 oracledb: ^6.3.0 pg: ^8.5.1 pg-native: ^3.0.0 pg-query-stream: ^4.0.0 redis: ^3.1.1 || ^4.0.0 || ^5.0.14 - reflect-metadata: ^0.1.14 || ^0.2.0 sql.js: ^1.4.0 sqlite3: ^5.0.3 ts-node: ^10.7.0 @@ -54778,42 +54797,42 @@ __metadata: typeorm: cli.js typeorm-ts-node-commonjs: cli-ts-node-commonjs.js typeorm-ts-node-esm: cli-ts-node-esm.js - checksum: 10c0/a09ed0609a5799718bc837450b84593f6a64e6698e0662162eee2f7f12591ad9cb6f9173b42ae1d16f784d1ea09712c6e886481f4a3bdc7f851402cfde54e65a + checksum: 10c0/9fe642e87657ff81005edfcf983f183a3172adba0eaca90fdc36fba1dd1348b41444f2b168d98adc57f3dc16b20b86bdde65c489cad9ba35bb7627c103dcc413 languageName: node linkType: hard -"typeorm@patch:typeorm@0.3.26#./patches/typeorm+0.3.26.patch::locator=twenty-server%40workspace%3Apackages%2Ftwenty-server": - version: 0.3.26 - resolution: "typeorm@patch:typeorm@npm%3A0.3.26#./patches/typeorm+0.3.26.patch::version=0.3.26&hash=e61204&locator=twenty-server%40workspace%3Apackages%2Ftwenty-server" +"typeorm@patch:typeorm@0.3.29#./patches/typeorm+0.3.29.patch::locator=twenty-server%40workspace%3Apackages%2Ftwenty-server": + version: 0.3.29 + resolution: "typeorm@patch:typeorm@npm%3A0.3.29#./patches/typeorm+0.3.29.patch::version=0.3.29&hash=e61204&locator=twenty-server%40workspace%3Apackages%2Ftwenty-server" dependencies: "@sqltools/formatter": "npm:^1.2.5" - ansis: "npm:^3.17.0" + ansis: "npm:^4.2.0" app-root-path: "npm:^3.1.0" buffer: "npm:^6.0.3" - dayjs: "npm:^1.11.13" - debug: "npm:^4.4.0" - dedent: "npm:^1.6.0" - dotenv: "npm:^16.4.7" - glob: "npm:^10.4.5" - sha.js: "npm:^2.4.11" - sql-highlight: "npm:^6.0.0" + dayjs: "npm:^1.11.20" + debug: "npm:^4.4.3" + dedent: "npm:^1.7.2" + dotenv: "npm:^16.6.1" + glob: "npm:^10.5.0" + reflect-metadata: "npm:^0.2.2" + sha.js: "npm:^2.4.12" + sql-highlight: "npm:^6.1.0" tslib: "npm:^2.8.1" - uuid: "npm:^11.1.0" + uuid: "npm:^11.1.1" yargs: "npm:^17.7.2" peerDependencies: - "@google-cloud/spanner": ^5.18.0 || ^6.0.0 || ^7.0.0 + "@google-cloud/spanner": ^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 "@sap/hana-client": ^2.14.22 better-sqlite3: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 ioredis: ^5.0.4 mongodb: ^5.8.0 || ^6.0.0 - mssql: ^9.1.1 || ^10.0.1 || ^11.0.1 + mssql: ^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0 mysql2: ^2.2.5 || ^3.0.1 oracledb: ^6.3.0 pg: ^8.5.1 pg-native: ^3.0.0 pg-query-stream: ^4.0.0 redis: ^3.1.1 || ^4.0.0 || ^5.0.14 - reflect-metadata: ^0.1.14 || ^0.2.0 sql.js: ^1.4.0 sqlite3: ^5.0.3 ts-node: ^10.7.0 @@ -54855,7 +54874,7 @@ __metadata: typeorm: cli.js typeorm-ts-node-commonjs: cli-ts-node-commonjs.js typeorm-ts-node-esm: cli-ts-node-esm.js - checksum: 10c0/66268d90c1019c0b1c39971985d0f3f673f0236ce9a21835c7de16d5db54e3dcee39cbfad1985b0e0feb603b4f440fb25c6c6222c55a17452ac1b746d3a9e0f5 + checksum: 10c0/8966a5471cb4b54922a2b1b408f9d1cef0cdd0c247807741cef6f510ce1b2954e77d788fa4f772d38c2edd0625640c3357be57aee57dd59add9b326c59f301b6 languageName: node linkType: hard