3035 improve rest api syntax (#3047)

This commit is contained in:
martmull
2023-12-18 13:46:21 +01:00
committed by GitHub
parent b36d86e52c
commit 576492f3c0
6 changed files with 102 additions and 39 deletions

View File

@ -19,7 +19,7 @@ if needed.
## Programmatic use? ## Programmatic use?
You can call the REST API in your application using this endpoint You can call the REST API in your application using this endpoint
[https://api.twenty.com](https://api.twenty.com). [https://api.twenty.com/rest](https://api.twenty.com/rest).
You will need to provide your API key as a Bearer token in You will need to provide your API key as a Bearer token in
your `headers.Authorization = 'Bearer <YOUR_API_KEY>'`. your `headers.Authorization = 'Bearer <YOUR_API_KEY>'`.

View File

@ -33,7 +33,7 @@ export const mapFieldMetadataToGraphqlQuery = (
const relationMetadataItem = objectMetadataItems.find( const relationMetadataItem = objectMetadataItems.find(
(objectMetadataItem) => (objectMetadataItem) =>
objectMetadataItem.id === objectMetadataItem.id ===
(field.toRelationMetadata as any)?.fromObjectMetadata?.id, (field.toRelationMetadata as any)?.fromObjectMetadataId,
); );
return `${field.name} return `${field.name}
@ -58,7 +58,7 @@ export const mapFieldMetadataToGraphqlQuery = (
const relationMetadataItem = objectMetadataItems.find( const relationMetadataItem = objectMetadataItems.find(
(objectMetadataItem) => (objectMetadataItem) =>
objectMetadataItem.id === objectMetadataItem.id ===
(field.fromRelationMetadata as any)?.toObjectMetadata?.id, (field.fromRelationMetadata as any)?.toObjectMetadataId,
); );
return `${field.name} return `${field.name}

View File

@ -3,17 +3,7 @@ import { Controller, Delete, Get, Post, Put, Req, Res } from '@nestjs/common';
import { Request, Response } from 'express'; import { Request, Response } from 'express';
import { ApiRestService } from 'src/core/api-rest/api-rest.service'; import { ApiRestService } from 'src/core/api-rest/api-rest.service';
import { ApiRestResponse } from 'src/core/api-rest/types/api-rest-response.type'; import { handleResult } from 'src/core/api-rest/api-rest.controller.utils';
const handleResult = (res: Response, result: ApiRestResponse) => {
if (result.data.error) {
res
.status(result.data.status || 400)
.send({ error: `${result.data.error}` });
} else {
res.send(result.data);
}
};
@Controller('rest/*') @Controller('rest/*')
export class ApiRestController { export class ApiRestController {

View File

@ -0,0 +1,53 @@
import { cleanGraphQLResponse } from 'src/core/api-rest/api-rest.controller.utils';
describe('cleanGraphQLResponse', () => {
it('should remove edges/node from results', () => {
const data = {
companies: {
edges: [
{
node: { id: 'id', createdAt: '2023-01-01' },
},
],
},
};
const expectedResult = {
companies: [{ id: 'id', createdAt: '2023-01-01' }],
};
expect(cleanGraphQLResponse(data)).toEqual(expectedResult);
});
it('should remove nested edges/node from results', () => {
const data = {
companies: {
edges: [
{
node: {
id: 'id',
createdAt: '2023-01-01',
people: {
edges: [{ node: { id: 'id1' } }, { node: { id: 'id2' } }],
},
},
},
],
},
};
const expectedResult = {
companies: [
{
id: 'id',
createdAt: '2023-01-01',
people: [{ id: 'id1' }, { id: 'id2' }],
},
],
};
expect(cleanGraphQLResponse(data)).toEqual(expectedResult);
});
it('should not format when no list returned', () => {
const data = { company: { id: 'id' } };
expect(cleanGraphQLResponse(data)).toEqual(data);
});
});

View File

@ -0,0 +1,36 @@
import { Response } from 'express';
import { ApiRestResponse } from 'src/core/api-rest/types/api-rest-response.type';
// https://gist.github.com/ManUtopiK/469aec75b655d6a4d912aeb3b75af3c9
export const cleanGraphQLResponse = (input) => {
if (!input) return null;
const output = {};
const isObject = (obj) => {
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
};
Object.keys(input).forEach((key) => {
if (input[key] && input[key].edges) {
output[key] = input[key].edges.map((edge) =>
cleanGraphQLResponse(edge.node),
);
} else if (isObject(input[key])) {
output[key] = cleanGraphQLResponse(input[key]);
} else if (key !== '__typename') {
output[key] = input[key];
}
});
return output;
};
export const handleResult = (res: Response, result: ApiRestResponse) => {
if (result.data.error) {
res
.status(result.data.status || 400)
.send({ error: `${result.data.error}` });
} else {
res.send(cleanGraphQLResponse(result.data));
}
};

View File

@ -13,21 +13,11 @@ export const getManyResultResponse200 = (item: ObjectMetadataEntity) => {
type: 'object', type: 'object',
properties: { properties: {
[item.namePlural]: { [item.namePlural]: {
type: 'object', type: 'array',
properties: { items: {
edges: { $ref: `#/components/schemas/${capitalize(
type: 'array', item.nameSingular,
items: { )}`,
type: 'object',
properties: {
node: {
$ref: `#/components/schemas/${capitalize(
item.nameSingular,
)}`,
},
},
},
},
}, },
}, },
}, },
@ -35,16 +25,10 @@ export const getManyResultResponse200 = (item: ObjectMetadataEntity) => {
}, },
example: { example: {
data: { data: {
properties: { [item.namePlural]: [
[item.namePlural]: { `${capitalize(item.nameSingular)}Object`,
edges: [ '...',
{ ],
node: `${capitalize(item.nameSingular)}Object`,
},
'...',
],
},
},
}, },
}, },
}, },