f308970531d8eac111439fc1cb9fb6e9432b5909
Add logrus as the primary logging framework with dependency injection pattern. All errors now use WithError() for context, and structured logging uses camelCase field names. Tag runtime service with service field for better log organization. - Add logrus dependency - Update Runtime to accept logger via dependency injection - Add WithLogger() option for logger configuration - Log errors with WithError() for context - Log async function failures with service context - Document logging practices in AGENTS.md
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
Description
Languages
Go
98.6%
Nix
1.4%