Commit Graph
100 Commits
Author SHA1 Message Date
Jérémy MandCharles Bochet de20c564c7 feat: add eslint rule for enforcing WorkspaceService naming convention (#6308)
### Description

This PR introduces a custom ESLint rule named
`inject-workspace-repository`. The purpose of this rule is to enforce
naming conventions for files and classes that use the
`@InjectWorkspaceRepository` decorator or include services ending with
`WorkspaceService` in their constructors.

### Rule Overview

The new ESLint rule checks for the following conditions:

1. **File Naming**:
- Only file ending with `.service.ts` or `.workspace-service.ts` are
checked.
- If a file contains a class using the `@InjectWorkspaceRepository`
decorator or a service ending with `WorkspaceService` in the
constructor, the file name must end with `.workspace-service.ts`.

2. **Class Naming**:
- Classes that use the `@InjectWorkspaceRepository` decorator or include
services ending with `WorkspaceService` in their constructors must have
names that end with `WorkspaceService`.

### How It Works

The rule inspects each TypeScript file to ensure that the naming
conventions are adhered to. It specifically looks for:

- Constructor parameters with the `@InjectWorkspaceRepository`
decorator.
- Constructor parameters with a type annotation ending with
`WorkspaceService`.

When such parameters are found, it checks the class name and the file
name to ensure they conform to the expected patterns.

### Example Code

#### Valid Cases

1. **Correct File and Class Name with Decorator**:
    ```typescript
    // Filename: my.workspace-service.ts
    class MyWorkspaceService {
      constructor(@InjectWorkspaceRepository() private repository) {}
    }
    ```

2. **Service Dependency**:
    ```typescript
    // Filename: another.workspace-service.ts
    class AnotherWorkspaceService {
      constructor(private myWorkspaceService: MyWorkspaceService) {}
    }
    ```

#### Invalid Cases

1. **Incorrect Class Name**:
    ```typescript
    // Filename: my.workspace-service.ts
    class MyService {
      constructor(@InjectWorkspaceRepository() private repository) {}
    }
    // Error: Class name should end with 'WorkspaceService'.
    ```

2. **Incorrect File Name**:
    ```typescript
    // Filename: my.service.ts
    class MyWorkspaceService {
      constructor(@InjectWorkspaceRepository() private repository) {}
    }
    // Error: File name should end with '.workspace-service.ts'.
    ```

3. **Incorrect File and Class Name**:
    ```typescript
    // Filename: my.service.ts
    class MyService {
      constructor(@InjectWorkspaceRepository() private repository) {}
    }
    // Error: Class name should end with 'WorkspaceService'.
    // Error: File name should end with '.workspace-service.ts'.
    ```

4. **Incorrect File Type**:
    ```typescript
    // Filename: another.service.ts
    class AnotherService {
      constructor(private myWorkspaceService: MyWorkspaceService) {}
    }
    // Error: Class name should end with 'WorkspaceService'.
    // Error: File name should end with '.workspace-service.ts'.

    ```

5. **Incorrect Class Name with Dependency**:
    ```typescript
    // Filename: another.workspace-service.ts
    class AnotherService {
      constructor(private myWorkspaceService: MyWorkspaceService) {}
    }
    // Error: Class name should end with 'WorkspaceService'.
    ```

### First step

This rule is only a warning for now, and then we'll migrate all the code
that need to be migrated and move from `warn` to `error`.

Fix #6309

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-07-19 19:17:57 +02:00
088d061b3e feat: twenty orm for standard and custom objects (#6178)
### Overview

This PR builds upon #5153, adding the ability to get a repository for
custom objects. The `entitySchema` is now generated for both standard
and custom objects based on metadata stored in the database instead of
the decorated `WorkspaceEntity` in the code. This change ensures that
standard objects with custom fields and relations can also support
custom objects.

### Implementation Details

#### Key Changes:

- **Dynamic Schema Generation:** The `entitySchema` for standard and
custom objects is now dynamically generated from the metadata stored in
the database. This shift allows for greater flexibility and
adaptability, particularly for standard objects with custom fields and
relations.
  
- **Custom Object Repository Retrieval:** A repository for a custom
object can be retrieved using `TwentyORMManager` based on the object's
name. Here's an example of how this can be achieved:

  ```typescript
const repository = await this.twentyORMManager.getRepository('custom');
  /*
* `repository` variable will be typed as follows, ensuring that standard
fields and relations are properly typed:
   * const repository: WorkspaceRepository<CustomWorkspaceEntity & {
   *    [key: string]: any;
   * }>
   */
  const res = await repository.find({});
  ```

Fix #6179

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Weiko <corentin@twenty.com>
2024-07-19 18:23:52 +02:00
Jérémy M cfb36ec0fb feat: bump yarn to last stable version (#6081)
This PR bump yarn version to latest stable version
2024-07-19 15:38:03 +02:00
Jérémy M 5df0ea6466 fix: message queue injection issue (#6126) 2024-07-04 12:22:58 +02:00
Jérémy M 921b311c65 fix: small PR fixes workspace-sync-fields (#6107)
Small fixes of PR #6069
2024-07-03 19:19:37 +02:00
Jérémy MandMarie 5b26452649 feat: refactor workspace sync fields (#6069)
This PR was first here to fix the issue related to ticket #5004, after
some testing it seems that changing the name of a relation is actually
properly working, if we rename `ONE-TO-MANY` side, the only things that
is going to be updated is the FieldMetadata as the `joinColumn` is
stored on the opposite object.
For `MANY-TO-ONE` relations, the `joinColumn` migration is properly
generated. We need to take care that if we rename a side of a relation,
sometimes the opposite side doesn't have `inverseSideFieldKey`
implemented and used by default the name of the opposite object, so this
is going to throw an error as the field can't be found in the object.

---------

Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com>
2024-07-02 17:21:13 +02:00
Jérémy M 632e34fc7b fix: message cleaner find operator (#6080)
This PR fix an issue with the `IsNull()` find operator applied on
one-to-many relation, this one is not supported by TypeORM.
We can instead filter by an empty array to retrieve object with empty
relations.
2024-07-01 11:23:22 +02:00
Jérémy M 13f213a05e feat: message cleaner drop repository (#6052)
This PR use the new `TwentyORM` for the message-cleaner module by using
the new injection system with `@InjectWorkspaceRepository`.
2024-06-30 21:57:18 +02:00
Jérémy M 95c5602a4e feat: manually implement joinColumn (#6022)
This PR introduce a new decorator named `@WorkspaceJoinColumn`, the goal
of this one is to manually declare the join columns inside the workspace
entities, so we don't have to rely on `ObjectRecord` type.

This decorator can be used that way:

```typescript
  @WorkspaceRelation({
    standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.company,
    type: RelationMetadataType.MANY_TO_ONE,
    label: 'Company',
    description: 'ActivityTarget company',
    icon: 'IconBuildingSkyscraper',
    inverseSideTarget: () => CompanyWorkspaceEntity,
    inverseSideFieldKey: 'activityTargets',
  })
  @WorkspaceIsNullable()
  company: Relation<CompanyWorkspaceEntity> | null;

  // The argument is the name of the relation above
  @WorkspaceJoinColumn('company')
  companyId: string | null;
```
2024-06-27 11:41:22 +02:00
Jérémy MandWeiko 7c2e745b45 feat: Dynamic hook registration for WorkspaceQueryHooks (#6008)
#### Overview

This PR introduces a new API for dynamically registering and executing
pre and post query hooks in the Workspace Query Hook system using the
`@WorkspaceQueryHook` decorator. This approach eliminates the need for
manual provider registration, and fix the issue of `undefined` or `null`
repository using `@InjectWorkspaceRepository`.

#### New API

**Define a Hook**

Use the `@WorkspaceQueryHook` decorator to define pre or post hooks:

```typescript
@WorkspaceQueryHook({
  key: `calendarEvent.findMany`,
  scope: Scope.REQUEST,
})
export class CalendarEventFindManyPreQueryHook implements WorkspaceQueryHookInstance {
  async execute(userId: string, workspaceId: string, payload: FindManyResolverArgs): Promise<void> {
    if (!payload?.filter?.id?.eq) {
      throw new BadRequestException('id filter is required');
    }

    // Implement hook logic here
  }
}
```

This API simplifies the registration and execution of query hooks,
providing a more flexible and maintainable approach.

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-06-25 12:41:46 +02:00
0b4bfce324 feat: drop calendar repository (#5824)
This PR is replacing and removing all the raw queries and repositories
with the new `TwentyORM` and injection system using
`@InjectWorkspaceRepository`.
Some logic that was contained inside repositories has been moved to the
services.
In this PR we're only replacing repositories for calendar feature.

---------

Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-06-22 09:26:58 +02:00
Jérémy MandWeiko d99b9d1d6b feat: Enhancements to MessageQueue Module with Decorators (#5657)
### Overview

This PR introduces significant enhancements to the MessageQueue module
by integrating `@Processor`, `@Process`, and `@InjectMessageQueue`
decorators. These changes streamline the process of defining and
managing queue processors and job handlers, and also allow for
request-scoped handlers, improving compatibility with services that rely
on scoped providers like TwentyORM repositories.

### Key Features

1. **Decorator-based Job Handling**: Use `@Processor` and `@Process`
decorators to define job handlers declaratively.
2. **Request Scope Support**: Job handlers can be scoped per request,
enhancing integration with request-scoped services.

### Usage

#### Defining Processors and Job Handlers

The `@Processor` decorator is used to define a class that processes jobs
for a specific queue. The `@Process` decorator is applied to methods
within this class to define specific job handlers.

##### Example 1: Specific Job Handlers

```typescript
import { Processor, Process, InjectMessageQueue } from 'src/engine/integrations/message-queue';

@Processor('taskQueue')
export class TaskProcessor {

  @Process('taskA')
  async handleTaskA(job: { id: string, data: any }) {
    console.log(`Handling task A with data:`, job.data);
    // Logic for task A
  }

  @Process('taskB')
  async handleTaskB(job: { id: string, data: any }) {
    console.log(`Handling task B with data:`, job.data);
    // Logic for task B
  }
}
```

In the example above, `TaskProcessor` is responsible for processing jobs
in the `taskQueue`. The `handleTaskA` method will only be called for
jobs with the name `taskA`, while `handleTaskB` will be called for
`taskB` jobs.

##### Example 2: General Job Handler

```typescript
import { Processor, Process, InjectMessageQueue } from 'src/engine/integrations/message-queue';

@Processor('generalQueue')
export class GeneralProcessor {

  @Process()
  async handleAnyJob(job: { id: string, name: string, data: any }) {
    console.log(`Handling job ${job.name} with data:`, job.data);
    // Logic for any job
  }
}
```

In this example, `GeneralProcessor` handles all jobs in the
`generalQueue`, regardless of the job name. The `handleAnyJob` method
will be invoked for every job added to the `generalQueue`.

#### Adding Jobs to a Queue

You can use the `@InjectMessageQueue` decorator to inject a queue into a
service and add jobs to it.

##### Example:

```typescript
import { Injectable } from '@nestjs/common';
import { InjectMessageQueue, MessageQueue } from 'src/engine/integrations/message-queue';

@Injectable()
export class TaskService {
  constructor(
    @InjectMessageQueue('taskQueue') private readonly taskQueue: MessageQueue,
  ) {}

  async addTaskA(data: any) {
    await this.taskQueue.add('taskA', data);
  }

  async addTaskB(data: any) {
    await this.taskQueue.add('taskB', data);
  }
}
```

In this example, `TaskService` adds jobs to the `taskQueue`. The
`addTaskA` and `addTaskB` methods add jobs named `taskA` and `taskB`,
respectively, to the queue.

#### Using Scoped Job Handlers

To utilize request-scoped job handlers, specify the scope in the
`@Processor` decorator. This is particularly useful for services that
use scoped repositories like those in TwentyORM.

##### Example:

```typescript
import { Processor, Process, InjectMessageQueue, Scope } from 'src/engine/integrations/message-queue';

@Processor({ name: 'scopedQueue', scope: Scope.REQUEST })
export class ScopedTaskProcessor {

  @Process('scopedTask')
  async handleScopedTask(job: { id: string, data: any }) {
    console.log(`Handling scoped task with data:`, job.data);
    // Logic for scoped task, which might use request-scoped services
  }
}
```

Here, the `ScopedTaskProcessor` is associated with `scopedQueue` and
operates with request scope. This setup is essential when the job
handler relies on services that need to be instantiated per request,
such as scoped repositories.

### Migration Notes

- **Decorators**: Refactor job handlers to use `@Processor` and
`@Process` decorators.
- **Request Scope**: Utilize the scope option in `@Processor` if your
job handlers depend on request-scoped services.

Fix #5628

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-06-17 09:49:37 +02:00
Jérémy MandQuentin Galliano 04edf2bf7b feat: add resolve absolute path util (#5836)
Add a new util called `resolveAbsolutePath` to allow providing absolute
path for environment variable like `STORAGE_LOCAL_PATH`.
If the path in the env start with `/` we'll not prefix it with
`process.cwd()`.

Also we're using a static path for the old `db_initialized` file now
named `db_status` and stop using the env variable for this file as this
one shouldn't ne stored in the `STORAGE_LOCAL_PATH`.

Fix #4794

---------

Co-authored-by: Quentin Galliano <qgalliano@gmail.com>
2024-06-12 21:17:31 +02:00
Jérémy M 453525ca25 fix: workspace health showing error for multi select (#5547)
Fix `workspace:health` command not working properly with `MULTI_SELECT`
field metadata type.
2024-05-23 12:02:40 +02:00
Jérémy M bb6df43d17 fix: twentyORM datasource configuration for ssl (#5529)
We need to specify ssl configuration for TwentyORM datasources when
needed, otherwise connection will be broken.
2024-05-22 11:11:05 +02:00
Jérémy M 66a23a852f fix: unwanted change moving back datetime to date (#5499)
Moving back datetime to date, due to an unwanted change.
2024-05-21 13:29:59 +02:00
Jérémy M 8b5f79ddbf fix: multiple twenty orm issues & show an example of use (#5439)
This PR is fixing some issues and adding enhancement in TwentyORM:

- [x] Composite fields in nested relations are not formatted properly
- [x] Passing operators like `Any` in `where` condition is breaking the
query
- [x] Ability to auto load workspace-entities based on a regex path

I've also introduced an example of use for `CalendarEventService`:


https://github.com/twentyhq/twenty/pull/5439/files#diff-3a7dffc0dea57345d10e70c648e911f98fe237248bcea124dafa9c8deb1db748R15
2024-05-20 11:01:47 +02:00
Jérémy MandWeiko f0383e3147 feat: twenty orm sync (#5266)
This PR is updating all object metadata entities with the new
decorators, and deleting the old ones.
This way we can use the new TwentyORM with all the standard objects.

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-05-15 16:58:47 +02:00
Jérémy M b207d10312 feat: extend twenty orm (#5238)
This PR is a follow up of PR #5153.
This one introduce some changes on how we're querying composite fields.
We can do:

```typescript
export class CompanyService {
  constructor(
    @InjectWorkspaceRepository(CompanyObjectMetadata)
    private readonly companyObjectMetadataRepository: WorkspaceRepository<CompanyObjectMetadata>,
  ) {}

  async companies(): Promise<CompanyObjectMetadata[]> {
    // Old way
    // const companiesFilteredByLinkLabel = await this.companyObjectMetadataRepository.find({
    //   where: { xLinkLabel: 'MyLabel' },
    // });
    // Result will return xLinkLabel property

    // New way
    const companiesFilteredByLinkLabel = await this.companyObjectMetadataRepository.find({
      where: { xLink: { label:  'MyLabel' } },
    });
    // Result will return { xLink: { label: 'MyLabel' } } property instead of  { xLinkLabel: 'MyLabel' }

    return companiesFilteredByLinkLabel;
  }
}
```

Also we can now inject `TwentyORMManage` class to manually create a
repository based on a given `workspaceId` using
`getRepositoryForWorkspace` function that way:

```typescript
export class CompanyService {
  constructor(
    // TwentyORMModule should be initialized
    private readonly twentyORMManager,
  ) {}

  async companies(): Promise<CompanyObjectMetadata[]> {
    const repository = await this.twentyORMManager.getRepositoryForWorkspace(
      '8bb6e872-a71f-4341-82b5-6b56fa81cd77',
      CompanyObjectMetadata,
    );

    const companies = await repository.find();

    return companies;
  }
}
```
2024-05-06 14:12:11 +02:00
Jérémy MandWeiko e2185448ed Feat/twenty orm (#5153)
## Introduction

This PR introduces "TwentyORM," a custom ORM module designed to
streamline database interactions within our workspace schema, reducing
the need for raw SQL queries. The API mirrors TypeORM's to provide a
familiar interface while integrating enhancements specific to our
project's needs.

To facilitate this integration, new decorators prefixed with `Workspace`
have been implemented. These decorators are used to define entity
metadata more explicitly and are critical in constructing our schema
dynamically.

## New Features

- **Custom ORM System**: Named "TwentyORM," which aligns closely with
TypeORM for ease of use but is tailored to our application's specific
requirements.
- **Decorator-Driven Configuration**: Entities are now configured with
`Workspace`-prefixed decorators that clearly define schema mappings and
relationships directly within the entity classes.
- **Injectable Repositories**: Repositories can be injected similarly to
TypeORM, allowing for flexible and straightforward data management.

## Example Implementations

### Decorated Entity Definitions

Entities are defined with new decorators that outline table and field
metadata, relationships, and constraints. Here are examples of these
implementations:

#### Company Metadata Object

```typescript
@WorkspaceObject({
  standardId: STANDARD_OBJECT_IDS.company,
  namePlural: 'companies',
  labelSingular: 'Company',
  labelPlural: 'Companies',
  description: 'A company',
  icon: 'IconBuildingSkyscraper',
})
export class CompanyObjectMetadata extends BaseObjectMetadata {
  @WorkspaceField({
    standardId: COMPANY_STANDARD_FIELD_IDS.name,
    type: FieldMetadataType.TEXT,
    label: 'Name',
    description: 'The company name',
    icon: 'IconBuildingSkyscraper',
  })
  name: string;

  @WorkspaceField({
    standardId: COMPANY_STANDARD_FIELD_IDS.xLink,
    type: FieldMetadataType.LINK,
    label: 'X',
    description: 'The company Twitter/X account',
    icon: 'IconBrandX',
  })
  @WorkspaceIsNullable()
  xLink: LinkMetadata;

  @WorkspaceField({
    standardId: COMPANY_STANDARD_FIELD_IDS.position,
    type: FieldMetadataType.POSITION,
    label: 'Position',
    description: 'Company record position',
    icon: 'IconHierarchy2',
  })
  @WorkspaceIsSystem()
  @WorkspaceIsNullable()
  position: number;

  @WorkspaceRelation({
    standardId: COMPANY_STANDARD_FIELD_IDS.accountOwner,
    label: 'Account Owner',
    description: 'Your team member responsible for managing the company account',
    type: RelationMetadataType.MANY_TO_ONE,
    inverseSideTarget: () => WorkspaceMemberObjectMetadata,
    inverseSideFieldKey: 'accountOwnerForCompanies',
    onDelete: RelationOnDeleteAction.SET_NULL,
  })
  @WorkspaceIsNullable()
  accountOwner: WorkspaceMemberObjectMetadata;
}
```

#### Workspace Member Metadata Object

```typescript
@WorkspaceObject({
  standardId: STANDARD_OBJECT_IDS.workspaceMember,
  namePlural: 'workspaceMembers',
  labelSingular: 'Workspace Member',
  labelPlural: 'Workspace Members',
  description: 'A workspace member',
  icon: 'IconUserCircle',
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata {
  @WorkspaceField({
    standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name,
    type: FieldMetadataType.FULL_NAME,
    label: 'Name',
    description: 'Workspace member name',
    icon: 'IconCircleUser',
  })
  name: FullNameMetadata;

  @WorkspaceRelation({
    standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.accountOwnerForCompanies,
    label: 'Account Owner For Companies',
    description: 'Account owner for companies',
    icon: 'IconBriefcase',
    type: RelationMetadataType.ONE_TO_MANY,
    inverseSideTarget: () => CompanyObjectMetadata,
    inverseSideFieldKey: 'accountOwner',
    onDelete: RelationOnDeleteAction.SET_NULL,
  })
  accountOwnerForCompanies: Relation

<CompanyObjectMetadata[]>;
}
```

### Injectable Repository Usage

Repositories can be directly injected into services, allowing for
streamlined query operations:

```typescript
export class CompanyService {
  constructor(
    @InjectWorkspaceRepository(CompanyObjectMetadata)
    private readonly companyObjectMetadataRepository: WorkspaceRepository<CompanyObjectMetadata>,
  ) {}

  async companies(): Promise<CompanyObjectMetadata[]> {
    // Example queries demonstrating simple and relation-loaded operations
    const simpleCompanies = await this.companyObjectMetadataRepository.find({});
    const companiesWithOwners = await this.companyObjectMetadataRepository.find({
      relations: ['accountOwner'],
    });
    const companiesFilteredByLinkLabel = await this.companyObjectMetadataRepository.find({
      where: { xLinkLabel: 'MyLabel' },
    });

    return companiesFilteredByLinkLabel;
  }
}
```

## Conclusions

This PR sets the foundation for a decorator-driven ORM layer that
simplifies data interactions and supports complex entity relationships
while maintaining clean and manageable code architecture. This is not
finished yet, and should be extended.
All the standard objects needs to be migrated and all the module using
the old decorators too.

---------

Co-authored-by: Weiko <corentin@twenty.com>
2024-04-29 16:47:42 +02:00
Jérémy M 35717fce8b feat: sync command missing ability to rename standard object (#4819)
We've introduced in PR #4373 standard ids to be able to rename standard
fields and objects.
Fields part was working properly, but objects part was not yet
implemented.
This PR is adding the missing parts to make it work.
2024-04-09 10:20:34 +02:00
Jérémy MandCharles Bochet 5019b5febc feat: drop target column map (#4670)
This PR is dropping the column `targetColumnMap` of fieldMetadata
entities.
The goal of this column was to properly map field to their respecting
column in the table.
We decide to drop it and instead compute the column name on the fly when
we need it, as it's more easier to support.
Some parts of the code has been refactored to try making implementation
of composite type more easier to understand and maintain.

Fix #3760

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-04-08 16:00:28 +02:00
Jérémy M 04c06e3f91 fix: isIconDisplayedOnHoverOnly marked as required (#4805)
Fix PR #4676, `isIconDisplayedOnHoverOnly` should be provided or not
marked as required
2024-04-04 14:38:54 +02:00
Jérémy M 5c0b65eecb feat: simplification of default-value specification in FieldMetadata (#4592)
* feat: wip refactor default-value

* feat: health check to migrate default value

* fix: tests

* fix: refactor defaultValue to make it more clean

* fix: unit tests

* fix: front-end default value
2024-03-27 10:56:04 +01:00
Jérémy M 3acec7731c Fix/enum bug (#4659)
* fix: sever not throwing when enum contains two identical values

* fix: enum column name cannot be change

* fix: put field create/update inside transactions

* fix: check for options duplicate values front-end

* fix: missing commit transaction
2024-03-26 16:16:29 +01:00
Jérémy MandCharles Bochet d1ab063000 feat: use ApolloFactory for metadata client (#4608)
Co-authored-by: Charles Bochet <charles@twenty.com>
2024-03-25 19:15:46 +01:00
Jérémy M 04c5d066f8 fix: create deterministic uuids for standards relation on custom object (#4642)
* fix: create deterministic uuids for standards relation on custom object

* fix: remove check if standardId already exist to override old ones
2024-03-25 16:58:58 +01:00
Jérémy M e5c1309e8c feat: wip server folder structure (#4573)
* feat: wip server folder structure

* fix: merge

* fix: wrong merge

* fix: remove unused file

* fix: comment

* fix: lint

* fix: merge

* fix: remove console.log

* fix: metadata graphql arguments broken
2024-03-20 16:23:46 +01:00
Jérémy MandCharles Bochet 94487f6737 feat: refactor folder structure (#4498)
* feat: wip refactor folder structure

* Fix

* fix position

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-03-15 14:40:58 +01:00
Jérémy M d8b370720c feat: wip sync standard id (#4373)
* feat: wip sync standard id

feat: implement standardId for sync command

* fix: rebase

* fix: tests

* fix: deterministic uuid

* fix: sync custom not working

* fix: create custom not adding standardId

* fix: readability
2024-03-13 12:06:10 +01:00
Jérémy MandCharles Bochet af6ffbcc68 feat: standard fields on custom (#4332)
* feat: add ability to sync standard fields on custom object

* fix: clean

* fix: wrong compute during object creation

* fix: missing cascade delete

* fix: remove unused injected class

* fix: naming

* fix: rename factory to paramsFactory and clean

* fix: rename ExtendCustomObjectMetadata to BaseCustomObjectMetadata

* fix: partial fix inconsistent label and description

* Fixes

* Fix

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-03-07 17:21:50 +01:00
Jérémy M c3a024b047 feat: sync all workspaces (#4353) 2024-03-07 15:40:09 +01:00
Jérémy MandThaïs Guigon e69c462b70 feat: allow backend to rename field of custom object (#4097)
* feat: allow backend to rename field of custom object

* feat: allow custom field label edition in Settings

Closes #4080

* fix: avoid renaming standard fields

---------

Co-authored-by: Thaïs Guigon <guigon.thais@gmail.com>
2024-02-21 18:59:51 +01:00
Jérémy M e3e940327e fix: workspace health undefined relation (#4107) 2024-02-21 15:36:18 +01:00
Jérémy M 3914e8d77c fix: sync and health (#4095)
* fix: throw error if we try to create a migration without columnName

* fix: typeorm save for update breaking everything
2024-02-20 17:55:23 +01:00
Jérémy M 22e8a3ba77 fix: unwanted comment on graphQL input (#4071) 2024-02-20 16:13:18 +01:00
Jérémy M 2f9e503a8b fix: ignore enum options sync for now (#4056) 2024-02-19 17:29:30 +01:00
Jérémy M e293abe332 Fix/workspace health type (#4053)
* fix: memory issue with truncate command

* fix: LINK doesn't have any default value

* fix: Cannot convert LINK to column type.

* fix: handle old column type and add a warn to fix them manually
2024-02-19 17:28:40 +01:00
Jérémy M 44ac16c82e fix: impact too many records (#3993)
* fix: impact too many records

* fix: change env name

* fix: remove env name from error
2024-02-16 11:17:37 +01:00
Jérémy M c2c14d79a9 fix: workspace cache version (#3999) 2024-02-16 11:06:51 +01:00
Jérémy M f47159d84d fix: invalidate cache when no record inside workspace cache version (#3994)
* fix: invalidate cache when no record inside workspace cache version

* fix: use getVersion
2024-02-16 10:37:25 +01:00
Jérémy M 34d02cf4ed feat: add default value for some type of fields (#3991)
feat: add default value for some kind of fields
2024-02-16 10:34:42 +01:00
Jérémy M 990cb107a1 feat: workspace health target column map fix (#3932)
* feat: workspace health fix target column map

* fix: remove log

* feat: refactor health fixer

* fix: default-value issue and health check not working with composite

* fix: enhance target column map fix

* feat: create workspace migrations for target-column-map issues

* feat: enhance workspace-health issue detection
2024-02-15 18:04:12 +01:00
Jérémy M 8ce7020b12 feat: sync metadata can alter and update a field (#3944) 2024-02-13 19:36:58 +01:00
Jérémy M 35fce6a6b4 feat: health check enum (#3913)
* feat: health check enum

* fix: cleaner if condition
2024-02-12 17:32:05 +01:00
Jérémy M b0b033aec9 fix: workspace health (#3916)
* fix: workspace health applying migrations multiple times

* fix: remove log

* fix: use logger
2024-02-12 16:17:17 +01:00
Jérémy M 2560ce25e0 feat: workspace health default-value fix (#3894)
* feat: workspace health default-value fix

* fix: rename function regarding review
2024-02-09 14:16:11 +01:00
Jérémy MandCharles Bochet 7ec968d5a2 feat: workspace health type fix (#3890)
* feat: workspace health type fix

* Fix

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-02-08 18:59:17 +01:00
Jérémy M d3fe1b9e31 feat: workspace:health nullable fix (#3882) 2024-02-08 18:22:29 +01:00
Jérémy M 6e3a8e3461 Feat/workspace health core fix (#3863)
* feat: add deletion support on sync metadata command

* fix: remove debug

* feat: wip workspace health command add --fix option

fix: remove test

* feat: core of --fix option for workspace-health
2024-02-07 18:27:35 +01:00
Jérémy M a908353955 feat: add deletion support on sync metadata command (#3826)
* feat: add deletion support on sync metadata command

* fix: remove debug
2024-02-07 15:38:23 +01:00
Jérémy Mandcorentin a802338996 fix: options value can't contain special characters (#3738)
* fix: options value can't contain special characters

* add tests for formatFieldMetadataItemInput util

* fix test

* fix: add emoji test

---------

Co-authored-by: corentin <corentin@twenty.com>
2024-02-05 15:12:08 +01:00
Jérémy M 5fd982b009 feat: execute pending migrations command (#3767) 2024-02-02 11:10:26 +01:00
Jérémy M 25f4a80c7c fix: exception handler (#3768)
* fix: user is not sent to sentry

* fix: too much exceptions thrown
2024-02-02 09:26:48 +01:00
Jérémy M 9799326533 fix: logs folder doesn't exist (#3759) 2024-02-01 16:47:36 +01:00
Jérémy M 3c89a97a9f feat: add dry-run option to sync-metadata command (#3758)
* feat: add dry-run option to sync-metadata command

* feat: save metadata logs in dry-run mode
2024-02-01 16:35:32 +01:00
Jérémy M cdc51add7d feat: add user to sentry (#3467)
* feat: wip add user to sentry

* feat: wip interceptor

* feat: wip add user to sentry

* feat: add user into sentry errors

* fix: hide stack trace in production

* fix: properly log commands and handle exceptions

* fix: filter command exceptions

* feat: handle jobs errors
2024-02-01 16:14:08 +01:00
Jérémy M 8abd5be4b5 fix: sync metadata shouldn't remove non custom fields (#3750)
* fix: sync metadata shouldn't remove non custom fields

* fix: filter out custom relations
2024-02-01 14:25:50 +01:00
Jérémy M fc01c8cd4f fix: grapQL errors are not detailed enough (#3622) 2024-02-01 09:45:58 +01:00
Jérémy M 73f6876641 feat: workspace sync (#3505)
* feat: wip workspace sync

* feat: wip lot of debugging

* feat: refactor and fix sync

* fix: clean

fix: clean

* feat: add simple comparator tests

* fix: remove debug

* feat: wip drop table

* fix: main merge

* fix: some issues, and prepare storage system to handle complex deletion

* feat: wip clean and fix

* fix: reflect issue when using array instead of map and clean

* fix: test & sync

* fix: yarn files

* fix: unecesary if-else

* fix: if condition not needed

* fix: remove debug

* fix: replace EQUAL by SKIP

* fix: sync metadata relation not applied properly

* fix: lint issues

* fix: merge issue
2024-01-30 14:40:55 +01:00
Jérémy MandCharles Bochet da8dd671d1 fix: rating type issues (#3638)
* fix: rating type issues

* fix: rebase

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2024-01-30 09:57:30 +01:00
Jérémy M 6f98d1847f Fix/nested filter (#3624)
* fix: typo

* fix: relation type shouldn't be exposed in filter
2024-01-25 16:15:46 +01:00
Jérémy M 4b7e42c38e feat: workspace health relation (#3466)
feat: add check relation health
2024-01-17 17:05:35 +01:00
Jérémy M 3e8f4ec2c5 fix: auth user decorator cannot destruct property of undefined (#3394)
* fix: auth user decorator cannot destruct property of undefined

* fix: change naming
2024-01-12 12:12:33 +01:00
Jérémy M d0ed9ee2e0 feat: pagination with total count (#3384)
* feat: add totalCount

* feat: add command for production to fix existing tables
2024-01-12 10:41:38 +01:00
Jérémy M 5f0c9f67c9 feat: workspace health (#3344)
* feat: wip workspace health

* feat: split structure and metadata check

* feat: check default value structure health

* feat: check targetColumnMap structure health

* fix: composite types doesn't have default value properly defined

* feat: check default value structure health

* feat: check options structure health

* fix: verbose option not working properly

* fix: word issue

* fix: tests

* fix: remove console.log

* fix: TRUE and FALSE instead of YES and NO

* fix: fieldMetadataType instead of type
2024-01-11 16:41:25 +01:00
Jérémy M 1aa0f86724 feat: use apollo playground in debug mode (#3295) 2024-01-11 10:21:51 +01:00
Jérémy M 2dae94dec6 fix: pg_graphql performance (#3204) 2024-01-02 16:06:15 +01:00
d532f22fbb feat: migration can be applied on a specific schema & some enhancements (#2998)
* fix: remove old metadata seed files

* feat: wip standard to core relation

* fix: lint

* fix: merge

* fix: remove debug files

* feat: add feature flag for core object metadata

* fix: remove debug

* feat: always disable the standard core relation

* fix: missing feature flag

* fix: remove debug

* fix: feature flag doesn't seems to disable relation

* fix: delete .vscode folder, change this in another PR

* Update packages/twenty-server/src/workspace/workspace-sync-metadata/reflective-metadata.factory.ts

Co-authored-by: Weiko <corentin@twenty.com>

* Update packages/twenty-server/src/workspace/workspace-sync-metadata/reflective-metadata.factory.ts

Co-authored-by: Weiko <corentin@twenty.com>

* Update packages/twenty-server/src/workspace/workspace-sync-metadata/workspace-sync.metadata.service.ts

Co-authored-by: Weiko <corentin@twenty.com>

* fix: remove optional fields from metadata entities

* fix: renamed variable

* fix: put back CursorScalarType

* fix: delete test command

* fix: remove unused workspace standard migration command

* fix: drop core object metadata declaration

* fix: rename variable

* fix: drop creation of core datasource

* fix: remove feature flag

* fix: drop support of standard to core relations

* feat: add user email field on workspace-member standard object

* fix: update seed accordingly

* fix: missing remove command file

* fix: datasource label should remain nullable

* fix: better asserts

* Remove unused code

* Remove unused code

---------

Co-authored-by: Weiko <corentin@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2023-12-21 19:15:05 +01:00
Jérémy M 3234134a30 fix: composite type migrations not well formatted (#3088) 2023-12-21 19:00:33 +01:00
Jérémy M d59a37129f fix: sentry doesn't catch exceptions from flexible backend (#3074)
* fix: sentry doesn't catch exceptions from flexible backend

* fix: send remaining errors to Sentry

* fix: missing debug

* feat: use an util exception handler instead of Nest.JS class
2023-12-20 12:04:59 +01:00
Jérémy M 8381869c7f fix: workspace migration isNullable (#2939) 2023-12-12 15:18:37 +01:00
Jérémy M 44f1fe54e1 fix: use proper variable name (#2938) 2023-12-12 14:57:42 +01:00
Jérémy M b9de9f1a08 fix: add vscode workspace (#2937) 2023-12-11 15:45:45 +01:00
Jérémy M 63196f866f fix: relation on self not working (#2875) 2023-12-08 12:06:31 +01:00
Jérémy M cf334ada0e feat: exceptions handlers (#2855)
* feat: wip exception handlers

* feat: exception capturer

* fix: rename exception-capturer into exception-handler

* fix: remove unused variable
2023-12-08 10:18:50 +01:00
Jérémy M d70f8deeec Fix/enum validation (#2863)
* fix: SELECT enum can have a color key

* fix: "findOneOrFail" of undefined

* feat: alter column migration store previous metadata informations

* fix: enum validation extra keys
2023-12-07 17:04:49 +01:00
Jérémy MandWeiko 93decaceab fix: FieldMetadata default value and options better validation (#2785)
* fix: wip better field metadata validation

* fix: remove files

* fix: default value and options validation

* fix: small fix

* fix: try to limit patch

* fix: tests

* Update server/src/metadata/field-metadata/validators/is-field-metadata-options.validator.ts

Co-authored-by: Weiko <corentin@twenty.com>

* fix: lint

* fix: standard fields update security

---------

Co-authored-by: Weiko <corentin@twenty.com>
2023-12-06 15:19:23 +01:00
Jérémy M 9df83c9a5a feat: better server lint (#2850)
* feat: add stylistic eslint plugin

* feat: add missing line return

* feat: secure line-break style

* feat: disallow break before else

* feat: line between class members

* feat: better new line lint rule
2023-12-06 12:19:00 +01:00
Jérémy M 474db1e142 fix: nested relations not working and relations not prefixed (#2782)
* fix: nested relations n+n

* fix: prefix custom relations

* fix: only apply targetColumnMap when it's a custom object

* fix: force workspaceId to be provided

* fix: toIsCustom -> isToCustom

* fix: remove console.log
2023-12-01 15:26:48 +01:00
Jérémy M 6e6f0af26e feat: Adding support for new FieldMetadataType with Postgres enums (#2674)
* feat: add enum type (RATING, SELECT, MULTI_SELECT)

feat: wip enum type

feat: try to alter enum

feat: wip enum

feat: wip enum

feat: schema-builder can handle enum

fix: return default value in field metadata response

* fix: create fieldMedata with options

* fix: lint issues

* fix: rename abstract factory

* feat: drop `PHONE` and `EMAIL` fieldMetadata types

* feat: drop `VARCHAR` fieldMetadata type and rely on `TEXT`

* Revert "feat: drop `PHONE` and `EMAIL` fieldMetadata types"

This reverts commit 3857539f7d42f17c81f6ab92a6db950140b3c8e5.
2023-11-30 15:24:26 +01:00
Jérémy MandCharles Bochet 2b597d817c fix: empty string as default value for string types (#2691)
* fix: empty string as default value for string types

* Fixes

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2023-11-24 16:30:28 +01:00
Jérémy M 0da1a98021 fix: wrong file name (#2676) 2023-11-23 15:31:09 +01:00
Jérémy M 4c1c6a3407 fix: can't create fields of type UUID (#2642) 2023-11-22 14:58:13 +01:00
Jérémy M 5c8c141556 feat: workspace cache version instead of event emitter (#2637) 2023-11-22 14:51:26 +01:00
Jérémy M dd125ddfcc feat: add memory cache to boost performance (#2620)
* feat: add memory cache to boost performance

* fix: tests

* fix: logging

* fix: missing commented stuff
2023-11-21 18:29:31 +01:00
Jérémy MandCharles Bochet 3ad30a0498 fix: not able to filter by nullable values (#2580)
Co-authored-by: Charles Bochet <charles@twenty.com>
2023-11-20 15:46:20 +01:00
Jérémy MandCharles Bochet b86ada6d2b feat: rename tenant into workspace (#2553)
* feat: rename tenant into workspace

* fix: missing some files and reset not working

* fix: wrong import

* Use link in company seeds

* Use link in company seeds

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2023-11-17 11:26:33 +01:00
Jérémy M e9827486c0 feat: add default value capability (#2544)
* feat: add default value capability

* feat: update seeds with default value
2023-11-16 18:25:11 +01:00
Jérémy MandCharles Bochet e026b2b6e9 feat: expose foreign key (#2505)
* fix: typo

* feat: expose foreign key

* fix: foreign key exposition

* fix: be able to filter by foreign key

* feat: add `isSystem` on field metadata

* feat: update all seeds

* fix: seed issues

* fix: sync metadata generated files

* fix: squash metadata migrations

* Fix conflicts

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2023-11-16 12:30:40 +01:00
Jérémy M c02717c1e3 fix: schema builder use same type definitions storage across tenant (#2525) 2023-11-15 17:23:30 +01:00
Jérémy M 65af954671 fix: relations issues (#2497)
* fix: relations issues

one-to-one relation not working
alias should not be used on the foreignKey side

* fix: naming
2023-11-14 12:07:17 +01:00
Jérémy M 6a700ad1a5 feat: schema-builder and resolver-builder can handle relations (#2398)
* feat: wip add relation

* feat: add relation for custom and standards objects

* fix: use enum instead of magic string

* fix: remove dead code & fix tests

* fix: typo

* fix: BooleanFilter is missing

* fix: Malformed result error
2023-11-10 12:32:02 +01:00
Jérémy M 3432615a17 fix: small tenant refactor fixes (#2375) 2023-11-06 15:49:06 +01:00
Jérémy MandCharles Bochet 1ed4965a95 feat: refactor schema builder and resolver builder (#2215)
* feat: wip refactor schema builder

* feat: wip store types and first queries generation

* feat: refactor schema-builder and resolver-builder

* fix: clean & small type fix

* fix: avoid breaking change

* fix: remove util from pg-graphql classes

* fix: required default fields

* Refactor frontend accordingly

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2023-11-03 17:16:37 +01:00
Jérémy M 80a6223d7d feat: custom objects delete one (#2278)
* feat: custom objects delete one

* fix: delete one issue
2023-10-30 12:05:03 +01:00
Jérémy M 3e83cb6846 feat: conditional filtering & aggregation support & data ordering support (#2107)
* feat: wip

* feat: add filter on findOne

* fix: tests & small bug

* feat: add test and support aggregation

* feat: add order by support

* fix: fix comments

* fix: tests
2023-10-19 15:24:36 +02:00
Jérémy M c4fa36402b feat: add default filter types (#2087)
* feat: add default filter types

* fix: fields doesn't need to be a function
2023-10-17 17:57:02 +02:00
Jérémy M 4a96ae225e feat: easier makefile commands (#2077)
* feat: easier makefile commands

* fix: cleaner command
2023-10-17 10:38:10 +02:00
Jérémy M 4e993316a6 feat: conditional schema based on column map instead of column field (#1978)
* feat: wip conditional schema based on column map instead of column field

* feat: conditionalSchema columnMap and singular plural

* fix: remove uuid fix

* feat: add name and label (singular/plural) drop old tableColumnName
2023-10-12 18:28:27 +02:00