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>
This commit is contained in:
Jérémy M
2024-06-22 09:26:58 +02:00
committed by GitHub
parent 91b0c2bb8e
commit 0b4bfce324
90 changed files with 979 additions and 1541 deletions

View File

@ -0,0 +1,39 @@
import { Inject, Type } from '@nestjs/common';
import { ModuleRef, createContextId } from '@nestjs/core';
import { Injector } from '@nestjs/core/injector/injector';
export class LoadServiceWithWorkspaceContext {
private readonly injector = new Injector();
constructor(
@Inject(ModuleRef)
private readonly moduleRef: ModuleRef,
) {}
async load<T>(service: T, workspaceId: string): Promise<T> {
const modules = this.moduleRef['container'].getModules();
const host = [...modules.values()].find((module) =>
module.providers.has((service as Type<T>).constructor),
);
if (!host) {
throw new Error('Host module not found for the service');
}
const contextId = createContextId();
if (this.moduleRef.registerRequestByContextId) {
this.moduleRef.registerRequestByContextId(
{ req: { workspaceId } },
contextId,
);
}
return this.injector.loadPerContext(
service,
host,
new Map(host.providers),
contextId,
);
}
}

View File

@ -36,7 +36,7 @@ export class CustomWorkspaceEntity extends BaseWorkspaceEntity {
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
position: number;
position: number | null;
@WorkspaceRelation({
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.activityTargets,

View File

@ -6,8 +6,8 @@ import {
QueryRunner,
} from 'typeorm';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/entity.manager';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
export class WorkspaceDataSource extends DataSource {
readonly manager: WorkspaceEntityManager;

View File

@ -32,10 +32,9 @@ export class WorkspaceDatasourceFactory {
dataSourceMetadata.url ??
this.environmentService.get('PG_DATABASE_URL'),
type: 'postgres',
// logging: this.environmentService.get('DEBUG_MODE')
// ? ['query', 'error']
// : ['error'],
logging: 'all',
logging: this.environmentService.get('DEBUG_MODE')
? ['query', 'error']
: ['error'],
schema: dataSourceMetadata.schema,
entities,
ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED')

View File

@ -1,6 +1,7 @@
import {
DeepPartial,
DeleteResult,
EntityManager,
FindManyOptions,
FindOneOptions,
FindOptionsWhere,
@ -29,9 +30,13 @@ export class WorkspaceRepository<
/**
* FIND METHODS
*/
override async find(options?: FindManyOptions<Entity>): Promise<Entity[]> {
override async find(
options?: FindManyOptions<Entity>,
entityManager?: EntityManager,
): Promise<Entity[]> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions(options);
const result = await super.find(computedOptions);
const result = await manager.find(this.target, computedOptions);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -39,9 +44,11 @@ export class WorkspaceRepository<
override async findBy(
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<Entity[]> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
const result = await super.findBy(computedOptions.where);
const result = await manager.findBy(this.target, computedOptions.where);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -49,9 +56,11 @@ export class WorkspaceRepository<
override async findAndCount(
options?: FindManyOptions<Entity>,
entityManager?: EntityManager,
): Promise<[Entity[], number]> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions(options);
const result = await super.findAndCount(computedOptions);
const result = await manager.findAndCount(this.target, computedOptions);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -59,9 +68,14 @@ export class WorkspaceRepository<
override async findAndCountBy(
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<[Entity[], number]> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
const result = await super.findAndCountBy(computedOptions.where);
const result = await manager.findAndCountBy(
this.target,
computedOptions.where,
);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -69,9 +83,11 @@ export class WorkspaceRepository<
override async findOne(
options: FindOneOptions<Entity>,
entityManager?: EntityManager,
): Promise<Entity | null> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions(options);
const result = await super.findOne(computedOptions);
const result = await manager.findOne(this.target, computedOptions);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -79,9 +95,11 @@ export class WorkspaceRepository<
override async findOneBy(
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<Entity | null> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
const result = await super.findOneBy(computedOptions.where);
const result = await manager.findOneBy(this.target, computedOptions.where);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -89,9 +107,11 @@ export class WorkspaceRepository<
override async findOneOrFail(
options: FindOneOptions<Entity>,
entityManager?: EntityManager,
): Promise<Entity> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions(options);
const result = await super.findOneOrFail(computedOptions);
const result = await manager.findOneOrFail(this.target, computedOptions);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -99,9 +119,14 @@ export class WorkspaceRepository<
override async findOneByOrFail(
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<Entity> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
const result = await super.findOneByOrFail(computedOptions.where);
const result = await manager.findOneByOrFail(
this.target,
computedOptions.where,
);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -113,29 +138,40 @@ export class WorkspaceRepository<
override save<T extends DeepPartial<Entity>>(
entities: T[],
options: SaveOptions & { reload: false },
entityManager?: EntityManager,
): Promise<T[]>;
override save<T extends DeepPartial<Entity>>(
entities: T[],
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<(T & Entity)[]>;
override save<T extends DeepPartial<Entity>>(
entity: T,
options: SaveOptions & { reload: false },
entityManager?: EntityManager,
): Promise<T>;
override save<T extends DeepPartial<Entity>>(
entity: T,
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<T & Entity>;
override async save<T extends DeepPartial<Entity>>(
entityOrEntities: T | T[],
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<T | T[]> {
const manager = entityManager || this.manager;
const formattedEntityOrEntities = this.formatData(entityOrEntities);
const result = await super.save(formattedEntityOrEntities as any, options);
const result = await manager.save(
this.target,
formattedEntityOrEntities as any,
options,
);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -147,15 +183,27 @@ export class WorkspaceRepository<
override remove(
entities: Entity[],
options?: RemoveOptions,
entityManager?: EntityManager,
): Promise<Entity[]>;
override remove(entity: Entity, options?: RemoveOptions): Promise<Entity>;
override remove(
entity: Entity,
options?: RemoveOptions,
entityManager?: EntityManager,
): Promise<Entity>;
override async remove(
entityOrEntities: Entity | Entity[],
options?: RemoveOptions,
entityManager?: EntityManager,
): Promise<Entity | Entity[]> {
const manager = entityManager || this.manager;
const formattedEntityOrEntities = this.formatData(entityOrEntities);
const result = await super.remove(formattedEntityOrEntities as any);
const result = await manager.remove(
this.target,
formattedEntityOrEntities,
options,
);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -172,40 +220,50 @@ export class WorkspaceRepository<
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
entityManager?: EntityManager,
): Promise<DeleteResult> {
const manager = entityManager || this.manager;
if (typeof criteria === 'object' && 'where' in criteria) {
criteria = this.transformOptions(criteria);
}
return this.delete(criteria);
return manager.delete(this.target, criteria);
}
override softRemove<T extends DeepPartial<Entity>>(
entities: T[],
options: SaveOptions & { reload: false },
entityManager?: EntityManager,
): Promise<T[]>;
override softRemove<T extends DeepPartial<Entity>>(
entities: T[],
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<(T & Entity)[]>;
override softRemove<T extends DeepPartial<Entity>>(
entity: T,
options: SaveOptions & { reload: false },
entityManager?: EntityManager,
): Promise<T>;
override softRemove<T extends DeepPartial<Entity>>(
entity: T,
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<T & Entity>;
override async softRemove<T extends DeepPartial<Entity>>(
entityOrEntities: T | T[],
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<T | T[]> {
const manager = entityManager || this.manager;
const formattedEntityOrEntities = this.formatData(entityOrEntities);
const result = await super.softRemove(
const result = await manager.softRemove(
this.target,
formattedEntityOrEntities as any,
options,
);
@ -225,12 +283,15 @@ export class WorkspaceRepository<
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
entityManager?: EntityManager,
): Promise<UpdateResult> {
const manager = entityManager || this.manager;
if (typeof criteria === 'object' && 'where' in criteria) {
criteria = this.transformOptions(criteria);
}
return this.softDelete(criteria);
return manager.softDelete(this.target, criteria);
}
/**
@ -239,29 +300,36 @@ export class WorkspaceRepository<
override recover<T extends DeepPartial<Entity>>(
entities: T[],
options: SaveOptions & { reload: false },
entityManager?: EntityManager,
): Promise<T[]>;
override recover<T extends DeepPartial<Entity>>(
entities: T[],
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<(T & Entity)[]>;
override recover<T extends DeepPartial<Entity>>(
entity: T,
options: SaveOptions & { reload: false },
entityManager?: EntityManager,
): Promise<T>;
override recover<T extends DeepPartial<Entity>>(
entity: T,
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<T & Entity>;
override async recover<T extends DeepPartial<Entity>>(
entityOrEntities: T | T[],
options?: SaveOptions,
entityManager?: EntityManager,
): Promise<T | T[]> {
const manager = entityManager || this.manager;
const formattedEntityOrEntities = this.formatData(entityOrEntities);
const result = await super.recover(
const result = await manager.recover(
this.target,
formattedEntityOrEntities as any,
options,
);
@ -281,12 +349,15 @@ export class WorkspaceRepository<
| ObjectId
| ObjectId[]
| FindOptionsWhere<Entity>,
entityManager?: EntityManager,
): Promise<UpdateResult> {
const manager = entityManager || this.manager;
if (typeof criteria === 'object' && 'where' in criteria) {
criteria = this.transformOptions(criteria);
}
return this.restore(criteria);
return manager.restore(this.target, criteria);
}
/**
@ -294,9 +365,11 @@ export class WorkspaceRepository<
*/
override async insert(
entity: QueryDeepPartialEntity<Entity> | QueryDeepPartialEntity<Entity>[],
entityManager?: EntityManager,
): Promise<InsertResult> {
const manager = entityManager || this.manager;
const formatedEntity = this.formatData(entity);
const result = await super.insert(formatedEntity);
const result = await manager.insert(this.target, formatedEntity);
const formattedResult = this.formatResult(result);
return formattedResult;
@ -317,12 +390,15 @@ export class WorkspaceRepository<
| ObjectId[]
| FindOptionsWhere<Entity>,
partialEntity: QueryDeepPartialEntity<Entity>,
entityManager?: EntityManager,
): Promise<UpdateResult> {
const manager = entityManager || this.manager;
if (typeof criteria === 'object' && 'where' in criteria) {
criteria = this.transformOptions(criteria);
}
return this.update(criteria, partialEntity);
return manager.update(this.target, criteria, partialEntity);
}
override upsert(
@ -330,50 +406,63 @@ export class WorkspaceRepository<
| QueryDeepPartialEntity<Entity>
| QueryDeepPartialEntity<Entity>[],
conflictPathsOrOptions: string[] | UpsertOptions<Entity>,
entityManager?: EntityManager,
): Promise<InsertResult> {
const manager = entityManager || this.manager;
const formattedEntityOrEntities = this.formatData(entityOrEntities);
return this.upsert(formattedEntityOrEntities, conflictPathsOrOptions);
return manager.upsert(
this.target,
formattedEntityOrEntities,
conflictPathsOrOptions,
);
}
/**
* EXIST METHODS
*/
override exist(options?: FindManyOptions<Entity>): Promise<boolean> {
override exists(
options?: FindManyOptions<Entity>,
entityManager?: EntityManager,
): Promise<boolean> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions(options);
return super.exist(computedOptions);
}
override exists(options?: FindManyOptions<Entity>): Promise<boolean> {
const computedOptions = this.transformOptions(options);
return super.exists(computedOptions);
return manager.exists(this.target, computedOptions);
}
override existsBy(
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<boolean> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
return super.existsBy(computedOptions.where);
return manager.existsBy(this.target, computedOptions.where);
}
/**
* COUNT METHODS
*/
override count(options?: FindManyOptions<Entity>): Promise<number> {
override count(
options?: FindManyOptions<Entity>,
entityManager?: EntityManager,
): Promise<number> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions(options);
return super.count(computedOptions);
return manager.count(this.target, computedOptions);
}
override countBy(
where: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<number> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
return super.countBy(computedOptions.where);
return manager.countBy(this.target, computedOptions.where);
}
/**
@ -382,57 +471,79 @@ export class WorkspaceRepository<
override sum(
columnName: PickKeysByType<Entity, number>,
where?: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<number | null> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
return super.sum(columnName, computedOptions.where);
return manager.sum(this.target, columnName, computedOptions.where);
}
override average(
columnName: PickKeysByType<Entity, number>,
where?: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<number | null> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
return super.average(columnName, computedOptions.where);
return manager.average(this.target, columnName, computedOptions.where);
}
override minimum(
columnName: PickKeysByType<Entity, number>,
where?: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<number | null> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
return super.minimum(columnName, computedOptions.where);
return manager.minimum(this.target, columnName, computedOptions.where);
}
override maximum(
columnName: PickKeysByType<Entity, number>,
where?: FindOptionsWhere<Entity> | FindOptionsWhere<Entity>[],
entityManager?: EntityManager,
): Promise<number | null> {
const manager = entityManager || this.manager;
const computedOptions = this.transformOptions({ where });
return super.maximum(columnName, computedOptions.where);
return manager.maximum(this.target, columnName, computedOptions.where);
}
override increment(
conditions: FindOptionsWhere<Entity>,
propertyPath: string,
value: number | string,
entityManager?: EntityManager,
): Promise<UpdateResult> {
const manager = entityManager || this.manager;
const computedConditions = this.transformOptions({ where: conditions });
return this.increment(computedConditions.where, propertyPath, value);
return manager.increment(
this.target,
computedConditions.where,
propertyPath,
value,
);
}
override decrement(
conditions: FindOptionsWhere<Entity>,
propertyPath: string,
value: number | string,
entityManager?: EntityManager,
): Promise<UpdateResult> {
const manager = entityManager || this.manager;
const computedConditions = this.transformOptions({ where: conditions });
return this.decrement(computedConditions.where, propertyPath, value);
return manager.decrement(
this.target,
computedConditions.where,
propertyPath,
value,
);
}
/**

View File

@ -30,12 +30,21 @@ import {
ConfigurableModuleClass,
MODULE_OPTIONS_TOKEN,
} from 'src/engine/twenty-orm/twenty-orm.module-definition';
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
@Global()
@Module({
imports: [DataSourceModule],
providers: [...entitySchemaFactories, TwentyORMManager],
exports: [EntitySchemaFactory, TwentyORMManager],
providers: [
...entitySchemaFactories,
TwentyORMManager,
LoadServiceWithWorkspaceContext,
],
exports: [
EntitySchemaFactory,
TwentyORMManager,
LoadServiceWithWorkspaceContext,
],
})
export class TwentyORMCoreModule
extends ConfigurableModuleClass