mirror of
https://github.com/wavetermdev/wails.git
synced 2026-04-22 15:26:15 -07:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b3a9332a5b | |||
| e91b7832ee | |||
| 0d25edc0c4 | |||
| eb36258c73 | |||
| bdb138d42c | |||
| abe6f520b4 | |||
| 130fab6c01 | |||
| b5f1eab59b | |||
| 5988cdca9a | |||
| 93d7c6b5f3 | |||
| 7d28ad1a3b | |||
| a7278b4224 | |||
| e2b7b68ec9 | |||
| 47af68a8cb | |||
| 77f053068c | |||
| e3edea1cb3 | |||
| a0b7eb4ab6 |
@@ -22,12 +22,12 @@ jobs:
|
||||
website/**/*.json
|
||||
|
||||
- name: Set node
|
||||
if: steps.verify-changed-files.outputs.files_changed != 'true'
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Push files
|
||||
if: steps.verify-changed-files.outputs.files_changed == 'true'
|
||||
env:
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
run: |
|
||||
|
||||
@@ -97,6 +97,7 @@ This project is supported by these kind people / companies:
|
||||
<p align="center">
|
||||
<img src="https://wails.io/img/sponsor/jetbrains-grayscale.webp" style="width: 100px"/>
|
||||
</p>
|
||||
|
||||
## FAQ
|
||||
|
||||
- Is this an alternative to Electron?
|
||||
|
||||
@@ -1 +1 @@
|
||||
v2.4.0
|
||||
v2.4.1
|
||||
@@ -78,7 +78,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -88,6 +87,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
@@ -166,10 +166,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
}
|
||||
result.assets = assets
|
||||
|
||||
// Start 10 processors to handle requests in parallel
|
||||
for i := 0; i < 10; i++ {
|
||||
go result.startRequestProcessor()
|
||||
}
|
||||
go result.startRequestProcessor()
|
||||
}
|
||||
|
||||
go result.startMessageProcessor()
|
||||
@@ -461,50 +458,16 @@ func processMessage(message *C.char) {
|
||||
messageBuffer <- goMessage
|
||||
}
|
||||
|
||||
var requestBuffer = make(chan unsafe.Pointer, 100)
|
||||
var requestBuffer = make(chan webview.Request, 100)
|
||||
|
||||
func (f *Frontend) startRequestProcessor() {
|
||||
for request := range requestBuffer {
|
||||
f.processRequest(request)
|
||||
C.g_object_unref(C.gpointer(request))
|
||||
f.assets.ServeWebViewRequest(request)
|
||||
request.Release()
|
||||
}
|
||||
}
|
||||
|
||||
//export processURLRequest
|
||||
func processURLRequest(request unsafe.Pointer) {
|
||||
// Increment reference counter to allow async processing, will be decremented after the processing
|
||||
// has been finished by a worker.
|
||||
C.g_object_ref(C.gpointer(request))
|
||||
requestBuffer <- request
|
||||
}
|
||||
|
||||
func (f *Frontend) processRequest(request unsafe.Pointer) {
|
||||
req := (*C.WebKitURISchemeRequest)(request)
|
||||
uri := C.webkit_uri_scheme_request_get_uri(req)
|
||||
goURI := C.GoString(uri)
|
||||
|
||||
rw := &webKitResponseWriter{req: req}
|
||||
defer rw.Close()
|
||||
|
||||
f.assets.ProcessHTTPRequestLegacy(
|
||||
rw,
|
||||
func() (*http.Request, error) {
|
||||
method := webkit_uri_scheme_request_get_http_method(req)
|
||||
r, err := http.NewRequest(method, goURI, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.Header = webkit_uri_scheme_request_get_http_headers(req)
|
||||
|
||||
if r.URL.Host != f.startURL.Host {
|
||||
if r.Body != nil {
|
||||
r.Body.Close()
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Expected host '%s' in request, but was '%s'", f.startURL.Host, r.URL.Host)
|
||||
}
|
||||
|
||||
return r, nil
|
||||
})
|
||||
|
||||
requestBuffer <- webview.NewRequest(request)
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/linux"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||
)
|
||||
|
||||
func validateWebKit2Version(options *options.App) {
|
||||
if C.webkit_get_major_version() == 2 && C.webkit_get_minor_version() >= webkit2MinMinorVersion {
|
||||
if C.webkit_get_major_version() == 2 && C.webkit_get_minor_version() >= webview.Webkit2MinMinorVersion {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -24,6 +26,6 @@ func validateWebKit2Version(options *options.App) {
|
||||
msg = options.Linux.Messages
|
||||
}
|
||||
|
||||
v := fmt.Sprintf("2.%d.0", webkit2MinMinorVersion)
|
||||
v := fmt.Sprintf("2.%d.0", webview.Webkit2MinMinorVersion)
|
||||
showModalDialogAndExit("WebKit2GTK", fmt.Sprintf(msg.WebKit2GTKMinRequired, v))
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ window.wails = {
|
||||
defaultCursor: null,
|
||||
borderThickness: 6,
|
||||
shouldDrag: false,
|
||||
deferDragToMouseMove: false,
|
||||
deferDragToMouseMove: true,
|
||||
cssDragProperty: "--wails-draggable",
|
||||
cssDragValue: "drag",
|
||||
}
|
||||
@@ -130,7 +130,7 @@ window.addEventListener('mousedown', (e) => {
|
||||
}
|
||||
}
|
||||
if (window.wails.flags.deferDragToMouseMove) {
|
||||
window.wails.flags.shouldDrag = true;
|
||||
window.wails.flags.shouldDrag = true;
|
||||
} else {
|
||||
e.preventDefault()
|
||||
window.WailsInvoke("drag");
|
||||
@@ -152,10 +152,9 @@ function setResize(cursor) {
|
||||
|
||||
window.addEventListener('mousemove', function (e) {
|
||||
if (window.wails.flags.shouldDrag) {
|
||||
window.wails.flags.shouldDrag = false;
|
||||
let mousePressed = e.buttons !== undefined ? e.buttons : e.which;
|
||||
if(mousePressed <= 0) {
|
||||
window.wails.flags.shouldDrag = false;
|
||||
} else {
|
||||
if (mousePressed > 0) {
|
||||
window.WailsInvoke("drag");
|
||||
return;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,85 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package webview
|
||||
|
||||
/*
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
|
||||
|
||||
#include "gtk/gtk.h"
|
||||
#include "webkit2/webkit2.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// NewRequest creates as new WebViewRequest based on a pointer to an `WebKitURISchemeRequest`
|
||||
//
|
||||
// Please make sure to call Release() when finished using the request.
|
||||
func NewRequest(webKitURISchemeRequest unsafe.Pointer) Request {
|
||||
webkitReq := (*C.WebKitURISchemeRequest)(webKitURISchemeRequest)
|
||||
req := &request{req: webkitReq}
|
||||
req.AddRef()
|
||||
return req
|
||||
}
|
||||
|
||||
var _ Request = &request{}
|
||||
|
||||
type request struct {
|
||||
req *C.WebKitURISchemeRequest
|
||||
|
||||
header http.Header
|
||||
body io.ReadCloser
|
||||
rw *responseWriter
|
||||
}
|
||||
|
||||
func (r *request) AddRef() error {
|
||||
C.g_object_ref(C.gpointer(r.req))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) Release() error {
|
||||
C.g_object_unref(C.gpointer(r.req))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) URL() (string, error) {
|
||||
return C.GoString(C.webkit_uri_scheme_request_get_uri(r.req)), nil
|
||||
}
|
||||
|
||||
func (r *request) Method() (string, error) {
|
||||
return webkit_uri_scheme_request_get_http_method(r.req), nil
|
||||
}
|
||||
|
||||
func (r *request) Header() (http.Header, error) {
|
||||
if r.header != nil {
|
||||
return r.header, nil
|
||||
}
|
||||
|
||||
r.header = webkit_uri_scheme_request_get_http_headers(r.req)
|
||||
return r.header, nil
|
||||
}
|
||||
|
||||
func (r *request) Body() (io.ReadCloser, error) {
|
||||
if r.body != nil {
|
||||
return r.body, nil
|
||||
}
|
||||
|
||||
// WebKit2GTK has currently no support for request bodies.
|
||||
r.body = http.NoBody
|
||||
|
||||
return r.body, nil
|
||||
}
|
||||
|
||||
func (r *request) Response() ResponseWriter {
|
||||
if r.rw != nil {
|
||||
return r.rw
|
||||
}
|
||||
|
||||
r.rw = &responseWriter{req: r.req}
|
||||
return r.rw
|
||||
}
|
||||
@@ -1,9 +1,20 @@
|
||||
package webview
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderContentLength = "Content-Length"
|
||||
HeaderContentType = "Content-Type"
|
||||
)
|
||||
|
||||
var (
|
||||
errRequestStopped = errors.New("request has been stopped")
|
||||
errResponseFinished = errors.New("response has been finished")
|
||||
)
|
||||
|
||||
// A ResponseWriter interface is used by an HTTP handler to
|
||||
// construct an HTTP response for the WebView.
|
||||
type ResponseWriter interface {
|
||||
|
||||
@@ -69,16 +69,10 @@ import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
errRequestStopped = errors.New("request has been stopped")
|
||||
errResponseFinished = errors.New("response has been finished")
|
||||
)
|
||||
|
||||
var _ ResponseWriter = &responseWriter{}
|
||||
|
||||
type responseWriter struct {
|
||||
|
||||
+24
-12
@@ -1,7 +1,7 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package linux
|
||||
package webview
|
||||
|
||||
/*
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
|
||||
@@ -20,28 +20,31 @@ import (
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
)
|
||||
|
||||
type webKitResponseWriter struct {
|
||||
type responseWriter struct {
|
||||
req *C.WebKitURISchemeRequest
|
||||
|
||||
header http.Header
|
||||
wroteHeader bool
|
||||
finished bool
|
||||
|
||||
w io.WriteCloser
|
||||
wErr error
|
||||
}
|
||||
|
||||
func (rw *webKitResponseWriter) Header() http.Header {
|
||||
func (rw *responseWriter) Header() http.Header {
|
||||
if rw.header == nil {
|
||||
rw.header = http.Header{}
|
||||
}
|
||||
return rw.header
|
||||
}
|
||||
|
||||
func (rw *webKitResponseWriter) Write(buf []byte) (int, error) {
|
||||
func (rw *responseWriter) Write(buf []byte) (int, error) {
|
||||
if rw.finished {
|
||||
return 0, errResponseFinished
|
||||
}
|
||||
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
if rw.wErr != nil {
|
||||
return 0, rw.wErr
|
||||
@@ -49,14 +52,14 @@ func (rw *webKitResponseWriter) Write(buf []byte) (int, error) {
|
||||
return rw.w.Write(buf)
|
||||
}
|
||||
|
||||
func (rw *webKitResponseWriter) WriteHeader(code int) {
|
||||
if rw.wroteHeader {
|
||||
func (rw *responseWriter) WriteHeader(code int) {
|
||||
if rw.wroteHeader || rw.finished {
|
||||
return
|
||||
}
|
||||
rw.wroteHeader = true
|
||||
|
||||
contentLength := int64(-1)
|
||||
if sLen := rw.Header().Get(assetserver.HeaderContentLength); sLen != "" {
|
||||
if sLen := rw.Header().Get(HeaderContentLength); sLen != "" {
|
||||
if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 {
|
||||
contentLength = pLen
|
||||
}
|
||||
@@ -72,7 +75,7 @@ func (rw *webKitResponseWriter) WriteHeader(code int) {
|
||||
}
|
||||
rw.w = w
|
||||
|
||||
stream := C.g_unix_input_stream_new(C.int(rFD), gtkBool(true))
|
||||
stream := C.g_unix_input_stream_new(C.int(rFD), C.gboolean(1))
|
||||
defer C.g_object_unref(C.gpointer(stream))
|
||||
|
||||
if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil {
|
||||
@@ -81,13 +84,22 @@ func (rw *webKitResponseWriter) WriteHeader(code int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *webKitResponseWriter) Close() {
|
||||
func (rw *responseWriter) Finish() error {
|
||||
if !rw.wroteHeader {
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
if rw.finished {
|
||||
return nil
|
||||
}
|
||||
rw.finished = true
|
||||
if rw.w != nil {
|
||||
rw.w.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rw *webKitResponseWriter) finishWithError(code int, err error) {
|
||||
func (rw *responseWriter) finishWithError(code int, err error) {
|
||||
if rw.w != nil {
|
||||
rw.w.Close()
|
||||
rw.w = &nopCloser{io.Discard}
|
||||
+3
-5
@@ -1,6 +1,6 @@
|
||||
//go:build linux && webkit2_36
|
||||
|
||||
package linux
|
||||
package webview
|
||||
|
||||
/*
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
|
||||
@@ -15,11 +15,9 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
)
|
||||
|
||||
const webkit2MinMinorVersion = 36
|
||||
const Webkit2MinMinorVersion = 36
|
||||
|
||||
func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
|
||||
method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
|
||||
@@ -51,7 +49,7 @@ func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, h
|
||||
C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
|
||||
C.free(unsafe.Pointer(cReason))
|
||||
|
||||
cMimeType := C.CString(header.Get(assetserver.HeaderContentType))
|
||||
cMimeType := C.CString(header.Get(HeaderContentType))
|
||||
C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
|
||||
C.free(unsafe.Pointer(cMimeType))
|
||||
|
||||
+3
-5
@@ -1,6 +1,6 @@
|
||||
//go:build linux && !webkit2_36
|
||||
|
||||
package linux
|
||||
package webview
|
||||
|
||||
/*
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
|
||||
@@ -14,11 +14,9 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"unsafe"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||
)
|
||||
|
||||
const webkit2MinMinorVersion = 0
|
||||
const Webkit2MinMinorVersion = 0
|
||||
|
||||
func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) string {
|
||||
return http.MethodGet
|
||||
@@ -33,7 +31,7 @@ func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, h
|
||||
return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code))
|
||||
}
|
||||
|
||||
cMimeType := C.CString(header.Get(assetserver.HeaderContentType))
|
||||
cMimeType := C.CString(header.Get(HeaderContentType))
|
||||
C.webkit_uri_scheme_request_finish(req, stream, C.gint64(streamLength), cMimeType)
|
||||
C.free(unsafe.Pointer(cMimeType))
|
||||
return nil
|
||||
@@ -53,10 +53,10 @@ This package contains the static analyser used for parsing Wails projects so tha
|
||||
- [x] Recursive
|
||||
- [x] Anonymous
|
||||
- [ ] Generation of models
|
||||
- [ ] Scalars
|
||||
- [x] Scalars
|
||||
- [ ] Arrays
|
||||
- [ ] Maps
|
||||
- [ ] Structs
|
||||
- [x] Structs
|
||||
- [ ] Generation of bindings
|
||||
|
||||
## Limitations
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
@@ -35,13 +37,34 @@ const modelsHeader = `// @ts-check
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
`
|
||||
|
||||
func pkgAlias(fullPkg string) string {
|
||||
pkgParts := strings.Split(fullPkg, "/")
|
||||
return pkgParts[len(pkgParts)-1]
|
||||
}
|
||||
|
||||
func GenerateModels(models map[packagePath]map[structName]*StructDef) (string, error) {
|
||||
if models == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString(modelsHeader)
|
||||
for pkg, pkgModels := range models {
|
||||
|
||||
// sort pkgs by alias (e.g. services) instead of full pkg name (e.g. github.com/wailsapp/wails/somedir/services)
|
||||
// and then sort resulting list by the alias
|
||||
var keys []string
|
||||
for pkg, _ := range models {
|
||||
keys = append(keys, pkg)
|
||||
}
|
||||
|
||||
sort.Slice(keys, func(i, j int) bool {
|
||||
return pkgAlias(keys[i]) < pkgAlias(keys[j])
|
||||
})
|
||||
|
||||
for _, pkg := range keys {
|
||||
err := GenerateModel(&buffer, &ModelDefinitions{
|
||||
Package: pkg,
|
||||
Models: pkgModels,
|
||||
Package: pkgAlias(pkg),
|
||||
Models: models[pkg],
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -2,132 +2,76 @@ package parser
|
||||
|
||||
import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"strings"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const expected = `
|
||||
export namespace main {
|
||||
|
||||
export class Person {
|
||||
name: string;
|
||||
parent: Person;
|
||||
details: anon1;
|
||||
address: package.Address;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Person(source);
|
||||
}
|
||||
func TestGenerateModels(t *testing.T) {
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) {
|
||||
source = JSON.parse(source);
|
||||
}
|
||||
|
||||
this.name = source["name"]
|
||||
this.parent = source["parent"]
|
||||
this.details = source["details"]
|
||||
this.address = source["address"]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export class anon1 {
|
||||
age: int;
|
||||
address: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new anon1(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) {
|
||||
source = JSON.parse(source);
|
||||
}
|
||||
|
||||
this.age = source["age"]
|
||||
this.address = source["address"]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
`
|
||||
|
||||
func TestGenerateClass(t *testing.T) {
|
||||
person := StructDef{
|
||||
Name: "Person",
|
||||
Fields: []*Field{
|
||||
{
|
||||
Name: "Name",
|
||||
Type: &ParameterType{
|
||||
Name: "string",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Parent",
|
||||
Type: &ParameterType{
|
||||
Name: "Person",
|
||||
IsStruct: true,
|
||||
IsPointer: true,
|
||||
Package: "main",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Details",
|
||||
Type: &ParameterType{
|
||||
Name: "anon1",
|
||||
IsStruct: true,
|
||||
Package: "main",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Address",
|
||||
Type: &ParameterType{
|
||||
Name: "Address",
|
||||
IsStruct: true,
|
||||
IsPointer: true,
|
||||
Package: "github.com/some/other/package",
|
||||
},
|
||||
},
|
||||
tests := []struct {
|
||||
dir string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
"testdata/function_single",
|
||||
"",
|
||||
},
|
||||
}
|
||||
anon1 := StructDef{
|
||||
Name: "anon1",
|
||||
Fields: []*Field{
|
||||
{
|
||||
Name: "Age",
|
||||
Type: &ParameterType{
|
||||
Name: "int",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Address",
|
||||
Type: &ParameterType{
|
||||
Name: "string",
|
||||
},
|
||||
},
|
||||
{
|
||||
"testdata/function_from_imported_package",
|
||||
getFile("testdata/function_from_imported_package/models.ts"),
|
||||
},
|
||||
{
|
||||
"testdata/variable_single",
|
||||
"",
|
||||
},
|
||||
{
|
||||
"testdata/variable_single_from_function",
|
||||
"",
|
||||
},
|
||||
{
|
||||
"testdata/variable_single_from_other_function",
|
||||
getFile("testdata/variable_single_from_other_function/models.ts"),
|
||||
},
|
||||
{
|
||||
"testdata/struct_literal_single",
|
||||
getFile("testdata/struct_literal_single/models.ts"),
|
||||
},
|
||||
{
|
||||
"testdata/struct_literal_multiple",
|
||||
"",
|
||||
},
|
||||
{
|
||||
"testdata/struct_literal_multiple_other",
|
||||
getFile("testdata/struct_literal_multiple_other/models.ts"),
|
||||
},
|
||||
{
|
||||
"testdata/struct_literal_multiple_files",
|
||||
"",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.dir, func(t *testing.T) {
|
||||
// Run parser on directory
|
||||
project, err := ParseProject(tt.dir)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseProject() error = %v", err)
|
||||
}
|
||||
|
||||
var builder strings.Builder
|
||||
models := make(map[string]*StructDef)
|
||||
models["Person"] = &person
|
||||
models["anon1"] = &anon1
|
||||
def := ModelDefinitions{
|
||||
Package: "main",
|
||||
Models: models,
|
||||
}
|
||||
// Generate Models
|
||||
got, err := GenerateModels(project.Models)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateModels() error = %v", err)
|
||||
}
|
||||
|
||||
err := GenerateModel(&builder, &def)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
text := builder.String()
|
||||
println("Built string")
|
||||
println(text)
|
||||
if diff := cmp.Diff(expected, text); diff != "" {
|
||||
t.Errorf("GenerateClass() failed:\n" + diff)
|
||||
if diff := cmp.Diff(tt.want, got); diff != "" {
|
||||
err = os.WriteFile(filepath.Join(tt.dir, "models.got.ts"), []byte(got), 0644)
|
||||
if err != nil {
|
||||
t.Errorf("os.WriteFile() error = %v", err)
|
||||
return
|
||||
}
|
||||
t.Fatalf("GenerateModels() mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,16 +90,39 @@ func (f *Field) JSName() string {
|
||||
return strings.ToLower(f.Name[0:1]) + f.Name[1:]
|
||||
}
|
||||
|
||||
func (f *Field) JSDef(pkg string) string {
|
||||
name := f.JSName()
|
||||
|
||||
var result string
|
||||
// TSBuild contains the typescript to build a field for a JS object
|
||||
// via assignment for simple types or constructors for structs
|
||||
func (f *Field) TSBuild(pkg string) string {
|
||||
if !f.Type.IsStruct {
|
||||
return fmt.Sprintf("source['%s']", f.JSName())
|
||||
}
|
||||
|
||||
if f.Type.Package == "" || f.Type.Package == pkg {
|
||||
result += fmt.Sprintf("%s: %s;", name, f.Type.Name)
|
||||
return fmt.Sprintf("%s.createFrom(source['%s'])", f.Type.Name, f.JSName())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s.%s.createFrom(source['%s'])", pkgAlias(f.Type.Package), f.Type.Name, f.JSName())
|
||||
}
|
||||
|
||||
func (f *Field) JSDef(pkg string) string {
|
||||
var jsType string
|
||||
switch f.Type.Name {
|
||||
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64":
|
||||
jsType = "number"
|
||||
case "string":
|
||||
jsType = "string"
|
||||
case "bool":
|
||||
jsType = "boolean"
|
||||
default:
|
||||
jsType = f.Type.Name
|
||||
}
|
||||
|
||||
var result string
|
||||
if f.Type.Package == "" || f.Type.Package == pkg {
|
||||
result += fmt.Sprintf("%s: %s;", f.JSName(), jsType)
|
||||
} else {
|
||||
parts := strings.Split(f.Type.Package, "/")
|
||||
result += fmt.Sprintf("%s: %s.%s;", name, parts[len(parts)-1], f.Type.Name)
|
||||
result += fmt.Sprintf("%s: %s.%s;", f.JSName(), parts[len(parts)-1], jsType)
|
||||
}
|
||||
|
||||
if !ast.IsExported(f.Name) {
|
||||
|
||||
@@ -13,7 +13,7 @@ export namespace {{.Package}} {
|
||||
source = JSON.parse(source);
|
||||
}
|
||||
|
||||
{{range $def.Fields}}this.{{.JSName}} = source["{{.JSName}}"]
|
||||
{{range $def.Fields}}this.{{.JSName}} = {{.TSBuild $pkg}};
|
||||
{{end}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Ă‚ MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
export namespace main {
|
||||
|
||||
export class Person {
|
||||
name: string;
|
||||
address: services.Address;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Person(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) {
|
||||
source = JSON.parse(source);
|
||||
}
|
||||
|
||||
this.name = source['name'];
|
||||
this.address = services.Address.createFrom(source['address']);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace services {
|
||||
|
||||
export class Address {
|
||||
street: string;
|
||||
state: string;
|
||||
country: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Address(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) {
|
||||
source = JSON.parse(source);
|
||||
}
|
||||
|
||||
this.street = source['street'];
|
||||
this.state = source['state'];
|
||||
this.country = source['country'];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user