File size: 2,292 Bytes
1f21206
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { create } from 'zustand'
import { openTargetsApi, type OpenTarget } from '../api/openTargets'

export type { OpenTarget } from '../api/openTargets'

const CLIENT_CACHE_TTL_MS = 60_000

type OpenTargetState = {
  targets: OpenTarget[]
  platform: string | null
  primaryTargetId: string | null
  lastSuccessfulTargetId: string | null
  loading: boolean
  error: string | null
  fetchedAt: number
  ensureTargets: () => Promise<void>
  refreshTargets: () => Promise<void>
  openTarget: (targetId: string, path: string) => Promise<void>
}

function choosePrimaryTarget(targets: OpenTarget[], apiPrimary: string | null, lastSuccessful: string | null) {
  if (lastSuccessful && targets.some((target) => target.id === lastSuccessful)) return lastSuccessful
  if (apiPrimary && targets.some((target) => target.id === apiPrimary)) return apiPrimary
  return targets[0]?.id ?? null
}

export const useOpenTargetStore = create<OpenTargetState>((set, get) => ({
  targets: [],
  platform: null,
  primaryTargetId: null,
  lastSuccessfulTargetId: null,
  loading: false,
  error: null,
  fetchedAt: 0,

  ensureTargets: async () => {
    const state = get()
    if (state.loading) return
    if (state.fetchedAt > 0 && Date.now() - state.fetchedAt < CLIENT_CACHE_TTL_MS) return
    await get().refreshTargets()
  },

  refreshTargets: async () => {
    set({ loading: true, error: null })
    try {
      const result = await openTargetsApi.list()
      const primaryTargetId = choosePrimaryTarget(
        result.targets,
        result.primaryTargetId,
        get().lastSuccessfulTargetId,
      )
      set({
        targets: result.targets,
        platform: result.platform,
        primaryTargetId,
        fetchedAt: Date.now(),
        loading: false,
        error: null,
      })
    } catch (error) {
      set({
        loading: false,
        error: error instanceof Error ? error.message : String(error),
      })
    }
  },

  openTarget: async (targetId, path) => {
    try {
      await openTargetsApi.open(targetId, path)
      set({ lastSuccessfulTargetId: targetId, primaryTargetId: targetId, error: null })
    } catch (error) {
      await get().refreshTargets()
      set({ error: error instanceof Error ? error.message : String(error) })
      throw error
    }
  },
}))