Skip to content

Commit

Permalink
Add crud actions (#8500)
Browse files Browse the repository at this point in the history
Adding update / delete / find actions

Update and delete are not really different than creation.

Find uses the same logique as for graphql filters.
Expected formats are:

Filter
```
{
  "and": [
    {
      "name": {
        "eq": "salut"
      }
    },
    {
      "employees": {
        "eq": "0"
      }
    }
  ]
}
```

Order
`[ { "name": 'AscNullsFirst' } ]`
  • Loading branch information
thomtrp authored Nov 15, 2024
1 parent 736635a commit a2a272f
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class GraphqlQueryParser {

public applyDeletedAtToBuilder(
queryBuilder: SelectQueryBuilder<any>,
recordFilter: ObjectRecordFilter,
recordFilter: Partial<ObjectRecordFilter>,
): SelectQueryBuilder<any> {
if (this.checkForDeletedAtFilter(recordFilter)) {
queryBuilder.withDeleted();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import { checkStringIsDatabaseEventAction } from 'src/engine/api/graphql/graphql
import { INDEX_FILE_NAME } from 'src/engine/core-modules/serverless/drivers/constants/index-file-name';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service';
import { generateFakeValue } from 'src/engine/utils/generate-fake-value';
import { CodeIntrospectionService } from 'src/modules/code-introspection/code-introspection.service';
import { generateFakeObjectRecord } from 'src/modules/workflow/workflow-builder/utils/generate-fake-object-record';
import { generateFakeObjectRecordEvent } from 'src/modules/workflow/workflow-builder/utils/generate-fake-object-record-event';
import { WorkflowSendEmailStepOutputSchema } from 'src/modules/workflow/workflow-executor/workflow-actions/mail-sender/send-email.workflow-action';
import { WorkflowRecordCRUDType } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/types/workflow-record-crud-action-input.type';
import {
WorkflowAction,
WorkflowActionType,
Expand Down Expand Up @@ -44,7 +46,7 @@ export class WorkflowBuilderWorkspaceService {

switch (stepType) {
case WorkflowTriggerType.DATABASE_EVENT: {
return await this.computeDatabaseEventTriggerOutputSchema({
return this.computeDatabaseEventTriggerOutputSchema({
eventName: step.settings.eventName,
workspaceId,
objectMetadataRepository: this.objectMetadataRepository,
Expand All @@ -57,7 +59,7 @@ export class WorkflowBuilderWorkspaceService {
return {};
}

return await this.computeRecordOutputSchema({
return this.computeRecordOutputSchema({
objectType,
workspaceId,
objectMetadataRepository: this.objectMetadataRepository,
Expand All @@ -70,7 +72,7 @@ export class WorkflowBuilderWorkspaceService {
const { serverlessFunctionId, serverlessFunctionVersion } =
step.settings.input;

return await this.computeCodeActionOutputSchema({
return this.computeCodeActionOutputSchema({
serverlessFunctionId,
serverlessFunctionVersion,
workspaceId,
Expand All @@ -79,8 +81,9 @@ export class WorkflowBuilderWorkspaceService {
});
}
case WorkflowActionType.RECORD_CRUD:
return await this.computeRecordOutputSchema({
return this.computeRecordCrudOutputSchema({
objectType: step.settings.input.objectName,
operationType: step.settings.input.type,
workspaceId,
objectMetadataRepository: this.objectMetadataRepository,
});
Expand Down Expand Up @@ -122,6 +125,34 @@ export class WorkflowBuilderWorkspaceService {
);
}

private async computeRecordCrudOutputSchema<Entity>({
objectType,
operationType,
workspaceId,
objectMetadataRepository,
}: {
objectType: string;
operationType: string;
workspaceId: string;
objectMetadataRepository: Repository<ObjectMetadataEntity>;
}) {
const recordOutputSchema = await this.computeRecordOutputSchema<Entity>({
objectType,
workspaceId,
objectMetadataRepository,
});

if (operationType === WorkflowRecordCRUDType.READ) {
return {
first: recordOutputSchema,
last: recordOutputSchema,
totalCount: generateFakeValue('number'),
};
}

return recordOutputSchema;
}

private async computeRecordOutputSchema<Entity>({
objectType,
workspaceId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CustomException } from 'src/utils/custom-exception';

export class RecordCRUDActionException extends CustomException {
code: RecordCRUDActionExceptionCode;
constructor(message: string, code: RecordCRUDActionExceptionCode) {
super(message, code);
}
}

export enum RecordCRUDActionExceptionCode {
INVALID_REQUEST = 'INVALID_REQUEST',
RECORD_NOT_FOUND = 'RECORD_NOT_FOUND',
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Module } from '@nestjs/common';

import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { RecordCRUDWorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/record-crud/record-crud.workflow-action';

@Module({
providers: [RecordCRUDWorkflowAction],
imports: [WorkspaceCacheStorageModule],
providers: [RecordCRUDWorkflowAction, ScopedWorkspaceContextFactory],
exports: [RecordCRUDWorkflowAction],
})
export class RecordCRUDActionModule {}
Loading

0 comments on commit a2a272f

Please sign in to comment.