1
+ import { useQuery } from "@tanstack/react-query"
2
+ import { getApplicationsHost , getWorkspaceProxies } from "api/api"
1
3
import { Region } from "api/typesGenerated"
2
4
import { useDashboard } from "components/Dashboard/DashboardProvider"
3
5
import { createContext , FC , PropsWithChildren , useContext , useState } from "react"
4
6
5
7
interface ProxyContextValue {
6
- value : PreferredProxy
7
- setValue : ( regions : Region [ ] , selectedRegion : Region | undefined ) => void
8
+ proxy : PreferredProxy
9
+ isLoading : boolean
10
+ error ?: Error | unknown
11
+ setProxy : ( regions : Region [ ] , selectedRegion : Region | undefined ) => void
8
12
}
9
13
10
14
interface PreferredProxy {
11
- // Regions is a list of all the regions returned by coderd.
12
- regions : Region [ ]
13
15
// SelectedRegion is the region the user has selected.
16
+ // Do not use the fields 'path_app_url' or 'wildcard_hostname' from this
17
+ // object. Use the preferred fields.
14
18
selectedRegion : Region | undefined
15
19
// PreferredPathAppURL is the URL of the proxy or it is the empty string
16
20
// to indicte using relative paths. To add a path to this:
17
21
// PreferredPathAppURL + "/path/to/app"
18
22
preferredPathAppURL : string
19
23
// PreferredWildcardHostname is a hostname that includes a wildcard.
20
- // TODO: If the preferred proxy does not have this set, should we default to'
21
- // the primary's?
22
- // Example: "*.example.com"
23
24
preferredWildcardHostname : string
24
25
}
25
26
@@ -32,24 +33,56 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
32
33
// Try to load the preferred proxy from local storage.
33
34
let savedProxy = loadPreferredProxy ( )
34
35
if ( ! savedProxy ) {
35
- savedProxy = getURLs ( [ ] , undefined )
36
+ savedProxy = getURLs ( [ ] )
36
37
}
37
38
38
39
// The initial state is no regions and no selected region.
39
- const [ state , setState ] = useState < PreferredProxy > ( savedProxy )
40
+ const [ proxy , setProxy ] = useState < PreferredProxy > ( savedProxy )
41
+ const setAndSaveProxy = ( regions : Region [ ] , selectedRegion : Region | undefined ) => {
42
+ const preferred = getURLs ( regions , selectedRegion )
43
+ // Save to local storage to persist the user's preference across reloads
44
+ // and other tabs.
45
+ savePreferredProxy ( preferred )
46
+ // Set the state for the current context.
47
+ setProxy ( preferred )
48
+ }
49
+
50
+ const queryKey = [ "get-regions" ]
51
+ const { error : regionsError , isLoading : regionsLoading } = useQuery ( {
52
+ queryKey,
53
+ queryFn : getWorkspaceProxies ,
54
+ // This onSucccess ensures the local storage is synchronized with the
55
+ // regions returned by coderd. If the selected region is not in the list,
56
+ // then the user selection is removed.
57
+ onSuccess : ( data ) => {
58
+ setAndSaveProxy ( data . regions , proxy . selectedRegion )
59
+ } ,
60
+ } )
40
61
41
62
// ******************************* //
42
63
// ** This code can be removed **
43
64
// ** when the experimental is **
44
65
// ** dropped ** //
45
66
const dashboard = useDashboard ( )
67
+ const appHostQueryKey = [ "get-application-host" ]
68
+ const { data : applicationHostResult , error : appHostError , isLoading : appHostLoading } = useQuery ( {
69
+ queryKey : appHostQueryKey ,
70
+ queryFn : getApplicationsHost ,
71
+ } )
46
72
// If the experiment is disabled, then make the setState do a noop.
47
73
// This preserves an empty state, which is the default behavior.
48
74
if ( ! dashboard ?. experiments . includes ( "moons" ) ) {
75
+ const value = getURLs ( [ ] )
76
+
49
77
return (
50
78
< ProxyContext . Provider value = { {
51
- value : getURLs ( [ ] , undefined ) ,
52
- setValue : ( ) => {
79
+ proxy : {
80
+ ...value ,
81
+ preferredWildcardHostname : applicationHostResult ?. host || value . preferredWildcardHostname ,
82
+ } ,
83
+ isLoading : appHostLoading ,
84
+ error : appHostError ,
85
+ setProxy : ( ) => {
53
86
// Does a noop
54
87
} ,
55
88
} } >
@@ -64,17 +97,12 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
64
97
65
98
return (
66
99
< ProxyContext . Provider value = { {
67
- value : state ,
100
+ proxy : proxy ,
101
+ isLoading : regionsLoading ,
102
+ error : regionsError ,
68
103
// A function that takes the new regions and selected region and updates
69
104
// the state with the appropriate urls.
70
- setValue : ( regions , selectedRegion ) => {
71
- const preferred = getURLs ( regions , selectedRegion )
72
- // Save to local storage to persist the user's preference across reloads
73
- // and other tabs.
74
- savePreferredProxy ( preferred )
75
- // Set the state for the current context.
76
- setState ( preferred )
77
- } ,
105
+ setProxy : setAndSaveProxy ,
78
106
} } >
79
107
{ children }
80
108
</ ProxyContext . Provider >
@@ -99,19 +127,19 @@ export const useProxy = (): ProxyContextValue => {
99
127
* @param regions Is the list of regions returned by coderd. If this is empty, default behavior is used.
100
128
* @param selectedRegion Is the region the user has selected. If this is undefined, default behavior is used.
101
129
*/
102
- const getURLs = ( regions : Region [ ] , selectedRegion : Region | undefined ) : PreferredProxy => {
130
+ const getURLs = ( regions : Region [ ] , selectedRegion ? : Region ) : PreferredProxy => {
103
131
// By default we set the path app to relative and disable wilcard hostnames.
104
132
// We will set these values if we find a proxy we can use that supports them.
105
133
let pathAppURL = ""
106
134
let wildcardHostname = ""
107
135
108
- if ( selectedRegion === undefined ) {
136
+ // If a region is selected, make sure it is in the list of regions. If it is not
137
+ // we should default to the primary.
138
+ selectedRegion = regions . find ( ( region ) => selectedRegion && region . id === selectedRegion . id )
139
+
140
+ if ( ! selectedRegion ) {
109
141
// If no region is selected, default to the primary region.
110
142
selectedRegion = regions . find ( ( region ) => region . name === "primary" )
111
- } else {
112
- // If a region is selected, make sure it is in the list of regions. If it is not
113
- // we should default to the primary.
114
- selectedRegion = regions . find ( ( region ) => region . id === selectedRegion ?. id )
115
143
}
116
144
117
145
// Only use healthy regions.
@@ -126,10 +154,8 @@ const getURLs = (regions: Region[], selectedRegion: Region | undefined): Preferr
126
154
127
155
// TODO: @emyrk Should we notify the user if they had an unhealthy region selected?
128
156
129
-
130
157
return {
131
- regions : regions ,
132
- selectedRegion : selectedRegion ,
158
+ selectedRegion,
133
159
// Trim trailing slashes to be consistent
134
160
preferredPathAppURL : pathAppURL . replace ( / \/ $ / , "" ) ,
135
161
preferredWildcardHostname : wildcardHostname ,
0 commit comments