Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit 7fb63ce

Browse files
Feat: custom worflow related APIs (#235)
* Feat: custom worflow related APIs * Fix: naming of description --------- Co-authored-by: Manoj K <saimanoj58@gmail.com>
1 parent c5a7f5a commit 7fb63ce

File tree

15 files changed

+250
-95
lines changed

15 files changed

+250
-95
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[name,teamId]` on the table `Workflow` will be added. If there are existing duplicate values, this will fail.
5+
6+
*/
7+
-- AlterTable
8+
ALTER TABLE "Workflow" ADD COLUMN "description" TEXT;
9+
10+
-- CreateIndex
11+
CREATE UNIQUE INDEX "_ci" ON "Workflow"("name", "teamId");

apps/server/prisma/schema.prisma

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,16 @@ model Workflow {
561561
updatedAt DateTime @updatedAt
562562
deleted DateTime?
563563
564-
name String
565-
position Int
566-
color String
567-
category WorkflowCategory
564+
name String
565+
description String?
566+
position Int
567+
color String
568+
category WorkflowCategory
568569
569570
team Team? @relation(fields: [teamId], references: [id])
570571
teamId String
572+
573+
@@unique([name, teamId], map: "_ci")
571574
}
572575

573576
model Workspace {
@@ -576,9 +579,9 @@ model Workspace {
576579
updatedAt DateTime @updatedAt
577580
deleted DateTime?
578581
579-
name String
580-
slug String @unique
581-
icon String?
582+
name String
583+
slug String @unique
584+
icon String?
582585
583586
actionsEnabled Boolean @default(false)
584587

apps/server/src/modules/logger/logger.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ export class LoggerService {
112112
if (isConsoleFormat) {
113113
const consoleFormat = [
114114
chalk.green(loggerPrintFormat.timestamp),
115-
chalk.green(loggerPrintFormat.lvl),
115+
loggerPrintFormat.lvl === 'ERROR'
116+
? chalk.red(loggerPrintFormat.lvl)
117+
: chalk.green(loggerPrintFormat.lvl),
116118
chalk.blue(loggerPrintFormat.ctx),
117119
chalk.cyan(loggerPrintFormat.msg),
118120
];

apps/server/src/modules/workflows/workflows.controller.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ import {
77
Post,
88
UseGuards,
99
} from '@nestjs/common';
10-
import { Workflow } from '@tegonhq/types';
10+
import {
11+
CreateWorkflowDTO,
12+
UpdateWorkflowDTO,
13+
Workflow,
14+
WorkflowRequestParamsDto,
15+
} from '@tegonhq/types';
1116

1217
import { AuthGuard } from 'modules/auth/auth.guard';
1318

14-
import {
15-
UpdateWorkflowInput,
16-
WorkflowRequestIdBody,
17-
TeamRequestIdBody,
18-
} from './workflows.interface';
1919
import WorkflowsService from './workflows.service';
2020

2121
@Controller({
@@ -28,36 +28,51 @@ export class WorkflowsController {
2828
@Get()
2929
@UseGuards(AuthGuard)
3030
async getAllWorkflows(
31-
@Param() teamId: TeamRequestIdBody,
31+
@Param() workflowRequestParams: WorkflowRequestParamsDto,
3232
): Promise<Workflow[]> {
33-
return await this.workflowsService.getAllWorkflows(teamId);
33+
return await this.workflowsService.getAllWorkflows(workflowRequestParams);
34+
}
35+
36+
@Post()
37+
@UseGuards(AuthGuard)
38+
async createWorkflow(
39+
@Param() workflowRequestParams: WorkflowRequestParamsDto,
40+
@Body() workflowData: CreateWorkflowDTO,
41+
): Promise<Workflow> {
42+
return await this.workflowsService.createWorkflow(
43+
workflowRequestParams,
44+
workflowData,
45+
);
3446
}
3547

3648
@Get(':workflowId')
3749
@UseGuards(AuthGuard)
3850
async getWorkflow(
3951
@Param()
40-
workflowId: WorkflowRequestIdBody,
52+
workflowRequestParams: WorkflowRequestParamsDto,
4153
): Promise<Workflow> {
42-
return await this.workflowsService.getWorkflow(workflowId);
54+
return await this.workflowsService.getWorkflow(workflowRequestParams);
4355
}
4456

4557
@Post(':workflowId')
4658
@UseGuards(AuthGuard)
4759
async updateWorkflow(
4860
@Param()
49-
workflowId: WorkflowRequestIdBody,
50-
@Body() workflowData: UpdateWorkflowInput,
61+
workflowRequestParams: WorkflowRequestParamsDto,
62+
@Body() workflowData: UpdateWorkflowDTO,
5163
): Promise<Workflow> {
52-
return await this.workflowsService.updateWorkflow(workflowId, workflowData);
64+
return await this.workflowsService.updateWorkflow(
65+
workflowRequestParams,
66+
workflowData,
67+
);
5368
}
5469

5570
@Delete(':workflowId')
5671
@UseGuards(AuthGuard)
5772
async deleteWorkflow(
5873
@Param()
59-
workflowId: WorkflowRequestIdBody,
74+
workflowRequestParams: WorkflowRequestParamsDto,
6075
): Promise<Workflow> {
61-
return await this.workflowsService.deleteWorkflow(workflowId);
76+
return await this.workflowsService.deleteWorkflow(workflowRequestParams);
6277
}
6378
}

apps/server/src/modules/workflows/workflows.interface.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

apps/server/src/modules/workflows/workflows.service.ts

Lines changed: 99 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,134 @@
1-
import { Injectable } from '@nestjs/common';
2-
import { Workflow } from '@tegonhq/types';
1+
import {
2+
BadRequestException,
3+
Injectable,
4+
InternalServerErrorException,
5+
} from '@nestjs/common';
6+
import {
7+
CreateWorkflowDTO,
8+
TeamRequestParamsDto,
9+
UpdateWorkflowDTO,
10+
Workflow,
11+
WorkflowRequestParamsDto,
12+
} from '@tegonhq/types';
313
import { PrismaService } from 'nestjs-prisma';
414

5-
import {
6-
TeamRequestIdBody,
7-
UpdateWorkflowInput,
8-
WorkflowRequestIdBody,
9-
} from './workflows.interface';
15+
import { LoggerService } from 'modules/logger/logger.service';
1016

1117
@Injectable()
1218
export default class WorkflowsService {
1319
constructor(private prisma: PrismaService) {}
20+
private readonly logger = new LoggerService(WorkflowsService.name);
1421

1522
async getAllWorkflows(
16-
teamRequestIdBody: TeamRequestIdBody,
23+
workflowRequestParams: WorkflowRequestParamsDto,
1724
): Promise<Workflow[]> {
25+
this.logger.debug({
26+
message: `Fetching all workflows for team ${workflowRequestParams.teamId}`,
27+
where: `WorkflowsService.getAllWorkflows`,
28+
});
29+
1830
return await this.prisma.workflow.findMany({
1931
where: {
20-
teamId: teamRequestIdBody.teamId,
32+
teamId: workflowRequestParams.teamId,
2133
},
2234
});
2335
}
2436

2537
async getWorkflow(
26-
WorkflowRequestIdBody: WorkflowRequestIdBody,
38+
workflowRequestParams: WorkflowRequestParamsDto,
2739
): Promise<Workflow> {
40+
this.logger.debug({
41+
message: `Fetching workflow with id ${workflowRequestParams.workflowId}`,
42+
where: `WorkflowsService.getWorkflow`,
43+
});
44+
2845
return await this.prisma.workflow.findUnique({
2946
where: {
30-
id: WorkflowRequestIdBody.workflowId,
47+
id: workflowRequestParams.workflowId,
3148
},
3249
});
3350
}
3451

52+
async createWorkflow(
53+
workflowRequestParams: TeamRequestParamsDto,
54+
workflowData: CreateWorkflowDTO,
55+
): Promise<Workflow> {
56+
this.logger.debug({
57+
message: `Creating new workflow for team ${workflowRequestParams.teamId}`,
58+
payload: { teamId: workflowRequestParams.teamId, workflowData },
59+
where: `WorkflowsService.createWorkflow`,
60+
});
61+
62+
try {
63+
return await this.prisma.workflow.create({
64+
data: { teamId: workflowRequestParams.teamId, ...workflowData },
65+
});
66+
} catch (error) {
67+
this.logger.error({
68+
message: `Error while creating workflow`,
69+
where: `WorkflowsService.createWorkflow`,
70+
error,
71+
payload: workflowData,
72+
});
73+
if (error.name === 'PrismaClientKnownRequestError') {
74+
throw new BadRequestException(
75+
'A workflow state with this name and type already exists for this team',
76+
);
77+
}
78+
throw new InternalServerErrorException(
79+
error,
80+
`Error while creating workflow`,
81+
);
82+
}
83+
}
84+
3585
async updateWorkflow(
36-
workflowRequestIdBody: WorkflowRequestIdBody,
37-
workflowData: UpdateWorkflowInput,
86+
workflowRequestParams: WorkflowRequestParamsDto,
87+
workflowData: UpdateWorkflowDTO,
3888
): Promise<Workflow> {
39-
return await this.prisma.workflow.update({
40-
data: {
41-
...workflowData,
42-
},
43-
where: {
44-
id: workflowRequestIdBody.workflowId,
45-
},
89+
this.logger.debug({
90+
message: `Updating workflow with id ${workflowRequestParams.workflowId}`,
91+
payload: { workflowId: workflowRequestParams.workflowId, workflowData },
92+
where: `WorkflowsService.updateWorkflow`,
4693
});
94+
95+
try {
96+
return await this.prisma.workflow.update({
97+
data: workflowData,
98+
where: {
99+
id: workflowRequestParams.workflowId,
100+
},
101+
});
102+
} catch (error) {
103+
this.logger.error({
104+
message: `Error while updating workflow`,
105+
where: `WorkflowsService.updateWorkflow`,
106+
error,
107+
payload: workflowData,
108+
});
109+
if (error.name === 'PrismaClientKnownRequestError') {
110+
throw new BadRequestException(
111+
'A workflow state with this name and type already exists for this team',
112+
);
113+
}
114+
throw new InternalServerErrorException(
115+
error,
116+
`Error while creating workflow`,
117+
);
118+
}
47119
}
48120

49121
async deleteWorkflow(
50-
workflowRequestIdBody: WorkflowRequestIdBody,
122+
workflowRequestParams: WorkflowRequestParamsDto,
51123
): Promise<Workflow> {
124+
this.logger.debug({
125+
message: `Deleting workflow with id ${workflowRequestParams.workflowId}`,
126+
where: `WorkflowsService.deleteWorkflow`,
127+
});
128+
52129
return await this.prisma.workflow.update({
53130
where: {
54-
id: workflowRequestIdBody.workflowId,
131+
id: workflowRequestParams.workflowId,
55132
},
56133
data: {
57134
deleted: new Date().toISOString(),

apps/server/src/modules/workspaces/workspaces.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ export default class WorkspacesService {
6161
const workspace = await prisma.workspace.create({
6262
data: {
6363
name: workspaceData.workspaceName,
64-
slug: workspaceData.workspaceName.toLowerCase().replace(/-/g, ''),
64+
slug: workspaceData.workspaceName
65+
.toLowerCase()
66+
.replace(/[^a-z0-9]/g, ''),
6567
usersOnWorkspaces: {
6668
create: { userId },
6769
},
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {
2+
CreateWorkflowDTO,
3+
Workflow,
4+
WorkflowRequestParamsDto,
5+
} from '@tegonhq/types';
6+
import axios from 'axios';
7+
8+
export interface CreateWorkflowInput
9+
extends WorkflowRequestParamsDto,
10+
CreateWorkflowDTO {}
11+
12+
export async function createWorkflows({
13+
teamId,
14+
...data
15+
}: CreateWorkflowInput): Promise<Workflow[]> {
16+
const response = await axios.post(`/api/v1/${teamId}/workflows`, data);
17+
18+
return response.data;
19+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from './get-workflows';
2+
export * from './create-workflow';
3+
export * from './update-workflow';

0 commit comments

Comments
 (0)