Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147import { Resource } from "@opencode/console-resource"import { and, Database, eq, isNull } from "../src/drizzle/index.js"import { Identifier } from "../src/identifier.js"import { AccountTable } from "../src/schema/account.sql.js"import { AuthTable } from "../src/schema/auth.sql.js"import { BillingTable } from "../src/schema/billing.sql.js"import { KeyTable } from "../src/schema/key.sql.js"import { UserTable } from "../src/schema/user.sql.js"import { WorkspaceTable } from "../src/schema/workspace.sql.js"import { centsToMicroCents } from "../src/util/price.js"
const args = parseArgs(process.argv.slice(2))if (!args.email) { console.error( "Usage: bun script/create-api-key.ts --email <email> [--workspace-id <wrk_...>] [--workspace-name <name>] [--key-name <name>] [--balance-dollars <amount>] [--allow-production]", ) process.exit(1)}if (Resource.App.stage === "production" && !args.allowProduction) { throw new Error("Refusing to create a production API key without --allow-production")}
const result = await Database.transaction(async (tx) => { const auth = await tx .select() .from(AuthTable) .where(and(eq(AuthTable.provider, "email"), eq(AuthTable.subject, args.email))) .then((rows) => rows[0]) const accountID = auth?.accountID ?? Identifier.create("account") if (!auth) { await tx.insert(AccountTable).values({ id: accountID }) await tx.insert(AuthTable).values({ id: Identifier.create("auth"), provider: "email", subject: args.email, accountID, }) }
const workspace = args.workspaceID ? await tx .select() .from(WorkspaceTable) .where(eq(WorkspaceTable.id, args.workspaceID)) .then((rows) => rows[0]) : await tx .select({ workspace: WorkspaceTable }) .from(UserTable) .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, UserTable.workspaceID)) .where(and(eq(UserTable.accountID, accountID), isNull(UserTable.timeDeleted))) .then((rows) => rows[0]?.workspace) if (args.workspaceID && !workspace) throw new Error(`Workspace not found: ${args.workspaceID}`) const workspaceID = workspace?.id ?? Identifier.create("workspace") if (!workspace) { await tx.insert(WorkspaceTable).values({ id: workspaceID, slug: null, name: args.workspaceName ?? `${args.email} manual`, }) }
const user = await tx .select() .from(UserTable) .where( and(eq(UserTable.workspaceID, workspaceID), eq(UserTable.accountID, accountID), isNull(UserTable.timeDeleted)), ) .then((rows) => rows[0]) const userID = user?.id ?? Identifier.create("user") if (!user) { await tx.insert(UserTable).values({ id: userID, workspaceID, accountID, email: args.email, name: args.email, role: "admin", }) }
const balance = centsToMicroCents(args.balanceDollars * 100) const billing = await tx .select() .from(BillingTable) .where(eq(BillingTable.workspaceID, workspaceID)) .then((rows) => rows[0]) if (!billing) { await tx.insert(BillingTable).values({ id: Identifier.create("billing"), workspaceID, balance, }) } else if (billing.balance < balance) { await tx.update(BillingTable).set({ balance }).where(eq(BillingTable.workspaceID, workspaceID)) }
const secretKey = createSecretKey() const keyID = Identifier.create("key") await tx.insert(KeyTable).values({ id: keyID, workspaceID, userID, name: args.keyName ?? "Manual API Key", key: secretKey, timeUsed: null, })
return { accountID, workspaceID, userID, keyID, secretKey }})
console.log(JSON.stringify({ stage: Resource.App.stage, ...result }, null, 2))
function createSecretKey() { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" const values = new Uint32Array(64) crypto.getRandomValues(values) return `sk-${Array.from(values, (value) => chars[value % chars.length]).join("")}`}
function parseArgs(argv: string[]) { const parsed = { email: "", workspaceID: "", workspaceName: "", keyName: "", balanceDollars: 100, allowProduction: false, } for (let index = 0; index < argv.length; index++) { const arg = argv[index] if (arg === "--email") parsed.email = requiredValue(argv, ++index, arg) if (arg === "--workspace-id") parsed.workspaceID = requiredValue(argv, ++index, arg) if (arg === "--workspace-name") parsed.workspaceName = requiredValue(argv, ++index, arg) if (arg === "--key-name") parsed.keyName = requiredValue(argv, ++index, arg) if (arg === "--balance-dollars") parsed.balanceDollars = Number(requiredValue(argv, ++index, arg)) if (arg === "--allow-production") parsed.allowProduction = true } if (!Number.isFinite(parsed.balanceDollars) || parsed.balanceDollars < 0) throw new Error("Invalid --balance-dollars") return parsed}
function requiredValue(argv: string[], index: number, arg: string) { const value = argv[index] if (!value || value.startsWith("--")) throw new Error(`Missing value for ${arg}`) return value}