feat(codegen): add TypeScript CLI output
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
12a7d2497b
commit
a928d01b9e
3 changed files with 46 additions and 13 deletions
|
|
@ -1,14 +1,16 @@
|
|||
//go:build !js
|
||||
|
||||
// Package main provides a build-time CLI for generating Web Component JS bundles.
|
||||
// Reads a JSON slot map from stdin, writes the generated JS to stdout.
|
||||
// Package main provides a build-time CLI for generating Web Component bundles.
|
||||
// Reads a JSON slot map from stdin, writes the generated JS or TypeScript to stdout.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// echo '{"H":"nav-bar","C":"main-content"}' | go run ./cmd/codegen/ > components.js
|
||||
// echo '{"H":"nav-bar","C":"main-content"}' | go run ./cmd/codegen/ -types > components.d.ts
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
goio "io"
|
||||
"os"
|
||||
|
||||
|
|
@ -18,7 +20,7 @@ import (
|
|||
log "dappco.re/go/core/log"
|
||||
)
|
||||
|
||||
func run(r goio.Reader, w goio.Writer) error {
|
||||
func run(r goio.Reader, w goio.Writer, emitTypes bool) error {
|
||||
data, err := goio.ReadAll(r)
|
||||
if err != nil {
|
||||
return log.E("codegen", "reading stdin", err)
|
||||
|
|
@ -30,19 +32,27 @@ func run(r goio.Reader, w goio.Writer) error {
|
|||
return log.E("codegen", "invalid JSON", err)
|
||||
}
|
||||
|
||||
js, err := codegen.GenerateBundle(slots)
|
||||
if err != nil {
|
||||
return log.E("codegen", "generate bundle", err)
|
||||
out := ""
|
||||
if emitTypes {
|
||||
out = codegen.GenerateTypeScriptDefinitions(slots)
|
||||
} else {
|
||||
out, err = codegen.GenerateBundle(slots)
|
||||
if err != nil {
|
||||
return log.E("codegen", "generate bundle", err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = goio.WriteString(w, js)
|
||||
_, err = goio.WriteString(w, out)
|
||||
if err != nil {
|
||||
return log.E("codegen", "writing bundle", err)
|
||||
return log.E("codegen", "writing output", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
emitTypes := flag.Bool("types", false, "emit TypeScript declarations instead of JavaScript")
|
||||
flag.Parse()
|
||||
|
||||
stdin, err := coreio.Local.Open("/dev/stdin")
|
||||
if err != nil {
|
||||
log.Error("failed to open stdin", "scope", "codegen.main", "err", log.E("codegen.main", "open stdin", err))
|
||||
|
|
@ -60,7 +70,7 @@ func main() {
|
|||
_ = stdout.Close()
|
||||
}()
|
||||
|
||||
if err := run(stdin, stdout); err != nil {
|
||||
if err := run(stdin, stdout, *emitTypes); err != nil {
|
||||
log.Error("codegen failed", "scope", "codegen.main", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ func TestRun_WritesBundle_Good(t *testing.T) {
|
|||
input := core.NewReader(`{"H":"nav-bar","C":"main-content"}`)
|
||||
output := core.NewBuilder()
|
||||
|
||||
err := run(input, output)
|
||||
err := run(input, output, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
js := output.String()
|
||||
|
|
@ -28,7 +28,7 @@ func TestRun_InvalidJSON_Bad(t *testing.T) {
|
|||
input := core.NewReader(`not json`)
|
||||
output := core.NewBuilder()
|
||||
|
||||
err := run(input, output)
|
||||
err := run(input, output, false)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid JSON")
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ func TestRun_InvalidTag_Bad(t *testing.T) {
|
|||
input := core.NewReader(`{"H":"notag"}`)
|
||||
output := core.NewBuilder()
|
||||
|
||||
err := run(input, output)
|
||||
err := run(input, output, false)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "hyphen")
|
||||
}
|
||||
|
|
@ -46,11 +46,26 @@ func TestRun_EmptySlots_Good(t *testing.T) {
|
|||
input := core.NewReader(`{}`)
|
||||
output := core.NewBuilder()
|
||||
|
||||
err := run(input, output)
|
||||
err := run(input, output, false)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, output.String())
|
||||
}
|
||||
|
||||
func TestRun_WritesTypeScriptDefinitions_Good(t *testing.T) {
|
||||
input := core.NewReader(`{"H":"nav-bar","C":"main-content"}`)
|
||||
output := core.NewBuilder()
|
||||
|
||||
err := run(input, output, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
dts := output.String()
|
||||
assert.Contains(t, dts, "declare global")
|
||||
assert.Contains(t, dts, `"nav-bar": NavBar;`)
|
||||
assert.Contains(t, dts, `"main-content": MainContent;`)
|
||||
assert.Contains(t, dts, "export declare class NavBar extends HTMLElement")
|
||||
assert.Contains(t, dts, "export declare class MainContent extends HTMLElement")
|
||||
}
|
||||
|
||||
func countSubstr(s, substr string) int {
|
||||
if substr == "" {
|
||||
return len(s) + 1
|
||||
|
|
|
|||
|
|
@ -145,6 +145,14 @@ echo '{"H":"site-header","C":"app-content","F":"site-footer"}' \
|
|||
|
||||
JSON keys are HLCRF slot letters (`H`, `L`, `C`, `R`, `F`). Values are custom element tag names (must contain a hyphen per the Web Components specification). Duplicate tag values are deduplicated.
|
||||
|
||||
Pass `-types` to emit ambient TypeScript declarations instead of JavaScript:
|
||||
|
||||
```bash
|
||||
echo '{"H":"site-header","C":"app-content"}' \
|
||||
| go run ./cmd/codegen/ -types \
|
||||
> components.d.ts
|
||||
```
|
||||
|
||||
To test the CLI:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue