[QRQC_2] No explicit any in twenty-server (#12068)

# Introduction

Added a no-explicit-any rule to the twenty-server, not applicable to
tests and integration tests folder

Related to https://github.com/twentyhq/core-team-issues/issues/975
Discussed with Charles

## In case of conflicts
Until this is approved I won't rebased and handle conflict, just need to
drop two latest commits and re run the scripts etc

## Legacy
We decided not to handle the existing lint error occurrences and
programmatically ignored them through a disable next line rule comment

## Open question
We might wanna activate the
[no-explicit-any](https://typescript-eslint.io/rules/no-explicit-any/)
`ignoreRestArgs` for our use case ?
```
    ignoreRestArgs?: boolean;
```

---------

Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
This commit is contained in:
Paul Rastoin
2025-05-15 16:26:38 +02:00
committed by GitHub
parent c95c4383b4
commit a8423e8503
213 changed files with 453 additions and 4 deletions

View File

@ -158,5 +158,6 @@ export class CustomWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
// eslint-disable-next-line @typescript-eslint/no-explicit-any
searchVector: any;
}

View File

@ -75,6 +75,7 @@ export class WorkspaceDataSource extends DataSource {
Object.assign(queryRunner, { manager: manager });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return queryRunner as any as WorkspaceQueryRunner;
}

View File

@ -8,6 +8,7 @@ import { TypedReflect } from 'src/utils/typed-reflect';
export function WorkspaceFieldIndex(
options?: WorkspaceIndexOptions,
): PropertyDecorator {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (target: any, propertyKey: string | symbol) => {
if (propertyKey === undefined) {
throw new Error('This decorator should be used with a field not a class');

View File

@ -16,6 +16,7 @@ export function WorkspaceGate(options: WorkspaceGateOptions) {
);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (target: any, propertyKey?: string | symbol) => {
if (propertyKey !== undefined) {
TypedReflect.defineMetadata(

View File

@ -18,6 +18,7 @@ export function WorkspaceIndex(
throw new Error('Class level WorkspaceIndex should be used with columns');
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (target: any) => {
const gate = TypedReflect.getMetadata(
'workspace:gate-metadata-args',

View File

@ -1,6 +1,7 @@
import { TypedReflect } from 'src/utils/typed-reflect';
export function WorkspaceIsSearchable() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return function (target: any): void {
TypedReflect.defineMetadata(
'workspace:is-searchable-metadata-args',

View File

@ -1,6 +1,7 @@
import { TypedReflect } from 'src/utils/typed-reflect';
export function WorkspaceIsSystem() {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return function (target: any, propertyKey?: string | symbol): void {
if (propertyKey !== undefined) {
TypedReflect.defineMetadata(

View File

@ -4,6 +4,7 @@ import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manag
import { TypedReflect } from 'src/utils/typed-reflect';
export function WorkspaceIsUnique(): PropertyDecorator {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (target: any, propertyKey: string | symbol) => {
if (propertyKey === undefined) {
throw new Error('This decorator should be used with a field not a class');

View File

@ -26,6 +26,7 @@ import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.
export class WorkspaceEntityManager extends EntityManager {
private readonly internalContext: WorkspaceInternalContext;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
readonly repositories: Map<string, Repository<any>>;
declare connection: WorkspaceDataSource;
@ -190,6 +191,7 @@ export class WorkspaceEntityManager extends EntityManager {
roleId,
shouldBypassPermissionChecks,
}: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
target: EntityTarget<any>;
dataSource: WorkspaceDataSource;
shouldBypassPermissionChecks: boolean;
@ -240,6 +242,7 @@ export class WorkspaceEntityManager extends EntityManager {
}
private extractTargetNameSingularFromEntityTarget(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
target: EntityTarget<any>,
): string {
return this.connection.getMetadata(target).name;

View File

@ -4,6 +4,7 @@ import { FactoryProvider, ModuleMetadata } from '@nestjs/common';
export interface TwentyORMOptions {}
export type TwentyORMModuleAsyncOptions = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
useFactory: (...args: any[]) => TwentyORMOptions | Promise<TwentyORMOptions>;
} & Pick<ModuleMetadata, 'imports'> &
Pick<FactoryProvider, 'inject'>;

View File

@ -39,6 +39,7 @@ export class WorkspaceInsertQueryBuilder<
) as this;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
override execute(): Promise<any> {
validateQueryIsPermittedOrThrow(
this.expressionMap,

View File

@ -50,12 +50,14 @@ export class WorkspaceSelectQueryBuilder<
return super.getMany();
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
override getRawOne<U = any>(): Promise<U | undefined> {
this.validatePermissions();
return super.getRawOne();
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
override getRawMany<U = any>(): Promise<U[]> {
this.validatePermissions();

View File

@ -23,6 +23,7 @@ export function formatData<T>(
) as T;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const newData: Record<string, any> = {};
const fieldMetadataByJoinColumnName =
objectMetadataItemWithFieldMaps.fields.reduce((acc, fieldMetadata) => {
@ -69,8 +70,10 @@ export function formatData<T>(
}
function formatCompositeField(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any,
fieldMetadata: FieldMetadataInterface,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): Record<string, any> {
const compositeType = compositeTypeDefinitions.get(
fieldMetadata.type as CompositeFieldMetadataType,
@ -82,6 +85,7 @@ function formatCompositeField(
);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const formattedCompositeField: Record<string, any> = {};
for (const property of compositeType.properties) {
@ -100,6 +104,7 @@ function formatCompositeField(
}
function formatFieldMetadataValue(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any,
fieldMetadata: FieldMetadataInterface,
) {

View File

@ -16,6 +16,7 @@ import { isDate } from 'src/utils/date/isDate';
import { isValidDate } from 'src/utils/date/isValidDate';
export function formatResult<T>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any,
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps | undefined,
objectMetadataMaps: ObjectMetadataMaps,
@ -194,6 +195,7 @@ export function getCompositeFieldMetadataMap(
}
function formatFieldMetadataValue(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any,
fieldMetadata: FieldMetadataInterface,
) {