Skip to content
Prev Previous commit
Next Next commit
wip: still trying to generate types with guts
  • Loading branch information
brettkolodny committed May 31, 2025
commit 46d876263826a726eee04bb516f08f099ed5c57b
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ build/preview.wasm: $(GO_SRC_FILES)
.PHONY: gen-types
gen-types: src/gen/types.ts

src/gen/types.ts: preview/scripts/types/main.go
src/gen/types.ts: preview/scripts/types/main.go preview/apitypes/apitypes.go
mkdir -p src/gen
go run -C ./preview/scripts/types main.go > $@
touch "$@"
5 changes: 5 additions & 0 deletions preview/apitypes/apitypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ type PreviewOutput struct {
// invalid terraform syntax.
ParserLogs string `json:"parser_logs,omitempty"`
}

type NullHCLString struct {
Value string `json:"value"`
Valid bool `json:"valid"`
}
61 changes: 57 additions & 4 deletions preview/scripts/types/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"log"

"github.com/coder/guts"
"github.com/coder/guts/bindings"
"github.com/coder/guts/config"
"golang.org/x/xerrors"
)

func main() {
Expand All @@ -14,14 +16,14 @@ func main() {
log.Fatalf("new convert: %v", err)
}

err = gen.IncludeGenerateWithPrefix("github.com/coder/parameters-playground/preview/apitypes", "PreviewOutput")
err = gen.IncludeGenerate("github.com/coder/parameters-playground/preview/apitypes")
if err != nil {
log.Fatalf("include generate: %v", err)
}

referencePackages := map[string]string{
"github.com/coder/preview": "Output",
"github.com/coder/preview/types": "Diagnostics",
"github.com/coder/preview/types": "FriendlyDiagnostic",
"github.com/hashicorp/hcl/v2": "File",
"github.com/hashicorp/hcl/v2/hclwrite": "Expression",
"github.com/zclconf/go-cty/cty": "Value",
Expand All @@ -35,11 +37,17 @@ func main() {
log.Fatalf("include reference package %q: %v", pkg, err)
}
}
// err = gen.IncludeReference("github.com/hashicorp/hcl/v2", "Expression")

// err = gen.IncludeReference("github.com/coder/preview/types", "FriendlyDiagnostic")
// if err != nil {
// log.Fatalf("include reference package %q: %v", "github.com/hashicorp/hcl/v2", "FileExpression")
// log.Fatalf("include reference package %q: %v", "github.com/coder/preview/types", err)
// }

err = typeMappings(gen)
if err != nil {
log.Fatalf("type mappings: %v", err)
}

ts, err := gen.ToTypescript()
ts.ApplyMutations(config.ExportTypes)

Expand All @@ -49,3 +57,48 @@ func main() {

fmt.Println(ts.Serialize())
}

func typeMappings(gen *guts.GoParser) error {
gen.IncludeCustomDeclaration(config.StandardMappings())

gen.IncludeCustomDeclaration(map[string]guts.TypeOverride{
"github.com/coder/coder/v2/codersdk.NullTime": config.OverrideNullable(config.OverrideLiteral(bindings.KeywordString)),
// opt.Bool can return 'null' if unset
"tailscale.com/types/opt.Bool": config.OverrideNullable(config.OverrideLiteral(bindings.KeywordBoolean)),
// hcl diagnostics should be cast to `preview.FriendlyDiagnostic`
"github.com/hashicorp/hcl/v2.Diagnostic": func() bindings.ExpressionType {
return bindings.Reference(bindings.Identifier{
Name: "FriendlyDiagnostic",
Package: nil,
Prefix: "",
})
},
"github.com/coder/preview/types.HCLString": func() bindings.ExpressionType {
return bindings.Reference(bindings.Identifier{
Name: "NullHCLString",
Package: nil,
Prefix: "",
})
},
})

err := gen.IncludeCustom(map[string]string{
// Serpent fields should be converted to their primitive types
"github.com/coder/serpent.Regexp": "string",
"github.com/coder/serpent.StringArray": "string",
"github.com/coder/serpent.String": "string",
"github.com/coder/serpent.YAMLConfigPath": "string",
"github.com/coder/serpent.Strings": "[]string",
"github.com/coder/serpent.Int64": "int64",
"github.com/coder/serpent.Bool": "bool",
"github.com/coder/serpent.Duration": "int64",
"github.com/coder/serpent.URL": "string",
"github.com/coder/serpent.HostPort": "string",
"encoding/json.RawMessage": "map[string]string",
})
if err != nil {
return xerrors.Errorf("include custom: %w", err)
}

return nil
}
115 changes: 115 additions & 0 deletions src/gen/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Code generated by 'guts'. DO NOT EDIT.

// From terraform/block.go
export interface BlockBlock {
}

// From hcl/structure.go
export interface FileFile {
Body: FileBody;
Bytes: string;
// empty interface{} type, falling back to unknown
Nav: unknown;
}

// From types/diagnostics.go
export type FriendlyDiagnosticDiagnostics = (FriendlyDiagnostic | null)[];

// From types/parameter.go
export interface FriendlyDiagnosticParameter extends FriendlyDiagnosticParameterData {
value: NullHCLString;
diagnostics: FriendlyDiagnosticDiagnostics;
}

// From types/parameter.go
export interface FriendlyDiagnosticParameterData {
name: string;
display_name: string;
description: string;
type: FriendlyDiagnosticParameterType;
form_type: ParameterFormTypeParameterFormType;
styling: FriendlyDiagnosticParameterStyling;
mutable: boolean;
default_value: NullHCLString;
icon: string;
options: (FriendlyDiagnosticParameterOption | null)[];
validations: (FriendlyDiagnosticParameterValidation | null)[];
required: boolean;
order: number;
ephemeral: boolean;
}

// From types/parameter.go
export interface FriendlyDiagnosticParameterOption {
name: string;
description: string;
value: NullHCLString;
icon: string;
}

// From types/parameter.go
export interface FriendlyDiagnosticParameterStyling {
placeholder?: string | null;
disabled?: boolean | null;
label?: string | null;
}

// From types/enum.go
export type FriendlyDiagnosticParameterType = string;

// From types/parameter.go
export interface FriendlyDiagnosticParameterValidation {
validation_error: string;
validation_regex: string | null;
validation_min: number | null;
validation_max: number | null;
validation_monotonic: string | null;
}

// From types/tags.go
export interface FriendlyDiagnosticTag {
Key: NullHCLString;
Value: NullHCLString;
}

// From types/tags.go
export interface FriendlyDiagnosticTagBlock {
Tags: FriendlyDiagnosticTags;
Block: BlockBlock | null;
}

// From types/tags.go
export type FriendlyDiagnosticTagBlocks = FriendlyDiagnosticTagBlock[];

// From types/tags.go
export type FriendlyDiagnosticTags = FriendlyDiagnosticTag[];

// From apitypes/apitypes.go
export interface NullHCLString {
value: string;
valid: boolean;
}

// From preview/preview.go
export interface OutputOutput {
ModuleOutput: ValueValue;
Parameters: FriendlyDiagnosticParameter[];
WorkspaceTags: FriendlyDiagnosticTagBlocks;
Files: Record<string, FileFile | null> | null;
}

// From provider/formtype.go
export type ParameterFormTypeParameterFormType = string;

// From apitypes/apitypes.go
export interface PreviewOutput {
output: OutputOutput | null;
diags: FriendlyDiagnosticDiagnostics;
parser_logs?: string;
}

// From cty/value.go
export interface ValueValue {
}

<nil>