Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ ENV NEXT_TELEMETRY_DISABLED=1
ENV DATABASE_URL="postgresql://dummy:dummy@dummy:5432/dummy"
ENV DIRECT_DATABASE_URL="postgresql://dummy:dummy@dummy:5432/dummy"
ENV BETTER_AUTH_SECRET="dummy-secret-for-build-only"
ENV BETTER_AUTH_URL="https://nodebase.tech"
ENV NEXT_PUBLIC_BETTER_AUTH_URL="https://nodebase.tech"
ENV NEXT_PUBLIC_APP_URL="https://nodebase.tech"
ENV BETTER_AUTH_URL="https://nodebase.mayanksaraswal.in"
ENV NEXT_PUBLIC_BETTER_AUTH_URL="https://nodebase.mayanksaraswal.in"
ENV NEXT_PUBLIC_APP_URL="https://nodebase.mayanksaraswal.in"
ENV GOOGLE_CLIENT_ID="dummy"
ENV GOOGLE_CLIENT_SECRET="dummy"
ENV GOOGLE_GMAIL_CLIENT_ID="dummy"
Expand Down
2 changes: 1 addition & 1 deletion next-sitemap.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @type {import('next-sitemap').IConfig} */
module.exports = {
siteUrl: "https://nodebase.tech",
siteUrl: "https://nodebase.mayanksaraswal.in",
generateRobotsTxt: true,
generateIndexSitemap: false,
changefreq: "weekly",
Expand Down
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
9 changes: 9 additions & 0 deletions prisma.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from '@prisma/config'
import 'dotenv/config'

// Fallback for DIRECT_DATABASE_URL if it's not provided
process.env.DIRECT_DATABASE_URL = process.env.DIRECT_DATABASE_URL || process.env.DATABASE_URL;

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