11import { useMemo , useState , Suspense } from "react" ;
22import { useAtomValue , useAtomSet } from "@effect/atom-react" ;
33import * as AsyncResult from "effect/unstable/reactivity/AsyncResult" ;
4- import { secretsAtom , secretUsagesAtom , removeSecret } from "../api/atoms" ;
4+ import * as Exit from "effect/Exit" ;
5+ import * as Option from "effect/Option" ;
6+ import { toast } from "sonner" ;
7+ import {
8+ removeSecretOptimistic ,
9+ secretsOptimisticAtom ,
10+ secretUsagesAtom ,
11+ } from "../api/atoms" ;
512import { secretWriteKeys } from "../api/reactivity-keys" ;
613import { useSecretProviderPlugins } from "@executor-js/sdk/client" ;
7- import { SecretId , type ScopeId } from "@executor-js/sdk" ;
14+ import { SecretId , SecretInUseError , type ScopeId } from "@executor-js/sdk" ;
815import { SecretForm } from "../plugins/secret-form" ;
916import { useScope } from "../hooks/use-scope" ;
1017import {
@@ -234,7 +241,7 @@ export function SecretsPage(props: {
234241 const secretProviderPlugins = useSecretProviderPlugins ( ) ;
235242 const [ addOpen , setAddOpen ] = useState ( false ) ;
236243 const scopeId = useScope ( ) ;
237- const secrets = useAtomValue ( secretsAtom ( scopeId ) ) ;
244+ const secrets = useAtomValue ( secretsOptimisticAtom ( scopeId ) ) ;
238245 const existingSecretIds = useMemo (
239246 ( ) =>
240247 AsyncResult . match ( secrets , {
@@ -244,19 +251,28 @@ export function SecretsPage(props: {
244251 } ) ,
245252 [ secrets ] ,
246253 ) ;
247- const doRemove = useAtomSet ( removeSecret , { mode : "promise" } ) ;
254+ const doRemove = useAtomSet ( removeSecretOptimistic ( scopeId ) , {
255+ mode : "promiseExit" ,
256+ } ) ;
248257
249258 const handleRemove = async ( secretId : string ) => {
250- try {
251- await doRemove ( {
252- params : {
253- scopeId,
254- secretId : SecretId . make ( secretId ) ,
255- } ,
256- reactivityKeys : secretWriteKeys ,
257- } ) ;
258- } catch {
259- // TODO: toast
259+ const exit = await doRemove ( {
260+ params : {
261+ scopeId,
262+ secretId : SecretId . make ( secretId ) ,
263+ } ,
264+ reactivityKeys : secretWriteKeys ,
265+ } ) ;
266+ if ( Exit . isFailure ( exit ) ) {
267+ const error = Exit . findErrorOption ( exit ) ;
268+ if ( Option . isSome ( error ) && error . value instanceof SecretInUseError ) {
269+ const count = error . value . usageCount ;
270+ toast . error (
271+ `Secret is used by ${ count } ${ count === 1 ? "source" : "sources" } . Detach it before removing it.` ,
272+ ) ;
273+ } else {
274+ toast . error ( "Failed to remove secret" ) ;
275+ }
260276 }
261277 } ;
262278
0 commit comments