[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

@ -47,6 +47,7 @@ registerEnumType(FieldMetadataType, {
@ObjectType('Field')
@Authorize({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authorize: (context: any) => ({
workspaceId: { eq: context?.req?.workspace?.id },
}),

View File

@ -69,6 +69,8 @@ export class FieldMetadataValidationService<
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private async validateSettings(validator: any, settings: any) {
try {
const settingsInstance = plainToInstance(validator, settings);
@ -77,6 +79,7 @@ export class FieldMetadataValidationService<
} catch (error) {
const errorMessages = Array.isArray(error)
? error
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.map((err: any) => Object.values(err.constraints))
.flat()
.join(', ')

View File

@ -530,9 +530,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
};
if ('standardOverrides' in fieldMetadataInput) {
updatableStandardFieldInput.standardOverrides = (
fieldMetadataInput as any
).standardOverrides;
updatableStandardFieldInput.standardOverrides =
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(fieldMetadataInput as any).standardOverrides;
}
if (

View File

@ -270,6 +270,7 @@ export class BeforeUpdateOneField<T extends UpdateFieldInput>
// Reset the override by setting it to null
const localeTranslations = update.standardOverrides.translations[locale];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(localeTranslations as Record<string, any>)[overrideKey] = null;
return true;
@ -325,6 +326,7 @@ export class BeforeUpdateOneField<T extends UpdateFieldInput>
const localeTranslations = update.standardOverrides.translations[locale];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(localeTranslations as Record<string, any>)[overrideKey] = value;
}

View File

@ -7,6 +7,7 @@ import { fieldMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-mod
export class FieldMetadataGraphqlApiExceptionInterceptor
implements NestInterceptor
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
intercept(_: ExecutionContext, next: CallHandler): Observable<any> {
return next
.handle()

View File

@ -8,6 +8,7 @@ export const assertDoesNotNullifyDefaultValueForNonNullableField = ({
defaultValueFromUpdate,
}: {
isNullable: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
defaultValueFromUpdate?: any;
}) => {
if (!isNullable && defaultValueFromUpdate === null) {

View File

@ -2,6 +2,7 @@ import { FieldMetadataDefaultSerializableValue } from 'src/engine/metadata-modul
export const unserializeDefaultValue = (
serializedDefaultValue: FieldMetadataDefaultSerializableValue,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): any => {
if (serializedDefaultValue === null) {
return null;

View File

@ -73,6 +73,7 @@ export const validateDefaultValueForType = (
};
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const validators = defaultValueValidatorsMap[type] as any[];
if (!validators) {
@ -88,6 +89,7 @@ export const validateDefaultValueForType = (
: { value: defaultValue };
const defaultValueInstance = plainToInstance<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any,
FieldMetadataClassValidation
>(validator, conputedDefaultValue as FieldMetadataClassValidation);

View File

@ -59,6 +59,7 @@ export const validateOptionsForType = (
const isValid = options.every((option) => {
return validators.some((validator) => {
const optionsInstance = plainToInstance<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any,
FieldMetadataDefaultOption | FieldMetadataComplexOption
>(validator, option);

View File

@ -12,6 +12,7 @@ export function IsQuotedString(validationOptions?: ValidationOptions) {
propertyName: propertyName,
options: validationOptions,
validator: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
validate(value: any) {
return typeof value === 'string' && /^'{1}.*'{1}$/.test(value);
},

View File

@ -14,6 +14,7 @@ export function IsValidGraphQLEnumName(validationOptions?: ValidationOptions) {
propertyName: propertyName,
options: validationOptions,
validator: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
validate(value: any) {
return typeof value === 'string' && graphQLEnumNameRegex.test(value);
},

View File

@ -16,6 +16,7 @@ import { IndexMetadataDTO } from './index-metadata.dto';
@ObjectType('IndexField')
@Authorize({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authorize: (context: any) => ({
workspaceId: { eq: context?.req?.workspace?.id },
}),

View File

@ -35,6 +35,7 @@ registerEnumType(IndexType, {
@ObjectType('Index')
@Authorize({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authorize: (context: any) => ({
workspaceId: { eq: context?.req?.workspace?.id },
}),

View File

@ -18,6 +18,7 @@ import { BeforeDeleteOneObject } from 'src/engine/metadata-modules/object-metada
@ObjectType('Object')
@Authorize({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authorize: (context: any) => ({
workspaceId: { eq: context?.req?.workspace?.id },
}),

View File

@ -13,6 +13,7 @@ export class BeforeCreateOneObject<T extends CreateObjectInput>
{
async run(
instance: CreateOneInputType<T>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: any,
): Promise<CreateOneInputType<T>> {
const workspaceId = context?.req?.workspace?.id;

View File

@ -17,6 +17,7 @@ export class BeforeDeleteOneObject implements BeforeDeleteOneHook {
async run(
instance: DeleteOneInputType,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: any,
): Promise<DeleteOneInputType> {
const workspaceId = context?.req?.workspace?.id;

View File

@ -246,6 +246,7 @@ export class BeforeUpdateOneObject<T extends UpdateObjectPayload>
// Reset the override by setting it to null
const localeTranslations = update.standardOverrides.translations[locale];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(localeTranslations as Record<string, any>)[overrideKey] = null;
return true;
@ -301,6 +302,7 @@ export class BeforeUpdateOneObject<T extends UpdateObjectPayload>
const localeTranslations = update.standardOverrides.translations[locale];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(localeTranslations as Record<string, any>)[overrideKey] = value;
}

View File

@ -7,6 +7,7 @@ import { objectMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-mo
export class ObjectMetadataGraphqlApiExceptionInterceptor
implements NestInterceptor
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
intercept(_: ExecutionContext, next: CallHandler): Observable<any> {
return next
.handle()

View File

@ -26,6 +26,7 @@ registerEnumType(RelationMetadataType, {
@ObjectType('RelationMetadata')
@Authorize({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authorize: (context: any) => ({
workspaceId: { eq: context?.req?.workspace?.id },
}),

View File

@ -13,6 +13,7 @@ export class BeforeCreateOneRelation<T extends CreateRelationInput>
{
async run(
instance: CreateOneInputType<T>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: any,
): Promise<CreateOneInputType<T>> {
const workspaceId = context?.req?.workspace?.id;

View File

@ -22,6 +22,7 @@ export class BeforeDeleteOneRelation implements BeforeDeleteOneHook {
async run(
instance: DeleteOneInputType,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: any,
): Promise<DeleteOneInputType> {
const workspaceId = context?.req?.workspace?.id;

View File

@ -7,6 +7,7 @@ import { relationMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-
export class RelationMetadataGraphqlApiExceptionInterceptor
implements NestInterceptor
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
intercept(_: ExecutionContext, next: CallHandler): Observable<any> {
return next
.handle()

View File

@ -16,6 +16,7 @@ export type DeepPartial<T> = {
export const buildUpdateRemoteServerRawQuery = (
remoteServerToUpdate: DeepPartial<RemoteServerEntity<RemoteServerType>> &
Pick<RemoteServerEntity<RemoteServerType>, 'workspaceId' | 'id'>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): [any[], string] => {
const options: string[] = [];
@ -67,7 +68,9 @@ export const buildUpdateRemoteServerRawQuery = (
const buildParametersAndPositions = (
remoteServerToUpdate: DeepPartial<RemoteServerEntity<RemoteServerType>> &
Pick<RemoteServerEntity<RemoteServerType>, 'workspaceId' | 'id'>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): [any[], object] => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const parameters: any[] = [remoteServerToUpdate.id];
const parametersPositions = {};

View File

@ -9,6 +9,7 @@ import {
RemoteServerExceptionCode,
} from 'src/engine/metadata-modules/remote-server/remote-server.exception';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const remoteServerGraphqlApiExceptionHandler = (error: any) => {
if (error instanceof RemoteServerException) {
switch (error.code) {

View File

@ -32,6 +32,7 @@ registerEnumType(ServerlessFunctionSyncStatus, {
@ObjectType('ServerlessFunction')
@Authorize({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
authorize: (context: any) => ({
workspaceId: { eq: context?.req?.workspace?.id },
}),

View File

@ -8,6 +8,7 @@ import {
ServerlessFunctionExceptionCode,
} from 'src/engine/metadata-modules/serverless-function/serverless-function.exception';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const serverlessFunctionGraphQLApiExceptionHandler = (error: any) => {
if (error instanceof ServerlessFunctionException) {
switch (error.code) {

View File

@ -6,6 +6,7 @@ export const isArgDefinedIfProvidedOrThrow = ({
}: {
input: object;
key: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
}) => {
if (key in input && !isDefined(value)) {

View File

@ -31,6 +31,7 @@ export interface WorkspaceMigrationColumnDefinition {
isArray?: boolean;
isNullable: boolean;
isUnique?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
defaultValue: any;
generatedType?: 'STORED' | 'VIRTUAL';
asExpression?: string;

View File

@ -26,6 +26,7 @@ export class WorkspaceMigrationFactory {
private factoriesMap: Map<
FieldMetadataType,
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
factory: WorkspaceColumnActionFactory<any>;
options?: WorkspaceColumnActionOptions;
}
@ -41,6 +42,7 @@ export class WorkspaceMigrationFactory {
this.factoriesMap = new Map<
FieldMetadataType,
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
factory: WorkspaceColumnActionFactory<any>;
options?: WorkspaceColumnActionOptions;
}