From 6d967c0e6bad2659caa6d12a601dfae176497a1b Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Tue, 1 Aug 2023 17:58:30 +0000 Subject: [PATCH 1/7] fix: generate typescript types for healthcheck --- coderd/apidoc/docs.go | 27 ++++---- coderd/apidoc/swagger.json | 27 ++++---- coderd/healthcheck/accessurl.go | 1 + coderd/healthcheck/database.go | 16 +++-- coderd/healthcheck/derp.go | 13 ++-- coderd/healthcheck/derp_test.go | 8 +-- coderd/healthcheck/healthcheck.go | 1 + coderd/healthcheck/websocket.go | 25 +++---- coderd/healthcheck/websocket_test.go | 4 +- docs/api/debug.md | 15 ++-- docs/api/schemas.md | 78 +++++++++------------ go.mod | 2 +- scripts/apitypings/main.go | 100 +++++++++++++++++++-------- site/src/api/typesGenerated.ts | 89 ++++++++++++++++++++++++ 14 files changed, 261 insertions(+), 145 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index d5ccfb06dfc47..8d213cd6952d6 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -11258,7 +11258,9 @@ const docTemplate = `{ "enabled": { "type": "boolean" }, - "error": {} + "error": { + "type": "string" + } } }, "healthcheck.DatabaseReport": { @@ -11271,6 +11273,9 @@ const docTemplate = `{ "type": "boolean" }, "latency": { + "type": "string" + }, + "latency_ms": { "type": "integer" }, "reachable": { @@ -11315,20 +11320,6 @@ const docTemplate = `{ } }, "healthcheck.WebsocketReport": { - "type": "object", - "properties": { - "error": { - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "response": { - "$ref": "#/definitions/healthcheck.WebsocketResponse" - } - } - }, - "healthcheck.WebsocketResponse": { "type": "object", "properties": { "body": { @@ -11336,6 +11327,12 @@ const docTemplate = `{ }, "code": { "type": "integer" + }, + "error": { + "type": "string" + }, + "healthy": { + "type": "boolean" } } }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 69b3e1f6a5453..35bc183a92ba6 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -10240,7 +10240,9 @@ "enabled": { "type": "boolean" }, - "error": {} + "error": { + "type": "string" + } } }, "healthcheck.DatabaseReport": { @@ -10253,6 +10255,9 @@ "type": "boolean" }, "latency": { + "type": "string" + }, + "latency_ms": { "type": "integer" }, "reachable": { @@ -10297,20 +10302,6 @@ } }, "healthcheck.WebsocketReport": { - "type": "object", - "properties": { - "error": { - "type": "string" - }, - "healthy": { - "type": "boolean" - }, - "response": { - "$ref": "#/definitions/healthcheck.WebsocketResponse" - } - } - }, - "healthcheck.WebsocketResponse": { "type": "object", "properties": { "body": { @@ -10318,6 +10309,12 @@ }, "code": { "type": "integer" + }, + "error": { + "type": "string" + }, + "healthy": { + "type": "boolean" } } }, diff --git a/coderd/healthcheck/accessurl.go b/coderd/healthcheck/accessurl.go index b25e956b7d918..b91889b2842a2 100644 --- a/coderd/healthcheck/accessurl.go +++ b/coderd/healthcheck/accessurl.go @@ -12,6 +12,7 @@ import ( "github.com/coder/coder/coderd/util/ptr" ) +// @typescript-generate AccessURLReport type AccessURLReport struct { AccessURL string `json:"access_url"` Healthy bool `json:"healthy"` diff --git a/coderd/healthcheck/database.go b/coderd/healthcheck/database.go index 291b9361b8314..c92ef3c447d56 100644 --- a/coderd/healthcheck/database.go +++ b/coderd/healthcheck/database.go @@ -10,11 +10,13 @@ import ( "github.com/coder/coder/coderd/database" ) +// @typescript-generate DatabaseReport type DatabaseReport struct { - Healthy bool `json:"healthy"` - Reachable bool `json:"reachable"` - Latency time.Duration `json:"latency"` - Error *string `json:"error"` + Healthy bool `json:"healthy"` + Reachable bool `json:"reachable"` + Latency string `json:"latency"` + LatencyMs int `json:"latency_ms"` + Error *string `json:"error"` } type DatabaseReportOptions struct { @@ -39,10 +41,12 @@ func (r *DatabaseReport) Run(ctx context.Context, opts *DatabaseReportOptions) { slices.Sort(pings) // Take the median ping. - r.Latency = pings[pingCount/2] + latency := pings[pingCount/2] + r.Latency = latency.String() + r.LatencyMs = int(latency.Milliseconds()) // Somewhat arbitrary, but if the latency is over 15ms, we consider it // unhealthy. - if r.Latency < 15*time.Millisecond { + if latency < 15*time.Millisecond { r.Healthy = true } r.Reachable = true diff --git a/coderd/healthcheck/derp.go b/coderd/healthcheck/derp.go index 0b77c42076254..42d25949935ef 100644 --- a/coderd/healthcheck/derp.go +++ b/coderd/healthcheck/derp.go @@ -24,6 +24,7 @@ import ( "github.com/coder/coder/coderd/util/ptr" ) +// @typescript-generate DERPReport type DERPReport struct { Healthy bool `json:"healthy"` @@ -36,6 +37,7 @@ type DERPReport struct { Error *string `json:"error"` } +// @typescript-generate DERPRegionReport type DERPRegionReport struct { mu sync.Mutex Healthy bool `json:"healthy"` @@ -44,6 +46,8 @@ type DERPRegionReport struct { NodeReports []*DERPNodeReport `json:"node_reports"` Error *string `json:"error"` } + +// @typescript-generate DERPNodeReport type DERPNodeReport struct { mu sync.Mutex clientCounter int @@ -62,10 +66,11 @@ type DERPNodeReport struct { STUN DERPStunReport `json:"stun"` } +// @typescript-generate DERPStunReport type DERPStunReport struct { Enabled bool CanSTUN bool - Error error + Error *string } type DERPReportOptions struct { @@ -301,20 +306,20 @@ func (r *DERPNodeReport) doSTUNTest(ctx context.Context) { addr, port, err := r.stunAddr(ctx) if err != nil { - r.STUN.Error = xerrors.Errorf("get stun addr: %w", err) + r.STUN.Error = convertError(xerrors.Errorf("get stun addr: %w", err)) return } // We only create a prober to call ProbeUDP manually. p, err := prober.DERP(prober.New(), "", time.Second, time.Second, time.Second) if err != nil { - r.STUN.Error = xerrors.Errorf("create prober: %w", err) + r.STUN.Error = convertError(xerrors.Errorf("create prober: %w", err)) return } err = p.ProbeUDP(addr, port)(ctx) if err != nil { - r.STUN.Error = xerrors.Errorf("probe stun: %w", err) + r.STUN.Error = convertError(xerrors.Errorf("probe stun: %w", err)) return } diff --git a/coderd/healthcheck/derp_test.go b/coderd/healthcheck/derp_test.go index 8fa1cb5f952da..da8a6acc8a989 100644 --- a/coderd/healthcheck/derp_test.go +++ b/coderd/healthcheck/derp_test.go @@ -76,7 +76,7 @@ func TestDERP(t *testing.T) { assert.False(t, node.STUN.Enabled) assert.False(t, node.STUN.CanSTUN) - assert.NoError(t, node.STUN.Error) + assert.Nil(t, node.STUN.Error) } } }) @@ -120,7 +120,7 @@ func TestDERP(t *testing.T) { assert.True(t, node.STUN.Enabled) assert.True(t, node.STUN.CanSTUN) - assert.NoError(t, node.STUN.Error) + assert.Nil(t, node.STUN.Error) } } }) @@ -185,7 +185,7 @@ func TestDERP(t *testing.T) { assert.False(t, node.STUN.Enabled) assert.False(t, node.STUN.CanSTUN) - assert.NoError(t, node.STUN.Error) + assert.Nil(t, node.STUN.Error) } } }) @@ -227,7 +227,7 @@ func TestDERP(t *testing.T) { assert.True(t, node.STUN.Enabled) assert.True(t, node.STUN.CanSTUN) - assert.NoError(t, node.STUN.Error) + assert.Nil(t, node.STUN.Error) } } }) diff --git a/coderd/healthcheck/healthcheck.go b/coderd/healthcheck/healthcheck.go index dea09600ca9f6..29a4398b8391c 100644 --- a/coderd/healthcheck/healthcheck.go +++ b/coderd/healthcheck/healthcheck.go @@ -29,6 +29,7 @@ type Checker interface { Database(ctx context.Context, opts *DatabaseReportOptions) DatabaseReport } +// @typescript-generate Report type Report struct { // Time is the time the report was generated at. Time time.Time `json:"time"` diff --git a/coderd/healthcheck/websocket.go b/coderd/healthcheck/websocket.go index f2ab754f452d3..0b4a56e2d5ca9 100644 --- a/coderd/healthcheck/websocket.go +++ b/coderd/healthcheck/websocket.go @@ -2,6 +2,7 @@ package healthcheck import ( "context" + "fmt" "io" "net/http" "net/url" @@ -10,8 +11,6 @@ import ( "golang.org/x/xerrors" "nhooyr.io/websocket" - - "github.com/coder/coder/coderd/httpapi" ) type WebsocketReportOptions struct { @@ -20,15 +19,12 @@ type WebsocketReportOptions struct { HTTPClient *http.Client } +// @typescript-generate WebsocketReport type WebsocketReport struct { - Healthy bool `json:"healthy"` - Response WebsocketResponse `json:"response"` - Error *string `json:"error"` -} - -type WebsocketResponse struct { - Body string `json:"body"` - Code int `json:"code"` + Healthy bool `json:"healthy"` + Body string `json:"body"` + Code int `json:"code"` + Error *string `json:"error"` } func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions) { @@ -60,10 +56,8 @@ func (r *WebsocketReport) Run(ctx context.Context, opts *WebsocketReportOptions) } } - r.Response = WebsocketResponse{ - Body: body, - Code: res.StatusCode, - } + r.Body = body + r.Code = res.StatusCode } if err != nil { r.Error = convertError(xerrors.Errorf("websocket dial: %w", err)) @@ -115,7 +109,8 @@ func (s *WebsocketEchoServer) ServeHTTP(rw http.ResponseWriter, r *http.Request) ctx := r.Context() c, err := websocket.Accept(rw, r, &websocket.AcceptOptions{}) if err != nil { - httpapi.Write(ctx, rw, http.StatusBadRequest, "unable to accept: "+err.Error()) + rw.WriteHeader(http.StatusBadRequest) + _, _ = rw.Write([]byte(fmt.Sprint("unable to accept:", err))) return } defer c.Close(websocket.StatusGoingAway, "goodbye") diff --git a/coderd/healthcheck/websocket_test.go b/coderd/healthcheck/websocket_test.go index 45f8a4ae5c31c..cb56081197577 100644 --- a/coderd/healthcheck/websocket_test.go +++ b/coderd/healthcheck/websocket_test.go @@ -63,7 +63,7 @@ func TestWebsocket(t *testing.T) { }) require.NotNil(t, wsReport.Error) - assert.Equal(t, wsReport.Response.Body, "test error") - assert.Equal(t, wsReport.Response.Code, http.StatusBadRequest) + assert.Equal(t, wsReport.Body, "test error") + assert.Equal(t, wsReport.Code, http.StatusBadRequest) }) } diff --git a/docs/api/debug.md b/docs/api/debug.md index cd68322a674fc..3097d1405d109 100644 --- a/docs/api/debug.md +++ b/docs/api/debug.md @@ -51,7 +51,8 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "database": { "error": "string", "healthy": true, - "latency": 0, + "latency": "string", + "latency_ms": 0, "reachable": true }, "derp": { @@ -122,7 +123,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -183,7 +184,7 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -218,12 +219,10 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "healthy": true, "time": "string", "websocket": { + "body": "string", + "code": 0, "error": "string", - "healthy": true, - "response": { - "body": "string", - "code": 0 - } + "healthy": true } } ``` diff --git a/docs/api/schemas.md b/docs/api/schemas.md index b9d5e3d1b78a1..110c5cca5530e 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -6505,7 +6505,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -6561,7 +6561,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -6672,7 +6672,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -6733,7 +6733,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -6784,7 +6784,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| { "canSTUN": true, "enabled": true, - "error": null + "error": "string" } ``` @@ -6794,7 +6794,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| | --------- | ------- | -------- | ------------ | ----------- | | `canSTUN` | boolean | false | | | | `enabled` | boolean | false | | | -| `error` | any | false | | | +| `error` | string | false | | | ## healthcheck.DatabaseReport @@ -6802,19 +6802,21 @@ If the schedule is empty, the user will be updated to use the default schedule.| { "error": "string", "healthy": true, - "latency": 0, + "latency": "string", + "latency_ms": 0, "reachable": true } ``` ### Properties -| Name | Type | Required | Restrictions | Description | -| ----------- | ------- | -------- | ------------ | ----------- | -| `error` | string | false | | | -| `healthy` | boolean | false | | | -| `latency` | integer | false | | | -| `reachable` | boolean | false | | | +| Name | Type | Required | Restrictions | Description | +| ------------ | ------- | -------- | ------------ | ----------- | +| `error` | string | false | | | +| `healthy` | boolean | false | | | +| `latency` | string | false | | | +| `latency_ms` | integer | false | | | +| `reachable` | boolean | false | | | ## healthcheck.Report @@ -6832,7 +6834,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "database": { "error": "string", "healthy": true, - "latency": 0, + "latency": "string", + "latency_ms": 0, "reachable": true }, "derp": { @@ -6903,7 +6906,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -6964,7 +6967,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "stun": { "canSTUN": true, "enabled": true, - "error": null + "error": "string" }, "uses_websocket": true } @@ -6999,12 +7002,10 @@ If the schedule is empty, the user will be updated to use the default schedule.| "healthy": true, "time": "string", "websocket": { + "body": "string", + "code": 0, "error": "string", - "healthy": true, - "response": { - "body": "string", - "code": 0 - } + "healthy": true } } ``` @@ -7024,40 +7025,23 @@ If the schedule is empty, the user will be updated to use the default schedule.| ## healthcheck.WebsocketReport -```json -{ - "error": "string", - "healthy": true, - "response": { - "body": "string", - "code": 0 - } -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ---------- | -------------------------------------------------------------- | -------- | ------------ | ----------- | -| `error` | string | false | | | -| `healthy` | boolean | false | | | -| `response` | [healthcheck.WebsocketResponse](#healthcheckwebsocketresponse) | false | | | - -## healthcheck.WebsocketResponse - ```json { "body": "string", - "code": 0 + "code": 0, + "error": "string", + "healthy": true } ``` ### Properties -| Name | Type | Required | Restrictions | Description | -| ------ | ------- | -------- | ------------ | ----------- | -| `body` | string | false | | | -| `code` | integer | false | | | +| Name | Type | Required | Restrictions | Description | +| --------- | ------- | -------- | ------------ | ----------- | +| `body` | string | false | | | +| `code` | integer | false | | | +| `error` | string | false | | | +| `healthy` | boolean | false | | | ## netcheck.Report diff --git a/go.mod b/go.mod index 9f8d043812df2..61b8f203d50bb 100644 --- a/go.mod +++ b/go.mod @@ -356,7 +356,7 @@ require ( go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/text v0.11.0 golang.org/x/time v0.3.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde // indirect diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index 53b64b9fd32c9..6e0b119a35408 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -15,6 +15,8 @@ import ( "text/template" "github.com/fatih/structtag" + "golang.org/x/text/cases" + "golang.org/x/text/language" "golang.org/x/tools/go/packages" "golang.org/x/xerrors" @@ -23,21 +25,23 @@ import ( "github.com/coder/coder/coderd/util/slice" ) -const ( - baseDir = "./codersdk" - indent = " " +var ( + baseDirs = [...]string{"./codersdk", "./coderd/healthcheck"} + indent = " " ) func main() { ctx := context.Background() log := slog.Make(sloghuman.Sink(os.Stderr)) - output, err := Generate(baseDir) - if err != nil { - log.Fatal(ctx, err.Error()) - } + for _, baseDir := range baseDirs { + output, err := Generate(baseDir) + if err != nil { + log.Fatal(ctx, err.Error()) + } - // Just cat the output to a file to capture it - _, _ = fmt.Println(output) + // Just cat the output to a file to capture it + _, _ = fmt.Println(output) + } } func Generate(directory string) (string, error) { @@ -176,6 +180,7 @@ func (g *Generator) generateAll() (*TypescriptTypes, error) { Enums: make(map[string]types.Object), EnumConsts: make(map[string][]*types.Const), IgnoredTypes: make(map[string]struct{}), + AllowedTypes: make(map[string]struct{}), } // Look for comments that indicate to ignore a type for typescript generation. @@ -196,6 +201,24 @@ func (g *Generator) generateAll() (*TypescriptTypes, error) { } } + // This allows opt-in generation, instead of opt-out. + allowRegex := regexp.MustCompile("@typescript-generate[:]?(?P.*)") + for _, file := range g.pkg.Syntax { + for _, comment := range file.Comments { + for _, line := range comment.List { + text := line.Text + matches := allowRegex.FindStringSubmatch(text) + allowed := allowRegex.SubexpIndex("allowed_types") + if len(matches) >= allowed && matches[allowed] != "" { + arr := strings.Split(matches[allowed], ",") + for _, s := range arr { + m.AllowedTypes[strings.TrimSpace(s)] = struct{}{} + } + } + } + } + } + for _, n := range g.pkg.Types.Scope().Names() { obj := g.pkg.Types.Scope().Lookup(n) err := g.generateOne(m, obj) @@ -260,6 +283,15 @@ type Maps struct { Enums map[string]types.Object EnumConsts map[string][]*types.Const IgnoredTypes map[string]struct{} + AllowedTypes map[string]struct{} +} + +// objName prepends the package name of a type if it is outside of codersdk. +func objName(obj types.Object) string { + if pkgName := obj.Pkg().Name(); pkgName != "codersdk" { + return cases.Title(language.English).String(pkgName) + obj.Name() + } + return obj.Name() } func (g *Generator) generateOne(m *Maps, obj types.Object) error { @@ -273,6 +305,13 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { return nil } + // If we have allowed types, only allow those to be generated. + if _, ok := m.AllowedTypes[obj.Name()]; len(m.AllowedTypes) > 0 && !ok { + return nil + } + + objName := objName(obj) + switch obj := obj.(type) { // All named types are type declarations case *types.TypeName: @@ -286,13 +325,13 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { // Structs are obvious. codeBlock, err := g.buildStruct(obj, underNamed) if err != nil { - return xerrors.Errorf("generate %q: %w", obj.Name(), err) + return xerrors.Errorf("generate %q: %w", objName, err) } - m.Structs[obj.Name()] = codeBlock + m.Structs[objName] = codeBlock case *types.Basic: // type string // These are enums. Store to expand later. - m.Enums[obj.Name()] = obj + m.Enums[objName] = obj case *types.Map, *types.Array, *types.Slice: // Declared maps that are not structs are still valid codersdk objects. // Handle them custom by calling 'typescriptType' directly instead of @@ -301,7 +340,7 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { // These are **NOT** enums, as a map in Go would never be used for an enum. ts, err := g.typescriptType(obj.Type().Underlying()) if err != nil { - return xerrors.Errorf("(map) generate %q: %w", obj.Name(), err) + return xerrors.Errorf("(map) generate %q: %w", objName, err) } var str strings.Builder @@ -311,8 +350,8 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { _, _ = str.WriteRune('\n') } // Use similar output syntax to enums. - _, _ = str.WriteString(fmt.Sprintf("export type %s = %s\n", obj.Name(), ts.ValueType)) - m.Structs[obj.Name()] = str.String() + _, _ = str.WriteString(fmt.Sprintf("export type %s = %s\n", objName, ts.ValueType)) + m.Structs[objName] = str.String() case *types.Interface: // Interfaces are used as generics. Non-generic interfaces are // not supported. @@ -330,9 +369,9 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { block, err := g.buildUnion(obj, union) if err != nil { - return xerrors.Errorf("generate union %q: %w", obj.Name(), err) + return xerrors.Errorf("generate union %q: %w", objName, err) } - m.Generics[obj.Name()] = block + m.Generics[objName] = block } case *types.Signature: // Ignore named functions. @@ -353,7 +392,7 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { case *types.Func: // Noop default: - _, _ = fmt.Println(obj.Name()) + _, _ = fmt.Println(objName) } return nil } @@ -361,7 +400,7 @@ func (g *Generator) generateOne(m *Maps, obj types.Object) error { func (g *Generator) posLine(obj types.Object) string { file := g.pkg.Fset.File(obj.Pos()) // Do not use filepath, as that changes behavior based on OS - return fmt.Sprintf("// From %s\n", path.Join("codersdk", filepath.Base(file.Name()))) + return fmt.Sprintf("// From %s\n", path.Join(obj.Pkg().Name(), filepath.Base(file.Name()))) } // buildStruct just prints the typescript def for a type. @@ -387,7 +426,7 @@ func (g *Generator) buildUnion(obj types.Object, st *types.Union) (string, error allTypes = slice.Unique(allTypes) - _, _ = s.WriteString(fmt.Sprintf("export type %s = %s\n", obj.Name(), strings.Join(allTypes, " | "))) + _, _ = s.WriteString(fmt.Sprintf("export type %s = %s\n", objName(obj), strings.Join(allTypes, " | "))) return s.String(), nil } @@ -421,7 +460,7 @@ func (g *Generator) buildStruct(obj types.Object, st *types.Struct) (string, err } state.PosLine = g.posLine(obj) - state.Name = obj.Name() + state.Name = objName(obj) // Handle named embedded structs in the codersdk package via extension. var extends []string @@ -453,6 +492,10 @@ func (g *Generator) buildStruct(obj types.Object, st *types.Struct) (string, err panic("invalid struct tags on type " + obj.String()) } + if !field.Exported() { + continue + } + // Use the json name if present jsonTag, err := tags.Get("json") var ( @@ -744,12 +787,13 @@ func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) { } // Then see if the type is defined elsewhere. If it is, we can just - // put the name as it will be defined in the typescript codeblock + // put the objName as it will be defined in the typescript codeblock // we generate. - name := n.Obj().Name() + objName := objName(n.Obj()) genericName := "" genericTypes := make(map[string]string) - if obj := g.pkg.Types.Scope().Lookup(name); obj != nil { + pkgName := n.Obj().Pkg().Name() + if obj := g.pkg.Types.Scope().Lookup(n.Obj().Name()); g.pkg.Name == pkgName && obj != nil { // Sweet! Using other typescript types as fields. This could be an // enum or another struct if args := n.TypeArgs(); args != nil && args.Len() > 0 { @@ -758,7 +802,7 @@ func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) { for i := 0; i < args.Len(); i++ { genType, err := g.typescriptType(args.At(i)) if err != nil { - return TypescriptType{}, xerrors.Errorf("generic field %q<%q>: %w", name, args.At(i).String(), err) + return TypescriptType{}, xerrors.Errorf("generic field %q<%q>: %w", objName, args.At(i).String(), err) } if param, ok := args.At(i).(*types.TypeParam); ok { @@ -773,13 +817,13 @@ func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) { genericConstraints = append(genericConstraints, genType.ValueType) } - genericName = name + fmt.Sprintf("<%s>", strings.Join(genericNames, ", ")) - name += fmt.Sprintf("<%s>", strings.Join(genericConstraints, ", ")) + genericName = objName + fmt.Sprintf("<%s>", strings.Join(genericNames, ", ")) + objName += fmt.Sprintf("<%s>", strings.Join(genericConstraints, ", ")) } return TypescriptType{ GenericTypes: genericTypes, GenericValue: genericName, - ValueType: name, + ValueType: objName, }, nil } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index e374e46e192f1..15127988901b5 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1908,3 +1908,92 @@ export const WorkspaceTransitions: WorkspaceTransition[] = [ // From codersdk/workspaceproxy.go export type RegionTypes = Region | WorkspaceProxy + +// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. + +// From healthcheck/accessurl.go +export interface HealthcheckAccessURLReport { + readonly access_url: string + readonly healthy: boolean + readonly reachable: boolean + readonly status_code: number + readonly healthz_response: string + readonly error?: string +} + +// From healthcheck/derp.go +export interface HealthcheckDERPNodeReport { + readonly healthy: boolean + // Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type + readonly node?: any + // Named type "tailscale.com/derp.ServerInfoMessage" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type + readonly node_info: any + readonly can_exchange_messages: boolean + // This is likely an enum in an external package ("time.Duration") + readonly round_trip_ping: number + readonly uses_websocket: boolean + readonly client_logs: string[][] + readonly client_errs: string[][] + readonly error?: string + readonly stun: HealthcheckDERPStunReport +} + +// From healthcheck/derp.go +export interface HealthcheckDERPRegionReport { + readonly healthy: boolean + // Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type + readonly region?: any + readonly node_reports: HealthcheckDERPNodeReport[] + readonly error?: string +} + +// From healthcheck/derp.go +export interface HealthcheckDERPReport { + readonly healthy: boolean + readonly regions: Record + // Named type "tailscale.com/net/netcheck.Report" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type + readonly netcheck?: any + readonly netcheck_err?: string + readonly netcheck_logs: string[] + readonly error?: string +} + +// From healthcheck/derp.go +export interface HealthcheckDERPStunReport { + readonly Enabled: boolean + readonly CanSTUN: boolean + readonly Error?: string +} + +// From healthcheck/database.go +export interface HealthcheckDatabaseReport { + readonly healthy: boolean + readonly reachable: boolean + readonly latency: string + readonly latency_ms: number + readonly error?: string +} + +// From healthcheck/healthcheck.go +export interface HealthcheckReport { + readonly time: string + readonly healthy: boolean + readonly failing_sections: string[] + readonly derp: HealthcheckDERPReport + readonly access_url: HealthcheckAccessURLReport + readonly websocket: HealthcheckWebsocketReport + readonly database: HealthcheckDatabaseReport + readonly coder_version: string +} + +// From healthcheck/websocket.go +export interface HealthcheckWebsocketReport { + readonly healthy: boolean + readonly body: string + readonly code: number + readonly error?: string +} From 9d6ffbbe1fc292c530c31fd6325cce22965ccc7a Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Tue, 1 Aug 2023 19:32:06 +0000 Subject: [PATCH 2/7] fixup! fix: generate typescript types for healthcheck --- scripts/apitypings/testdata/enums/enums.go | 2 +- .../testdata/genericmap/genericmap.go | 2 +- .../apitypings/testdata/generics/generics.go | 34 +++++++++---------- .../apitypings/testdata/generics/generics.ts | 22 ++++++------ 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/scripts/apitypings/testdata/enums/enums.go b/scripts/apitypings/testdata/enums/enums.go index dc153df934ce8..777a91441ab2f 100644 --- a/scripts/apitypings/testdata/enums/enums.go +++ b/scripts/apitypings/testdata/enums/enums.go @@ -1,4 +1,4 @@ -package enums +package codersdk type ( Enum string diff --git a/scripts/apitypings/testdata/genericmap/genericmap.go b/scripts/apitypings/testdata/genericmap/genericmap.go index ab9163b587a0a..721ba95313d58 100644 --- a/scripts/apitypings/testdata/genericmap/genericmap.go +++ b/scripts/apitypings/testdata/genericmap/genericmap.go @@ -1,4 +1,4 @@ -package genericmap +package codersdk type Foo struct { Bar string `json:"bar"` diff --git a/scripts/apitypings/testdata/generics/generics.go b/scripts/apitypings/testdata/generics/generics.go index a842cb5693c9b..0d1d53e2869e2 100644 --- a/scripts/apitypings/testdata/generics/generics.go +++ b/scripts/apitypings/testdata/generics/generics.go @@ -1,4 +1,4 @@ -package generics +package codersdk import "time" @@ -10,26 +10,26 @@ type Custom interface { string | bool | int | time.Duration | []string | *int } -// StaticGeneric has all generic fields defined in the field -type StaticGeneric struct { - Static GenericFields[string, int, time.Duration, string] `json:"static"` +// Static has all generic fields defined in the field +type Static struct { + Static Fields[string, int, time.Duration, string] `json:"static"` } -// DynamicGeneric can has some dynamic fields -type DynamicGeneric[A any, S Single] struct { - Dynamic GenericFields[bool, A, string, S] `json:"dynamic"` - Comparable bool `json:"comparable"` +// Dynamic has some dynamic fields. +type Dynamic[A any, S Single] struct { + Dynamic Fields[bool, A, string, S] `json:"dynamic"` + Comparable bool `json:"comparable"` } -type ComplexGeneric[C comparable, S Single, T Custom] struct { - Dynamic GenericFields[C, bool, string, S] `json:"dynamic"` - Order GenericFieldsDiffOrder[C, string, S, T] `json:"order"` - Comparable C `json:"comparable"` - Single S `json:"single"` - Static StaticGeneric `json:"static"` +type Complex[C comparable, S Single, T Custom] struct { + Dynamic Fields[C, bool, string, S] `json:"dynamic"` + Order FieldsDiffOrder[C, string, S, T] `json:"order"` + Comparable C `json:"comparable"` + Single S `json:"single"` + Static Static `json:"static"` } -type GenericFields[C comparable, A any, T Custom, S Single] struct { +type Fields[C comparable, A any, T Custom, S Single] struct { Comparable C `json:"comparable"` Any A `json:"any"` @@ -38,6 +38,6 @@ type GenericFields[C comparable, A any, T Custom, S Single] struct { SingleConstraint S `json:"single_constraint"` } -type GenericFieldsDiffOrder[A any, C comparable, S Single, T Custom] struct { - GenericFields[C, A, T, S] +type FieldsDiffOrder[A any, C comparable, S Single, T Custom] struct { + Fields Fields[C, A, T, S] } diff --git a/scripts/apitypings/testdata/generics/generics.ts b/scripts/apitypings/testdata/generics/generics.ts index ce851f0cc6ff5..36d56852adf4a 100644 --- a/scripts/apitypings/testdata/generics/generics.ts +++ b/scripts/apitypings/testdata/generics/generics.ts @@ -1,22 +1,22 @@ // Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. // From codersdk/generics.go -export interface ComplexGeneric { - readonly dynamic: GenericFields - readonly order: GenericFieldsDiffOrder +export interface Complex { + readonly dynamic: Fields + readonly order: FieldsDiffOrder readonly comparable: C readonly single: S - readonly static: StaticGeneric + readonly static: Static } // From codersdk/generics.go -export interface DynamicGeneric { - readonly dynamic: GenericFields +export interface Dynamic { + readonly dynamic: Fields readonly comparable: boolean } // From codersdk/generics.go -export interface GenericFields { +export interface Fields { readonly comparable: C readonly any: A readonly custom: T @@ -25,13 +25,13 @@ export interface GenericFields { - readonly GenericFields: GenericFields +export interface FieldsDiffOrder { + readonly Fields: Fields } // From codersdk/generics.go -export interface StaticGeneric { - readonly static: GenericFields +export interface Static { + readonly static: Fields } // From codersdk/generics.go From a673c2bbcfa719f9d01750d7f97753cf4babf44f Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Tue, 1 Aug 2023 19:42:45 +0000 Subject: [PATCH 3/7] fixup! fix: generate typescript types for healthcheck --- coderd/healthcheck/database_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/coderd/healthcheck/database_test.go b/coderd/healthcheck/database_test.go index bf9f64471333f..615728a8b573b 100644 --- a/coderd/healthcheck/database_test.go +++ b/coderd/healthcheck/database_test.go @@ -35,7 +35,8 @@ func TestDatabase(t *testing.T) { assert.True(t, report.Healthy) assert.True(t, report.Reachable) - assert.Equal(t, ping, report.Latency) + assert.Equal(t, ping.String(), report.Latency) + assert.Equal(t, int(ping.Milliseconds()), report.LatencyMs) assert.Nil(t, report.Error) }) @@ -81,7 +82,8 @@ func TestDatabase(t *testing.T) { assert.True(t, report.Healthy) assert.True(t, report.Reachable) - assert.Equal(t, time.Millisecond, report.Latency) + assert.Equal(t, time.Millisecond.String(), report.Latency) + assert.Equal(t, 1, report.LatencyMs) assert.Nil(t, report.Error) }) } From f393652539fa134a73a6a253ed345b8d2802c0c5 Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Tue, 1 Aug 2023 20:50:46 +0000 Subject: [PATCH 4/7] fixup! fix: generate typescript types for healthcheck --- coderd/apidoc/docs.go | 3 +++ coderd/apidoc/swagger.json | 3 +++ coderd/healthcheck/derp.go | 7 +++++-- coderd/healthcheck/derp_test.go | 6 ++++-- docs/api/debug.md | 6 ++++-- docs/api/schemas.md | 21 ++++++++++++++------- scripts/apitypings/main.go | 10 ++++------ site/src/api/typesGenerated.ts | 5 ----- 8 files changed, 37 insertions(+), 24 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 8d213cd6952d6..d79e3f65316e5 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -11190,6 +11190,9 @@ const docTemplate = `{ "$ref": "#/definitions/derp.ServerInfoMessage" }, "round_trip_ping": { + "type": "string" + }, + "round_trip_ping_ms": { "type": "integer" }, "stun": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 35bc183a92ba6..2dfc35578dc5a 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -10172,6 +10172,9 @@ "$ref": "#/definitions/derp.ServerInfoMessage" }, "round_trip_ping": { + "type": "string" + }, + "round_trip_ping_ms": { "type": "integer" }, "stun": { diff --git a/coderd/healthcheck/derp.go b/coderd/healthcheck/derp.go index 42d25949935ef..8237d422e1410 100644 --- a/coderd/healthcheck/derp.go +++ b/coderd/healthcheck/derp.go @@ -57,7 +57,8 @@ type DERPNodeReport struct { ServerInfo derp.ServerInfoMessage `json:"node_info"` CanExchangeMessages bool `json:"can_exchange_messages"` - RoundTripPing time.Duration `json:"round_trip_ping"` + RoundTripPing string `json:"round_trip_ping"` + RoundTripPingMs int `json:"round_trip_ping_ms"` UsesWebsocket bool `json:"uses_websocket"` ClientLogs [][]string `json:"client_logs"` ClientErrs [][]string `json:"client_errs"` @@ -256,7 +257,9 @@ func (r *DERPNodeReport) doExchangeMessage(ctx context.Context) { r.mu.Lock() r.CanExchangeMessages = true - r.RoundTripPing = time.Since(*t) + rtt := time.Since(*t) + r.RoundTripPing = rtt.String() + r.RoundTripPingMs = int(rtt.Milliseconds()) r.mu.Unlock() cancel() diff --git a/coderd/healthcheck/derp_test.go b/coderd/healthcheck/derp_test.go index da8a6acc8a989..8884fe698cef3 100644 --- a/coderd/healthcheck/derp_test.go +++ b/coderd/healthcheck/derp_test.go @@ -67,7 +67,8 @@ func TestDERP(t *testing.T) { for _, node := range region.NodeReports { assert.True(t, node.Healthy) assert.True(t, node.CanExchangeMessages) - assert.Positive(t, node.RoundTripPing) + assert.NotEmpty(t, node.RoundTripPing) + assert.Positive(t, node.RoundTripPingMs) assert.Len(t, node.ClientLogs, 2) assert.Len(t, node.ClientLogs[0], 1) assert.Len(t, node.ClientErrs[0], 0) @@ -111,7 +112,8 @@ func TestDERP(t *testing.T) { for _, node := range region.NodeReports { assert.True(t, node.Healthy) assert.True(t, node.CanExchangeMessages) - assert.Positive(t, node.RoundTripPing) + assert.NotEmpty(t, node.RoundTripPing) + assert.Positive(t, node.RoundTripPingMs) assert.Len(t, node.ClientLogs, 2) assert.Len(t, node.ClientLogs[0], 1) assert.Len(t, node.ClientErrs[0], 0) diff --git a/docs/api/debug.md b/docs/api/debug.md index 3097d1405d109..e3382c6586504 100644 --- a/docs/api/debug.md +++ b/docs/api/debug.md @@ -119,7 +119,8 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, @@ -180,7 +181,8 @@ curl -X GET http://coder-server:8080/api/v2/debug/health \ "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 110c5cca5530e..ee2f53655957a 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -6501,7 +6501,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, @@ -6522,7 +6523,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| | `healthy` | boolean | false | | | | `node` | [tailcfg.DERPNode](#tailcfgderpnode) | false | | | | `node_info` | [derp.ServerInfoMessage](#derpserverinfomessage) | false | | | -| `round_trip_ping` | integer | false | | | +| `round_trip_ping` | string | false | | | +| `round_trip_ping_ms` | integer | false | | | | `stun` | [healthcheck.DERPStunReport](#healthcheckderpstunreport) | false | | | | `uses_websocket` | boolean | false | | | @@ -6557,7 +6559,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, @@ -6668,7 +6671,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, @@ -6729,7 +6733,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, @@ -6902,7 +6907,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, @@ -6963,7 +6969,8 @@ If the schedule is empty, the user will be updated to use the default schedule.| "tokenBucketBytesBurst": 0, "tokenBucketBytesPerSecond": 0 }, - "round_trip_ping": 0, + "round_trip_ping": "string", + "round_trip_ping_ms": 0, "stun": { "canSTUN": true, "enabled": true, diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index 6e0b119a35408..b22f9235f37f9 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -33,6 +33,7 @@ var ( func main() { ctx := context.Background() log := slog.Make(sloghuman.Sink(os.Stderr)) + _, _ = fmt.Print("// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT.\n\n") for _, baseDir := range baseDirs { output, err := Generate(baseDir) if err != nil { @@ -40,7 +41,7 @@ func main() { } // Just cat the output to a file to capture it - _, _ = fmt.Println(output) + _, _ = fmt.Print(output, "\n\n") } } @@ -67,11 +68,6 @@ type TypescriptTypes struct { // String just combines all the codeblocks. func (t TypescriptTypes) String() string { var s strings.Builder - const prelude = ` -// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. - -` - _, _ = s.WriteString(prelude) sortedTypes := make([]string, 0, len(t.Types)) sortedEnums := make([]string, 0, len(t.Enums)) @@ -772,6 +768,8 @@ func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) { case "time.Time": // We really should come up with a standard for time. return TypescriptType{ValueType: "string"}, nil + case "time.Duration": + return TypescriptType{ValueType: "number"}, nil case "database/sql.NullTime": return TypescriptType{ValueType: "string", Optional: true}, nil case "github.com/coder/coder/codersdk.NullTime": diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 15127988901b5..98709febc8c19 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -234,7 +234,6 @@ export interface CreateTestAuditLogRequest { // From codersdk/apikey.go export interface CreateTokenRequest { - // This is likely an enum in an external package ("time.Duration") readonly lifetime: number readonly scope: APIKeyScope readonly token_name: string @@ -1056,7 +1055,6 @@ export interface TemplateVersionsByTemplateRequest extends Pagination { // From codersdk/apikey.go export interface TokenConfig { - // This is likely an enum in an external package ("time.Duration") readonly max_token_lifetime: number } @@ -1909,8 +1907,6 @@ export const WorkspaceTransitions: WorkspaceTransition[] = [ // From codersdk/workspaceproxy.go export type RegionTypes = Region | WorkspaceProxy -// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. - // From healthcheck/accessurl.go export interface HealthcheckAccessURLReport { readonly access_url: string @@ -1931,7 +1927,6 @@ export interface HealthcheckDERPNodeReport { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly node_info: any readonly can_exchange_messages: boolean - // This is likely an enum in an external package ("time.Duration") readonly round_trip_ping: number readonly uses_websocket: boolean readonly client_logs: string[][] From a7f1694854528971472240d30b7e894d6e356ec2 Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Wed, 2 Aug 2023 02:51:04 +0000 Subject: [PATCH 5/7] fixup! fix: generate typescript types for healthcheck --- scripts/apitypings/testdata/enums/enums.ts | 2 -- scripts/apitypings/testdata/genericmap/genericmap.ts | 2 -- scripts/apitypings/testdata/generics/generics.ts | 2 -- site/src/api/typesGenerated.ts | 3 ++- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/scripts/apitypings/testdata/enums/enums.ts b/scripts/apitypings/testdata/enums/enums.ts index bf9863da23dfe..2fc20f0e33d29 100644 --- a/scripts/apitypings/testdata/enums/enums.ts +++ b/scripts/apitypings/testdata/enums/enums.ts @@ -1,5 +1,3 @@ -// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. - // From codersdk/enums.go export type Enums = Enum[] diff --git a/scripts/apitypings/testdata/genericmap/genericmap.ts b/scripts/apitypings/testdata/genericmap/genericmap.ts index 5489d03970ac7..9ceca8b44d706 100644 --- a/scripts/apitypings/testdata/genericmap/genericmap.ts +++ b/scripts/apitypings/testdata/genericmap/genericmap.ts @@ -1,5 +1,3 @@ -// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. - // From codersdk/genericmap.go export interface Buzz { readonly foo: Foo diff --git a/scripts/apitypings/testdata/generics/generics.ts b/scripts/apitypings/testdata/generics/generics.ts index 36d56852adf4a..57cfdb7bc5fde 100644 --- a/scripts/apitypings/testdata/generics/generics.ts +++ b/scripts/apitypings/testdata/generics/generics.ts @@ -1,5 +1,3 @@ -// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. - // From codersdk/generics.go export interface Complex { readonly dynamic: Fields diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 98709febc8c19..ea766b02b2637 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1927,7 +1927,8 @@ export interface HealthcheckDERPNodeReport { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type readonly node_info: any readonly can_exchange_messages: boolean - readonly round_trip_ping: number + readonly round_trip_ping: string + readonly round_trip_ping_ms: number readonly uses_websocket: boolean readonly client_logs: string[][] readonly client_errs: string[][] From fc4b88392a39e7e6ca893ae6ecd6b856ae9c9a6c Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Wed, 2 Aug 2023 02:57:36 +0000 Subject: [PATCH 6/7] fixup! fix: generate typescript types for healthcheck --- coderd/healthcheck/derp_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/coderd/healthcheck/derp_test.go b/coderd/healthcheck/derp_test.go index 8884fe698cef3..d27cdc182ec31 100644 --- a/coderd/healthcheck/derp_test.go +++ b/coderd/healthcheck/derp_test.go @@ -68,7 +68,6 @@ func TestDERP(t *testing.T) { assert.True(t, node.Healthy) assert.True(t, node.CanExchangeMessages) assert.NotEmpty(t, node.RoundTripPing) - assert.Positive(t, node.RoundTripPingMs) assert.Len(t, node.ClientLogs, 2) assert.Len(t, node.ClientLogs[0], 1) assert.Len(t, node.ClientErrs[0], 0) @@ -113,7 +112,6 @@ func TestDERP(t *testing.T) { assert.True(t, node.Healthy) assert.True(t, node.CanExchangeMessages) assert.NotEmpty(t, node.RoundTripPing) - assert.Positive(t, node.RoundTripPingMs) assert.Len(t, node.ClientLogs, 2) assert.Len(t, node.ClientLogs[0], 1) assert.Len(t, node.ClientErrs[0], 0) @@ -176,7 +174,7 @@ func TestDERP(t *testing.T) { for _, node := range region.NodeReports { assert.False(t, node.Healthy) assert.True(t, node.CanExchangeMessages) - assert.Positive(t, node.RoundTripPing) + assert.NotEmpty(t, node.RoundTripPing) assert.Len(t, node.ClientLogs, 2) assert.Len(t, node.ClientLogs[0], 3) assert.Len(t, node.ClientLogs[1], 3) From 4d1d31b75a415bc2c86001bad495f7471ba8e7fa Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Wed, 2 Aug 2023 19:29:52 +0000 Subject: [PATCH 7/7] add header per dir --- scripts/apitypings/main.go | 1 + site/src/api/typesGenerated.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index b22f9235f37f9..3cf4b1fe79c11 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -35,6 +35,7 @@ func main() { log := slog.Make(sloghuman.Sink(os.Stderr)) _, _ = fmt.Print("// Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT.\n\n") for _, baseDir := range baseDirs { + _, _ = fmt.Printf("// The code below is generated from %s.\n\n", strings.TrimPrefix(baseDir, "./")) output, err := Generate(baseDir) if err != nil { log.Fatal(ctx, err.Error()) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index ea766b02b2637..886f95e06bbf1 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1,5 +1,7 @@ // Code generated by 'make site/src/api/typesGenerated.ts'. DO NOT EDIT. +// The code below is generated from codersdk. + // From codersdk/templates.go export interface ACLAvailable { readonly users: User[] @@ -1907,6 +1909,8 @@ export const WorkspaceTransitions: WorkspaceTransition[] = [ // From codersdk/workspaceproxy.go export type RegionTypes = Region | WorkspaceProxy +// The code below is generated from coderd/healthcheck. + // From healthcheck/accessurl.go export interface HealthcheckAccessURLReport { readonly access_url: string