Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: rest APIs to use twenty orm #7988

Closed

Conversation

DeepaPrasanna
Copy link

@DeepaPrasanna DeepaPrasanna commented Oct 23, 2024

fixes #3644

This isn't the whole refactoring yet. I tried to refactor the rest/batch/... endpoint first. I added comments too for the part that might have to be included which were in GraphqlQueryRunnerService. Please let me know if I am moving in the right direction and If there is anything that I might have missed.

Note: I will split the code in well scoped functionalities after knowing that I am moving in the right direction. Please excuse me until then.

@DeepaPrasanna DeepaPrasanna marked this pull request as draft October 23, 2024 08:13
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

This pull request refactors the REST APIs to utilize the Twenty ORM, focusing on the 'rest/batch/...' endpoint. Key changes include:

  • Added RestMetadataMiddleware for token validation and metadata handling in app.module.ts
  • Implemented createMany method in CoreQueryBuilderFactory to use Twenty ORM for batch operations
  • Removed cleanGraphQLResponse utility in rest-api-core-batch.controller.ts, potentially affecting response structure
  • Modified createMany method in rest-api-core.service.ts to return data directly and added LogExecutionTime decorator
  • Introduced new WorkspaceMetadataCacheModule and WorkspaceCacheStorageModule in core-query-builder.module.ts

7 file(s) reviewed, 5 comment(s)
Edit PR Review Bot Settings | Greptile

Comment on lines +61 to +66
if (metadataVersion === undefined) {
await this.workspaceMetadataCacheService.recomputeMetadataCache({
workspaceId: data.workspace.id,
});
throw new Error('Metadata cache version not found');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Recomputing metadata cache and then throwing an error may lead to unnecessary work. Consider reordering these operations.

req.workspaceMetadataVersion = metadataVersion;
req.workspaceMemberId = data.workspaceMemberId;
} catch (error) {
res.writeHead(200, { 'Content-Type': 'application/json' });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Using status code 200 for errors is unconventional. Consider using appropriate error status codes.

@Weiko Weiko self-requested a review October 23, 2024 13:47
@DeepaPrasanna
Copy link
Author

Hello @charlesBochet , may I get your feedback? As this is an incomplete PR, I would love to work on that after the feedback. Thank you for reviewing :)

@FelixMalfait
Copy link
Member

/award 1500 sorry we couldn't give more feedback earlier

Copy link

oss-gg bot commented Oct 31, 2024

Awarding DeepaPrasanna: 1500 points 🕹️ Well done! Check out your new contribution on oss.gg/DeepaPrasanna

@DeepaPrasanna
Copy link
Author

/award 1500 sorry we couldn't give more feedback earlier

No worries! Thank you :) I would like to continue this later after feedback

Copy link

oss-gg bot commented Oct 31, 2024

You are not allowed to award points! Please contact an admin.

Comment on lines +26 to +43
const excludedOperations = [
'GetClientConfig',
'GetCurrentUser',
'GetWorkspaceFromInviteHash',
'Track',
'CheckUserExists',
'Challenge',
'Verify',
'SignUp',
'RenewToken',
'EmailPasswordResetLink',
'ValidatePasswordResetToken',
'UpdatePasswordViaResetToken',
'IntrospectionQuery',
'ExchangeAuthorizationCode',
'GetAuthorizationUrl',
'FindAvailableSSOIdentityProviders',
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refactor this list with the list located in packages/twenty-server/src/engine/middlewares/graphql-hydrate-request-from-token.middleware.ts

Comment on lines +54 to +76
try {
data = await this.tokenService.validateToken(req);
const metadataVersion =
await this.workspaceStorageCacheService.getMetadataVersion(
data.workspace.id,
);

if (metadataVersion === undefined) {
await this.workspaceMetadataCacheService.recomputeMetadataCache({
workspaceId: data.workspace.id,
});
throw new Error('Metadata cache version not found');
}

const dataSourcesMetadata =
await this.dataSourceService.getDataSourcesMetadataFromWorkspaceId(
data.workspace.id,
);

if (!dataSourcesMetadata || dataSourcesMetadata.length === 0) {
throw new Error('No data sources found');
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lot of code in this new file is shared with packages/twenty-server/src/engine/middlewares/graphql-hydrate-request-from-token.middleware.ts. We should factorize this logic and create a base HydrateRequestFromTokenMiddleware middleware

req.workspaceMetadataVersion = metadataVersion;
req.workspaceMemberId = data.workspaceMemberId;
} catch (error) {
res.writeHead(200, { 'Content-Type': 'application/json' });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for rest api, we don't want 200 error indeed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes indeed! I really missed that

Comment on lines +155 to +196
if (!objectMetadataMap) {
await this.workspaceMetadataCacheService.recomputeMetadataCache({
workspaceId: context.workspace.id,
});
throw new Error('Object metadata collection not found');
}

const objectMetadataMapItem =
objectMetadataMap[objectMetadata.objectMetadataItem.nameSingular];

const dataSource =
await this.twentyORMGlobalManager.getDataSourceForWorkspace(
context.workspace.id,
);

const repository = dataSource.getRepository(
objectMetadataMapItem.nameSingular,
);

const objectRecords: InsertResult = !request.body.upsert
? await repository.insert(request.body)
: await repository.upsert(request.body, {
conflictPaths: ['id'],
skipUpdateIfNoValuesChanged: true,
});

const queryBuilder = repository.createQueryBuilder(
objectMetadataMapItem.nameSingular,
);

const nonFormattedUpsertedRecords = await queryBuilder
.where({
id: In(objectRecords.generatedMaps.map((record) => record.id)),
})
.take(QUERY_MAX_RECORDS)
.getMany();

const upsertedRecords = formatResult(
nonFormattedUpsertedRecords,
objectMetadataMapItem,
objectMetadataMap,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code shared lot of code with packages/twenty-server/src/engine/api/graphql/graphql-query-runner/resolvers/graphql-query-create-many-resolver.service.ts
We must factorize that shared code

@martmull
Copy link
Contributor

martmull commented Nov 5, 2024

Hey @DeepaPrasanna, added some comments on your PR. I think this is the good way to go. I just see duplicated code that we must factorize

@charlesBochet
Copy link
Member

Closing this PR to keep history clear :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make REST API use Twenty ORM direclty
4 participants