Skip to content

Commit 2b8a596

Browse files
feat(console): add go usage endpoint (#16513)
Co-authored-by: vimtor <vn4varro@gmail.com>
1 parent 36b2053 commit 2b8a596

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

  • packages/console/app/src/routes/zen/go/v1
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import type { APIEvent } from "@solidjs/start/server"
2+
import { and, Database, eq, isNull } from "@opencode-ai/console-core/drizzle/index.js"
3+
import { BillingTable, LiteTable } from "@opencode-ai/console-core/schema/billing.sql.js"
4+
import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
5+
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
6+
import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js"
7+
import { LiteData } from "@opencode-ai/console-core/lite.js"
8+
import { Subscription } from "@opencode-ai/console-core/subscription.js"
9+
10+
export async function GET(input: APIEvent) {
11+
const apiKey = input.request.headers.get("authorization")?.match(/^Bearer (\S+)$/)?.[1]
12+
13+
if (!apiKey) {
14+
return new Response(
15+
JSON.stringify({
16+
type: "error",
17+
error: {
18+
type: "AuthError",
19+
message: "Missing API key.",
20+
},
21+
}),
22+
{
23+
status: 401,
24+
headers: {
25+
"Content-Type": "application/json",
26+
},
27+
},
28+
)
29+
}
30+
31+
const auth = await Database.use((tx) =>
32+
tx
33+
.select({
34+
lite: BillingTable.lite,
35+
userID: KeyTable.userID,
36+
workspaceID: KeyTable.workspaceID,
37+
})
38+
.from(KeyTable)
39+
.innerJoin(
40+
UserTable,
41+
and(
42+
eq(UserTable.workspaceID, KeyTable.workspaceID),
43+
eq(UserTable.id, KeyTable.userID),
44+
isNull(UserTable.timeDeleted),
45+
),
46+
)
47+
.innerJoin(WorkspaceTable, and(eq(WorkspaceTable.id, KeyTable.workspaceID), isNull(WorkspaceTable.timeDeleted)))
48+
.innerJoin(
49+
BillingTable,
50+
and(eq(BillingTable.workspaceID, KeyTable.workspaceID), isNull(BillingTable.timeDeleted)),
51+
)
52+
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
53+
.then((rows) => rows[0]),
54+
)
55+
56+
if (!auth) {
57+
return new Response(
58+
JSON.stringify({
59+
type: "error",
60+
error: {
61+
type: "AuthError",
62+
message: "Unauthorized",
63+
},
64+
}),
65+
{
66+
status: 401,
67+
headers: {
68+
"Content-Type": "application/json",
69+
},
70+
},
71+
)
72+
}
73+
74+
const row = await Database.use((tx) =>
75+
tx
76+
.select({
77+
timeCreated: LiteTable.timeCreated,
78+
rollingUsage: LiteTable.rollingUsage,
79+
weeklyUsage: LiteTable.weeklyUsage,
80+
monthlyUsage: LiteTable.monthlyUsage,
81+
timeRollingUpdated: LiteTable.timeRollingUpdated,
82+
timeWeeklyUpdated: LiteTable.timeWeeklyUpdated,
83+
timeMonthlyUpdated: LiteTable.timeMonthlyUpdated,
84+
})
85+
.from(LiteTable)
86+
.where(
87+
and(
88+
eq(LiteTable.workspaceID, auth.workspaceID),
89+
eq(LiteTable.userID, auth.userID),
90+
isNull(LiteTable.timeDeleted),
91+
),
92+
)
93+
.then((rows) => rows[0]),
94+
)
95+
96+
if (!row) {
97+
return new Response(
98+
JSON.stringify({
99+
type: "error",
100+
error: {
101+
type: "EntitlementError",
102+
message: "OpenCode Go subscription required.",
103+
},
104+
}),
105+
{
106+
status: 403,
107+
headers: {
108+
"Content-Type": "application/json",
109+
},
110+
},
111+
)
112+
}
113+
114+
const limits = LiteData.getLimits()
115+
116+
return new Response(
117+
JSON.stringify({
118+
useBalance: auth.lite?.useBalance ?? false,
119+
rollingUsage: Subscription.analyzeRollingUsage({
120+
limit: limits.rollingLimit,
121+
window: limits.rollingWindow,
122+
usage: row.rollingUsage ?? 0,
123+
timeUpdated: row.timeRollingUpdated ?? new Date(),
124+
}),
125+
weeklyUsage: Subscription.analyzeWeeklyUsage({
126+
limit: limits.weeklyLimit,
127+
usage: row.weeklyUsage ?? 0,
128+
timeUpdated: row.timeWeeklyUpdated ?? new Date(),
129+
}),
130+
monthlyUsage: Subscription.analyzeMonthlyUsage({
131+
limit: limits.monthlyLimit,
132+
usage: row.monthlyUsage ?? 0,
133+
timeUpdated: row.timeMonthlyUpdated ?? new Date(),
134+
timeSubscribed: row.timeCreated,
135+
}),
136+
}),
137+
{
138+
status: 200,
139+
headers: {
140+
"Content-Type": "application/json",
141+
},
142+
},
143+
)
144+
}

0 commit comments

Comments
 (0)