Files
poiesis/README.md
2026-01-28 22:28:42 -05:00

3.6 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:

  1. internal/runtime - Runtime management

    • TypeScript transpilation with esbuild
    • JavaScript execution with qjs
    • Automatic function registration and execution
  2. internal/functions - Generic function registration framework

    • Type-safe registration with generics
    • Bidirectional Go ↔ JavaScript type conversion
    • Automatic TypeScript declaration generation
  3. internal/stdlib - Standard library implementations

    • fetch - HTTP requests
    • Extensible for additional standard functions

Installation & Build

go build ./cmd/poiesis

Testing

go test ./...
golangci-lint run

Usage

poiesis <typescript-file>
poiesis -print-types

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

Example

// TypeScript code
const response = fetch({input: "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 requests
    • options.input (string) - URL to fetch
    • options.init (object) - Optional init object with method, headers, body

Dependencies

  • github.com/evanw/esbuild/pkg/api - TypeScript transpilation
  • github.com/fastschema/qjs - JavaScript execution (QuickJS)
  • github.com/stretchr/testify/assert - Test assertions

Development

  • Test framework: Go's built-in testing package
  • 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