-
Notifications
You must be signed in to change notification settings - Fork 881
feat: generate typescript types from codersdk structs #1047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
175e9c2
670e7b7
1a04052
e25d5af
7f93018
23e36fc
1db1432
c430a2d
a511f6a
e31f2af
b5c2f27
733a17e
3b11dc3
4e65142
3ddbf42
4d97ec4
fdedb03
a1f5044
0bc5e2b
a7e1dcb
64e3102
89c8b2b
ae2940f
7b63673
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"go/ast" | ||
"go/parser" | ||
"go/token" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"golang.org/x/xerrors" | ||
) | ||
|
||
const ( | ||
baseDir = "./codersdk" | ||
) | ||
|
||
func main() { | ||
err := run() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
func run() error { | ||
fset := token.NewFileSet() | ||
entries, err := os.ReadDir(baseDir) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, entry := range entries { | ||
goFile, err := parser.ParseFile(fset, filepath.Join(baseDir, entry.Name()), nil, 0) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, node := range goFile.Decls { | ||
switch node.(type) { | ||
|
||
case *ast.GenDecl: | ||
genDecl := node.(*ast.GenDecl) | ||
for _, spec := range genDecl.Specs { | ||
switch spec.(type) { | ||
case *ast.TypeSpec: | ||
typeSpec := spec.(*ast.TypeSpec) | ||
s, err := writeStruct(typeSpec) | ||
if err != nil { | ||
continue | ||
} | ||
|
||
fmt.Printf(s) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func writeStruct(typeSpec *ast.TypeSpec) (string, error) { | ||
s := fmt.Sprintf("export interface %s {\n", typeSpec.Name.Name) | ||
jsonFields := 0 | ||
switch typeSpec.Type.(type) { | ||
case *ast.StructType: | ||
structType := typeSpec.Type.(*ast.StructType) | ||
for _, field := range structType.Fields.List { | ||
i, ok := field.Type.(*ast.Ident) | ||
if !ok { | ||
continue | ||
} | ||
fieldType := i.Name | ||
fieldName := "" | ||
if field.Tag != nil && field.Tag.Value != "" { | ||
for _, pair := range strings.Split(field.Tag.Value, " ") { | ||
if strings.HasPrefix(pair, "`json:\"") { | ||
fieldName = strings.TrimPrefix(pair, "`json:\"") | ||
fieldName = strings.Split(fieldName, ",")[0] | ||
fieldName = strings.TrimSuffix(fieldName, "`") | ||
fieldName = strings.TrimSuffix(fieldName, "\"") | ||
break | ||
} | ||
} | ||
} | ||
if fieldName == "" { | ||
break | ||
} | ||
|
||
s = fmt.Sprintf("%s %s: %s\n", s, fieldName, fieldType) | ||
jsonFields++ | ||
} | ||
default: | ||
return "", xerrors.New("not struct") | ||
} | ||
|
||
if jsonFields == 0 { | ||
return "", xerrors.New("no json fields") | ||
} | ||
|
||
return fmt.Sprintf("%s}\n\n", s), nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
export interface BuildInfoResponse { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could make these link directly to the Go files too... could be neat for documentation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Working on generating docs, may happen in this PR or a follow up. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added the doc codelines There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is cool af |
||
external_url: string | ||
version: string | ||
} | ||
|
||
export interface UploadResponse { | ||
hash: string | ||
} | ||
|
||
export interface GitSSHKey { | ||
public_key: string | ||
} | ||
|
||
export interface AgentGitSSHKey { | ||
private_key: string | ||
} | ||
|
||
export interface Organization { | ||
name: string | ||
} | ||
|
||
export interface CreateTemplateVersionRequest { | ||
storage_source: string | ||
} | ||
|
||
export interface CreateTemplateRequest { | ||
name: string | ||
} | ||
|
||
export interface CreateParameterRequest { | ||
name: string | ||
source_value: string | ||
} | ||
|
||
export interface ProvisionerJob { | ||
error: string | ||
status: ProvisionerJobStatus | ||
} | ||
|
||
export interface ProvisionerJobLog { | ||
stage: string | ||
output: string | ||
} | ||
|
||
export interface Template { | ||
name: string | ||
workspace_owner_count: uint32 | ||
} | ||
|
||
export interface TemplateVersion { | ||
name: string | ||
job: ProvisionerJob | ||
} | ||
|
||
export interface User { | ||
email: string | ||
username: string | ||
name: string | ||
} | ||
|
||
export interface CreateFirstUserRequest { | ||
email: string | ||
username: string | ||
password: string | ||
organization: string | ||
} | ||
|
||
export interface CreateUserRequest { | ||
email: string | ||
username: string | ||
password: string | ||
} | ||
|
||
export interface UpdateUserProfileRequest { | ||
email: string | ||
username: string | ||
} | ||
|
||
export interface LoginWithPasswordRequest { | ||
email: string | ||
password: string | ||
} | ||
|
||
export interface LoginWithPasswordResponse { | ||
session_token: string | ||
} | ||
|
||
export interface GenerateAPIKeyResponse { | ||
key: string | ||
} | ||
|
||
export interface CreateOrganizationRequest { | ||
name: string | ||
} | ||
|
||
export interface CreateWorkspaceRequest { | ||
name: string | ||
} | ||
|
||
export interface GoogleInstanceIdentityToken { | ||
json_web_token: string | ||
} | ||
|
||
export interface AWSInstanceIdentityToken { | ||
signature: string | ||
document: string | ||
} | ||
|
||
export interface WorkspaceAgentAuthenticateResponse { | ||
session_token: string | ||
} | ||
|
||
export interface WorkspaceBuild { | ||
name: string | ||
job: ProvisionerJob | ||
} | ||
|
||
export interface WorkspaceResource { | ||
type: string | ||
name: string | ||
} | ||
|
||
export interface WorkspaceAgent { | ||
status: WorkspaceAgentStatus | ||
name: string | ||
instance_id: string | ||
architecture: string | ||
operating_system: string | ||
startup_script: string | ||
} | ||
|
||
export interface WorkspaceAgentResourceMetadata { | ||
memory_total: uint64 | ||
disk_total: uint64 | ||
cpu_cores: uint64 | ||
cpu_model: string | ||
cpu_mhz: float64 | ||
} | ||
|
||
export interface WorkspaceAgentInstanceMetadata { | ||
jail_orchestrator: string | ||
operating_system: string | ||
platform: string | ||
platform_family: string | ||
kernel_version: string | ||
kernel_architecture: string | ||
cloud: string | ||
jail: string | ||
vnc: bool | ||
} | ||
|
||
export interface Workspace { | ||
template_name: string | ||
latest_build: WorkspaceBuild | ||
outdated: bool | ||
name: string | ||
autostart_schedule: string | ||
autostop_schedule: string | ||
} | ||
|
||
export interface CreateWorkspaceBuildRequest { | ||
dry_run: bool | ||
} | ||
|
||
export interface UpdateWorkspaceAutostartRequest { | ||
schedule: string | ||
} | ||
|
||
export interface UpdateWorkspaceAutostopRequest { | ||
schedule: string | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just put this in
cmd/typings
or something?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that but think this fits much more as a "generate.sh" type of script. I connected it to our make gen command, which I think fits nicer than making it a top level command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It breaks the idiom of all commands being inside the
cmd
folder. We have the DataDog CI report helper inscripts/datadog-cireport
, so it could be there too!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's not a command it's just a script that happens to be go. I'll move to scripts if we want. Is this really any different than the scripts in the
coderd/database
package? Or should those move intoscripts
as well ideally?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
dump
should totally move into scripts too. It's just nice to know whether a package should be imported or not based on folder structure.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool I moved it