summaryrefslogtreecommitdiffhomepage
path: root/packages/console/core/src/key.ts
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-09-18 10:59:01 -0400
committerFrank <[email protected]>2025-09-18 10:59:01 -0400
commit4ceabdffa07b1af8d99eb73622a4d549d99ec6d2 (patch)
tree72e2ae62084a9e24cc76caffbd1f30dafc69ea56 /packages/console/core/src/key.ts
parentc87480cf931a6f8f8b55552558ef521f1918b578 (diff)
downloadopencode-4ceabdffa07b1af8d99eb73622a4d549d99ec6d2.tar.gz
opencode-4ceabdffa07b1af8d99eb73622a4d549d99ec6d2.zip
wip: zen
Diffstat (limited to 'packages/console/core/src/key.ts')
-rw-r--r--packages/console/core/src/key.ts75
1 files changed, 75 insertions, 0 deletions
diff --git a/packages/console/core/src/key.ts b/packages/console/core/src/key.ts
new file mode 100644
index 000000000..28643a521
--- /dev/null
+++ b/packages/console/core/src/key.ts
@@ -0,0 +1,75 @@
+import { z } from "zod"
+import { fn } from "./util/fn"
+import { Actor } from "./actor"
+import { and, Database, eq, isNull, sql } from "./drizzle"
+import { Identifier } from "./identifier"
+import { KeyTable } from "./schema/key.sql"
+
+export namespace Key {
+ export const list = async () => {
+ const workspace = Actor.workspace()
+ const keys = await Database.use((tx) =>
+ tx
+ .select()
+ .from(KeyTable)
+ .where(and(eq(KeyTable.workspaceID, workspace), isNull(KeyTable.timeDeleted)))
+ .orderBy(sql`${KeyTable.timeCreated} DESC`),
+ )
+ return keys
+ }
+
+ export const create = fn(z.object({ name: z.string().min(1).max(255) }), async (input) => {
+ const workspaceID = Actor.workspace()
+ const { name } = input
+
+ // Generate secret key: sk- + 64 random characters (upper, lower, numbers)
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ let secretKey = "sk-"
+ const array = new Uint32Array(64)
+ crypto.getRandomValues(array)
+ for (let i = 0, l = array.length; i < l; i++) {
+ secretKey += chars[array[i] % chars.length]
+ }
+ const keyID = Identifier.create("key")
+
+ await Database.use((tx) =>
+ tx.insert(KeyTable).values({
+ id: keyID,
+ workspaceID,
+ actor: Actor.use(),
+ name,
+ key: secretKey,
+ timeUsed: null,
+ }),
+ ).catch((e: any) => {
+ if (e.message.match(/Duplicate entry '.*' for key 'key.name'/))
+ throw new Error("A key with this name already exists. Please choose a different name.")
+ throw e
+ })
+
+ return keyID
+ })
+
+ export const remove = fn(z.object({ id: z.string() }), async (input) => {
+ const workspace = Actor.workspace()
+ await Database.transaction(async (tx) => {
+ const row = await tx
+ .select({
+ name: KeyTable.name,
+ })
+ .from(KeyTable)
+ .where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace)))
+ .then((rows) => rows[0])
+ if (!row) return
+
+ await tx
+ .update(KeyTable)
+ .set({
+ timeDeleted: sql`now()`,
+ oldName: row.name,
+ name: input.id, // Use the key ID as the name
+ })
+ .where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace)))
+ })
+ })
+}