refactor(api): remove AI worker, add ai api route, add usage tiers

- Remove separate AI worker service
- Added generation limits:
  FREE: 1000/month (For the beta version)
  PRO: 500/month
  ENTERPRISE: 1000/month
- Integrate AI functionality into main API routes
- Added monthly generations reset and usage tier upgrade API routes
- Upgrade tier page to be added along with profile page section
This commit is contained in:
Akhileshrangani4
2024-11-23 20:31:24 -05:00
parent 4db378b5f1
commit 34994a8c69
29 changed files with 590 additions and 4049 deletions

View File

@ -1,7 +1,7 @@
{
"version": "5",
"dialect": "sqlite",
"id": "afe10bff-362b-402c-bdb5-038341692f35",
"id": "3241d14f-687f-4134-94ab-88bf36e8611e",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"sandbox": {
@ -140,13 +140,6 @@
"autoincrement": false,
"default": "CURRENT_TIMESTAMP"
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"generations": {
"name": "generations",
"type": "integer",

View File

@ -1,8 +1,8 @@
{
"version": "5",
"dialect": "sqlite",
"id": "e570d5ac-700d-4e62-8a46-482b21ae1fe1",
"prevId": "afe10bff-362b-402c-bdb5-038341692f35",
"id": "7eafd85c-d63d-43be-aa26-1a0eb2ca1805",
"prevId": "3241d14f-687f-4134-94ab-88bf36e8611e",
"tables": {
"sandbox": {
"name": "sandbox",
@ -147,6 +147,28 @@
"notNull": false,
"autoincrement": false,
"default": 0
},
"tier": {
"name": "tier",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "'FREE'"
},
"tierExpiresAt": {
"name": "tierExpiresAt",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"lastResetDate": {
"name": "lastResetDate",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {

View File

@ -5,29 +5,15 @@
{
"idx": 0,
"version": "5",
"when": 1731288423588,
"tag": "0000_cuddly_patriot",
"when": 1732400315508,
"tag": "0000_milky_hardball",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1731290863632,
"tag": "0001_opposite_newton_destine",
"breakpoints": true
},
{
"idx": 2,
"version": "5",
"when": 1731296235880,
"tag": "0002_rainy_fantastic_four",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1731297339306,
"tag": "0003_lying_snowbird",
"when": 1732408530094,
"tag": "0001_freezing_supreme_intelligence",
"breakpoints": true
}
]

View File

@ -232,32 +232,6 @@ export default {
return success
} else return methodNotAllowed
} else if (path === "/api/sandbox/generate" && method === "POST") {
const generateSchema = z.object({
userId: z.string(),
})
const body = await request.json()
const { userId } = generateSchema.parse(body)
const dbUser = await db.query.user.findFirst({
where: (user, { eq }) => eq(user.id, userId),
})
if (!dbUser) {
return new Response("User not found.", { status: 400 })
}
if (dbUser.generations !== null && dbUser.generations >= 10) {
return new Response("You reached the maximum # of generations.", {
status: 400,
})
}
await db
.update(user)
.set({ generations: sql`${user.generations} + 1` })
.where(eq(user.id, userId))
.get()
return success
} else if (path === "/api/user") {
if (method === "GET") {
const params = url.searchParams
@ -287,10 +261,12 @@ export default {
avatarUrl: z.string().optional(),
createdAt: z.string().optional(),
generations: z.number().optional(),
tier: z.enum(["FREE", "PRO", "ENTERPRISE"]).optional(),
tierExpiresAt: z.number().optional(),
})
const body = await request.json()
const { id, name, email, username, avatarUrl, createdAt, generations } = userSchema.parse(body)
const { id, name, email, username, avatarUrl, createdAt, generations, tier, tierExpiresAt } = userSchema.parse(body)
const res = await db
.insert(user)
@ -302,6 +278,8 @@ export default {
avatarUrl,
createdAt: createdAt ? new Date(createdAt) : new Date(),
generations,
tier,
tierExpiresAt,
})
.returning()
.get()
@ -330,6 +308,76 @@ export default {
return json({ exists: !!exists })
}
return methodNotAllowed
} else if (path === "/api/user/increment-generations" && method === "POST") {
const schema = z.object({
userId: z.string(),
})
const body = await request.json()
const { userId } = schema.parse(body)
await db
.update(user)
.set({ generations: sql`${user.generations} + 1` })
.where(eq(user.id, userId))
.get()
return success
} else if (path === "/api/user/update-tier" && method === "POST") {
const schema = z.object({
userId: z.string(),
tier: z.enum(["FREE", "PRO", "ENTERPRISE"]),
tierExpiresAt: z.date(),
})
const body = await request.json()
const { userId, tier, tierExpiresAt } = schema.parse(body)
await db
.update(user)
.set({
tier,
tierExpiresAt: tierExpiresAt.getTime(),
// Reset generations when upgrading tier
generations: 0
})
.where(eq(user.id, userId))
.get()
return success
} else if (path === "/api/user/check-reset" && method === "POST") {
const schema = z.object({
userId: z.string(),
})
const body = await request.json()
const { userId } = schema.parse(body)
const dbUser = await db.query.user.findFirst({
where: (user, { eq }) => eq(user.id, userId),
})
if (!dbUser) {
return new Response("User not found", { status: 404 })
}
const now = new Date()
const lastReset = dbUser.lastResetDate ? new Date(dbUser.lastResetDate) : new Date(0)
if (now.getMonth() !== lastReset.getMonth() || now.getFullYear() !== lastReset.getFullYear()) {
await db
.update(user)
.set({
generations: 0,
lastResetDate: now.getTime()
})
.where(eq(user.id, userId))
.get()
return new Response("Reset successful", { status: 200 })
}
return new Response("No reset needed", { status: 200 })
} else return notFound
},
}

View File

@ -15,6 +15,9 @@ export const user = sqliteTable("user", {
createdAt: integer("createdAt", { mode: "timestamp_ms" })
.default(sql`CURRENT_TIMESTAMP`),
generations: integer("generations").default(0),
tier: text("tier", { enum: ["FREE", "PRO", "ENTERPRISE"] }).default("FREE"),
tierExpiresAt: integer("tierExpiresAt"),
lastResetDate: integer("lastResetDate"),
})
export type User = typeof user.$inferSelect