import { useState } from "react"; import { useAtomSet, useAtomValue } from "@effect/atom-react"; import * as Exit from "effect/Exit"; import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"; import { ReactivityKey } from "@executor-js/react/api/reactivity-keys"; import { useScope } from "@executor-js/react/api/scope-context"; import { Button } from "@executor-js/react/components/button"; import { Input } from "@executor-js/react/components/input"; import { Label } from "@executor-js/react/components/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@executor-js/react/components/select"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, } from "@executor-js/react/components/dialog"; import { CardStackEntry, CardStackEntryActions, CardStackEntryContent, CardStackEntryDescription, } from "@executor-js/react/components/card-stack"; 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 } = AsyncResult.matchWithError( vaultsResult as AsyncResult.AsyncResult< { vaults: ReadonlyArray<{ id: string; name: string }> }, Error >, { onInitial: () => ({ vaults: [] as { id: string; name: string }[], isLoading: true, error: null, }), onError: () => ({ vaults: [] as { id: string; name: string }[], isLoading: false, error: "Failed to list vaults", }), onDefect: () => ({ vaults: [] as { id: string; name: string }[], isLoading: false, error: "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: "promiseExit" }); 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); const auth = authKind === "desktop-app" ? { kind: "desktop-app" as const, accountName: accountName.trim() } : { kind: "service-account" as const, tokenSecretId: accountName.trim() }; const exit = await doConfigure({ params: { scopeId }, payload: { auth, vaultId: vaultId.trim(), name: vaultName.trim() || "1Password" }, reactivityKeys: [ReactivityKey.secrets], }); if (Exit.isFailure(exit)) { setError("Failed to save configuration"); setSaving(false); return; } props.onOpenChange(false); reset(); }; 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: "promiseExit" }); const handleRemove = async () => { await doRemove({ params: { scopeId }, reactivityKeys: [ReactivityKey.secrets] }); }; const config: OnePasswordConfig | null = AsyncResult.match( configResult as AsyncResult.AsyncResult, { onInitial: () => null, onFailure: () => null, onSuccess: ({ value }) => value }, ); const isLoading = AsyncResult.match( configResult as AsyncResult.AsyncResult, { onInitial: () => true, onFailure: () => false, onSuccess: () => false, }, ); const isError = AsyncResult.match( configResult as AsyncResult.AsyncResult, { onInitial: () => false, onFailure: () => true, onSuccess: () => false, }, ); return ( <> {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. )}
{config ? ( <> ) : ( !isLoading && !isError && ( ) )}
{configOpen && ( )} ); }