Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ scripts/set-azure-env-vars.sh
NODEBASE_CONTEXT.md
tsc-errors.txt
*.tsc-errors.txt
github-node.md
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"test": "vitest run",
"test:watch": "vitest",
"migrate:razorpay-secrets": "tsx scripts/migrate-razorpay-secrets.ts",
"migrate:whatsapp-tokens": "tsx scripts/migrate-whatsapp-tokens.ts"
"migrate:whatsapp-tokens": "tsx scripts/migrate-whatsapp-tokens.ts",
"migrate:webhook-secrets": "tsx scripts/migrate-webhook-secrets.ts"
},
"dependencies": {
"@ai-sdk/anthropic": "^2.0.37",
Expand Down
6 changes: 6 additions & 0 deletions prisma.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineConfig } from '@prisma/config'
import 'dotenv/config'

export default defineConfig({
schema: "prisma/schema"
})
File renamed without changes.
99 changes: 99 additions & 0 deletions prisma/schema/auth.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// ─────────────────────────────────────────────────────────────
// Nodebase — Prisma Schema: Auth & Billing Models
// User, Session, Account, Verification, BillingEvent
// ─────────────────────────────────────────────────────────────

model User {
id String @id
name String
email String
emailVerified Boolean @default(false)
emailVerifyToken String? @unique
emailVerifyExpiry DateTime?
emailVerifyAttempts Int @default(0)
image String?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
sessions Session[]
accounts Account[]
workflows workflow[]
credentials Credential[]
executionCount Int @default(0)

// ── Subscription / Billing ───────────────────────────────────────────────
plan String @default("FREE") // FREE|STARTER|PRO|TEAM
planStatus String @default("active") // active|past_due|cancelled|paused
razorpayCustomerId String? @unique // cust_xxxx
razorpaySubId String? @unique // sub_xxxx
currentPeriodEnd DateTime?
cancelAtPeriodEnd Boolean @default(false)
workflowRunsUsed Int @default(0)
workflowRunsReset DateTime @default(now())
billingEvents BillingEvent[]

@@unique([email])
@@map("user")
}

model BillingEvent {
id String @id @default(cuid())
userId String
type String // subscription.activated | payment.captured | subscription.cancelled | etc.
razorpayEventId String? @unique
amount Int? // paise
currency String @default("INR")
plan String?
status String // success | failed | pending
rawPayload String @db.Text // full Razorpay webhook JSON
createdAt DateTime @default(now())

user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@index([userId])
@@index([type])
}

model Session {
id String @id
expiresAt DateTime
token String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
ipAddress String?
userAgent String?
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)

@@unique([token])
@@map("session")
}

model Account {
id String @id
accountId String
providerId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@map("account")
}

model Verification {
id String @id
identifier String
value String
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt

@@map("verification")
}
15 changes: 15 additions & 0 deletions prisma/schema/base.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// ─────────────────────────────────────────────────────────────
// Nodebase — Prisma Schema: Base Configuration
// Generator and datasource definitions
// ─────────────────────────────────────────────────────────────

generator client {
provider = "prisma-client-js"
output = "../../src/generated/prisma"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DIRECT_DATABASE_URL")
}
160 changes: 160 additions & 0 deletions prisma/schema/core.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// ─────────────────────────────────────────────────────────────
// Nodebase — Prisma Schema: Core Models
// workflow, Node, Connection, Credential, Execution, NodeExecution
// ─────────────────────────────────────────────────────────────

model workflow {
id String @id @default(cuid())
name String

createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
nodes Node[]
connections Connection[]
executions Execution[]
webhookTrigger WebhookTrigger?
scheduleTrigger ScheduleTrigger?
ifElseNodes IfElseNode[]
gmailNodes GmailNode[]
setVariableNodes SetVariableNode[]
googleSheetsNodes GoogleSheetsNode[]
googleDriveNodes GoogleDriveNode[]
codeNodes CodeNode[]
whatsAppNodes WhatsAppNode[]
loopNodes LoopNode[]
notionNodes NotionNode[]
razorpayNodes RazorpayNode[]
slackNodes SlackNode[]
gmailWatchers GmailWatcher[]
switchNodes SwitchNode[]
waitNodes WaitNode[]
mergeNodes MergeNode[]
errorTriggerNodes ErrorTriggerNode[]
razorpayTriggers RazorpayTrigger[]
whatsappTriggers WhatsAppTrigger[]
msg91Nodes Msg91Node[]
shiprocketNodes ShiprocketNode[]
zohoCrmNodes ZohoCrmNode[]
hubspotNodes HubspotNode[]
freshdeskNodes FreshdeskNode[]
aiNodes AINode[]
mediaUploadNodes MediaUploadNode[]
sortNodes SortNode[]
filterNodes FilterNode[]
cashfreeNodes CashfreeNode[]
aggregateNodes AggregateNode[]
postgresNodes PostgresNode[]
githubNodes GitHubNode[]
githubTriggerNodes GitHubTriggerNode[]
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Credential {
id String @id @default(cuid())
name String
value String
userId String
type CredentialType
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
Node Node[]
shiprocketNodes ShiprocketNode[]
zohoCrmNodes ZohoCrmNode[]
hubspotNodes HubspotNode[]
freshdeskNodes FreshdeskNode[]
cashfreeNodes CashfreeNode[]
postgresNodes PostgresNode[]
githubNodes GitHubNode[]

createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
razorpayNodes RazorpayNode[]
gmailNodes GmailNode[]
googleSheetsNodes GoogleSheetsNode[]
googleDriveNodes GoogleDriveNode[]
slackNodes SlackNode[]
whatsAppNodes WhatsAppNode[]
notionNodes NotionNode[]
msg91Nodes Msg91Node[]
ainodes AINode[]
mediaUploadNodes MediaUploadNode[]

// TODO: @@map("Credenial") has a typo — should be "credential"
// Fixing requires: ALTER TABLE "Credenial" RENAME TO "credential";
// plus updating all existing FK references. Do in a dedicated migration sprint.
@@map("credential")
}

model Node {
id String @id @default(cuid())
name String
type NodeType
workflowId String
position Json
data Json @default("{}")
outputConnections Connection[] @relation("FromNode")
inputConnections Connection[] @relation("ToNode")
workflow workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
credentialId String?
credential Credential? @relation(fields: [credentialId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
}

model Connection {
id String @id @default(cuid())
workflowId String
workflow workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
fromNodeId String
fromNode Node @relation("FromNode", fields: [fromNodeId], references: [id], onDelete: Cascade)
toNodeId String
toNode Node @relation("ToNode", fields: [toNodeId], references: [id], onDelete: Cascade)
fromOutput String @default("main")
toInput String @default("main")

createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt

@@unique([fromNodeId, toNodeId, fromOutput, toInput])
}

model Execution {
id String @id @default(cuid())
workflowId String
workflow workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
startedAt DateTime @default(now())
completedAt DateTime?
inngestEventId String @unique
output Json?
error String? @db.Text
errorStack String? @db.Text
status ExecutionStatus @default(RUNNING)
nodeExecutions NodeExecution[]
}

model NodeExecution {
id String @id @default(cuid())
executionId String
execution Execution @relation(fields: [executionId], references: [id], onDelete: Cascade)

nodeId String
nodeName String @default("")
nodeType String @default("")

status String @default("success")

inputJson String @default("") @db.Text
outputJson String @default("") @db.Text

errorMessage String @default("")

durationMs Int @default(0)

executionOrder Int @default(0)

createdAt DateTime @default(now())

@@index([executionId])
@@index([nodeId])
@@index([executionId, executionOrder])
}
Loading
Loading