Fix relation field unknown target object (#13129)
Fixes https://github.com/twentyhq/twenty/issues/12867 Issue: when you have a variable `toto` which is: `Record<string, MyType>` and you do toto['xxx'], this will be typed as `MyType` instead of `MyType | undefined` Solutions: - activate `noUncheckedIndexedAccess` check in tsconfig, this is the preferred solution but will take time to get there (this raises 600+ errors) - use a Map: cf https://github.com/twentyhq/twenty/pull/13125/files - set the type to Partial<Record<string, MyType>>. Drawback is that when you do Object.values(toto), you'll get `Array<MyType | undefined>`. Hence why we have to filter these behind <img width="1512" alt="image" src="https://github.com/user-attachments/assets/d0a0bfed-c441-4e53-84c2-2da98ccbcf50" />
This commit is contained in:
@ -5,7 +5,7 @@ import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/typ
|
||||
export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMaps[] =
|
||||
[
|
||||
{
|
||||
id: '',
|
||||
id: '20202020-8dec-43d5-b2ff-6eef05095bec',
|
||||
standardId: '',
|
||||
nameSingular: 'person',
|
||||
namePlural: 'people',
|
||||
@ -52,7 +52,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
fieldIdByJoinColumnName: {},
|
||||
},
|
||||
{
|
||||
id: '',
|
||||
id: '20202020-c03c-45d6-a4b0-04afe1357c5c',
|
||||
standardId: '',
|
||||
nameSingular: 'company',
|
||||
namePlural: 'companies',
|
||||
@ -112,7 +112,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
fieldIdByJoinColumnName: {},
|
||||
},
|
||||
{
|
||||
id: '',
|
||||
id: '20202020-3d75-4aab-bacd-ee176c5f63ca',
|
||||
standardId: '',
|
||||
nameSingular: 'regular-custom-object',
|
||||
namePlural: 'regular-custom-objects',
|
||||
@ -172,7 +172,7 @@ export const mockObjectMetadataItemsWithFieldMaps: ObjectMetadataItemWithFieldMa
|
||||
fieldIdByJoinColumnName: {},
|
||||
},
|
||||
{
|
||||
id: '',
|
||||
id: '20202020-540c-4397-b872-2a90ea2fb809',
|
||||
standardId: '',
|
||||
nameSingular: 'non-searchable-object',
|
||||
namePlural: 'non-searchable-objects',
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Query, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { SearchArgs } from 'src/engine/core-modules/search/dtos/search-args';
|
||||
@ -10,12 +12,16 @@ import { SearchService } from 'src/engine/core-modules/search/services/search.se
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
@Resolver()
|
||||
@UseFilters(SearchApiExceptionFilter, PreventNestToAutoLogGraphqlErrorsFilter)
|
||||
@UsePipes(ResolverValidationPipe)
|
||||
export class SearchResolver {
|
||||
constructor(private readonly searchService: SearchService) {}
|
||||
constructor(
|
||||
private readonly searchService: SearchService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
) {}
|
||||
|
||||
@Query(() => SearchResultConnectionDTO)
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
@ -31,12 +37,16 @@ export class SearchResolver {
|
||||
after,
|
||||
}: SearchArgs,
|
||||
) {
|
||||
const objectMetadataItemWithFieldMaps =
|
||||
await this.searchService.getObjectMetadataItemWithFieldMaps(workspace);
|
||||
const objectMetadataMaps =
|
||||
await this.workspaceCacheStorageService.getObjectMetadataMapsOrThrow(
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
const filteredObjectMetadataItems =
|
||||
this.searchService.filterObjectMetadataItems({
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataItemWithFieldMaps: Object.values(
|
||||
objectMetadataMaps.byId,
|
||||
).filter(isDefined),
|
||||
includedObjectNameSingulars: includedObjectNameSingulars ?? [],
|
||||
excludedObjectNameSingulars: excludedObjectNameSingulars ?? [],
|
||||
});
|
||||
|
||||
@ -29,13 +29,11 @@ import {
|
||||
} from 'src/engine/core-modules/search/exceptions/search.exception';
|
||||
import { RecordsWithObjectMetadataItem } from 'src/engine/core-modules/search/types/records-with-object-metadata-item';
|
||||
import { formatSearchTerms } from 'src/engine/core-modules/search/utils/format-search-terms';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/constants/search-vector-field.constants';
|
||||
import { ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||
import { generateObjectMetadataMaps } from 'src/engine/metadata-modules/utils/generate-object-metadata-maps.util';
|
||||
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
type LastRanks = { tsRankCD: number; tsRank: number };
|
||||
|
||||
@ -51,18 +49,8 @@ export class SearchService {
|
||||
constructor(
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly fileService: FileService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
) {}
|
||||
|
||||
async getObjectMetadataItemWithFieldMaps(workspace: Workspace) {
|
||||
const objectMetadataMaps =
|
||||
await this.workspaceCacheStorageService.getObjectMetadataMapsOrThrow(
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
return Object.values(objectMetadataMaps.byId);
|
||||
}
|
||||
|
||||
async getAllRecordsWithObjectMetadataItems({
|
||||
objectMetadataItemWithFieldMaps,
|
||||
includedObjectNameSingulars,
|
||||
|
||||
Reference in New Issue
Block a user