diff --git a/v2/internal/binding/binding_test/binding_test.go b/v2/internal/binding/binding_test/binding_test.go index 0b143db17..c2e351915 100644 --- a/v2/internal/binding/binding_test/binding_test.go +++ b/v2/internal/binding/binding_test/binding_test.go @@ -39,6 +39,8 @@ func TestBindings_GenerateModels(t *testing.T) { GeneratedJsEntityTest, AnonymousSubStructTest, AnonymousSubStructMultiLevelTest, + GeneratedJsEntityWithNestedStructTest, + EntityWithDiffNamespaces, } testLogger := &logger.Logger{} @@ -50,8 +52,6 @@ func TestBindings_GenerateModels(t *testing.T) { require.NoError(t, err) } b.SetTsPrefix(tt.TsPrefix) - - // TODO - rename this to SetTsSuffix b.SetTsSuffix(tt.TsSuffix) got, err := b.GenerateModels() if (err != nil) != tt.shouldError { diff --git a/v2/internal/binding/binding_test/binding_tsgeneration_test.go b/v2/internal/binding/binding_test/binding_tsgeneration_test.go index b808ad9c6..d2c5349c5 100644 --- a/v2/internal/binding/binding_test/binding_tsgeneration_test.go +++ b/v2/internal/binding/binding_test/binding_tsgeneration_test.go @@ -1,5 +1,9 @@ package binding_test +import ( + "github.com/wailsapp/wails/v2/internal/binding/binding_test/binding_test_import" +) + type GeneratedJsEntity struct { Name string `json:"name"` } @@ -9,7 +13,7 @@ func (s GeneratedJsEntity) Get() GeneratedJsEntity { } var GeneratedJsEntityTest = BindingTest{ - name: "GeneratedJsEntityTest ", + name: "GeneratedJsEntityTest", structs: []interface{}{ &GeneratedJsEntity{}, }, @@ -39,3 +43,235 @@ export namespace binding_test { `, } + +type ParentEntity struct { + Name string `json:"name"` + Ref ChildEntity `json:"ref"` + ParentProp string `json:"parentProp"` +} + +func (p ParentEntity) Get() ParentEntity { + return p +} + +type ChildEntity struct { + Name string `json:"name"` + ChildProp int `json:"childProp"` +} + +var GeneratedJsEntityWithNestedStructTest = BindingTest{ + name: "GeneratedJsEntityWithNestedStructTest", + structs: []interface{}{ + &ParentEntity{}, + }, + exemptions: nil, + shouldError: false, + TsGenerationOptionsTest: TsGenerationOptionsTest{ + TsPrefix: "MY_PREFIX_", + TsSuffix: "_MY_SUFFIX", + }, + want: ` +export namespace binding_test { + + export class MY_PREFIX_ChildEntity_MY_SUFFIX { + name: string; + childProp: number; + + static createFrom(source: any = {}) { + return new MY_PREFIX_ChildEntity_MY_SUFFIX(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.childProp = source["childProp"]; + } + } + export class MY_PREFIX_ParentEntity_MY_SUFFIX { + name: string; + ref: MY_PREFIX_ChildEntity_MY_SUFFIX; + parentProp: string; + + static createFrom(source: any = {}) { + return new MY_PREFIX_ParentEntity_MY_SUFFIX(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.ref = this.convertValues(source["ref"], MY_PREFIX_ChildEntity_MY_SUFFIX); + this.parentProp = source["parentProp"]; + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + + } +`, +} + +type ParentPackageEntity struct { + Name string `json:"name"` + Ref ChildPackageEntity `json:"ref"` +} + +func (p ParentPackageEntity) Get() ParentPackageEntity { + return p +} + +type ChildPackageEntity struct { + Name string `json:"name"` + ImportedPackage binding_test_import.AWrapper `json:"importedPackage"` +} + +var EntityWithDiffNamespaces = BindingTest{ + name: "EntityWithDiffNamespaces ", + structs: []interface{}{ + &ParentPackageEntity{}, + }, + exemptions: nil, + shouldError: false, + TsGenerationOptionsTest: TsGenerationOptionsTest{ + TsPrefix: "MY_PREFIX_", + TsSuffix: "_MY_SUFFIX", + }, + want: ` +export namespace binding_test { + + export class MY_PREFIX_ChildPackageEntity_MY_SUFFIX { + name: string; + importedPackage: binding_test_import.MY_PREFIX_AWrapper_MY_SUFFIX; + + static createFrom(source: any = {}) { + return new MY_PREFIX_ChildPackageEntity_MY_SUFFIX(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.importedPackage = this.convertValues(source["importedPackage"], binding_test_import.MY_PREFIX_AWrapper_MY_SUFFIX); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + export class MY_PREFIX_ParentPackageEntity_MY_SUFFIX { + name: string; + ref: MY_PREFIX_ChildPackageEntity_MY_SUFFIX; + + static createFrom(source: any = {}) { + return new MY_PREFIX_ParentPackageEntity_MY_SUFFIX(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.ref = this.convertValues(source["ref"], MY_PREFIX_ChildPackageEntity_MY_SUFFIX); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + + } + + export namespace binding_test_import { + + export class MY_PREFIX_AWrapper_MY_SUFFIX { + AWrapper: binding_test_nestedimport.MY_PREFIX_A_MY_SUFFIX; + + static createFrom(source: any = {}) { + return new MY_PREFIX_AWrapper_MY_SUFFIX(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.AWrapper = this.convertValues(source["AWrapper"], binding_test_nestedimport.MY_PREFIX_A_MY_SUFFIX); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + + } + + export namespace binding_test_nestedimport { + + export class MY_PREFIX_A_MY_SUFFIX { + A: string; + + static createFrom(source: any = {}) { + return new MY_PREFIX_A_MY_SUFFIX(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.A = source["A"]; + } + } + + } + +`, +} diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go index 8109a73af..6513f293f 100644 --- a/v2/internal/binding/generate.go +++ b/v2/internal/binding/generate.go @@ -74,7 +74,8 @@ func (b *Bindings) GenerateGoBindings(baseDir string) error { args.Clear() for count, input := range methodDetails.Inputs { arg := fmt.Sprintf("arg%d", count+1) - args.Add(arg + ":" + goTypeToTypescriptType(input.TypeName, &importNamespaces)) + entityName := entityFullReturnType(input.TypeName, b.tsPrefix, b.tsSuffix, &importNamespaces) + args.Add(arg + ":" + goTypeToTypescriptType(entityName, &importNamespaces)) } tsBody.WriteString(args.Join(",") + "):") // now build Typescript return types diff --git a/v2/internal/typescriptify/typescriptify.go b/v2/internal/typescriptify/typescriptify.go index c30b6bf83..b14059a51 100644 --- a/v2/internal/typescriptify/typescriptify.go +++ b/v2/internal/typescriptify/typescriptify.go @@ -839,13 +839,11 @@ func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.St func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect.StructField, isAnyType bool) { strippedFieldName := strings.ReplaceAll(fieldName, "?", "") - fqname := field.Type.Name() classname := "null" - namespace := strings.Split(field.Type.String(), ".")[0] - + fqname := t.prefix + field.Type.Name() + t.suffix if namespace != t.namespace { - fqname = field.Type.String() + fqname = namespace + "." + fqname } if !isAnyType { @@ -892,6 +890,7 @@ func (t *typeScriptClassBuilder) addField(fld, fldType string, isAnyType bool) { } } if isAnyType { + fldType = strings.Split(fldType, ".")[0] t.fields = append(t.fields, fmt.Sprint(t.indent, "// Go type: ", fldType, "\n", t.indent, fld, ": any;")) } else { t.fields = append(t.fields, fmt.Sprint(t.indent, fld, ": ", fldType, ";"))