Files
twenty_crm/packages/twenty-server/src/engine/api/rest/services/rest-api-metadata.service.ts
martmull 1ba7037fdc 5581 get httpsapitwentycomrestmetadata relations not working (#5867)
Filtering relations is not allowed
(see`packages/twenty-server/src/engine/metadata-modules/relation-metadata/dtos/relation-metadata.dto.ts`)
so we remove filtering for find many relation

we also fixed some bug in result structure and metadata open-api schema
2024-06-17 10:59:29 +02:00

291 lines
6.9 KiB
TypeScript

import { BadRequestException, Injectable } from '@nestjs/common';
import { Query } from 'src/engine/api/rest/types/query.type';
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
import { capitalize } from 'src/utils/capitalize';
import { parseMetadataPath } from 'src/engine/api/rest/rest-api-core-query-builder/utils/path-parsers/parse-metadata-path.utils';
import {
GraphqlApiType,
RestApiService,
} from 'src/engine/api/rest/services/rest-api.service';
@Injectable()
export class RestApiMetadataService {
constructor(
private readonly tokenService: TokenService,
private readonly restApiService: RestApiService,
) {}
fetchMetadataFields(objectNamePlural: string) {
const fields = `
type
name
label
description
icon
isCustom
isActive
isSystem
isNullable
createdAt
updatedAt
fromRelationMetadata {
id
relationType
toObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
toFieldMetadataId
}
toRelationMetadata {
id
relationType
fromObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
fromFieldMetadataId
}
defaultValue
options
`;
switch (objectNamePlural) {
case 'objects':
return `
dataSourceId
nameSingular
namePlural
labelSingular
labelPlural
description
icon
isCustom
isActive
isSystem
createdAt
updatedAt
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
fields(paging: { first: 1000 }) {
edges {
node {
id
${fields}
}
}
}
`;
case 'fields':
return fields;
case 'relations':
return `
relationType
fromObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
fromObjectMetadataId
toObjectMetadata {
id
dataSourceId
nameSingular
namePlural
isSystem
}
toObjectMetadataId
fromFieldMetadataId
toFieldMetadataId
`;
}
}
generateFindManyQuery(objectNameSingular: string, objectNamePlural: string) {
const fields = this.fetchMetadataFields(objectNamePlural);
let filterType = '';
let filterValue = '';
if (objectNamePlural !== 'relations') {
filterType = `($filter: ${objectNameSingular}Filter)`;
filterValue = 'filter: $filter,';
}
return `
query FindMany${capitalize(objectNamePlural)}${filterType} {
${objectNamePlural}(
${filterValue}
paging: { first: 1000 }
) {
edges {
node {
id
${fields}
}
}
}
}
`;
}
generateFindOneQuery(objectNameSingular: string, objectNamePlural: string) {
const fields = this.fetchMetadataFields(objectNamePlural);
return `
query FindOne${capitalize(objectNameSingular)}(
$id: UUID!,
) {
${objectNameSingular}(id: $id) {
id
${fields}
}
}
`;
}
async get(request) {
await this.tokenService.validateToken(request);
const { objectNameSingular, objectNamePlural, id } =
parseMetadataPath(request);
const query = id
? this.generateFindOneQuery(objectNameSingular, objectNamePlural)
: this.generateFindManyQuery(objectNameSingular, objectNamePlural);
const data: Query = {
query,
variables: id ? { id } : request.body,
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async create(request) {
await this.tokenService.validateToken(request);
const { objectNameSingular: objectName, objectNamePlural } =
parseMetadataPath(request);
const objectNameCapitalized = capitalize(objectName);
const fields = this.fetchMetadataFields(objectNamePlural);
const query = `
mutation Create${objectNameCapitalized}($input: CreateOne${objectNameCapitalized}Input!) {
createOne${objectNameCapitalized}(input: $input) {
id
${fields}
}
}
`;
const data: Query = {
query,
variables: {
input: {
[objectName]: request.body,
},
},
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async update(request) {
await this.tokenService.validateToken(request);
const {
objectNameSingular: objectName,
objectNamePlural,
id,
} = parseMetadataPath(request);
const objectNameCapitalized = capitalize(objectName);
if (!id) {
throw new BadRequestException(
`update ${objectName} query invalid. Id missing. eg: /rest/metadata/${objectName}/0d4389ef-ea9c-4ae8-ada1-1cddc440fb56`,
);
}
const fields = this.fetchMetadataFields(objectNamePlural);
const query = `
mutation Update${objectNameCapitalized}($input: UpdateOne${objectNameCapitalized}Input!) {
updateOne${objectNameCapitalized}(input: $input) {
id
${fields}
}
}
`;
const data: Query = {
query,
variables: {
input: {
update: request.body,
id,
},
},
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
async delete(request) {
await this.tokenService.validateToken(request);
const { objectNameSingular: objectName, id } = parseMetadataPath(request);
const objectNameCapitalized = capitalize(objectName);
if (!id) {
throw new BadRequestException(
`delete ${objectName} query invalid. Id missing. eg: /rest/metadata/${objectName}/0d4389ef-ea9c-4ae8-ada1-1cddc440fb56`,
);
}
const query = `
mutation Delete${objectNameCapitalized}($input: DeleteOne${objectNameCapitalized}Input!) {
deleteOne${objectNameCapitalized}(input: $input) {
id
}
}
`;
const data: Query = {
query,
variables: {
input: {
id,
},
},
};
return await this.restApiService.call(
GraphqlApiType.METADATA,
request,
data,
);
}
}