import { json, query, action, useParams, createAsync, useSubmission } from "@solidjs/router" import { createEffect, createSignal, For, Show } from "solid-js" import { IconCopy, IconCheck } from "~/component/icon" import { Key } from "@opencode/console-core/key.js" import { withActor } from "~/context/auth.withActor" import { createStore } from "solid-js/store" import { formatDateUTC, formatDateForTable } from "./common" import styles from "./key-section.module.css" const removeKey = action(async (form: FormData) => { "use server" const id = form.get("id")?.toString() if (!id) return { error: "ID is required" } const workspaceID = form.get("workspaceID")?.toString() if (!workspaceID) return { error: "Workspace ID is required" } return json(await withActor(() => Key.remove({ id }), workspaceID), { revalidate: listKeys.key }) }, "key.remove") const createKey = action(async (form: FormData) => { "use server" const name = form.get("name")?.toString().trim() if (!name) return { error: "Name is required" } const workspaceID = form.get("workspaceID")?.toString() if (!workspaceID) return { error: "Workspace ID is required" } return json( await withActor( () => Key.create({ name }) .then((data) => ({ error: undefined, data })) .catch((e) => ({ error: e.message as string })), workspaceID, ), { revalidate: listKeys.key }, ) }, "key.create") const listKeys = query(async (workspaceID: string) => { "use server" return withActor(() => Key.list(), workspaceID) }, "key.list") export function KeyCreateForm() { const params = useParams() const submission = useSubmission(createKey) const [store, setStore] = createStore({ show: false }) let input: HTMLInputElement createEffect(() => { if (!submission.pending && submission.result && !submission.result.error) { hide() } }) function show() { // submission.clear() does not clear the result in some cases, ie. // 1. Create key with empty name => error shows // 2. Put in a key name and creates the key => form hides // 3. Click add key button again => form shows with the same error if // submission.clear() is called only once while (true) { submission.clear() if (!submission.result) break } setStore("show", true) input.focus() } function hide() { setStore("show", false) } return ( show()}> Create API Key } >
(input = r)} data-component="input" name="name" type="text" placeholder="Enter key name" /> {(err) =>
{err()}
}
) } export function KeySection() { const params = useParams() const keys = createAsync(() => listKeys(params.id)) function formatKey(key: string) { if (key.length <= 11) return key return `${key.slice(0, 7)}...${key.slice(-4)}` } return (

API Keys

Manage your API keys for accessing opencode services.

Create an opencode Gateway API key

} > {(key) => { const [copied, setCopied] = createSignal(false) // const submission = useSubmission(removeKey, ([fd]) => fd.get("id")?.toString() === key.id) return ( ) }}
Name Key Created
{key.name} {formatDateForTable(key.timeCreated)}
) }