diff --git a/apps/hooks/src/index.ts b/apps/hooks/src/index.ts index 6d09c48..b020e9f 100644 --- a/apps/hooks/src/index.ts +++ b/apps/hooks/src/index.ts @@ -7,6 +7,8 @@ app.use(express.json()); app.post("/hooks/catch/:userId/:workflowId", async (req, res) => { try { + + console.log("THIS LOG IS FROM HOOKS BACKEND THAT WE HAVE RECIEVED THE REQUEST") const { userId, workflowId } = req.params; const { triggerData } = req.body; @@ -24,7 +26,7 @@ app.post("/hooks/catch/:userId/:workflowId", async (req, res) => { const workflowExecution = await tx.workflowExecution.create({ data: { workflowId: workflow.id, -// next time you see this line validate the trigger data thinnnnnnnnnn + // next time you see this line validate the trigger data thinnnnnnnnnn status: "Pending", metadata: triggerData, }, @@ -39,13 +41,13 @@ app.post("/hooks/catch/:userId/:workflowId", async (req, res) => { }); return res.status(200).json({ success: true, - workflowExecutionId: result.workflowExecution.id, + workflowExecutionId: result.workflowExecution.id, }); } catch (error: any) { console.log(error); - res.status(500).json({ - success: false, - error: "Failed to process webhook" + res.status(500).json({ + success: false, + error: "Failed to process webhook" }); } }); diff --git a/apps/http-backend/src/routes/google_callback.ts b/apps/http-backend/src/routes/google_callback.ts index 82d06d6..2b1e9ba 100644 --- a/apps/http-backend/src/routes/google_callback.ts +++ b/apps/http-backend/src/routes/google_callback.ts @@ -72,6 +72,7 @@ googleAuth.get( "/callback", userMiddleware, async (req: Request, res: Response) => { + console.log("Request recieved to the callback from fronted ") const code = req.query.code; const state = req.query.state; const Oauth = new GoogleOAuthService(); diff --git a/apps/http-backend/src/routes/userRoutes/userRoutes.ts b/apps/http-backend/src/routes/userRoutes/userRoutes.ts index 490bf4d..44d7d18 100644 --- a/apps/http-backend/src/routes/userRoutes/userRoutes.ts +++ b/apps/http-backend/src/routes/userRoutes/userRoutes.ts @@ -13,8 +13,11 @@ import { NodeUpdateSchema, TriggerUpdateSchema, workflowUpdateSchema, + ExecuteWorkflow, + HOOKS_URL, } from "@repo/common/zod"; import { GoogleSheetsNodeExecutor } from "@repo/nodes"; +import axios, { Axios } from "axios"; const router: Router = Router(); router.post("/createAvaliableNode", async (req: AuthRequest, res: Response) => { @@ -140,7 +143,7 @@ router.get( userMiddleware, async (req: AuthRequest, res) => { try { - console.log("user from getcredentials: ", req.user); + // console.log("user from getcredentials: ", req.user); if (!req.user) { return res.status(statusCodes.BAD_REQUEST).json({ message: "User is not Loggedin", @@ -148,7 +151,8 @@ router.get( } const userId = req.user.sub; const type = req.params.type; - console.log(userId, " -userid"); + console.log("The type of data comming to backed is ", type) + // console.log(userId, " -userid"); if (!type || !userId) { return res.status(statusCodes.BAD_REQUEST).json({ @@ -182,8 +186,6 @@ router.get( if (credentials.length === 0) { return res.status(200).json({ message: "No credentials found", - data: [], // always array - hasCredentials: false, }); } @@ -278,9 +280,9 @@ router.post( error: e instanceof Error ? e.message : "Unknown error" }); } - } + } + - ); // ------------------------------------ FETCHING WORKFLOWS ----------------------------------- @@ -519,13 +521,17 @@ router.post( // Use an empty array for credentials (if required) or don't pass it at all // Config must be valid JSON (not an empty string) // const stage = dataSafe.data.Position + console.log("This is from the backend log of positions", dataSafe.data.position) const createdNode = await prismaClient.node.create({ data: { name: dataSafe.data.Name, workflowId: dataSafe.data.WorkflowId, config: dataSafe.data.Config || {}, stage: Number(dataSafe.data.stage ?? 0), - position: {}, + position: { + x: dataSafe.data.position.x, + y: dataSafe.data.position.y + }, AvailableNodeID: dataSafe.data.AvailableNodeId, }, }); @@ -626,6 +632,74 @@ router.put( } ); +router.post("/executeWorkflow", userMiddleware, async (req: AuthRequest, res) => { + console.log("REcieved REquest to the execute route ") + const Data = req.body + if (!req.user) { + return res.status(statusCodes.UNAUTHORIZED).json({ + message: "User Not Authorized" + }) + } + const parsedData = ExecuteWorkflow.safeParse(Data); + console.log("This is the log data of execute work flow zod", parsedData.error) + if (!parsedData.success) { + return res.status(statusCodes.FORBIDDEN).json({ + message: "Error in Zod Schma", + Data: parsedData.error + }) + } + const workflowId = parsedData.data.workflowId; + const userId = req.user.id + try { + const trigger = await prismaClient.workflow.findFirst({ + where: { id: workflowId, userId: userId }, + include: { + Trigger: true + } + }) + if (!trigger) { + return res.status(statusCodes.NOT_FOUND).json({ + message: "Workflow not found or not authorized" + }); + } + console.log("This is the Trigger Name of the workflow", trigger?.Trigger?.name) + console.log("This is the Trigger Data of the workflow", trigger) + + if (trigger?.Trigger?.name === "webhook") { + const data = await axios.post(`${HOOKS_URL}/hooks/catch/${userId}/${workflowId}`, { + triggerData: "", + + }, + { timeout: 30000 },) + console.log("Workflow Execution for webhook started with Execution Id is ", data.data.workflowExecutionId) + const workflowExecutionId = data.data.workflowExecutionId; + if (!workflowExecutionId) { + return res.status(statusCodes.INTERNAL_SERVER_ERROR).json({ + message: "Failed to start workflow execution" + } + ) + } + return res.status(200).json({ + success: true, + workflowExecutionId: data.data.workflowExecutionId + }); + } + else { + + return res.status(statusCodes.FORBIDDEN).json({ + message: "Trigger is not webhook" + }); + } + + + } catch (error: any) { + return res.status(statusCodes.INTERNAL_SERVER_ERROR).json({ + message: "Internal Server Error ", + Error: error instanceof Error ? error.message : "Unknown Error" + }) + } + +}) router.get("/protected", userMiddleware, (req: AuthRequest, res) => { return res.json({ ok: true, diff --git a/apps/web/app/components/ui/Design/WorkflowButton.tsx b/apps/web/app/components/ui/Design/WorkflowButton.tsx index d431ff9..e03c008 100644 --- a/apps/web/app/components/ui/Design/WorkflowButton.tsx +++ b/apps/web/app/components/ui/Design/WorkflowButton.tsx @@ -9,7 +9,13 @@ export default function ParentComponent() { return (
- + {/* The Modal is conditionally rendered here */} {isOpen && setIsOpen(false)} />} diff --git a/apps/web/app/hooks/useCredential.ts b/apps/web/app/hooks/useCredential.ts index 2abea42..4faddc2 100644 --- a/apps/web/app/hooks/useCredential.ts +++ b/apps/web/app/hooks/useCredential.ts @@ -18,7 +18,8 @@ export const useCredentials = (type: string, workflowId?: string): any => { } const response = await getCredentials(type); - + const data = JSON.stringify(response) + console.log("This is the log from usecredentials" , data) // Backend should ONLY return stored credentials if (Array.isArray(response)) { setCred(response); diff --git a/apps/web/app/lib/api.ts b/apps/web/app/lib/api.ts index ade5c0f..cfe242c 100644 --- a/apps/web/app/lib/api.ts +++ b/apps/web/app/lib/api.ts @@ -8,11 +8,11 @@ import { getCredentials } from "../workflow/lib/config"; export const api = { user: { get: async () => { - return await axios.get(`${BACKEND_URL}/user/workflows`, + return await axios.get(`${BACKEND_URL}/user/workflows`, { - withCredentials: true, - headers: { "Content-Type": "application/json" }, - }) + withCredentials: true, + headers: { "Content-Type": "application/json" }, + }) } }, workflows: { @@ -38,6 +38,12 @@ export const api = { withCredentials: true, headers: { "Content-Type": "application/json" }, }) + }, + execute: async (data: any) => { + return await axios.post(`${BACKEND_URL}/user/executeWorkflow`, data, { + withCredentials: true, + headers: { "Content-Type": "application/json" }, + }) } }, triggers: { diff --git a/apps/web/app/lib/nodeConfigs/gmail.action.ts b/apps/web/app/lib/nodeConfigs/gmail.action.ts index bb6df74..57c37a2 100644 --- a/apps/web/app/lib/nodeConfigs/gmail.action.ts +++ b/apps/web/app/lib/nodeConfigs/gmail.action.ts @@ -6,7 +6,7 @@ export const gmailActionConfig: NodeConfig = { label: "Gmail", // ✅ Clean name icon: "📧", // ✅ Email icon description: "Send emails via Gmail", - credentials: "google", + credentials: "google_oauth", fields: [ { diff --git a/apps/web/app/login/page.tsx b/apps/web/app/login/page.tsx index 2379ed7..5ebc250 100644 --- a/apps/web/app/login/page.tsx +++ b/apps/web/app/login/page.tsx @@ -59,7 +59,7 @@ const Page = () => { } if(result?.ok){ toast.success("Login successful!") - router.push('/workflow') + router.push('/workflows') } } catch(e) { setError({...newErrors, auth:"Login failed. Please try again"}) diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx index fd1b77a..ad4b7d6 100644 --- a/apps/web/app/page.tsx +++ b/apps/web/app/page.tsx @@ -31,7 +31,7 @@ export default async function Home() { ) : ( <>

Status: Not authenticated

-
+ + + +
diff --git a/apps/web/app/workflows/[id]/page.tsx b/apps/web/app/workflows/[id]/page.tsx index 683be30..c2c2327 100644 --- a/apps/web/app/workflows/[id]/page.tsx +++ b/apps/web/app/workflows/[id]/page.tsx @@ -19,12 +19,28 @@ import { TriggerSideBar } from "@/app/components/nodes/TriggerSidebar"; import ActionSideBar from "@/app/components/Actions/ActionSidebar"; import { api } from "@/app/lib/api"; import ConfigModal from "./components/ConfigModal"; +import { toast } from "sonner"; export default function WorkflowCanvas() { const params = useParams(); const workflowId = params.id as string; // State + const handleExecute = async () => { + setLoading(true); + try { + const data = await api.workflows.execute({workflowId}) + console.log("This is from the Execute Button", data) + toast.success("Execution Started") + } + catch (error: any) { + toast.error("Failed to save config"); + + } + finally { + setLoading(false); + } + } const [nodes, setNodes, onNodesChange] = useNodesState([ { id: "trigger-placeholder", @@ -46,11 +62,12 @@ export default function WorkflowCanvas() { const [configOpen, setConfigOpen] = useState(false); const [selectedNode, setSelectedNode] = useState(null); const [error, setError] = useState(null); - + const [loading, setLoading] = useState("") const nodeTypes = { customNode: BaseNode, }; + // Safe default position - reused everywhere below const DEFAULT_TRIGGER_POSITION = { x: 250, y: 50 }; const DEFAULT_ACTION_POSITION = { x: 500, y: 200 }; @@ -62,7 +79,7 @@ export default function WorkflowCanvas() { } return pos; } - + console.log("The Detaisl of Selected Node is ", selectedNode) useEffect(() => { const loadWorkflows = async () => { try { @@ -72,6 +89,7 @@ export default function WorkflowCanvas() { const dbNodes = Array.isArray(workflows?.data?.Data?.nodes) ? workflows.data.Data.nodes : []; + console.log("the node data is", dbNodes) const dbEdges = Array.isArray(workflows?.data?.Data?.Edges) ? workflows.data.Data.Edges : []; @@ -100,6 +118,7 @@ export default function WorkflowCanvas() { onConfigure: () => handleNodeConfigure({ id: Trigger.id, + name: Trigger.name }), }, }; @@ -119,7 +138,7 @@ export default function WorkflowCanvas() { onConfigure: () => handleNodeConfigure({ id: node.id, - name: node.data?.label || node.Name, + name: node.data?.label || node.name, type: "action", actionType: node.AvailableNodeId, }), @@ -249,7 +268,6 @@ export default function WorkflowCanvas() { return; } - let cuont = 0; // Calculate next available action node index (excluding placeholders) const currentActionNodes = nodes.filter( (n) => n.data.nodeType === "action" && !n.data.isPlaceholder @@ -274,9 +292,9 @@ export default function WorkflowCanvas() { }, WorkflowId: workflowId, position: newNodePosition, - stage: cuont, + stage: nextIndex, }); - + console.log("The data of Node Positions from 201", newNodePosition) const actionId = result.data.data.id; const newNode = { @@ -451,6 +469,7 @@ export default function WorkflowCanvas() { ); } }; + console.log("THis log from page.tsx about the nodeConfig", selectedNode) return (
@@ -505,13 +524,27 @@ export default function WorkflowCanvas() { > - + + +
+ + +
{ try { const triggerNode = nodes.find( @@ -560,6 +594,7 @@ export default function WorkflowCanvas() { } }} /> + setTriggerOpen(false)} diff --git a/apps/web/app/workflows/page.tsx b/apps/web/app/workflows/page.tsx index fcae037..ed99f14 100644 --- a/apps/web/app/workflows/page.tsx +++ b/apps/web/app/workflows/page.tsx @@ -13,6 +13,7 @@ import { } from "@workspace/ui/components/card" import { Button } from "@workspace/ui/components/button" import { useRouter } from "next/navigation"; +import ParentComponent from "../components/ui/Design/WorkflowButton"; // Removed: import { Router } from "next/router"; export const UserWorkflows = () => { @@ -76,8 +77,21 @@ export const UserWorkflows = () => { )} -
-                                    {JSON.stringify(workflow.config || workflow.Config, null, 2)}
+                                
+                                    {(() => {
+                                        const config = workflow.config ?? workflow.Config;
+                                        if (
+                                            config == null ||
+                                            (typeof config === 'object' &&
+                                                !Array.isArray(config) &&
+                                                Object.keys(config).length === 0
+                                            ) ||
+                                            (Array.isArray(config) && config.length === 0)
+                                        ) {
+                                            return "Not Configured";
+                                        }
+                                        return JSON.stringify(config, null, 2);
+                                    })()}
                                 
@@ -95,6 +109,13 @@ export const UserWorkflows = () => { ))}
)} + +
+
+ +
+
+ ); }; diff --git a/apps/web/store/slices/userSlice.ts b/apps/web/store/slices/userSlice.ts index 9e5d51b..93162b3 100644 --- a/apps/web/store/slices/userSlice.ts +++ b/apps/web/store/slices/userSlice.ts @@ -19,7 +19,7 @@ const userSlice = createSlice({ name: 'user', initialState, reducers:{ - setUserId(state, action: PayloadAction){ +setUserId(state, action: PayloadAction){ state.userId = action.payload; }, setUserStatus(state, action: PayloadAction){ diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 18231bd..f59ab28 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -2,7 +2,7 @@ import z from "zod"; import { number } from "zod/v4"; export const BACKEND_URL = "http://localhost:3002"; -export const HOOKS_URL = "http://localhost:3002"; +export const HOOKS_URL = "http://localhost:3003"; export const AvailableTriggers = z.object({ Name: z.string(), AvailableTriggerID: z.string().optional(), @@ -31,8 +31,15 @@ export const NodeSchema = z.object({ Config: z.any().optional(), stage: z.number().optional(), WorkflowId: z.string(), + position : z.object({ + x : z.number() , + y : z.number() + }) }); +export const ExecuteWorkflow = z.object({ + workflowId : z.string(), +}) export const NodeUpdateSchema = z.object({ NodeId: z.string(), Config: z.any().optional(), diff --git a/packages/nodes/src/common/google-oauth-service.ts b/packages/nodes/src/common/google-oauth-service.ts index 6eeffd1..dec8e01 100644 --- a/packages/nodes/src/common/google-oauth-service.ts +++ b/packages/nodes/src/common/google-oauth-service.ts @@ -66,7 +66,7 @@ class GoogleOAuthService { try { // const credentialId = `cred_google_${userId}_${Date.now()}` - await this.prisma.credential.create({ + const Data = await this.prisma.credential.create({ data: { // id:credentialId, userId: userId, @@ -75,6 +75,7 @@ class GoogleOAuthService { nodeId: nodeId || null, }, }); + console.log("THis log is writing to see if google auth tokens is storing to db or not ",Data) } catch (error) { throw new Error( `failed to store data in Credentials: ${error instanceof Error ? error.message : "Unknown Error"}`