-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
199 lines (156 loc) · 4.51 KB
/
client.go
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package gomts
import (
"fmt"
"log/slog"
"net/http"
"os"
)
const (
defaultProtocol = "https"
defaultUserAgent = "go.charbar.io/gomts"
defaultHost = "api.mytimestation.com"
defaultAPIVersion = "v1.2"
authTokenEnvVar = "MTS_AUTH_TOKEN"
)
// NewClient returns a new client with the given config.
func NewClient(conf *Config) Client {
return newClient(conf)
}
// Client represents client to the MyTimeStation API.
type Client interface {
// Employees returns the EmployeeClient, which handles operations related
// to employees within MyTimeStation.
Employees() EmployeeClient
// Departments returns the DepartmentClient, which handles operations
// related to departments within MyTimeStation.
Departments() DepartmentClient
}
// Config configures the underlying HTTP client that interfaces with
// MyTimeStation API methods.
type Config struct {
// Protocol specifies the protocol to use.
// NB: HTTPS is the only supported scheme for the production API.
Protocol string
// UserAgent specifies the value for the User-Agent header.
UserAgent string
// Host specifies the host of the MyTimeStation API to use.
Host string
// APIVersion specifies the version of the MyTimeStation API to use.
APIVersion string
// Debug enables request and response dumping.
Debug bool
// Token is the auth token to use for Basic Auth.
// If not set $MTS_AUTH_TOKEN is used.
AuthToken string
// Transport can be specified to implement RoundTrip or the underlying
// HTTP client. Will be called after the base MTS transport's RoundTrip is
// called so all headers will be set on the request. Defaults to
// http.DefaultTransport.
Transport http.RoundTripper
// LogHandler can be specified to cutomize the slog.Logger.
LogHandler slog.Handler
}
// GetAuthToken gets the configured auth token or the MTS_AUTH_TOKEN
// environment variable.
func (c *Config) GetAuthToken() string {
if c.AuthToken == "" {
return os.Getenv(authTokenEnvVar)
}
return c.AuthToken
}
// GetUserAgent gets the configured user agent or the default.
func (c *Config) GetUserAgent() string {
if c.AuthToken == "" {
return defaultUserAgent
}
return c.UserAgent
}
// GetProtocol gets the configured protocol or the default.
func (c *Config) GetProtocol() string {
if c.Protocol == "" {
return defaultProtocol
}
return c.Protocol
}
// GetAPIVersion gets the configured API version or the default.
func (c *Config) GetAPIVersion() string {
if c.APIVersion == "" {
return defaultAPIVersion
}
return c.APIVersion
}
// GetHost gets the configured API host or the default.
func (c *Config) GetHost() string {
if c.Host == "" {
return defaultHost
}
return c.Host
}
// GetBaseURL build the base MyTimeStation API URL from the configured
// protocol, host and API version.
//
// e.g. https://api.mytimestation.com/v1.0
func (c *Config) GetBaseURL() string {
return fmt.Sprintf("%s://%s/%s",
c.GetProtocol(),
c.GetHost(),
c.GetAPIVersion())
}
// GetLogger returns a *slog.Logger built from the configured slog.Handler or
// builds a default, text-based logger.
//
// Default log level will be `info`. If `debug` is `true`, it will be `debug`.
func (c *Config) GetLogger() *slog.Logger {
if c.LogHandler != nil {
// use user-specified log handler
return slog.New(c.LogHandler)
}
level := slog.LevelInfo.Level()
if c.Debug {
// up the log level to enable debug logging
level = slog.LevelDebug.Level()
}
return slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
Level: level,
}))
}
// GetTransport returns an http.Transport implementation for MyTimeStation
// authentication and request/response dumping.
func (c *Config) GetTransport() *mtsTransport {
return &mtsTransport{
conf: c,
logr: slog.Default(),
}
}
type client struct {
conf *Config
httpClient *http.Client
logr *slog.Logger
departments *departmentClient
employees *employeeClient
}
func newClient(conf *Config) *client {
logr := conf.GetLogger().WithGroup("gomts")
transport := conf.GetTransport()
transport.logr = logr.WithGroup("transport")
httpClient := &http.Client{Transport: transport}
c := &client{
conf: conf,
logr: logr,
httpClient: httpClient,
}
c.employees = (*employeeClient)(c)
c.departments = &departmentClient{c}
return c
}
func (c *client) Employees() EmployeeClient {
return c.employees
}
func (c *client) Departments() DepartmentClient {
return c.departments
}
// formRequest is an interface that request structs can implement to use form
// encoding instead of JSON.
type formRequest interface {
form()
}