Commit Graph

518 Commits

Author SHA1 Message Date
martmull 71d97c5398 14064 extensibility add coretriggereventlistener table (#14138)
This Pr continues the extensibility journey
- adds a `core.databaseEventTrigger` table
- add a oneToMany relation between `core.serverlessFunction` and
`core.databaseEventTrigger`
- add a job `CallDatabaseEventTriggerJobsJob` triggered by
`EntityEventsToDbListener` triggering `serverlessFunction` based on the
`core.databaseEventTrigger.settings.eventName`
- add a new `trigger-queue` to carry this job
- renamed `DatabaseEventTriggerListener` into
`WorkflowDatabaseEventTriggerListener`
2025-08-29 08:11:35 +02:00
Paul Rastoin b364acf5bb Morph relation validation v2 (#14141)
## Introduction
Binding morph relation validation to relation validation code flow
Please note that ALL create field will go through basic atomic
validation, which involve name availability and so on

close https://github.com/twentyhq/core-team-issues/issues/1407
2025-08-28 16:05:58 +00:00
Paul Rastoin 7c481abf0c Handle input transpilation morph relation v2 (#14124)
# Introduction
From `morphRelationCreationPayload` to `flatFieldMetadatas`

close https://github.com/twentyhq/core-team-issues/issues/1406

## Unit testing
I'm not a fan of covering things this way, where we could have some
strong integration testing tests in the first place
But I wanted to freeze the optimistic path computation, also covered the
exception because it was cheap, doesn't mean I won't cover them through
integration tests later anw
2025-08-28 17:22:03 +02:00
Félix Malfait e264d7f32b fix: Enable Lingui recommended rules and fix all translation violations (#14133)
- Enable lingui/no-single-variables-to-translate and all other
recommended Lingui rules
- Fix single variable translation patterns (t`${variable}` → variable)
- Fix expression-in-message violations by extracting variables
- Fix t-call-in-function violations by moving translations inside
functions
- Update ESLint configs to use linguiPlugin.configs['flat/recommended']
- Clean up unused imports and improve translation patterns
2025-08-28 15:12:38 +02:00
martmull 9b41a3be54 Add cron trigger table (#14110)
This Pr begins the extensibility journey
- adds a `core.cronTrigger` table
- add a oneToMany relation between core.serverlessFunction and
`core.cronTrigger` (one serverlessFunction can be triggered by multiple
cronTriggers)
- add a job to trigger a serverless function
- adds a cron to trigger serverlessFunction (via the trigger job) based
on the core.cronTrigger.setting.pattern
- adds a command to register the cron
- add the command in `cron-register-all.command.ts`
2025-08-28 14:47:48 +02:00
Weiko dec2239ae7 Remove typeorm service (#14116)
## Context
To simplify the way we inject our default datasource, I've recently
removed the token injection that was confusion since we only had once
configured on the module level. Now I'm removing TypeORM service which
allows us to instantiate a new Datasource with the same parameters as
the default one, it was redundant and confusing.
2025-08-28 13:21:26 +02:00
Paul Rastoin 59d90bedaa Integration testing v2 enum field types fail and success path (#14010)
# Introduction
Migrating and improving performances of field enum integrations tests
success and failing tests cases to be using the new v2 api

## Discovered issue
When deleting an object in v1 it will leave related enums until the
object is re-created
Something not done anymore within the create in v2 but in the delete
operation
We should implem an upgrade command to remove such relicas

## Bugs
- Update/create default value multi select runner wrong sql query -> FIX
- Update default value multi select regression, we should allow option
without an id to be inserted -> FIX
- default value compare dynamic json stringify convertion or not in
compare tools for object and fields
2025-08-28 10:23:04 +00:00
Weiko 533d7fe49a Deprecate legacy core datasource token (#14096) 2025-08-27 20:09:54 +02:00
Abdul Rahman 9098df7ddf Add preconfigured Workflow creation agent (#13855)
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-08-27 14:20:38 +02:00
Weiko f06786d603 Add missing FK on view tables (#14084)
## Context
View tables were missing some FK, we are also introducing delete cascade
on those tables when needed to leverage pg cascade deletion instead of
having to implement it.
Also renaming those classes with Entity suffix to follow repo
guidelines.
2025-08-26 18:59:20 +02:00
Weiko d433a576d7 Create related records after object creation with migration v2 (view, view filters, favorite) (#14068)
## Context
This PR introduces view actions for the migration v2. We should be able
to create, update and delete views through the migration runner
independently from object actions (this is not 100% true in this PR
though as I'm still passing the object metadata to build the view)
Note: Once favorite are moved out of the workspace schema, we will have
favorite actions as well, in the meantime I have to inject some code at
the end of the createOne method from the object metadata service
2025-08-26 10:54:03 +02:00
Guillim 35df56e7d8 morph fix for release 1.4 (#14029)
DataLoader Specific update du to Morph relations that have many rows

Fixes https://github.com/twentyhq/twenty/issues/14018
2025-08-21 14:43:14 +00:00
Weiko 707043c3ba Rollout field permissions (#14024)
Rolling out field permissions feature
2025-08-21 16:17:28 +02:00
Antoine Moreaux 809fe5699f feat(ai): enhance metadata handling and add support for tools, prompt… (#14002)
…s, and resources

- Removed unused `ObjectMetadataStandardIdToIdMap`.
- Updated Vite config with additional allowed hosts.
- Improved MCP service to handle `ping` method and lists for tools,
prompts, and resources.
- Refactored utility function `isFieldMetadataEntityOfType` for improved
type handling.
- Expanded MCP metadata service to include tools, prompts, and resources
support.
2025-08-21 08:45:46 +00:00
Paul Rastoin e99c67d6b5 Fail slow + structured validator error response scoped by object and fields (#13980)
# Introduction
Example of returned response: ( snapshot copy don't mind jest expect any
values )
```json
{
  "extensions": {
    "code": "BAD_USER_INPUT",
    "errors": {
      "fieldMetadata": [
        {
          "errors": [
            {
              "code": "INVALID_FIELD_INPUT",
              "message": "Name is too long",
              "userFriendlyMessage": "Name is too long",
              "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            },
          ],
          "id": Any<String>,
          "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "objectMetadataId": Any<String>,
          "operation": "create_field",
        },
        {
          "errors": [
            {
              "code": "INVALID_FIELD_INPUT",
              "message": "Name is too long",
              "userFriendlyMessage": "Name is too long",
              "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            },
          ],
          "id": Any<String>,
          "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "objectMetadataId": Any<String>,
          "operation": "create_field",
        },
        {
          "errors": [
            {
              "code": "INVALID_FIELD_INPUT",
              "message": "Name is too long",
              "userFriendlyMessage": "Name is too long",
              "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            },
          ],
          "id": Any<String>,
          "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "objectMetadataId": Any<String>,
          "operation": "create_field",
        },
        {
          "errors": [
            {
              "code": "INVALID_FIELD_INPUT",
              "message": "Name is too long",
              "userFriendlyMessage": "Name is too long",
              "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            },
          ],
          "id": Any<String>,
          "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "objectMetadataId": Any<String>,
          "operation": "create_field",
        },
        {
          "errors": [
            {
              "code": "INVALID_FIELD_INPUT",
              "message": "Name is too long",
              "userFriendlyMessage": "Name is too long",
              "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            },
          ],
          "id": Any<String>,
          "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "objectMetadataId": Any<String>,
          "operation": "create_field",
        },
      ],
      "objectMetadata": [
        {
          "errors": [
            {
              "code": "INVALID_OBJECT_INPUT",
              "message": "Name is too long",
              "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            },
          ],
          "fields": [],
          "id": Any<String>,
          "namePlural": "listingas",
          "nameSingular": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "operation": "create_object",
        },
      ],
    },
    "message": "Validation failed for 1 object(s) and 5 field(s)",
    "summary": {
      "invalidFields": 5,
      "invalidObjects": 1,
      "totalErrors": 6,
    },
    "userFriendlyMessage": "Validation failed for 1 object(s) and 5 field(s)",
  },
  "message": "Multiple validation errors occurred while creating object",
  "name": "GraphQLError",
}
```

## Note
We should put in place integrations tests on REST API too, in order to
ensure we receive the same response error
2025-08-20 17:33:15 +00:00
Weiko deec9c96da Refactor schema migration runner service discovery (#13988)
## Context
This refactoring improves scalability in the workspace migration runner
in terms of actions. Instead of relying on a switch case and multiple
changes and services + duplicate things between metadata and workspace
schema, we now have a unique module for all kind of actions and a
registry pattern to register them and run them dynamically.

Example on how to add a new "create_role" action with the future design:
```typescript
// packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/role/services/create-role-action-handler.service.ts
export class CreateRoleActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
  'create_role',
) {
  constructor(
    private readonly workspaceSchemaManagerService: WorkspaceSchemaManagerService,
    private readonly roleRepository: Repository<Role>,
  ) {}

  async executeForMetadata(
    context: WorkspaceMigrationActionRunnerArgs<CreateRoleAction>,
  ): Promise<void> {
      this.roleRepository.save({...}); // technically could use the queryRunner from context param directly instead of injecting the repository
  }

  async executeForWorkspaceSchema(
    context: WorkspaceMigrationActionRunnerArgs<CreateRoleAction>,
  ): Promise<void> {
      // this.workspaceSchemaManagerService.tableManager... -> Nothing to do in the workspace schema in the role case
  }
}
```
```typescript
// packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts
@Module({
  imports: [WorkspaceSchemaManagerModule, +TypeOrmModule.forFeature([Role]),
  providers: [
     ...
     +RoleCreateActionService
  ],
})
export class WorkspaceSchemaMigrationRunnerActionHandlersModule {}
```
```typescript
export type WorkspaceMigrationAction=
  | WorkspaceMigrationObjectAction
  ...
  +| WorkspaceMigrationRoleAction;

export type CreateRoleAction = {
   type = 'create_role',
   role: RoleEntity
};

export type WorkspaceMigrationRoleAction = CreateRoleAction;
```
2025-08-20 18:30:40 +02:00
neo773 3ef94f6e8c Refactor read only object and fields (#13936)
Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-19 18:10:35 +02:00
Guillim 90c237a185 Morph-front-settings (#13872)
# Implement Morph Frontend Settings

Possiblity to create a morh relation from the Settings !

## Overview
Morph object system with new frontend settings UI for configuring morph
relations.

## What Changed
- **New Components**: `SettingsDataModelFieldMorphRelationForm`,
`SettingsMorphRelationMultiSelect`
- **Form System**: React Hook Form + Zod validation for morph relation
configuration
- **Preview System**: Live preview of field configurations with
validation
- **State Management**: Enhanced component state handling for complex
form interactions

## Technical Details
- **Architecture**: Restructured field input/display components for
better maintainability
- **Types**: Added comprehensive TypeScript types for morph relations
(`isFieldMorphRelation`, etc.)
- **Validation**: Dynamic validation rules based on field types and
relation patterns
- **Performance**: Optimized rendering with proper state management

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-19 16:37:26 +02:00
Paul Rastoin 9eaede6e1e Fix default relation standard field deletion (#13975)
Authorize relation standard field deletion if targetObjectMetadata is
not present in existingFlatObjectMetadataMaps
2025-08-19 16:12:04 +02:00
Paul Rastoin 86170c705e Standard relation field for custom objects (#13968)
## Introduction
Introducing default standard relation field for custom objects
2025-08-19 13:53:46 +02:00
Weiko aa51ecb9d2 Fix relations creation with metadata v2 (#13967) 2025-08-18 21:48:39 +02:00
Paul Rastoin 6c23c9c46b fix(server): field metadata creation service v2 (#13963) 2025-08-18 17:50:33 +02:00
Weiko 43bb8d6043 Workspace schema migration runner v2 - Fix Enums and Create TsVector (#13955)
## Context
- Adding ts-vector generatedType/asExpression as TS_VECTOR settings
- Using those settings to setup properly tsVector searchVector column
through the new migration runner
- Fix enum creation/suppression

Note: regarding the new tsVector, we should implement a command to
update existing fields

TODO: 
- TS_VECTOR search vector column update (note: should be properly
updated whenever the object labelIdentifier is updated or a new TEXT
field is added to the object to follow the current logic)
- relation type fields and columns are not implemented yet 
- index migrations
2025-08-18 16:33:51 +02:00
Paul Rastoin 3d3191425e Workspace migration v2 builder embed field metadata validation (#13960)
# Introduction
Following https://github.com/twentyhq/twenty/pull/13934
Finalizing object migration
Also refactored existing to follow same for const loop pattern
2025-08-18 16:00:58 +02:00
Paul Rastoin 6629092645 Refactor builder to embed Object validation create/delete/update (#13934)
# Introduction
Moving validation directly in the builder that has the perfect
granularity to do it.
When importing we won't have to infer and dispatch on the operation
nature ( update delete create ) and validate accordingly

## Objects
Only migrated object validation for the moment even though create object
involves a validate flat field metadata creation call too

## TODO
- improve `otherFlatObjectMetadataMapsToValidate` naming too vague

## Next
- handle fields validation within fields actions build
- Unit test coverage validation issue on builder and validate
- integration test plugging with new feature flag

## Manual tested
- Update
- Delete
- Create TODO
2025-08-18 11:16:16 +02:00
Weiko 1707e00ad4 Workspace schema migration runner v2 (#13899) 2025-08-14 15:58:25 +02:00
Paul Rastoin ad77d2f462 ObjectMetadataServiceV2.updateOne (#13891)
# Introduction
Last service to get migrated, `updateOne` object metadata service v2
2025-08-14 09:37:52 +00:00
Paul Rastoin e8e81957a6 ObjectMetadataServiceV2.deleteOne (#13871)
# Introduction
- Implementing the delete one for the new object metadata service v2.
- Handling relation fields and fields in the first place to finally
remove the object
- puting back updatedAt and createdAt in flat metadatas
- duplicate criteria addition for flat object
- removing datasource id from object metadata dto
2025-08-13 09:20:17 +00:00
Etienne 6936993557 Unique fields - fixes (#13848)
- Enable update to unique for composite field with defaultValue
different from default defaultValue on subfield not included in unique
constraint
- Enable update to unique for standard field + Disable update to
non-unique for standard index
- Fix typo

Fixes https://github.com/twentyhq/core-team-issues/issues/1360
2025-08-13 08:40:46 +02:00
Paul Rastoin de0468d104 ObjectMetadataServiceV2.createOne (#13849)
# Introduction

Introducing v2 object metadata service create one handler v2, not
overkilling the flatObjectMetadata validation for the moment that will
require sequential validation for the import in order to handle
relations and morph relations
2025-08-12 16:49:35 +02:00
Paul Rastoin d4b5ed93a3 FieldMetadataServiceV2.updateOne (#13784)
# Introduction
Implementing the `updateOne` service handler following workspace
migration v2 style
2025-08-12 10:05:53 +00:00
Guillim 63c8bb9530 morph backend CORE api (#13517)
# Morph Relation needs some work on the core API

Especially on the Morph types

<img width="682" height="394" alt="Screenshot 2025-07-31 at 12 19 40"
src="https://github.com/user-attachments/assets/8b185ae3-3fe7-4886-97b1-ec143bb1b0f4"
/>


## Focus Areas:
- GraphQL schema generation
- Query parsing and field selection
- Morph relation field support
- Input type definition preparation
2025-08-12 11:47:02 +02:00
Charles Bochet b14063fe06 Re-add prettier (#13812)
Re add prettier in eslint.configs
2025-08-11 14:10:04 +02:00
Abdul Rahman 9b11735c57 Code first roles sync (#13667) 2025-08-11 13:14:45 +02:00
Félix Malfait 464a480043 Continue ESLINT9 Migration (#13795)
Might already fix #13793
2025-08-10 23:25:58 +02:00
Charles Bochet b55c46f4a3 Few fixes before release 1.3.0 (#13791) 2025-08-09 03:08:11 +02:00
Etienne e06fc34cbe Unique fields - add unicity toggle on data model settings (#13592)
To review after https://github.com/twentyhq/twenty/pull/13539

closes https://github.com/twentyhq/core-team-issues/issues/1224

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-08 19:15:49 +02:00
Etienne 7ce96049b8 Unique field - add unique property creation/deletion on field (#13539)
Done : 
- add isUnique prop availability on gql update/create fieldMetadata
resolvers
- add unique index creation logic at update & creation
- add unique index deletion logic at update
- update unique index if field name updated
- edge cases : can't have default value and unique fields / standard
default value excluded from index (where clause) / can't have composite
unique fields / can't create unique fields on MORPH


closes https://github.com/twentyhq/core-team-issues/issues/1222
2025-08-08 17:42:50 +02:00
Paul Rastoin 4523ee45bc Multiple errors on field input transpilation improvement (#13774)
# Introduction
- ~~returning deleted field on deleteOneField~~ postponed for later
cannot build dto from flat atm
- refactor createFieldInput transpilation to handle multiple errors
instead of throwing
- renamed extract function
2025-08-08 16:24:47 +02:00
Félix Malfait 5fae14377a Eslint migration 4 (#13773)
A new attempt to migrate!
2025-08-08 16:21:57 +02:00
Paul Rastoin 28e5186f23 FieldMetadataServiceV2.deleteOneField (#13744)
# Introduction
- Migrated the `deleteOneField` handler to new workspace migration v2
style
- Refactored the build to expect `flatObjectMetadataMaps` that he
instantly translate at the be beginning
Commented `ObjectMetadataServiceV2` as it's still not implemented
neither used
2025-08-08 15:11:47 +02:00
Marie 4708ff34c7 [permissions] Fix update of relation field permissions (#13755)
In this PR, we add some validation logic and rules in both FE and BE to
ensure field permissions are handled correctly for relation fields.

- (BE) Only one field permission per fieldMetadata is accepted per
input. This is already guaranteed in the FE. It was added to help
guarantee that, when looking within the field permissions input for a
potential field permission on a relationTargetFieldMetadataId for a
relation field, there can only be 0 or 1.
- (FE) Only field permission with new values are sent to save, to avoid
sending contradictory field permissions for related fields. E.g. let's
say I have an existing field permission restricting read permission on
company's people field. By definition I also have one on person's
company field. If I update this field permission to enable the read
permission by updating company's people field, in the previous logic I
was also going to send for upsert the existing obsolete field permission
on person's company. Thus the server does not know which is the right
value so we should only send the new value.
- (BE) If the server receives two contradictory field permissions on two
related fields, e.g. on company's people with canRead = null and
person's company with canRead = false, it throws an error.
2025-08-08 08:27:53 +00:00
Félix Malfait 0236f79ccf Fix assert unreachable, remove unused variables (#13753)
Small code cleanup
2025-08-08 09:04:45 +02:00
Félix Malfait 8b4b9ef8da Change type import rule (#13751)
Forcing "type" to be explicit, works best will rollup on the frontend to
exclude depdendencies
2025-08-08 01:27:05 +02:00
Félix Malfait b44b46109c Update try/catch syntax (#13732)
Update try/catch syntax to prepare for eslint migration
2025-08-07 22:19:43 +02:00
Raphaël Bosi 593b064448 Create resolvers and controllers for core views (#13624)
Created:
- Services
- Resolvers
- Controllers
- Tests for services
- Integration tests for GraphQL and Rest

Updated the Rest API playground

Added new feature flag `IS_CORE_VIEW_ENABLED`

Updated `viewFilter` `operand` and `view` `type` to be enums rather than
strings and generated migration file.

Closes https://github.com/twentyhq/core-team-issues/issues/1259

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-07 18:45:04 +02:00
Marie ee19ee5119 [permissions] QA fixes (#13698)
In this PR

- Introduction of readableFields and updatableFields in
objectMetadataItem selector to ease filtering from a developer
experience perspective ( + to help developers think to do it). In
discussion @lucasbordeau @charlesBochet
- Remove non-updatable field from CSV import process (@etiennejouan)
- QA fix / Non-readable fields should not show on show page
- QA fix / It should not be offered to create a kanban view on a
non-readable field
- QA fix / It should not be offered to create view groups on a
non-readable field
- QA fix / Rating field should have a readonly mode

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-07 18:21:59 +02:00
Paul Rastoin 83a560c936 Refactor FieldMetadataService and validation to consume FlatObjectMetadataMaps (#13719)
# Introduction
Following recent `FlatObjectMetadataMaps` manipulation, transpilers
utils introduction in https://github.com/twentyhq/twenty/pull/13620
Refactored the field metadata service and validator to iterate over
`FlatObjectMetadataMaps` instead of `FlatObjectMetadata[]`.

The object metadata service v2 is shadow coding
2025-08-07 17:19:07 +02:00
Marie 05c23a1297 [permissions] Fix delete and soft-delete + enable fieldPermissions in devSeeds (#13646)
In this PR
1. Fix delete and soft-delete repository methods for repositories where
permission checks are NOT bypassed: they need to have a selection of
columns to return by default. To match what we did for insert I set it
to `'*'` by default. But I feel this may be bug prone as developers will
not necessarily think to fill the right values in. Maybe we should
change the api to use selectable fields by default. @charlesBochet
2. Add field permission seeds and enable field permission feature flag
in dev
2025-08-07 10:43:28 +02:00
Charles Bochet fecf8ca913 Fix i18n issues on datamodel translation (#13710)
As per title, I believe calling i18n is bad because it's a singleton.

This singleton is being set back and force by users in
i18n.middleware.ts

Strategy:
we need to load the translations dynamically! Should be straight
forward:
- singleton (i18nService) containing all translationMessages
- singleton also containing a map of i18n instances loaded for each
locale => I've checked it's not heavy on RAM at all
- some methods to get the translation for a messageId x locale or the
whole i18n instance

==> use it everywhere, this PR only takes care of data model translation
2025-08-07 01:28:40 +02:00