import { useState } from "react"; import { useAtomSet, useAtomValue, useAtomRefresh } from "@effect-atom/atom-react"; import { Result } from "@effect-atom/atom-react"; import { useScope } from "@executor/react/api/scope-context"; import { Button } from "@executor/react/components/button"; import { Input } from "@executor/react/components/input"; import { Label } from "@executor/react/components/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@executor/react/components/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, } from "@executor/react/components/dialog"; import { onepasswordConfigAtom, onepasswordVaultsAtom, configureOnePassword, removeOnePasswordConfig, } from "./atoms"; import type { OnePasswordConfig } from "../sdk/types"; // --------------------------------------------------------------------------- // Vault picker // --------------------------------------------------------------------------- function VaultPicker(props: { authKind: "desktop-app" | "service-account"; accountName: string; vaultId: string; onVaultSelect: (id: string, name: string) => void; }) { const account = props.accountName.trim(); const scopeId = useScope(); const vaultsResult = useAtomValue( onepasswordVaultsAtom(props.authKind, account, scopeId), ); const { vaults, isLoading, error } = Result.matchWithError( vaultsResult as Result.Result<{ vaults: ReadonlyArray<{ id: string; name: string }> }, Error>, { onInitial: () => ({ vaults: [] as { id: string; name: string }[], isLoading: true, error: null }), onError: (error) => ({ vaults: [] as { id: string; name: string }[], isLoading: false, error: error.message, }), onDefect: (defect) => ({ vaults: [] as { id: string; name: string }[], isLoading: false, error: defect instanceof Error ? defect.message : "Failed to list vaults", }), onSuccess: ({ value }) => { const v = value.vaults; if (v.length > 0 && !props.vaultId) { queueMicrotask(() => props.onVaultSelect(v[0].id, v[0].name)); } return { vaults: [...v], isLoading: false, error: null }; }, }, ); if (!account) { return

Enter account details to load vaults.

; } return (
{error && (

{error}

)}
); } // --------------------------------------------------------------------------- // Config dialog // --------------------------------------------------------------------------- function ConfigDialog(props: { open: boolean; onOpenChange: (v: boolean) => void; initial?: { authKind: string; accountName: string; vaultId: string; name: string }; }) { const isEdit = !!props.initial; const [authKind, setAuthKind] = useState<"desktop-app" | "service-account">( (props.initial?.authKind as "desktop-app" | "service-account") ?? "desktop-app", ); const [accountName, setAccountName] = useState(props.initial?.accountName ?? "my.1password.com"); const [vaultId, setVaultId] = useState(props.initial?.vaultId ?? ""); const [vaultName, setVaultName] = useState(props.initial?.name ?? ""); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const scopeId = useScope(); const doConfigure = useAtomSet(configureOnePassword, { mode: "promise" }); const refreshConfig = useAtomRefresh(onepasswordConfigAtom(scopeId)); const reset = () => { if (!isEdit) { setAuthKind("desktop-app"); setAccountName("my.1password.com"); setVaultId(""); setVaultName(""); } setError(null); setSaving(false); }; const handleSave = async () => { if (!accountName.trim() || !vaultId.trim()) return; setSaving(true); setError(null); try { const auth = authKind === "desktop-app" ? { kind: "desktop-app" as const, accountName: accountName.trim() } : { kind: "service-account" as const, tokenSecretId: accountName.trim() }; await doConfigure({ path: { scopeId }, payload: { auth, vaultId: vaultId.trim(), name: vaultName.trim() || "1Password" }, }); props.onOpenChange(false); refreshConfig(); reset(); } catch (e) { setError(e instanceof Error ? e.message : "Failed to save configuration"); setSaving(false); } }; return ( { if (!v) reset(); props.onOpenChange(v); }}> {isEdit ? "Edit 1Password" : "Connect 1Password"} Link a vault to resolve secrets via the 1Password desktop app or a service account.
{/* Auth method */}
{/* Account / token */}
setAccountName((e.target as HTMLInputElement).value)} className="font-mono text-[13px] h-9" />

{authKind === "desktop-app" ? "Requires the 1Password desktop app with biometric unlock." : "Reference an executor secret that holds the service account token."}

{/* Vault */}
{ setVaultId(id); setVaultName(name); }} /> {vaultId && (

{vaultId}

)}
{/* Display name */}
setVaultName((e.target as HTMLInputElement).value)} className="text-[13px] h-9" />
{error && (

{error}

)}
); } // --------------------------------------------------------------------------- // Settings card // --------------------------------------------------------------------------- export default function OnePasswordSettings() { const [configOpen, setConfigOpen] = useState(false); const scopeId = useScope(); const configResult = useAtomValue(onepasswordConfigAtom(scopeId)); const doRemove = useAtomSet(removeOnePasswordConfig, { mode: "promise" }); const refreshConfig = useAtomRefresh(onepasswordConfigAtom(scopeId)); const handleRemove = async () => { try { await doRemove({ path: { scopeId } }); refreshConfig(); } catch { /* TODO: toast */ } }; const config: OnePasswordConfig | null = Result.match( configResult as Result.Result, { onInitial: () => null, onFailure: () => null, onSuccess: ({ value }) => value }, ); const isLoading = Result.match( configResult as Result.Result, { onInitial: () => true, onFailure: () => false, onSuccess: () => false }, ); const isError = Result.match( configResult as Result.Result, { onInitial: () => false, onFailure: () => true, onSuccess: () => false }, ); return (
{/* Header */}

1Password

{isLoading ? ( ) : isError ? ( Error ) : config ? ( Connected ) : ( Not configured )}
{config && (
)}
{/* Body */}
{isLoading ? (

Loading…

) : isError ? (

Failed to load configuration

) : config ? (
Auth {config.auth.kind === "desktop-app" ? config.auth.accountName : "service-account"} Vault
{config.name} {config.vaultId}
) : (

Resolve secrets from your 1Password vault.

)}
{configOpen && ( )}
); }