Skip to content

Add support for functions, arbitrary tag names and exporting all types#1

Draft
gwennlbh wants to merge 5 commits intoolahol:mainfrom
ortfo:main
Draft

Add support for functions, arbitrary tag names and exporting all types#1
gwennlbh wants to merge 5 commits intoolahol:mainfrom
ortfo:main

Conversation

@gwennlbh
Copy link
Copy Markdown

@gwennlbh gwennlbh commented Apr 20, 2024

Hi! I'm using this package to automatically generate types of bound functions in a webview desktop app.

Essentially, the webview allows exposing to frontend (JS) code functions that run on the Go backend.

With this package, the frontend code can very easily have typedefinitions for the bound functions with zero effort.

Obviously, since I need to use this patch right now (and vendoring packages seems complicated when using go workspaces), this PR contains a change that renames the module

--- a/go.mod
+++ b/go.mod
@@ -1,2 +1,2 @@
-module github.com/olahol/tsreflect
+module github.com/ortfo/tsreflect

... i'll remove it before merging (if you want to merge this) ^^

Thanks a bunch for this package! It's a real time saver! :D

This PR adds three things:

  • support for adding functions with (*tsreflect.Generator).AddFunc(typ, name, async, implementation?) where:
    • name is the function's name (since it's not stored in typ)
    • async can be set to true to mark the function as asynchronous (this generates async function name(...): Promise<...> instead of function name(...): ...
    • implementation (optional argument) is a string with source code, useful when the implementation is easy, like in my use case. Adds a body to the function: export function ... { ... } instead of export function ...
  • a new option to export all types and functions by adding the export keyword before interface / function: tsreflect.ExportEverything
  • allowing tags other than json to take precedence when naming struct fields: in my use case, I have also yaml tags on some structs since they are (un)marshaled from and to YAML files. sometimes there are both YAML and JSON tags, when they differ, sometimes not. For now YAML is hardcoded but I plan to make another option: tsreflect.UseTags(names... string) that takes tag names, in their order of priority (last elements are used as fallback when the elements before are not tag names on the structs' fields)

Note that error values in the return types are handled correctly, they are elided from the generated code, since they should, in their typescript implementation, be translated into throws

Note also: I haven't done the jsdoc part yet, but I suppose errors could be added there as a @throws, but appart from adding @throws {Error} i can't see where we would get more specific info

TODO:

  • JSDoc generation
  • Documentation of all functions
  • Implementation of WithStructTags

@gwennlbh
Copy link
Copy Markdown
Author

gwennlbh commented Apr 20, 2024

Exemple usage in my project (see https://github.com/ortfo/gui/blob/e248e2c73baf5f1900e7e970766f6e25066b453a/backend/main.go#L284)

typescript := tsreflect.New(tsreflect.ExportEverything())

// ... //

for name, function := range BackendFunctions {
	// binds the function to the webview
	w.Bind(fmt.Sprintf("backend__%s", name), function)

	// Generate comma-separated list of arguments for the call (looks like "arg0, arg1," etc)
	argslist := ""
	for i := 0; i < reflect.TypeOf(function).NumIn(); i++ {
		if i > 0 {
			argslist += ", "
		}
		argslist += fmt.Sprintf("arg%d", i)
	}

	typescript.AddFunc(
		reflect.TypeOf(function), 
		name, 
		true, 
		fmt.Sprintf("return backend__%s(%s);", name, argslist)
	)
}

wd, _ := os.Getwd()
os.WriteFile(filepath.Join(wd, "../frontend/backend.generated.ts"), []byte(typescript.DeclarationsTypeScript()), 0644)

Where BackendFunctions is a map of function names to their definitions (https://github.com/ortfo/gui/blob/e248e2c73baf5f1900e7e970766f6e25066b453a/backend/main.go#L73)

The output generated file looks like this: https://github.com/ortfo/gui/blob/e248e2c73baf5f1900e7e970766f6e25066b453a/frontend/backend.generated.ts#L20

@gwennlbh
Copy link
Copy Markdown
Author

btw I can split this into 3 PRs if you prefer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant