Skip to content

Commit 6abde1e

Browse files
committed
chore: refactor codersdk.Client creation into builder
1 parent 4cd0ada commit 6abde1e

File tree

3 files changed

+108
-10
lines changed

3 files changed

+108
-10
lines changed

codersdk/agentsdk/agentsdk.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ var ExternalLogSourceID = uuid.MustParse("3b579bf4-1ed8-4b99-87a8-e9a1e3410410")
4646
type SessionTokenSetup func(client *codersdk.Client) RefreshableSessionTokenProvider
4747

4848
func New(serverURL *url.URL, setup SessionTokenSetup) *Client {
49-
c := codersdk.New(serverURL)
50-
provider := setup(c)
51-
c.SessionTokenProvider = provider
49+
b := codersdk.NewClientBuilder(serverURL)
50+
provider := setup(b.DangerouslyGetUnbuiltClient())
51+
c := b.SessionTokenProvider(provider).Build()
5252
return &Client{
5353
SDK: c,
5454
RefreshableSessionTokenProvider: provider,

codersdk/builder.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package codersdk
2+
3+
import (
4+
"io"
5+
"net/http"
6+
"net/url"
7+
8+
"cdr.dev/slog"
9+
)
10+
11+
// ClientBuilder is a builder for a Client.
12+
// @typescript-ignore ClientBuilder
13+
type ClientBuilder struct {
14+
serverURL *url.URL
15+
httpClient *http.Client
16+
sessionTokenProvider SessionTokenProvider
17+
logger slog.Logger
18+
logBodies bool
19+
plainLogger io.Writer
20+
trace bool
21+
disableDirectConnections bool
22+
23+
// unbuiltClient is the client that is built when Build is called. Used for cases where the code building the client
24+
// needs to reference the client while building it.
25+
unbuiltClient *Client
26+
}
27+
28+
func NewClientBuilder(serverURL *url.URL) *ClientBuilder {
29+
return &ClientBuilder{
30+
serverURL: serverURL,
31+
httpClient: &http.Client{},
32+
sessionTokenProvider: FixedSessionTokenProvider{},
33+
unbuiltClient: &Client{},
34+
}
35+
}
36+
37+
func (b *ClientBuilder) SessionToken(sessionToken string) *ClientBuilder {
38+
b.sessionTokenProvider = FixedSessionTokenProvider{SessionToken: sessionToken}
39+
return b
40+
}
41+
42+
func (b *ClientBuilder) SessionTokenProvider(sessionTokenProvider SessionTokenProvider) *ClientBuilder {
43+
b.sessionTokenProvider = sessionTokenProvider
44+
return b
45+
}
46+
47+
func (b *ClientBuilder) Logger(logger slog.Logger) *ClientBuilder {
48+
b.logger = logger
49+
return b
50+
}
51+
52+
func (b *ClientBuilder) LogBodies(logBodies bool) *ClientBuilder {
53+
b.logBodies = logBodies
54+
return b
55+
}
56+
57+
func (b *ClientBuilder) PlainLogger(plainLogger io.Writer) *ClientBuilder {
58+
b.plainLogger = plainLogger
59+
return b
60+
}
61+
62+
func (b *ClientBuilder) Trace() *ClientBuilder {
63+
b.trace = true
64+
return b
65+
}
66+
67+
func (b *ClientBuilder) DisableDirectConnections() *ClientBuilder {
68+
b.disableDirectConnections = true
69+
return b
70+
}
71+
72+
func (b *ClientBuilder) HTTPClient(httpClient *http.Client) *ClientBuilder {
73+
b.httpClient = httpClient
74+
return b
75+
}
76+
77+
// DangerouslyGetUnbuiltClient returns the unbuilt client.
78+
//
79+
// This is dangerous to use because the client can be modified after it is built. Only use this if you need a reference
80+
// to the client during the building process, e.g. to give to a client component like the SessionTokenProvider.
81+
func (b *ClientBuilder) DangerouslyGetUnbuiltClient() *Client {
82+
return b.unbuiltClient
83+
}
84+
85+
func (b *ClientBuilder) Build() *Client {
86+
client := b.unbuiltClient
87+
b.unbuiltClient = &Client{} // clear this so that the client cannot be modified after it is built
88+
client.URL = b.serverURL
89+
client.HTTPClient = b.httpClient
90+
client.SessionTokenProvider = b.sessionTokenProvider
91+
client.logger = b.logger
92+
client.logBodies = b.logBodies
93+
client.PlainLogger = b.plainLogger
94+
client.Trace = b.trace
95+
client.DisableDirectConnections = b.disableDirectConnections
96+
return client
97+
}

codersdk/client.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ var loggableMimeTypes = map[string]struct{}{
106106
}
107107

108108
// New creates a Coder client for the provided URL.
109+
// Deprecated: Use the ClientBuilder to create a client.
109110
func New(serverURL *url.URL) *Client {
110111
return &Client{
111112
URL: serverURL,
@@ -129,15 +130,18 @@ type Client struct {
129130

130131
// PlainLogger may be set to log HTTP traffic in a human-readable form.
131132
// It uses the LogBodies option.
133+
// Deprecated: Use the ClientBuilder to set this.
132134
PlainLogger io.Writer
133135

134136
// Trace can be enabled to propagate tracing spans to the Coder API.
135137
// This is useful for tracking a request end-to-end.
138+
// Deprecated: Use the ClientBuilder to set this.
136139
Trace bool
137140

138141
// DisableDirectConnections forces any connections to workspaces to go
139142
// through DERP, regardless of the BlockEndpoints setting on each
140143
// connection.
144+
// Deprecated: Use the ClientBuilder to set this.
141145
DisableDirectConnections bool
142146
}
143147

@@ -149,6 +153,7 @@ func (c *Client) Logger() slog.Logger {
149153
}
150154

151155
// SetLogger sets the logger for the client.
156+
// Deprecated: Use the ClientBuilder to set this.
152157
func (c *Client) SetLogger(logger slog.Logger) {
153158
c.mu.Lock()
154159
defer c.mu.Unlock()
@@ -163,6 +168,7 @@ func (c *Client) LogBodies() bool {
163168
}
164169

165170
// SetLogBodies sets whether to log request and response bodies.
171+
// Deprecated: Use the ClientBuilder to set this.
166172
func (c *Client) SetLogBodies(logBodies bool) {
167173
c.mu.Lock()
168174
defer c.mu.Unlock()
@@ -177,16 +183,11 @@ func (c *Client) SessionToken() string {
177183
}
178184

179185
// SetSessionToken sets a fixed token for the client.
180-
// Deprecated: Create a new client instead of changing the token after creation.
186+
// Deprecated: Build a new client using the ClientBuilder instead of changing the token after creation.
181187
func (c *Client) SetSessionToken(token string) {
182-
c.SetSessionTokenProvider(FixedSessionTokenProvider{SessionToken: token})
183-
}
184-
185-
// SetSessionTokenProvider sets the session token provider for the client.
186-
func (c *Client) SetSessionTokenProvider(provider SessionTokenProvider) {
187188
c.mu.Lock()
188189
defer c.mu.Unlock()
189-
c.SessionTokenProvider = provider
190+
c.SessionTokenProvider = FixedSessionTokenProvider{SessionToken: token}
190191
}
191192

192193
func prefixLines(prefix, s []byte) []byte {

0 commit comments

Comments
 (0)