diff --git a/codersdk/client.go b/codersdk/client.go index 0c6f1986d664c..d13927513ae38 100644 --- a/codersdk/client.go +++ b/codersdk/client.go @@ -26,6 +26,7 @@ func New(serverURL *url.URL) *Client { } // Client is an HTTP caller for methods to the Coder API. +// @typescript-ignore Client type Client struct { HTTPClient *http.Client SessionToken string @@ -113,6 +114,7 @@ func readBodyAsError(res *http.Response) error { } // Error represents an unaccepted or invalid request to the API. +// @typescript-ignore Error type Error struct { httpapi.Response diff --git a/go.mod b/go.mod index a30067885133f..32a0550c2ec56 100644 --- a/go.mod +++ b/go.mod @@ -109,6 +109,7 @@ require ( golang.org/x/sys v0.0.0-20220412211240-33da011f77ad golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/text v0.3.7 + golang.org/x/tools v0.1.10 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f google.golang.org/api v0.75.0 google.golang.org/protobuf v1.28.0 diff --git a/go.sum b/go.sum index 3ef6a63131c9a..ce5e08df20904 100644 --- a/go.sum +++ b/go.sum @@ -2287,6 +2287,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/scripts/apitypings/README.md b/scripts/apitypings/README.md new file mode 100644 index 0000000000000..32451ec77e5df --- /dev/null +++ b/scripts/apitypings/README.md @@ -0,0 +1,40 @@ +# APITypings + +This main.go generates typescript types from the codersdk types in Go. + +# Features + +- Supports Go types + - [x] Basics (string/int/etc) + - [x] Maps + - [x] Slices + - [x] Enums + - [x] Pointers + - [ ] External Types (uses `any` atm) + - Some custom external types are hardcoded in (eg: time.Time) + + +## Type overrides + +```golang +type Foo struct { + // Force the typescript type to be a number + CreatedAt time.Duration `json:"created_at" typescript:"number"` +} +``` + +## Ignore Types + +Do not generate ignored types. + +```golang +// @typescript-ignore InternalType +type InternalType struct { + // ... +} +``` + +# Future Ideas + +- Should `omitempty` in the `json` tag indicate optional? +- Use a yaml config for overriding certain types diff --git a/scripts/apitypings/main.go b/scripts/apitypings/main.go index a738e553e01ac..529b7ae0f42f2 100644 --- a/scripts/apitypings/main.go +++ b/scripts/apitypings/main.go @@ -1,208 +1,426 @@ package main import ( + "context" "fmt" - "go/ast" - "go/parser" - "go/token" - "log" + "go/types" "os" "path/filepath" + "reflect" + "regexp" "sort" "strings" + "golang.org/x/tools/go/packages" "golang.org/x/xerrors" + + "cdr.dev/slog" + "cdr.dev/slog/sloggers/sloghuman" ) const ( baseDir = "./codersdk" + indent = " " ) func main() { - err := run() + ctx := context.Background() + log := slog.Make(sloghuman.Sink(os.Stderr)) + codeBlocks, err := GenerateFromDirectory(ctx, log, baseDir) if err != nil { - log.Fatal(err) + log.Fatal(ctx, err.Error()) } + + // Just cat the output to a file to capture it + _, _ = fmt.Println(codeBlocks.String()) } -func run() error { - var ( - astFiles []*ast.File - enums = make(map[string]string) - ) - fset := token.NewFileSet() - entries, err := os.ReadDir(baseDir) - if err != nil { - return xerrors.Errorf("reading dir %s: %w", baseDir, err) +// TypescriptTypes holds all the code blocks created. +type TypescriptTypes struct { + // Each entry is the type name, and it's typescript code block. + Types map[string]string + Enums map[string]string +} + +// String just combines all the codeblocks. +func (t TypescriptTypes) String() string { + var s strings.Builder + _, _ = s.WriteString("// Code generated by 'make coder/scripts/apitypings/main.go'. DO NOT EDIT.\n\n") + + sortedTypes := make([]string, 0, len(t.Types)) + sortedEnums := make([]string, 0, len(t.Enums)) + + for k := range t.Types { + sortedTypes = append(sortedTypes, k) + } + for k := range t.Enums { + sortedEnums = append(sortedEnums, k) } - // loop each file in directory - for _, entry := range entries { - astFile, err := parser.ParseFile(fset, filepath.Join(baseDir, entry.Name()), nil, 0) - if err != nil { - return xerrors.Errorf("parsing file %s: %w", filepath.Join(baseDir, entry.Name()), err) - } + sort.Strings(sortedTypes) + sort.Strings(sortedEnums) - astFiles = append(astFiles, astFile) + for _, k := range sortedTypes { + v := t.Types[k] + _, _ = s.WriteString(v) + _, _ = s.WriteRune('\n') } - // TypeSpec case for structs and type alias - loopSpecs(astFiles, func(spec ast.Spec) { - pos := fset.Position(spec.Pos()) - s, ok := spec.(*ast.TypeSpec) - if !ok { - return - } - out, err := handleTypeSpec(s, pos, enums) - if err != nil { - return - } + for _, k := range sortedEnums { + v := t.Enums[k] + _, _ = s.WriteString(v) + _, _ = s.WriteRune('\n') + } - _, _ = fmt.Printf(out) - }) + return strings.TrimRight(s.String(), "\n") +} - // ValueSpec case for loading type alias values into the enum map - loopSpecs(astFiles, func(spec ast.Spec) { - s, ok := spec.(*ast.ValueSpec) - if !ok { - return - } - handleValueSpec(s, enums) - }) +// GenerateFromDirectory will return all the typescript code blocks for a directory +func GenerateFromDirectory(ctx context.Context, log slog.Logger, directory string) (*TypescriptTypes, error) { + g := Generator{ + log: log, + } + err := g.parsePackage(ctx, directory) + if err != nil { + return nil, xerrors.Errorf("parse package %q: %w", directory, err) + } - // sort keys so output is always the same - var keys []string - for k := range enums { - keys = append(keys, k) + codeBlocks, err := g.generateAll() + if err != nil { + return nil, xerrors.Errorf("parse package %q: %w", directory, err) + } + + return codeBlocks, nil +} + +type Generator struct { + // Package we are scanning. + pkg *packages.Package + log slog.Logger +} + +// parsePackage takes a list of patterns such as a directory, and parses them. +func (g *Generator) parsePackage(ctx context.Context, patterns ...string) error { + cfg := &packages.Config{ + // Just accept the fact we need these flags for what we want. Feel free to add + // more, it'll just increase the time it takes to parse. + Mode: packages.NeedTypes | packages.NeedName | packages.NeedTypesInfo | + packages.NeedTypesSizes | packages.NeedSyntax, + Tests: false, + Context: ctx, + } + + pkgs, err := packages.Load(cfg, patterns...) + if err != nil { + return xerrors.Errorf("load package: %w", err) } - sort.Strings(keys) - // write each type alias declaration with possible values - for _, k := range keys { - _, _ = fmt.Printf("%s\n", enums[k]) + // Only support 1 package for now. We can expand it if we need later, we + // just need to hook up multiple packages in the generator. + if len(pkgs) != 1 { + return xerrors.Errorf("expected 1 package, found %d", len(pkgs)) } + g.pkg = pkgs[0] return nil } -func loopSpecs(astFiles []*ast.File, fn func(spec ast.Spec)) { - for _, astFile := range astFiles { - // loop each declaration in file - for _, node := range astFile.Decls { - genDecl, ok := node.(*ast.GenDecl) - if !ok { - continue - } - for _, spec := range genDecl.Specs { - fn(spec) +// generateAll will generate for all types found in the pkg +func (g *Generator) generateAll() (*TypescriptTypes, error) { + structs := make(map[string]string) + enums := make(map[string]types.Object) + enumConsts := make(map[string][]*types.Const) + + // Look for comments that indicate to ignore a type for typescript generation. + ignoredTypes := make(map[string]struct{}) + ignoreRegex := regexp.MustCompile("@typescript-ignore[:]?(?P.*)") + for _, file := range g.pkg.Syntax { + for _, comment := range file.Comments { + for _, line := range comment.List { + text := line.Text + matches := ignoreRegex.FindStringSubmatch(text) + ignored := ignoreRegex.SubexpIndex("ignored_types") + if len(matches) >= ignored && matches[ignored] != "" { + arr := strings.Split(matches[ignored], ",") + for _, s := range arr { + ignoredTypes[strings.TrimSpace(s)] = struct{}{} + } + } } } } -} -func handleTypeSpec(typeSpec *ast.TypeSpec, pos token.Position, enums map[string]string) (string, error) { - jsonFields := 0 - s := fmt.Sprintf("// From %s.\n", pos.String()) - switch t := typeSpec.Type.(type) { - // Struct declaration - case *ast.StructType: - s = fmt.Sprintf("%sexport interface %s {\n", s, typeSpec.Name.Name) - for _, field := range t.Fields.List { - i, optional, err := getIdent(field.Type) - if err != nil { - continue - } + for _, n := range g.pkg.Types.Scope().Names() { + obj := g.pkg.Types.Scope().Lookup(n) + if obj == nil || obj.Type() == nil { + // This would be weird, but it is if the package does not have the type def. + continue + } - fieldType := toTsType(i.Name) - if fieldType == "" { - continue - } + // Exclude ignored types + if _, ok := ignoredTypes[obj.Name()]; ok { + continue + } - fieldName := toJSONField(field) - if fieldName == "" { - continue + switch obj := obj.(type) { + // All named types are type declarations + case *types.TypeName: + named, ok := obj.Type().(*types.Named) + if !ok { + panic("all typename should be named types") } - - s = fmt.Sprintf("%s readonly %s%s: %s\n", s, fieldName, optional, fieldType) - jsonFields++ + switch named.Underlying().(type) { + case *types.Struct: + // type struct + // Structs are obvious. + st, _ := obj.Type().Underlying().(*types.Struct) + codeBlock, err := g.buildStruct(obj, st) + if err != nil { + return nil, xerrors.Errorf("generate %q: %w", obj.Name()) + } + structs[obj.Name()] = codeBlock + case *types.Basic: + // type string + // These are enums. Store to expand later. + enums[obj.Name()] = obj + } + case *types.Var: + // TODO: Are any enums var declarations? This is also codersdk.Me. + case *types.Const: + // We only care about named constant types, since they are enums + if named, ok := obj.Type().(*types.Named); ok { + name := named.Obj().Name() + enumConsts[name] = append(enumConsts[name], obj) + } + case *types.Func: + // Noop + default: + fmt.Println(obj.Name()) } + } - // Do not print struct if it has no json fields - if jsonFields == 0 { - return "", xerrors.New("no json fields") + // Write all enums + enumCodeBlocks := make(map[string]string) + for name, v := range enums { + var values []string + for _, elem := range enumConsts[name] { + // TODO: If we have non string constants, we need to handle that + // here. + values = append(values, elem.Val().String()) } + sort.Strings(values) + var s strings.Builder + _, _ = s.WriteString(g.posLine(v)) + _, _ = s.WriteString(fmt.Sprintf("export type %s = %s\n", + name, strings.Join(values, " | "), + )) - return fmt.Sprintf("%s}\n\n", s), nil - // Type alias declaration - case *ast.Ident: - // save type declaration to map of types - // later we come back and add union types to this declaration - enums[typeSpec.Name.Name] = fmt.Sprintf("%sexport type %s = \n", s, typeSpec.Name.Name) - return "", xerrors.New("enums are not printed at this stage") - default: - return "", xerrors.New("not struct or alias") + enumCodeBlocks[name] = s.String() } + + return &TypescriptTypes{ + Types: structs, + Enums: enumCodeBlocks, + }, nil } -func handleValueSpec(valueSpec *ast.ValueSpec, enums map[string]string) { - valueValue := "" - i, ok := valueSpec.Type.(*ast.Ident) - if !ok { - return - } - valueType := i.Name +func (g *Generator) posLine(obj types.Object) string { + file := g.pkg.Fset.File(obj.Pos()) + position := file.Position(obj.Pos()) + position.Filename = filepath.Join("codersdk", filepath.Base(position.Filename)) + return fmt.Sprintf("// From %s\n", + position.String(), + ) +} + +// buildStruct just prints the typescript def for a type. +func (g *Generator) buildStruct(obj types.Object, st *types.Struct) (string, error) { + var s strings.Builder + _, _ = s.WriteString(g.posLine(obj)) - for _, value := range valueSpec.Values { - bl, ok := value.(*ast.BasicLit) - if !ok { - return + _, _ = s.WriteString(fmt.Sprintf("export interface %s {\n", obj.Name())) + // For each field in the struct, we print 1 line of the typescript interface + for i := 0; i < st.NumFields(); i++ { + field := st.Field(i) + tag := reflect.StructTag(st.Tag(i)) + + // Use the json name if present + jsonName := tag.Get("json") + arr := strings.Split(jsonName, ",") + jsonName = arr[0] + if jsonName == "" { + jsonName = field.Name() } - valueValue = bl.Value - break - } - enums[valueType] = fmt.Sprintf("%s | %s\n", enums[valueType], valueValue) -} + var tsType TypescriptType + // If a `typescript:"string"` exists, we take this, and do not try to infer. + typescriptTag := tag.Get("typescript") + if typescriptTag == "-" { + // Ignore this field + continue + } else if typescriptTag != "" { + tsType.ValueType = typescriptTag + } else { + var err error + tsType, err = g.typescriptType(field.Type()) + if err != nil { + return "", xerrors.Errorf("typescript type: %w", err) + } + } -func getIdent(e ast.Expr) (*ast.Ident, string, error) { - switch t := e.(type) { - case *ast.Ident: - return t, "", nil - case *ast.StarExpr: - i, ok := t.X.(*ast.Ident) - if !ok { - return nil, "", xerrors.New("failed to cast star expr to indent") + if tsType.AboveTypeLine != "" { + _, _ = s.WriteString(tsType.AboveTypeLine) + _, _ = s.WriteRune('\n') + } + optional := "" + if tsType.Optional { + optional = "?" } - return i, "?", nil - default: - return nil, "", xerrors.New("unknown expr type") + _, _ = s.WriteString(fmt.Sprintf("%sreadonly %s%s: %s\n", indent, jsonName, optional, tsType.ValueType)) } + _, _ = s.WriteString("}\n") + return s.String(), nil } -func toTsType(fieldType string) string { - switch fieldType { - case "bool": - return "boolean" - case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64": - return "number" - } - - return fieldType +type TypescriptType struct { + ValueType string + // AboveTypeLine lets you put whatever text you want above the typescript + // type line. + AboveTypeLine string + // Optional indicates the value is an optional field in typescript. + Optional bool } -func toJSONField(field *ast.Field) string { - if field.Tag != nil && field.Tag.Value != "" { - fieldName := strings.Trim(field.Tag.Value, "`") - for _, pair := range strings.Split(fieldName, " ") { - if strings.Contains(pair, `json:`) { - fieldName := strings.TrimPrefix(pair, `json:`) - fieldName = strings.Trim(fieldName, `"`) - fieldName = strings.Split(fieldName, ",")[0] +// typescriptType this function returns a typescript type for a given +// golang type. +// Eg: +// []byte returns "string" +func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) { + switch ty := ty.(type) { + case *types.Basic: + bs := ty + // All basic literals (string, bool, int, etc). + switch { + case bs.Info()&types.IsNumeric > 0: + return TypescriptType{ValueType: "number"}, nil + case bs.Info()&types.IsBoolean > 0: + return TypescriptType{ValueType: "boolean"}, nil + case bs.Kind() == types.Byte: + // TODO: @emyrk What is a byte for typescript? A string? A uint8? + return TypescriptType{ValueType: "number", AboveTypeLine: indentedComment("This is a byte in golang")}, nil + default: + return TypescriptType{ValueType: bs.Name()}, nil + } + case *types.Struct: + // This handles anonymous structs. This should never happen really. + // Such as: + // type Name struct { + // Embedded struct { + // Field string `json:"field"` + // } + // } + return TypescriptType{ + ValueType: "any", + AboveTypeLine: fmt.Sprintf("%s\n%s", + indentedComment("Embedded struct, please fix by naming it"), + indentedComment("eslint-disable-next-line @typescript-eslint/no-explicit-any"), + ), + }, nil + case *types.Map: + // map[string][string] -> Record + m := ty + keyType, err := g.typescriptType(m.Key()) + if err != nil { + return TypescriptType{}, xerrors.Errorf("map key: %w", err) + } + valueType, err := g.typescriptType(m.Elem()) + if err != nil { + return TypescriptType{}, xerrors.Errorf("map key: %w", err) + } + + return TypescriptType{ + ValueType: fmt.Sprintf("Record<%s, %s>", keyType.ValueType, valueType.ValueType), + }, nil + case *types.Slice, *types.Array: + // Slice/Arrays are pretty much the same. + type hasElem interface { + Elem() types.Type + } - return fieldName + arr, _ := ty.(hasElem) + switch { + // When type checking here, just use the string. You can cast it + // to a types.Basic and get the kind if you want too :shrug: + case arr.Elem().String() == "byte": + // All byte arrays are strings on the typescript. + // Is this ok? + return TypescriptType{ValueType: "string"}, nil + default: + // By default, just do an array of the underlying type. + underlying, err := g.typescriptType(arr.Elem()) + if err != nil { + return TypescriptType{}, xerrors.Errorf("array: %w", err) } + return TypescriptType{ValueType: underlying.ValueType + "[]", AboveTypeLine: underlying.AboveTypeLine}, nil + } + case *types.Named: + n := ty + // First 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 + // we generate. + name := n.Obj().Name() + if obj := g.pkg.Types.Scope().Lookup(name); obj != nil { + // Sweet! Using other typescript types as fields. This could be an + // enum or another struct + return TypescriptType{ValueType: name}, nil + } + + // These are external named types that we handle uniquely. + switch n.String() { + case "net/url.URL": + return TypescriptType{ValueType: "string"}, nil + case "time.Time": + // We really should come up with a standard for time. + return TypescriptType{ValueType: "string"}, nil + case "database/sql.NullTime": + return TypescriptType{ValueType: "string", Optional: true}, nil + case "github.com/google/uuid.NullUUID": + return TypescriptType{ValueType: "string", Optional: true}, nil + case "github.com/google/uuid.UUID": + return TypescriptType{ValueType: "string"}, nil } + + // If it's a struct, just use the name of the struct type + if _, ok := n.Underlying().(*types.Struct); ok { + return TypescriptType{ValueType: "any", AboveTypeLine: fmt.Sprintf("%s\n%s", + indentedComment(fmt.Sprintf("Named type %q unknown, using \"any\"", n.String())), + indentedComment("eslint-disable-next-line @typescript-eslint/no-explicit-any"), + )}, nil + } + + // Defer to the underlying type. + ts, err := g.typescriptType(ty.Underlying()) + if err != nil { + return TypescriptType{}, xerrors.Errorf("named underlying: %w", err) + } + ts.AboveTypeLine = indentedComment(fmt.Sprintf("This is likely an enum in an external package (%q)", n.String())) + return ts, nil + case *types.Pointer: + // Dereference pointers. + pt := ty + resp, err := g.typescriptType(pt.Elem()) + if err != nil { + return TypescriptType{}, xerrors.Errorf("pointer: %w", err) + } + resp.Optional = true + return resp, nil } - return "" + // These are all the other types we need to support. + // time.Time, uuid, etc. + return TypescriptType{}, xerrors.Errorf("unknown type: %s", ty.String()) +} + +func indentedComment(comment string) string { + return fmt.Sprintf("%s// %s", indent, comment) } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 10acc3acbc4fb..e47bfa7957846 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1,197 +1,328 @@ -// From codersdk/buildinfo.go:10:6. -export interface BuildInfoResponse { - readonly external_url: string - readonly version: string -} +// Code generated by 'make coder/scripts/apitypings/main.go'. DO NOT EDIT. -// From codersdk/files.go:16:6. -export interface UploadResponse { - readonly hash: string -} - -// From codersdk/gitsshkey.go:14:6. -export interface GitSSHKey { - readonly public_key: string +// From codersdk/workspaceagents.go:35:6 +export interface AWSInstanceIdentityToken { + readonly signature: string + readonly document: string } -// From codersdk/gitsshkey.go:21:6. +// From codersdk/gitsshkey.go:21:6 export interface AgentGitSSHKey { readonly public_key: string readonly private_key: string } -// From codersdk/organizations.go:17:6. -export interface Organization { - readonly name: string +// From codersdk/users.go:94:6 +export interface AuthMethods { + readonly password: boolean + readonly github: boolean } -// From codersdk/organizations.go:25:6. -export interface CreateTemplateVersionRequest { - readonly storage_source: string +// From codersdk/workspaceagents.go:40:6 +export interface AzureInstanceIdentityToken { + readonly signature: string + readonly encoding: string } -// From codersdk/organizations.go:38:6. -export interface CreateTemplateRequest { - readonly name: string +// From codersdk/buildinfo.go:10:6 +export interface BuildInfoResponse { + readonly external_url: string + readonly version: string } -// From codersdk/organizations.go:52:6. -export interface CreateWorkspaceRequest { - readonly name: string +// From codersdk/users.go:48:6 +export interface CreateFirstUserRequest { + readonly email: string + readonly username: string + readonly password: string + readonly organization: string } -// From codersdk/parameters.go:26:6. -export interface Parameter { - readonly scope: ParameterScope +// From codersdk/users.go:56:6 +export interface CreateFirstUserResponse { + readonly user_id: string + readonly organization_id: string +} + +// From codersdk/users.go:89:6 +export interface CreateOrganizationRequest { readonly name: string } -// From codersdk/parameters.go:38:6. +// From codersdk/parameters.go:38:6 export interface CreateParameterRequest { readonly name: string readonly source_value: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterSourceScheme") + readonly source_scheme: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterDestinationScheme") + readonly destination_scheme: string } -// From codersdk/provisionerdaemons.go:46:6. -export interface ProvisionerJob { - readonly error: string - readonly status: ProvisionerJobStatus -} - -// From codersdk/provisionerdaemons.go:56:6. -export interface ProvisionerJobLog { - readonly stage: string - readonly output: string +// From codersdk/organizations.go:38:6 +export interface CreateTemplateRequest { + readonly name: string + readonly template_version_id: string + readonly parameter_values: CreateParameterRequest[] } -// From codersdk/templates.go:17:6. -export interface Template { - readonly name: string - readonly workspace_owner_count: number +// From codersdk/organizations.go:25:6 +export interface CreateTemplateVersionRequest { + readonly template_id: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerStorageMethod") + readonly storage_method: string + readonly storage_source: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerType") + readonly provisioner: string + readonly parameter_values: CreateParameterRequest[] } -// From codersdk/templateversions.go:17:6. -export interface TemplateVersion { - readonly name: string - readonly job: ProvisionerJob +// From codersdk/users.go:61:6 +export interface CreateUserRequest { + readonly email: string + readonly username: string + readonly password: string + readonly organization_id: string } -// From codersdk/users.go:17:6. -export interface UsersRequest { - readonly search: string - readonly limit: number - readonly offset: number +// From codersdk/workspaces.go:33:6 +export interface CreateWorkspaceBuildRequest { + readonly template_version_id: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.WorkspaceTransition") + readonly transition: string + readonly dry_run: boolean } -// From codersdk/users.go:39:6. -export interface User { - readonly email: string - readonly username: string - readonly status: UserStatus +// From codersdk/organizations.go:52:6 +export interface CreateWorkspaceRequest { + readonly template_id: string + readonly name: string + readonly parameter_values: CreateParameterRequest[] } -// From codersdk/users.go:48:6. -export interface CreateFirstUserRequest { - readonly email: string - readonly username: string - readonly password: string - readonly organization: string +// From codersdk/users.go:85:6 +export interface GenerateAPIKeyResponse { + readonly key: string } -// From codersdk/users.go:61:6. -export interface CreateUserRequest { - readonly email: string - readonly username: string - readonly password: string +// From codersdk/gitsshkey.go:14:6 +export interface GitSSHKey { + readonly user_id: string + readonly created_at: string + readonly updated_at: string + readonly public_key: string } -// From codersdk/users.go:68:6. -export interface UpdateUserProfileRequest { - readonly email: string - readonly username: string +// From codersdk/workspaceagents.go:31:6 +export interface GoogleInstanceIdentityToken { + readonly json_web_token: string } -// From codersdk/users.go:74:6. +// From codersdk/users.go:74:6 export interface LoginWithPasswordRequest { readonly email: string readonly password: string } -// From codersdk/users.go:80:6. +// From codersdk/users.go:80:6 export interface LoginWithPasswordResponse { readonly session_token: string } -// From codersdk/users.go:85:6. -export interface GenerateAPIKeyResponse { - readonly key: string +// From codersdk/organizations.go:17:6 +export interface Organization { + readonly id: string + readonly name: string + readonly created_at: string + readonly updated_at: string } -// From codersdk/users.go:89:6. -export interface CreateOrganizationRequest { +// From codersdk/parameters.go:26:6 +export interface Parameter { + readonly id: string + readonly created_at: string + readonly updated_at: string + readonly scope: ParameterScope + readonly scope_id: string readonly name: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterSourceScheme") + readonly source_scheme: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterDestinationScheme") + readonly destination_scheme: string +} + +// From codersdk/provisionerdaemons.go:23:6 +export interface ProvisionerDaemon { + readonly id: string + readonly created_at: string + readonly updated_at?: string + readonly organization_id?: string + readonly name: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerType") + readonly provisioners: string[] } -// From codersdk/users.go:94:6. -export interface AuthMethods { - readonly password: boolean - readonly github: boolean +// From codersdk/provisionerdaemons.go:46:6 +export interface ProvisionerJob { + readonly id: string + readonly created_at: string + readonly started_at?: string + readonly completed_at?: string + readonly error: string + readonly status: ProvisionerJobStatus + readonly worker_id?: string } -// From codersdk/workspaceagents.go:31:6. -export interface GoogleInstanceIdentityToken { - readonly json_web_token: string +// From codersdk/provisionerdaemons.go:56:6 +export interface ProvisionerJobLog { + readonly id: string + readonly created_at: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.LogSource") + readonly log_source: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.LogLevel") + readonly log_level: string + readonly stage: string + readonly output: string } -// From codersdk/workspaceagents.go:35:6. -export interface AWSInstanceIdentityToken { - readonly signature: string - readonly document: string +// From codersdk/templates.go:17:6 +export interface Template { + readonly id: string + readonly created_at: string + readonly updated_at: string + readonly organization_id: string + readonly name: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ProvisionerType") + readonly provisioner: string + readonly active_version_id: string + readonly workspace_owner_count: number } -// From codersdk/workspaceagents.go:40:6. -export interface AzureInstanceIdentityToken { - readonly signature: string - readonly encoding: string +// From codersdk/templateversions.go:17:6 +export interface TemplateVersion { + readonly id: string + readonly template_id?: string + readonly created_at: string + readonly updated_at: string + readonly name: string + readonly job: ProvisionerJob } -// From codersdk/workspaceagents.go:47:6. -export interface WorkspaceAgentAuthenticateResponse { - readonly session_token: string +// From codersdk/templateversions.go:30:6 +export interface TemplateVersionParameter { + // Named type "github.com/coder/coder/coderd/database.ParameterValue" unknown, using "any" + // eslint-disable-next-line @typescript-eslint/no-explicit-any + readonly ParameterValue: any + readonly schema_id: string + readonly default_source_value: boolean } -// From codersdk/workspacebuilds.go:17:6. -export interface WorkspaceBuild { +// From codersdk/templateversions.go:27:6 +export interface TemplateVersionParameterSchema { + readonly id: string + readonly created_at: string + readonly job_id: string readonly name: string - readonly job: ProvisionerJob + readonly description: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterSourceScheme") + readonly default_source_scheme: string + readonly default_source_value: string + readonly allow_override_source: boolean + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterDestinationScheme") + readonly default_destination_scheme: string + readonly allow_override_destination: boolean + readonly default_refresh: string + readonly redisplay_value: boolean + readonly validation_error: string + readonly validation_condition: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.ParameterTypeSystem") + readonly validation_type_system: string + readonly validation_value_type: string +} + +// From codersdk/templates.go:28:6 +export interface UpdateActiveTemplateVersion { + readonly id: string +} + +// From codersdk/users.go:68:6 +export interface UpdateUserProfileRequest { + readonly email: string + readonly username: string } -// From codersdk/workspaceresources.go:23:6. -export interface WorkspaceResource { - readonly type: string +// From codersdk/workspaces.go:94:6 +export interface UpdateWorkspaceAutostartRequest { + readonly schedule: string +} + +// From codersdk/workspaces.go:114:6 +export interface UpdateWorkspaceAutostopRequest { + readonly schedule: string +} + +// From codersdk/files.go:16:6 +export interface UploadResponse { + readonly hash: string +} + +// From codersdk/users.go:39:6 +export interface User { + readonly id: string + readonly email: string + readonly created_at: string + readonly username: string + readonly status: UserStatus + readonly organization_ids: string[] +} + +// From codersdk/users.go:17:6 +export interface UsersRequest { + readonly after_user: string + readonly search: string + readonly limit: number + readonly offset: number +} + +// From codersdk/workspaces.go:18:6 +export interface Workspace { + readonly id: string + readonly created_at: string + readonly updated_at: string + readonly owner_id: string + readonly template_id: string + readonly template_name: string + readonly latest_build: WorkspaceBuild + readonly outdated: boolean readonly name: string + readonly autostart_schedule: string + readonly autostop_schedule: string } -// From codersdk/workspaceresources.go:33:6. +// From codersdk/workspaceresources.go:33:6 export interface WorkspaceAgent { + readonly id: string + readonly created_at: string + readonly updated_at: string + readonly first_connected_at?: string + readonly last_connected_at?: string + readonly disconnected_at?: string readonly status: WorkspaceAgentStatus readonly name: string + readonly resource_id: string readonly instance_id: string readonly architecture: string + readonly environment_variables: Record readonly operating_system: string readonly startup_script: string } -// From codersdk/workspaceresources.go:50:6. -export interface WorkspaceAgentResourceMetadata { - readonly memory_total: number - readonly disk_total: number - readonly cpu_cores: number - readonly cpu_model: string - readonly cpu_mhz: number +// From codersdk/workspaceagents.go:47:6 +export interface WorkspaceAgentAuthenticateResponse { + readonly session_token: string } -// From codersdk/workspaceresources.go:58:6. +// From codersdk/workspaceresources.go:58:6 export interface WorkspaceAgentInstanceMetadata { readonly jail_orchestrator: string readonly operating_system: string @@ -204,39 +335,51 @@ export interface WorkspaceAgentInstanceMetadata { readonly vnc: boolean } -// From codersdk/workspaces.go:18:6. -export interface Workspace { - readonly template_name: string - readonly latest_build: WorkspaceBuild - readonly outdated: boolean - readonly name: string - readonly autostart_schedule: string - readonly autostop_schedule: string -} - -// From codersdk/workspaces.go:33:6. -export interface CreateWorkspaceBuildRequest { - readonly dry_run: boolean +// From codersdk/workspaceresources.go:50:6 +export interface WorkspaceAgentResourceMetadata { + readonly memory_total: number + readonly disk_total: number + readonly cpu_cores: number + readonly cpu_model: string + readonly cpu_mhz: number } -// From codersdk/workspaces.go:94:6. -export interface UpdateWorkspaceAutostartRequest { - readonly schedule: string +// From codersdk/workspacebuilds.go:17:6 +export interface WorkspaceBuild { + readonly id: string + readonly created_at: string + readonly updated_at: string + readonly workspace_id: string + readonly template_version_id: string + readonly before_id: string + readonly after_id: string + readonly name: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.WorkspaceTransition") + readonly transition: string + readonly initiator_id: string + readonly job: ProvisionerJob } -// From codersdk/workspaces.go:114:6. -export interface UpdateWorkspaceAutostopRequest { - readonly schedule: string +// From codersdk/workspaceresources.go:23:6 +export interface WorkspaceResource { + readonly id: string + readonly created_at: string + readonly job_id: string + // This is likely an enum in an external package ("github.com/coder/coder/coderd/database.WorkspaceTransition") + readonly workspace_transition: string + readonly type: string + readonly name: string + readonly agents: WorkspaceAgent[] } -// From codersdk/parameters.go:16:6. +// From codersdk/parameters.go:16:6 export type ParameterScope = "organization" | "template" | "user" | "workspace" -// From codersdk/provisionerdaemons.go:26:6. -export type ProvisionerJobStatus = "pending" | "running" | "succeeded" | "canceling" | "canceled" | "failed" +// From codersdk/provisionerdaemons.go:26:6 +export type ProvisionerJobStatus = "canceled" | "canceling" | "failed" | "pending" | "running" | "succeeded" -// From codersdk/users.go:31:6. +// From codersdk/users.go:31:6 export type UserStatus = "active" | "suspended" -// From codersdk/workspaceresources.go:15:6. -export type WorkspaceAgentStatus = "connecting" | "connected" | "disconnected" +// From codersdk/workspaceresources.go:15:6 +export type WorkspaceAgentStatus = "connected" | "connecting" | "disconnected"