refactor(schema): reorganize IndexField and related types (#22439)

## Summary

Querying `indexMetadatas { indexFieldMetadatas { ... } }` on the
`/metadata` GraphQL endpoint fails with a 500:

> Nest could not find IndexFieldMetadataDTOAuthorizer element (this
provider does not
> exist in the current context)

The `@CursorConnection('indexFieldMetadatas', ...)` decorator on
`IndexMetadataDTO` makes nestjs-query auto-generate a relation resolver
that injects an authorizer for `IndexFieldMetadataDTO`. That authorizer
is never provided, because the DTO was never registered as a resolver in
`IndexMetadataModule` — so the field has been broken since it was
introduced in #7162.

Since the working, DataLoader-backed `indexFieldMetadataList` field
already exposes the same data (and is what the frontend uses), this PR
removes the dead connection instead of wiring up the authorizer.

## Changes

- Remove `@CursorConnection('indexFieldMetadatas', ...)` from
`IndexMetadataDTO`
- Regenerate frontend metadata GraphQL types
(`twenty-front/src/generated-metadata`)
- Regenerate client SDK metadata schema/types
(`twenty-client-sdk/src/metadata/generated`)

## Notes

- Not a breaking change in practice: the removed field always threw, so
no consumer can have been relying on it. Callers now get a standard
GraphQL validation error suggesting `indexFieldMetadataList` instead of
an internal server error.
- Verified locally: the failing query now returns `Cannot query field
"indexFieldMetadatas" on type "Index". Did you mean
"indexFieldMetadataList"?` and `indexFieldMetadataList` continues to
work.

Fixes [sonarly issue #54098](https://sonarly.com/issue/54098?type=bug)

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22439?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Abdul Rahman
2026-07-02 15:02:39 +05:30
committed by GitHub
parent a99431902d
commit 3bbc08d41f
5 changed files with 917 additions and 1089 deletions
@@ -529,15 +529,6 @@ enum FieldMetadataType {
UUID
}
type IndexField {
id: UUID!
fieldMetadataId: UUID!
order: Float!
subFieldName: String
createdAt: DateTime!
updatedAt: DateTime!
}
type Index {
id: UUID!
name: String!
@@ -555,13 +546,6 @@ type Index {
"""Specify to filter the records returned."""
filter: ObjectFilter! = {}
): IndexObjectMetadataConnection!
indexFieldMetadatas(
"""Limit or page results."""
paging: CursorPaging! = {first: 10}
"""Specify to filter the records returned."""
filter: IndexFieldFilter! = {}
): IndexIndexFieldMetadatasConnection!
}
"""Type of the index"""
@@ -622,13 +606,6 @@ input BooleanFieldComparison {
isNot: Boolean
}
input IndexFieldFilter {
and: [IndexFieldFilter!]
or: [IndexFieldFilter!]
id: UUIDFilterComparison
fieldMetadataId: UUIDFilterComparison
}
type ObjectStandardOverrides {
labelSingular: String
labelPlural: String
@@ -2021,6 +1998,15 @@ enum RelationType {
MANY_TO_ONE
}
type IndexField {
id: UUID!
fieldMetadataId: UUID!
order: Float!
subFieldName: String
createdAt: DateTime!
updatedAt: DateTime!
}
type IndexEdge {
"""The node containing the Index"""
node: Index!
@@ -2051,22 +2037,6 @@ type IndexConnection {
edges: [IndexEdge!]!
}
type IndexFieldEdge {
"""The node containing the IndexField"""
node: IndexField!
"""Cursor for this node."""
cursor: ConnectionCursor!
}
type IndexIndexFieldMetadatasConnection {
"""Paging information"""
pageInfo: PageInfo!
"""Array of edges."""
edges: [IndexFieldEdge!]!
}
type ObjectEdge {
"""The node containing the Object"""
node: Object!
@@ -387,16 +387,6 @@ export interface Field {
/** Type of the field */
export type FieldMetadataType = 'ACTOR' | 'ADDRESS' | 'ARRAY' | 'BOOLEAN' | 'CURRENCY' | 'DATE' | 'DATE_TIME' | 'EMAILS' | 'FILES' | 'FULL_NAME' | 'LINKS' | 'MORPH_RELATION' | 'MULTI_SELECT' | 'NUMBER' | 'NUMERIC' | 'PHONES' | 'POSITION' | 'RATING' | 'RAW_JSON' | 'RELATION' | 'RICH_TEXT' | 'SELECT' | 'TEXT' | 'TS_VECTOR' | 'UUID'
export interface IndexField {
id: Scalars['UUID']
fieldMetadataId: Scalars['UUID']
order: Scalars['Float']
subFieldName?: Scalars['String']
createdAt: Scalars['DateTime']
updatedAt: Scalars['DateTime']
__typename: 'IndexField'
}
export interface Index {
id: Scalars['UUID']
name: Scalars['String']
@@ -408,7 +398,6 @@ export interface Index {
updatedAt: Scalars['DateTime']
indexFieldMetadataList: IndexField[]
objectMetadata: IndexObjectMetadataConnection
indexFieldMetadatas: IndexIndexFieldMetadatasConnection
__typename: 'Index'
}
@@ -1655,6 +1644,16 @@ export interface Relation {
/** Relation type */
export type RelationType = 'ONE_TO_MANY' | 'MANY_TO_ONE'
export interface IndexField {
id: Scalars['UUID']
fieldMetadataId: Scalars['UUID']
order: Scalars['Float']
subFieldName?: Scalars['String']
createdAt: Scalars['DateTime']
updatedAt: Scalars['DateTime']
__typename: 'IndexField'
}
export interface IndexEdge {
/** The node containing the Index */
node: Index
@@ -1683,22 +1682,6 @@ export interface IndexConnection {
__typename: 'IndexConnection'
}
export interface IndexFieldEdge {
/** The node containing the IndexField */
node: IndexField
/** Cursor for this node. */
cursor: Scalars['ConnectionCursor']
__typename: 'IndexFieldEdge'
}
export interface IndexIndexFieldMetadatasConnection {
/** Paging information */
pageInfo: PageInfo
/** Array of edges. */
edges: IndexFieldEdge[]
__typename: 'IndexIndexFieldMetadatasConnection'
}
export interface ObjectEdge {
/** The node containing the Object */
node: Object
@@ -3408,17 +3391,6 @@ export interface FieldGenqlSelection{
__scalar?: boolean | number
}
export interface IndexFieldGenqlSelection{
id?: boolean | number
fieldMetadataId?: boolean | number
order?: boolean | number
subFieldName?: boolean | number
createdAt?: boolean | number
updatedAt?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface IndexGenqlSelection{
id?: boolean | number
name?: boolean | number
@@ -3434,11 +3406,6 @@ export interface IndexGenqlSelection{
paging: CursorPaging,
/** Specify to filter the records returned. */
filter: ObjectFilter} })
indexFieldMetadatas?: (IndexIndexFieldMetadatasConnectionGenqlSelection & { __args: {
/** Limit or page results. */
paging: CursorPaging,
/** Specify to filter the records returned. */
filter: IndexFieldFilter} })
__typename?: boolean | number
__scalar?: boolean | number
}
@@ -3459,8 +3426,6 @@ export interface UUIDFilterComparison {is?: (Scalars['Boolean'] | null),isNot?:
export interface BooleanFieldComparison {is?: (Scalars['Boolean'] | null),isNot?: (Scalars['Boolean'] | null)}
export interface IndexFieldFilter {and?: (IndexFieldFilter[] | null),or?: (IndexFieldFilter[] | null),id?: (UUIDFilterComparison | null),fieldMetadataId?: (UUIDFilterComparison | null)}
export interface ObjectStandardOverridesGenqlSelection{
labelSingular?: boolean | number
labelPlural?: boolean | number
@@ -4744,6 +4709,17 @@ export interface RelationGenqlSelection{
__scalar?: boolean | number
}
export interface IndexFieldGenqlSelection{
id?: boolean | number
fieldMetadataId?: boolean | number
order?: boolean | number
subFieldName?: boolean | number
createdAt?: boolean | number
updatedAt?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface IndexEdgeGenqlSelection{
/** The node containing the Index */
node?: IndexGenqlSelection
@@ -4775,24 +4751,6 @@ export interface IndexConnectionGenqlSelection{
__scalar?: boolean | number
}
export interface IndexFieldEdgeGenqlSelection{
/** The node containing the IndexField */
node?: IndexFieldGenqlSelection
/** Cursor for this node. */
cursor?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface IndexIndexFieldMetadatasConnectionGenqlSelection{
/** Paging information */
pageInfo?: PageInfoGenqlSelection
/** Array of edges. */
edges?: IndexFieldEdgeGenqlSelection
__typename?: boolean | number
__scalar?: boolean | number
}
export interface ObjectEdgeGenqlSelection{
/** The node containing the Object */
node?: ObjectGenqlSelection
@@ -6848,14 +6806,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const IndexField_possibleTypes: string[] = ['IndexField']
export const isIndexField = (obj?: { __typename?: any } | null): obj is IndexField => {
if (!obj?.__typename) throw new Error('__typename is missing in "isIndexField"')
return IndexField_possibleTypes.includes(obj.__typename)
}
const Index_possibleTypes: string[] = ['Index']
export const isIndex = (obj?: { __typename?: any } | null): obj is Index => {
if (!obj?.__typename) throw new Error('__typename is missing in "isIndex"')
@@ -7736,6 +7686,14 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const IndexField_possibleTypes: string[] = ['IndexField']
export const isIndexField = (obj?: { __typename?: any } | null): obj is IndexField => {
if (!obj?.__typename) throw new Error('__typename is missing in "isIndexField"')
return IndexField_possibleTypes.includes(obj.__typename)
}
const IndexEdge_possibleTypes: string[] = ['IndexEdge']
export const isIndexEdge = (obj?: { __typename?: any } | null): obj is IndexEdge => {
if (!obj?.__typename) throw new Error('__typename is missing in "isIndexEdge"')
@@ -7760,22 +7718,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const IndexFieldEdge_possibleTypes: string[] = ['IndexFieldEdge']
export const isIndexFieldEdge = (obj?: { __typename?: any } | null): obj is IndexFieldEdge => {
if (!obj?.__typename) throw new Error('__typename is missing in "isIndexFieldEdge"')
return IndexFieldEdge_possibleTypes.includes(obj.__typename)
}
const IndexIndexFieldMetadatasConnection_possibleTypes: string[] = ['IndexIndexFieldMetadatasConnection']
export const isIndexIndexFieldMetadatasConnection = (obj?: { __typename?: any } | null): obj is IndexIndexFieldMetadatasConnection => {
if (!obj?.__typename) throw new Error('__typename is missing in "isIndexIndexFieldMetadatasConnection"')
return IndexIndexFieldMetadatasConnection_possibleTypes.includes(obj.__typename)
}
const ObjectEdge_possibleTypes: string[] = ['ObjectEdge']
export const isObjectEdge = (obj?: { __typename?: any } | null): obj is ObjectEdge => {
if (!obj?.__typename) throw new Error('__typename is missing in "isObjectEdge"')
File diff suppressed because it is too large Load Diff
@@ -2050,7 +2050,6 @@ export type Index = {
createdAt: Scalars['DateTime']['output'];
id: Scalars['UUID']['output'];
indexFieldMetadataList: Array<IndexField>;
indexFieldMetadatas: IndexIndexFieldMetadatasConnection;
indexType: IndexType;
indexWhereClause?: Maybe<Scalars['String']['output']>;
isCustom?: Maybe<Scalars['Boolean']['output']>;
@@ -2061,12 +2060,6 @@ export type Index = {
};
export type IndexIndexFieldMetadatasArgs = {
filter?: IndexFieldFilter;
paging?: CursorPaging;
};
export type IndexObjectMetadataArgs = {
filter?: ObjectFilter;
paging?: CursorPaging;
@@ -2098,21 +2091,6 @@ export type IndexField = {
updatedAt: Scalars['DateTime']['output'];
};
export type IndexFieldEdge = {
__typename?: 'IndexFieldEdge';
/** Cursor for this node. */
cursor: Scalars['ConnectionCursor']['output'];
/** The node containing the IndexField */
node: IndexField;
};
export type IndexFieldFilter = {
and?: InputMaybe<Array<IndexFieldFilter>>;
fieldMetadataId?: InputMaybe<UuidFilterComparison>;
id?: InputMaybe<UuidFilterComparison>;
or?: InputMaybe<Array<IndexFieldFilter>>;
};
export type IndexFilter = {
and?: InputMaybe<Array<IndexFilter>>;
id?: InputMaybe<UuidFilterComparison>;
@@ -2120,14 +2098,6 @@ export type IndexFilter = {
or?: InputMaybe<Array<IndexFilter>>;
};
export type IndexIndexFieldMetadatasConnection = {
__typename?: 'IndexIndexFieldMetadatasConnection';
/** Array of edges. */
edges: Array<IndexFieldEdge>;
/** Paging information */
pageInfo: PageInfo;
};
export type IndexObjectMetadataConnection = {
__typename?: 'IndexObjectMetadataConnection';
/** Array of edges. */
@@ -24,7 +24,6 @@ import {
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
import { IndexFieldMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-field-metadata.dto';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
@@ -46,7 +45,6 @@ registerEnumType(IndexType, {
maxResultsSize: 1000,
})
@CursorConnection('objectMetadata', () => ObjectMetadataDTO)
@CursorConnection('indexFieldMetadatas', () => IndexFieldMetadataDTO)
export class IndexMetadataDTO {
@IsUUID()
@IsNotEmpty()