mirror of
https://github.com/sst/opencode.git
synced 2025-08-24 15:04:10 +00:00
71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import { Resource } from "sst"
|
|
import { Stripe } from "stripe"
|
|
import { Database, eq, sql } from "./drizzle"
|
|
import { BillingTable, UsageTable } from "./schema/billing.sql"
|
|
import { Actor } from "./actor"
|
|
import { fn } from "./util/fn"
|
|
import { z } from "zod"
|
|
import { Identifier } from "./identifier"
|
|
import { centsToMicroCents } from "./util/price"
|
|
|
|
export namespace Billing {
|
|
export const stripe = () =>
|
|
new Stripe(Resource.STRIPE_SECRET_KEY.value, {
|
|
apiVersion: "2025-03-31.basil",
|
|
})
|
|
|
|
export const get = async () => {
|
|
return Database.use(async (tx) =>
|
|
tx
|
|
.select({
|
|
customerID: BillingTable.customerID,
|
|
paymentMethodID: BillingTable.paymentMethodID,
|
|
balance: BillingTable.balance,
|
|
reload: BillingTable.reload,
|
|
})
|
|
.from(BillingTable)
|
|
.where(eq(BillingTable.workspaceID, Actor.workspace()))
|
|
.then((r) => r[0]),
|
|
)
|
|
}
|
|
|
|
export const consume = fn(
|
|
z.object({
|
|
requestID: z.string().optional(),
|
|
model: z.string(),
|
|
inputTokens: z.number(),
|
|
outputTokens: z.number(),
|
|
reasoningTokens: z.number().optional(),
|
|
cacheReadTokens: z.number().optional(),
|
|
cacheWriteTokens: z.number().optional(),
|
|
costInCents: z.number(),
|
|
}),
|
|
async (input) => {
|
|
const workspaceID = Actor.workspace()
|
|
const cost = centsToMicroCents(input.costInCents)
|
|
|
|
return await Database.transaction(async (tx) => {
|
|
await tx.insert(UsageTable).values({
|
|
workspaceID,
|
|
id: Identifier.create("usage"),
|
|
requestID: input.requestID,
|
|
model: input.model,
|
|
inputTokens: input.inputTokens,
|
|
outputTokens: input.outputTokens,
|
|
reasoningTokens: input.reasoningTokens,
|
|
cacheReadTokens: input.cacheReadTokens,
|
|
cacheWriteTokens: input.cacheWriteTokens,
|
|
cost,
|
|
})
|
|
const [updated] = await tx
|
|
.update(BillingTable)
|
|
.set({
|
|
balance: sql`${BillingTable.balance} - ${cost}`,
|
|
})
|
|
.where(eq(BillingTable.workspaceID, workspaceID))
|
|
.returning()
|
|
return updated.balance
|
|
})
|
|
},
|
|
)
|
|
}
|