diff --git a/v2/cmd/wails/generate.go b/v2/cmd/wails/generate.go index 15a6b33d868..2f0ef10c8c5 100644 --- a/v2/cmd/wails/generate.go +++ b/v2/cmd/wails/generate.go @@ -48,11 +48,12 @@ func generateModule(f *flags.GenerateModule) error { } _, err = bindings.GenerateBindings(bindings.Options{ - Compiler: f.Compiler, - Tags: buildTags, - TsPrefix: projectConfig.Bindings.TsGeneration.Prefix, - TsSuffix: projectConfig.Bindings.TsGeneration.Suffix, - TsOutputType: projectConfig.Bindings.TsGeneration.OutputType, + Compiler: f.Compiler, + Tags: buildTags, + TsPrefix: projectConfig.Bindings.TsGeneration.Prefix, + TsSuffix: projectConfig.Bindings.TsGeneration.Suffix, + TsOutputType: projectConfig.Bindings.TsGeneration.OutputType, + GenerateAllExportedFields: projectConfig.Bindings.GenerateAllExportedFields, }) if err != nil { return err diff --git a/v2/internal/app/app_bindings.go b/v2/internal/app/app_bindings.go index be031819c65..56e5c4451f0 100644 --- a/v2/internal/app/app_bindings.go +++ b/v2/internal/app/app_bindings.go @@ -4,9 +4,6 @@ package app import ( "flag" - "os" - "path/filepath" - "github.com/leaanthony/gosod" "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend/runtime/wrapper" @@ -14,6 +11,9 @@ import ( "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/project" "github.com/wailsapp/wails/v2/pkg/options" + "os" + "path/filepath" + "strconv" ) func (a *App) Run() error { @@ -32,6 +32,7 @@ func (a *App) Run() error { var tsPrefixFlag *string var tsPostfixFlag *string var tsOutputTypeFlag *string + var generateallexportedfieldsFlag *bool tsPrefix := os.Getenv("tsprefix") if tsPrefix == "" { @@ -48,6 +49,17 @@ func (a *App) Run() error { tsOutputTypeFlag = bindingFlags.String("tsoutputtype", "", "Output type for generated typescript entities (classes|interfaces)") } + generateallexportedfields := os.Getenv("generateallexportedfields") + if generateallexportedfields != "" { + value, err := strconv.ParseBool(generateallexportedfields) + if err != nil { + return err + } + generateallexportedfieldsFlag = bindingFlags.Bool("generateallexportedfields", value, "Generate bindings for all exported fields") + } else { + generateallexportedfieldsFlag = bindingFlags.Bool("generateallexportedfields", false, "Generate bindings for all exported fields") + } + _ = bindingFlags.Parse(os.Args[1:]) if tsPrefixFlag != nil { tsPrefix = *tsPrefixFlag @@ -64,6 +76,7 @@ func (a *App) Run() error { appBindings.SetTsPrefix(tsPrefix) appBindings.SetTsSuffix(tsSuffix) appBindings.SetOutputType(tsOutputType) + appBindings.SetGenerateAllExportedFields(*generateallexportedfieldsFlag) err := generateBindings(appBindings) if err != nil { diff --git a/v2/internal/binding/binding.go b/v2/internal/binding/binding.go index b42718bffd2..1c4e3721d46 100644 --- a/v2/internal/binding/binding.go +++ b/v2/internal/binding/binding.go @@ -22,12 +22,13 @@ type Bindings struct { logger logger.CustomLogger exemptions slicer.StringSlicer - structsToGenerateTS map[string]map[string]interface{} - enumsToGenerateTS map[string]map[string]interface{} - tsPrefix string - tsSuffix string - tsInterface bool - obfuscate bool + structsToGenerateTS map[string]map[string]interface{} + enumsToGenerateTS map[string]map[string]interface{} + tsPrefix string + tsSuffix string + tsInterface bool + obfuscate bool + generateAllExportedFields bool } // NewBindings returns a new Bindings object @@ -106,6 +107,7 @@ func (b *Bindings) GenerateModels() ([]byte, error) { w.WithPrefix(b.tsPrefix) w.WithSuffix(b.tsSuffix) w.WithInterface(b.tsInterface) + w.GenerateAllExportedFields = b.generateAllExportedFields w.Namespace = packageName w.WithBackupDir("") w.KnownStructs = allStructNames @@ -137,7 +139,6 @@ func (b *Bindings) GenerateModels() ([]byte, error) { } seenEnumsPackages.Add(packageName) } - str, err := w.Convert(nil) if err != nil { return nil, err @@ -158,6 +159,7 @@ func (b *Bindings) GenerateModels() ([]byte, error) { w.WithPrefix(b.tsPrefix) w.WithSuffix(b.tsSuffix) w.WithInterface(b.tsInterface) + w.GenerateAllExportedFields = b.generateAllExportedFields w.Namespace = packageName w.WithBackupDir("") @@ -326,6 +328,11 @@ func (b *Bindings) SetOutputType(outputType string) *Bindings { return b } +func (b *Bindings) SetGenerateAllExportedFields(generateAllExportedFields bool) *Bindings { + b.generateAllExportedFields = generateAllExportedFields + return b +} + func (b *Bindings) getAllStructNames() *slicer.StringSlicer { var result slicer.StringSlicer for packageName, structsToGenerate := range b.structsToGenerateTS { @@ -351,8 +358,13 @@ func (b *Bindings) hasExportedJSONFields(typeOf reflect.Type) bool { jsonFieldName := "" f := typeOf.Field(i) jsonTag, hasTag := f.Tag.Lookup("json") - if !hasTag && f.IsExported() { - return true + if !hasTag { + // If we're generating all exported fields and the field is exported, + // consider it as a valid JSON field + if b.generateAllExportedFields && f.IsExported() { + return true + } + continue } if len(jsonTag) == 0 { continue diff --git a/v2/internal/project/project.go b/v2/internal/project/project.go index a1de1b9433c..060b9a0ca42 100644 --- a/v2/internal/project/project.go +++ b/v2/internal/project/project.go @@ -238,7 +238,8 @@ type Protocol struct { } type Bindings struct { - TsGeneration TsGeneration `json:"ts_generation"` + TsGeneration TsGeneration `json:"ts_generation"` + GenerateAllExportedFields bool `json:"generate_all_exported_fields"` } type TsGeneration struct { diff --git a/v2/internal/typescriptify/typescriptify.go b/v2/internal/typescriptify/typescriptify.go index 1d22a1b65d7..14df98bc71f 100644 --- a/v2/internal/typescriptify/typescriptify.go +++ b/v2/internal/typescriptify/typescriptify.go @@ -105,6 +105,8 @@ type TypeScriptify struct { Namespace string KnownStructs *slicer.StringSlicer KnownEnums *slicer.StringSlicer + + GenerateAllExportedFields bool } func New() *TypeScriptify { @@ -554,10 +556,14 @@ func (t *TypeScriptify) getFieldOptions(structType reflect.Type, field reflect.S func (t *TypeScriptify) getJSONFieldName(field reflect.StructField, isPtr bool) string { jsonFieldName := "" jsonTag, hasTag := field.Tag.Lookup("json") - if !hasTag && field.IsExported() { - jsonFieldName = field.Name - if isPtr { - jsonFieldName += "?" + if !hasTag { + // If we're generating all exported fields and the field is exported, + // consider it as a valid JSON field + if t.GenerateAllExportedFields && field.IsExported() { + jsonFieldName = field.Name + if isPtr { + jsonFieldName += "?" + } } } if len(jsonTag) > 0 { diff --git a/v2/pkg/commands/bindings/bindings.go b/v2/pkg/commands/bindings/bindings.go index d1c8d60bfb1..1b1c5da91cb 100644 --- a/v2/pkg/commands/bindings/bindings.go +++ b/v2/pkg/commands/bindings/bindings.go @@ -15,16 +15,17 @@ import ( // Options for generating bindings type Options struct { - Filename string - Tags []string - ProjectDirectory string - Compiler string - GoModTidy bool - Platform string - Arch string - TsPrefix string - TsSuffix string - TsOutputType string + Filename string + Tags []string + ProjectDirectory string + Compiler string + GoModTidy bool + Platform string + Arch string + TsPrefix string + TsSuffix string + TsOutputType string + GenerateAllExportedFields bool } // GenerateBindings generates bindings for the Wails project in the given ProjectDirectory. @@ -82,6 +83,7 @@ func GenerateBindings(options Options) (string, error) { env = shell.SetEnv(env, "tsprefix", options.TsPrefix) env = shell.SetEnv(env, "tssuffix", options.TsSuffix) env = shell.SetEnv(env, "tsoutputtype", options.TsOutputType) + env = shell.SetEnv(env, "generateallexportedfields", fmt.Sprintf("%v", options.GenerateAllExportedFields)) stdout, stderr, err = shell.RunCommandWithEnv(env, workingDirectory, filename) if err != nil { diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go index f247f2db180..e99cceea9ba 100644 --- a/v2/pkg/commands/build/build.go +++ b/v2/pkg/commands/build/build.go @@ -228,14 +228,15 @@ func GenerateBindings(buildOptions *Options) error { // Generate Bindings output, err := bindings.GenerateBindings(bindings.Options{ - Compiler: buildOptions.Compiler, - Tags: buildOptions.UserTags, - GoModTidy: !buildOptions.SkipModTidy, - Platform: buildOptions.Platform, - Arch: buildOptions.Arch, - TsPrefix: buildOptions.ProjectData.Bindings.TsGeneration.Prefix, - TsSuffix: buildOptions.ProjectData.Bindings.TsGeneration.Suffix, - TsOutputType: buildOptions.ProjectData.Bindings.TsGeneration.OutputType, + Compiler: buildOptions.Compiler, + Tags: buildOptions.UserTags, + GoModTidy: !buildOptions.SkipModTidy, + Platform: buildOptions.Platform, + Arch: buildOptions.Arch, + TsPrefix: buildOptions.ProjectData.Bindings.TsGeneration.Prefix, + TsSuffix: buildOptions.ProjectData.Bindings.TsGeneration.Suffix, + TsOutputType: buildOptions.ProjectData.Bindings.TsGeneration.OutputType, + GenerateAllExportedFields: buildOptions.ProjectData.Bindings.GenerateAllExportedFields, }) if err != nil { return err diff --git a/website/docs/reference/project-config.mdx b/website/docs/reference/project-config.mdx index 3a6f09495a0..0ade2558f72 100644 --- a/website/docs/reference/project-config.mdx +++ b/website/docs/reference/project-config.mdx @@ -109,6 +109,8 @@ The project config resides in the `wails.json` file in the project directory. Th "garbleargs": "", // Bindings configurations "bindings": { + // Whether to generate all exported fields regardless of if they have JSON tags + "generate_all_exported_fields": false, // model.ts file generation config "ts_generation": { // All generated JavaScript entities will be prefixed with this value diff --git a/website/static/schemas/config.v2.json b/website/static/schemas/config.v2.json index 7a6d26f1509..d704cb7c8d8 100644 --- a/website/static/schemas/config.v2.json +++ b/website/static/schemas/config.v2.json @@ -256,6 +256,11 @@ "type": "object", "description": "Bindings configurations", "properties": { + "generate_all_exported_fields": { + "type": "boolean", + "default": false, + "description": "When set to true, all exported fields will be generated, even if they have no JSON tag." + }, "ts_generation": { "type": "object", "description": "model.ts file generation config",