Replace simple argument parsing with cobra to provide better CLI experience: - Add 'execute' subcommand for running TypeScript files - Add 'types' subcommand for printing TypeScript type declarations - Add help text and error handling - Update documentation with new usage examples Add dependencies: github.com/spf13/cobra, github.com/spf13/pflag
4.8 KiB
4.8 KiB
Poiesis
A Go tool that transpiles TypeScript to JavaScript using esbuild and executes it with qjs, with an extensible function system.
Project Structure
reichard.io/poiesis/
├── cmd/
│ └── poiesis/ # CLI application entry point
│ └── main.go
├── internal/
│ ├── runtime/ # Runtime management, transpilation, execution
│ │ ├── runtime.go # Core runtime, transpilation, execution
│ │ └── runtime_test.go # Runtime tests
│ ├── functions/ # Function registration framework
│ │ ├── registry.go # Registration system
│ │ ├── types.go # Core interfaces and types
│ │ ├── typescript.go # TypeScript definition generation
│ │ ├── collector.go # Type collection utilities
│ │ └── typescript_test.go # Type system tests
│ └── stdlib/ # Standard library implementations
│ ├── fetch.go # HTTP fetch implementation
│ └── fetch_test.go # Fetch tests
Architecture
The project is cleanly separated into three packages:
-
internal/runtime- Runtime management- TypeScript transpilation with esbuild
- JavaScript execution with qjs
- Automatic function registration and execution
-
internal/functions- Generic function registration framework- Type-safe registration with generics
- Bidirectional Go ↔ JavaScript type conversion
- Automatic TypeScript declaration generation
-
internal/stdlib- Standard library implementationsfetch- HTTP requests- Extensible for additional standard functions
Installation & Build
go build ./cmd/poiesis
CLI Options
[file]- Path to TypeScript file to execute (optional)--print-types- Print TypeScript type declarations for all registered functions--help- Show help information
Testing
go test ./...
golangci-lint run
Usage
poiesis execute [file] # Run TypeScript file
poiesis types # Print TypeScript type declarations
poiesis --help # Show help
Function System
The function system allows you to easily expose Go functions to TypeScript/JavaScript.
Adding a Function
Just write a Go function and register it:
package mystdlib
import (
"context"
"reichard.io/poiesis/internal/functions"
)
type AddArgs struct {
A int `json:"a"`
B int `json:"b"`
}
func (a AddArgs) Validate() error {
return nil
}
func Add(_ context.Context, args AddArgs) (int, error) {
return args.A + args.B, nil
}
func init() {
functions.RegisterFunction[AddArgs, int]("add", Add)
}
That's it! The framework automatically:
- Converts JavaScript values to Go types
- Handles errors (panics as JS errors)
- Generates TypeScript definitions
- Manages the qjs integration
Calling Convention
Important: There's an important difference between how functions are defined in Go versus how they're called in JavaScript:
- Go side: The function receives a single argument struct containing all parameters
- JavaScript side: The function is called with the struct fields as individual arguments (in the order they appear in the struct)
// Go: Single struct argument
type AddArgs struct {
A int `json:"a"`
B int `json:"b"`
}
func Add(_ context.Context, args AddArgs) (int, error) {
return args.A + args.B, nil
}
// JavaScript: Individual arguments (not an object!)
const result = add(5, 10); // NOT add({ a: 5, b: 10 })
The framework extracts the JSON tags from the struct fields and uses them to generate the correct TypeScript function signature.
Example
// TypeScript code - call with individual arguments matching struct fields
const response = fetch("https://httpbin.org/get");
console.log("OK:", response.ok);
console.log("Status:", response.status);
console.log("Body:", response.body);
Built-in Functions
fetch(options)- HTTP requestsoptions.input(string) - URL to fetchoptions.init(object) - Optional init object withmethod,headers,body
Dependencies
github.com/evanw/esbuild/pkg/api- TypeScript transpilationgithub.com/fastschema/qjs- JavaScript execution (QuickJS)github.com/stretchr/testify/assert- Test assertions
Development
- Test framework: Go's built-in
testingpackage - Code style: Follow standard Go conventions
- Linting:
golangci-lint run- must pass before committing - TypeScript test files: Tests that require TypeScript files should create them inline using
os.CreateTemp()instead of relying on external test files