cmd/tsconnect: add dev-pkg command for two-sided development

Allows imports of the NPM package added by 1a093ef482
to be replaced with import("http://localhost:9090/pkg/pkg.js"), so that
changes can be made in parallel to both the module and code that uses
it (without any need for NPM publishing or even building of the package).

Updates #5415

Signed-off-by: Mihai Parparita <mihai@tailscale.com>
pull/5566/head
Mihai Parparita 2 years ago committed by Mihai Parparita
parent 672c2c8de8
commit 2f702b150e

@ -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). 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.

@ -11,13 +11,12 @@ import (
"os" "os"
"path" "path"
esbuild "github.com/evanw/esbuild/pkg/api"
"github.com/tailscale/hujson" "github.com/tailscale/hujson"
"tailscale.com/version" "tailscale.com/version"
) )
func runBuildPkg() { func runBuildPkg() {
buildOptions, err := commonSetup(prodMode) buildOptions, err := commonPkgSetup(prodMode)
if err != nil { if err != nil {
log.Fatalf("Cannot setup: %v", err) log.Fatalf("Cannot setup: %v", err)
} }
@ -31,10 +30,6 @@ func runBuildPkg() {
log.Fatalf("Cannot clean %s: %v", *pkgDir, err) 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.Write = true
buildOptions.MinifyWhitespace = true buildOptions.MinifyWhitespace = true
buildOptions.MinifyIdentifiers = true buildOptions.MinifyIdentifiers = true

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net"
"os" "os"
"os/exec" "os/exec"
"path" "path"
@ -68,6 +69,18 @@ func commonSetup(dev bool) (*esbuild.BuildOptions, error) {
}, nil }, 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 // cleanDir removes files from dirPath, except the ones specified by
// preserveFiles. // preserveFiles.
func cleanDir(dirPath string, preserveFiles ...string) error { func cleanDir(dirPath string, preserveFiles ...string) error {
@ -90,6 +103,27 @@ func cleanDir(dirPath string, preserveFiles ...string) error {
return nil 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 { func runEsbuild(buildOptions esbuild.BuildOptions) esbuild.BuildResult {
log.Printf("Running esbuild...\n") log.Printf("Running esbuild...\n")
result := esbuild.Build(buildOptions) result := esbuild.Build(buildOptions)

@ -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)
}

@ -6,10 +6,6 @@ package main
import ( import (
"log" "log"
"net"
"strconv"
esbuild "github.com/evanw/esbuild/pkg/api"
) )
func runDev() { func runDev() {
@ -17,22 +13,5 @@ func runDev() {
if err != nil { if err != nil {
log.Fatalf("Cannot setup: %v", err) log.Fatalf("Cannot setup: %v", err)
} }
host, portStr, err := net.SplitHostPort(*addr) runEsbuildServe(*buildOptions)
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()
} }

@ -36,6 +36,8 @@ func main() {
switch flag.Arg(0) { switch flag.Arg(0) {
case "dev": case "dev":
runDev() runDev()
case "dev-pkg":
runDevPkg()
case "build": case "build":
runBuild() runBuild()
case "build-pkg": case "build-pkg":

Loading…
Cancel
Save