diff --git a/Screenshot 2024-10-15 180911.png b/Screenshot 2024-10-15 180911.png new file mode 100644 index 0000000..e28ba8f Binary files /dev/null and b/Screenshot 2024-10-15 180911.png differ diff --git a/frontend/app/config.ts b/frontend/app/config.ts index 3a2a8ac..684bf12 100644 --- a/frontend/app/config.ts +++ b/frontend/app/config.ts @@ -1,2 +1,2 @@ export const BACKEND_URL="http://localhost:3000" -export const HOOKS_URL="https://localhost:3002" \ No newline at end of file +export const HOOKS_URL="http://localhost:3002" \ No newline at end of file diff --git a/frontend/app/login/page.tsx b/frontend/app/login/page.tsx index 11abe3b..aaf3a54 100644 --- a/frontend/app/login/page.tsx +++ b/frontend/app/login/page.tsx @@ -12,11 +12,6 @@ export default function Page() { const [email,setEmail]=useState(""); const [password,setPassword]=useState(""); const router=useRouter(); - useEffect(()=>{ - if(localStorage.getItem("token")){ - router.push("/dashboard") - } - },[]) return (
diff --git a/hooks/package.json b/hooks/package.json index 205856a..d869d8f 100644 --- a/hooks/package.json +++ b/hooks/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "start": "tsc -b && node dist/index.js" + "dev": "tsc -b && node dist/index.js" }, "keywords": [], "author": "", diff --git a/primaryBackend/package.json b/primaryBackend/package.json index 21c6981..44ad0b3 100644 --- a/primaryBackend/package.json +++ b/primaryBackend/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "start": "tsc -b && node dist/index.js" + "dev": "tsc -b && node dist/index.js" }, "keywords": [], "author": "", diff --git a/processor/dist/index.js b/processor/dist/index.js index 5321812..56e70e2 100644 --- a/processor/dist/index.js +++ b/processor/dist/index.js @@ -31,7 +31,7 @@ function main() { topic: TOPIC_NAME, messages: pendingRows.map(r => { return { - value: r.zapRunId + value: JSON.stringify({ zapRunId: r.zapRunId, stage: 0 }) }; }) }); diff --git a/processor/package.json b/processor/package.json index dafa3e3..713820b 100644 --- a/processor/package.json +++ b/processor/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "start": "tsc -b && node dist/index.js" + "dev": "tsc -b && node dist/index.js" }, "keywords": [], "author": "", diff --git a/worker/.gitignore b/worker/.gitignore new file mode 100644 index 0000000..11ddd8d --- /dev/null +++ b/worker/.gitignore @@ -0,0 +1,3 @@ +node_modules +# Keep environment variables out of version control +.env diff --git a/worker/dist/index.js b/worker/dist/index.js index 578575c..15a120a 100644 --- a/worker/dist/index.js +++ b/worker/dist/index.js @@ -10,6 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }; Object.defineProperty(exports, "__esModule", { value: true }); const kafkajs_1 = require("kafkajs"); +const client_1 = require("@prisma/client"); +const prismaClient = new client_1.PrismaClient(); const TOPIC_NAME = "zap-events"; const kafka = new kafkajs_1.Kafka({ clientId: "outbox-processor", @@ -21,18 +23,68 @@ function main() { groupId: "main-worker", }); yield consumer.connect(); + const producer = kafka.producer(); + yield producer.connect(); yield consumer.subscribe({ topic: TOPIC_NAME, fromBeginning: true }); yield consumer.run({ autoCommit: false, eachMessage: (_a) => __awaiter(this, [_a], void 0, function* ({ topic, partition, message }) { - var _b; + var _b, _c, _d, _e, _f; console.log({ partition, offset: message.offset, value: (_b = message.value) === null || _b === void 0 ? void 0 : _b.toString(), }); - // + if (!((_c = message.value) === null || _c === void 0 ? void 0 : _c.toString())) { + return; + } + const parsedValue = JSON.parse((_d = message.value) === null || _d === void 0 ? void 0 : _d.toString()); + const zapRunId = parsedValue.zapRunId; + const stage = parsedValue.stage; + const zapRunDetails = yield prismaClient.zapRun.findFirst({ + where: { + id: zapRunId + }, + include: { + zap: { + include: { + actions: { + include: { + type: true + } + } + } + } + } + }); + const currentAction = zapRunDetails === null || zapRunDetails === void 0 ? void 0 : zapRunDetails.zap.actions.find(x => x.sortingOrder === stage); + if (!currentAction) { + console.log('Current action not found'); + return; + } + console.log(currentAction); + if (currentAction.type.id === 'email') { + console.log('Sending out an email'); + //parse out the email to send + } + if (currentAction.type.id === 'send-sol') { + console.log('Sending out solana'); + //parse out the address and the amount to send + } yield new Promise((r) => setTimeout(r, 500)); + const zapId = (_e = message === null || message === void 0 ? void 0 : message.value) === null || _e === void 0 ? void 0 : _e.toString(); + const lastStage = (((_f = zapRunDetails === null || zapRunDetails === void 0 ? void 0 : zapRunDetails.zap.actions) === null || _f === void 0 ? void 0 : _f.length) || 1) - 1; + if (lastStage !== stage) { + yield producer.send({ + topic: TOPIC_NAME, + messages: [{ + value: JSON.stringify({ + stage: stage + 1, + zapRunId + }) + }] + }); + } console.log('processing done'); //you can do your action operation here! // diff --git a/worker/node_modules/.package-lock.json b/worker/node_modules/.package-lock.json index 7c73dd3..a98f2dd 100644 --- a/worker/node_modules/.package-lock.json +++ b/worker/node_modules/.package-lock.json @@ -4,6 +4,74 @@ "lockfileVersion": 3, "requires": true, "packages": { + "node_modules/@prisma/client": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.20.0.tgz", + "integrity": "sha512-CLv55ZuMuUawMsxoqxGtLT3bEZoa2W8L3Qnp6rDIFWy+ZBrUcOFKdoeGPSnbBqxc3SkdxJrF+D1veN/WNynZYA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.20.0.tgz", + "integrity": "sha512-oCx79MJ4HSujokA8S1g0xgZUGybD4SyIOydoHMngFYiwEwYDQ5tBQkK5XoEHuwOYDKUOKRn/J0MEymckc4IgsQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.20.0.tgz", + "integrity": "sha512-DtqkP+hcZvPEbj8t8dK5df2b7d3B8GNauKqaddRRqQBBlgkbdhJkxhoJTrOowlS3vaRt2iMCkU0+CSNn0KhqAQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.20.0", + "@prisma/engines-version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", + "@prisma/fetch-engine": "5.20.0", + "@prisma/get-platform": "5.20.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284.tgz", + "integrity": "sha512-Lg8AS5lpi0auZe2Mn4gjuCg081UZf88k3cn0RCwHgR+6cyHHpttPZBElJTHf83ZGsRNAmVCZCfUGA57WB4u4JA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.20.0.tgz", + "integrity": "sha512-JVcaPXC940wOGpCOwuqQRTz6I9SaBK0c1BAyC1pcz9xBi+dzFgUu3G/p9GV1FhFs9OKpfSpIhQfUJE9y00zhqw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.20.0", + "@prisma/engines-version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", + "@prisma/get-platform": "5.20.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.20.0.tgz", + "integrity": "sha512-8/+CehTZZNzJlvuryRgc77hZCWrUDYd/PmlZ7p2yNXtmf2Una4BWnTbak3us6WVdqoz5wmptk6IhsXdG2v5fmA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.20.0" + } + }, "node_modules/kafkajs": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz", @@ -11,6 +79,26 @@ "engines": { "node": ">=14.0.0" } + }, + "node_modules/prisma": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.20.0.tgz", + "integrity": "sha512-6obb3ucKgAnsGS9x9gLOe8qa51XxvJ3vLQtmyf52CTey1Qcez3A6W6ROH5HIz5Q5bW+0VpmZb8WBohieMFGpig==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/engines": "5.20.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + }, + "optionalDependencies": { + "fsevents": "2.3.3" + } } } } diff --git a/worker/package-lock.json b/worker/package-lock.json index 1e6a544..c5bb88a 100644 --- a/worker/package-lock.json +++ b/worker/package-lock.json @@ -9,7 +9,94 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@prisma/client": "^5.20.0", "kafkajs": "^2.2.4" + }, + "devDependencies": { + "prisma": "^5.20.0" + } + }, + "node_modules/@prisma/client": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.20.0.tgz", + "integrity": "sha512-CLv55ZuMuUawMsxoqxGtLT3bEZoa2W8L3Qnp6rDIFWy+ZBrUcOFKdoeGPSnbBqxc3SkdxJrF+D1veN/WNynZYA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.20.0.tgz", + "integrity": "sha512-oCx79MJ4HSujokA8S1g0xgZUGybD4SyIOydoHMngFYiwEwYDQ5tBQkK5XoEHuwOYDKUOKRn/J0MEymckc4IgsQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.20.0.tgz", + "integrity": "sha512-DtqkP+hcZvPEbj8t8dK5df2b7d3B8GNauKqaddRRqQBBlgkbdhJkxhoJTrOowlS3vaRt2iMCkU0+CSNn0KhqAQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.20.0", + "@prisma/engines-version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", + "@prisma/fetch-engine": "5.20.0", + "@prisma/get-platform": "5.20.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284.tgz", + "integrity": "sha512-Lg8AS5lpi0auZe2Mn4gjuCg081UZf88k3cn0RCwHgR+6cyHHpttPZBElJTHf83ZGsRNAmVCZCfUGA57WB4u4JA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.20.0.tgz", + "integrity": "sha512-JVcaPXC940wOGpCOwuqQRTz6I9SaBK0c1BAyC1pcz9xBi+dzFgUu3G/p9GV1FhFs9OKpfSpIhQfUJE9y00zhqw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.20.0", + "@prisma/engines-version": "5.20.0-12.06fc58a368dc7be9fbbbe894adf8d445d208c284", + "@prisma/get-platform": "5.20.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.20.0.tgz", + "integrity": "sha512-8/+CehTZZNzJlvuryRgc77hZCWrUDYd/PmlZ7p2yNXtmf2Una4BWnTbak3us6WVdqoz5wmptk6IhsXdG2v5fmA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.20.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/kafkajs": { @@ -19,6 +106,26 @@ "engines": { "node": ">=14.0.0" } + }, + "node_modules/prisma": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.20.0.tgz", + "integrity": "sha512-6obb3ucKgAnsGS9x9gLOe8qa51XxvJ3vLQtmyf52CTey1Qcez3A6W6ROH5HIz5Q5bW+0VpmZb8WBohieMFGpig==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/engines": "5.20.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + }, + "optionalDependencies": { + "fsevents": "2.3.3" + } } } } diff --git a/worker/package.json b/worker/package.json index 6698f0a..03489d8 100644 --- a/worker/package.json +++ b/worker/package.json @@ -3,13 +3,17 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "start": "tsc -b && node dist/index.js" + "dev": "tsc -b && node dist/index.js" }, "keywords": [], "author": "", "license": "ISC", "description": "", "dependencies": { + "@prisma/client": "^5.20.0", "kafkajs": "^2.2.4" + }, + "devDependencies": { + "prisma": "^5.20.0" } } diff --git a/worker/prisma/schema.prisma b/worker/prisma/schema.prisma new file mode 100644 index 0000000..5b129ea --- /dev/null +++ b/worker/prisma/schema.prisma @@ -0,0 +1,79 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model User { + id Int @id @default(autoincrement()) + name String + email String @unique + password String + zaps Zap[] +} + +model Zap { + id String @id @default(uuid()) + triggerId String? + userId Int + trigger Trigger? + actions Action[] + zapRuns ZapRun[] + user User @relation(fields: [userId], references: [id]) +} + +model Trigger { + id String @id @default(uuid()) + zapId String @unique + zap Zap @relation(fields: [zapId], references: [id]) + availableTriggerId String + metadata Json @default("{}") + type AvailableTrigger @relation(fields: [availableTriggerId], references: [id]) +} + +model Action { + id String @id @default(uuid()) + zapId String + zap Zap @relation(fields: [zapId], references: [id]) + actionId String + metadata Json @default("{}") + type AvailableAction @relation(fields: [actionId], references: [id]) + sortingOrder Int @default(0) +} + +model AvailableAction { + id String @id @default(uuid()) + name String + image String + actions Action[] +} + +model AvailableTrigger { + id String @id @default(uuid()) + name String + image String + triggers Trigger[] +} + +model ZapRun { + id String @id @default(uuid()) + zapId String + metadata Json + zap Zap @relation(fields: [zapId], references: [id]) + zapRunOutBox ZapRunOutbox? +} + +model ZapRunOutbox { + id String @id @default(uuid()) + zapRunId String @unique + zapRun ZapRun @relation(fields: [zapRunId], references: [id]) +} diff --git a/worker/src/index.ts b/worker/src/index.ts index fbf3667..dd53f76 100644 --- a/worker/src/index.ts +++ b/worker/src/index.ts @@ -1,4 +1,8 @@ import { Kafka } from "kafkajs"; +import { PrismaClient } from "@prisma/client"; +import { JsonObject } from "@prisma/client/runtime/library"; + +const prismaClient=new PrismaClient(); const TOPIC_NAME = "zap-events"; @@ -11,7 +15,13 @@ async function main() { const consumer = kafka.consumer({ groupId: "main-worker", }); + await consumer.connect(); + + const producer = kafka.producer(); + + await producer.connect(); + await consumer.subscribe({ topic: TOPIC_NAME, fromBeginning: true }); await consumer.run({ autoCommit: false, @@ -25,8 +35,62 @@ async function main() { return; } const parsedValue=JSON.parse(message.value?.toString()); - // + const zapRunId= parsedValue.zapRunId; + const stage=parsedValue.stage; + const zapRunDetails=await prismaClient.zapRun.findFirst({ + where:{ + id:zapRunId + }, + include:{ + zap:{ + include:{ + actions:{ + include:{ + type:true + } + } + } + } + } + }) + const currentAction=zapRunDetails?.zap.actions.find(x=>x.sortingOrder === stage) + + if(!currentAction){ + console.log('Current action not found') + return; + } + + if(currentAction.type.id==='email'){ + console.log('Sending out an email') + const body=(currentAction.metadata as JsonObject)?.body; + const to=(currentAction.metadata as JsonObject)?.email; + const zapRunMetadata=zapRunDetails?.metadata; + + } + + if(currentAction.type.id==='send-sol'){ + console.log('Sending out solana') + //parse out the address and the amount to send + } + await new Promise((r) => setTimeout(r, 500)); + + const zapId= message?.value?.toString(); + + const lastStage= (zapRunDetails?.zap.actions?.length || 1) - 1; + + if(lastStage!==stage){ + await producer.send({ + topic: TOPIC_NAME, + messages:[{ + value: JSON.stringify({ + stage : stage + 1, + zapRunId + }) + }] + }) + } + console.log('processing done') //you can do your action operation here! diff --git a/worker/src/parser.ts b/worker/src/parser.ts new file mode 100644 index 0000000..b6e2d17 --- /dev/null +++ b/worker/src/parser.ts @@ -0,0 +1,30 @@ +export function parse(text:string, values:any , startDelimeter:"{", endDelimeter:"}"){ + //you received {comment.amount} money from {comment.link} + let startIndex=0; + let endIndex=1; + + while(endIndex!=text.length){ + if(text[startIndex]===startDelimeter){ + let endPoint=startIndex+2; + while(text[endPoint] !=endDelimeter){ + endPoint++; + } + let stringHoldingValue = text.slice(startIndex+1, endPoint-1); + const keys= stringHoldingValue.split(".") + let localValues={ + ...values + } + for(let i=0;i