diff --git a/cmd/tsconnect/README.md b/cmd/tsconnect/README.md index fc01876a3..bb4dddfe6 100644 --- a/cmd/tsconnect/README.md +++ b/cmd/tsconnect/README.md @@ -38,3 +38,12 @@ The client is also available as an NPM package. To build it, run: ``` That places the output in the `pkg/` directory, which may then be uploaded to a package registry (or installed from the file path directly). + +To do two-sided development (on both the NPM package and code that uses it), run: + +``` +./tool/go run ./cmd/tsconnect dev-pkg + +``` + +This serves the module at http://localhost:9090/pkg/pkg.js and the generated wasm file at http://localhost:9090/pkg/main.wasm. The two files can be used as drop-in replacements for normal imports of the NPM module. diff --git a/cmd/tsconnect/build-pkg.go b/cmd/tsconnect/build-pkg.go index 26700d192..e0220b42f 100644 --- a/cmd/tsconnect/build-pkg.go +++ b/cmd/tsconnect/build-pkg.go @@ -11,13 +11,12 @@ import ( "os" "path" - esbuild "github.com/evanw/esbuild/pkg/api" "github.com/tailscale/hujson" "tailscale.com/version" ) func runBuildPkg() { - buildOptions, err := commonSetup(prodMode) + buildOptions, err := commonPkgSetup(prodMode) if err != nil { log.Fatalf("Cannot setup: %v", err) } @@ -31,10 +30,6 @@ func runBuildPkg() { log.Fatalf("Cannot clean %s: %v", *pkgDir, err) } - buildOptions.EntryPoints = []string{"src/pkg/pkg.ts", "src/pkg/pkg.css"} - buildOptions.Outdir = *pkgDir - buildOptions.Format = esbuild.FormatESModule - buildOptions.AssetNames = "[name]" buildOptions.Write = true buildOptions.MinifyWhitespace = true buildOptions.MinifyIdentifiers = true diff --git a/cmd/tsconnect/common.go b/cmd/tsconnect/common.go index da823829a..bea345902 100644 --- a/cmd/tsconnect/common.go +++ b/cmd/tsconnect/common.go @@ -8,6 +8,7 @@ import ( "fmt" "io/ioutil" "log" + "net" "os" "os/exec" "path" @@ -68,6 +69,18 @@ func commonSetup(dev bool) (*esbuild.BuildOptions, error) { }, nil } +func commonPkgSetup(dev bool) (*esbuild.BuildOptions, error) { + buildOptions, err := commonSetup(dev) + if err != nil { + return nil, err + } + buildOptions.EntryPoints = []string{"src/pkg/pkg.ts", "src/pkg/pkg.css"} + buildOptions.Outdir = *pkgDir + buildOptions.Format = esbuild.FormatESModule + buildOptions.AssetNames = "[name]" + return buildOptions, nil +} + // cleanDir removes files from dirPath, except the ones specified by // preserveFiles. func cleanDir(dirPath string, preserveFiles ...string) error { @@ -90,6 +103,27 @@ func cleanDir(dirPath string, preserveFiles ...string) error { return nil } +func runEsbuildServe(buildOptions esbuild.BuildOptions) { + host, portStr, err := net.SplitHostPort(*addr) + if err != nil { + log.Fatalf("Cannot parse addr: %v", err) + } + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + log.Fatalf("Cannot parse port: %v", err) + } + result, err := esbuild.Serve(esbuild.ServeOptions{ + Port: uint16(port), + Host: host, + Servedir: "./", + }, buildOptions) + if err != nil { + log.Fatalf("Cannot start esbuild server: %v", err) + } + log.Printf("Listening on http://%s:%d\n", result.Host, result.Port) + result.Wait() +} + func runEsbuild(buildOptions esbuild.BuildOptions) esbuild.BuildResult { log.Printf("Running esbuild...\n") result := esbuild.Build(buildOptions) diff --git a/cmd/tsconnect/dev-pkg.go b/cmd/tsconnect/dev-pkg.go new file mode 100644 index 000000000..f66290bf4 --- /dev/null +++ b/cmd/tsconnect/dev-pkg.go @@ -0,0 +1,17 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "log" +) + +func runDevPkg() { + buildOptions, err := commonPkgSetup(devMode) + if err != nil { + log.Fatalf("Cannot setup: %v", err) + } + runEsbuildServe(*buildOptions) +} diff --git a/cmd/tsconnect/dev.go b/cmd/tsconnect/dev.go index 4cbe6dfed..c2a264cea 100644 --- a/cmd/tsconnect/dev.go +++ b/cmd/tsconnect/dev.go @@ -6,10 +6,6 @@ package main import ( "log" - "net" - "strconv" - - esbuild "github.com/evanw/esbuild/pkg/api" ) func runDev() { @@ -17,22 +13,5 @@ func runDev() { if err != nil { log.Fatalf("Cannot setup: %v", err) } - host, portStr, err := net.SplitHostPort(*addr) - if err != nil { - log.Fatalf("Cannot parse addr: %v", err) - } - port, err := strconv.ParseUint(portStr, 10, 16) - if err != nil { - log.Fatalf("Cannot parse port: %v", err) - } - result, err := esbuild.Serve(esbuild.ServeOptions{ - Port: uint16(port), - Host: host, - Servedir: "./", - }, *buildOptions) - if err != nil { - log.Fatalf("Cannot start esbuild server: %v", err) - } - log.Printf("Listening on http://%s:%d\n", result.Host, result.Port) - result.Wait() + runEsbuildServe(*buildOptions) } diff --git a/cmd/tsconnect/tsconnect.go b/cmd/tsconnect/tsconnect.go index 91feaf727..6719e45dd 100644 --- a/cmd/tsconnect/tsconnect.go +++ b/cmd/tsconnect/tsconnect.go @@ -36,6 +36,8 @@ func main() { switch flag.Arg(0) { case "dev": runDev() + case "dev-pkg": + runDevPkg() case "build": runBuild() case "build-pkg":