ftl

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2025 License: Apache-2.0 Imports: 14 Imported by: 0

README

FTL Shared Package

This package provides shared types, schemas, and synthesis capabilities for FTL (Faster Tools) applications. It ensures consistency between the CLI and platform backend.

Overview

The ftl package is designed to be imported by both:

  • FTL CLI: For local operations, building, and deploying
  • Platform Backend: For processing deployments and synthesizing Spin manifests

Key Components

1. Types (types.go)

Canonical schema definitions for FTL applications:

  • Application: The core FTL application structure
  • Component: Individual component definitions
  • AuthConfig: Authentication configuration
  • ComponentSource: Local or registry-based sources
2. Synthesis (synthesis.go)

CUE-based transformation from FTL to Spin manifests:

  • Synthesizer: Transforms FTL apps to Spin manifests
  • SynthesizeToSpin(): Creates Spin manifest struct
  • SynthesizeToTOML(): Creates Spin TOML string
3. Deployment (deployment.go)

Deployment request/response contracts:

  • DeploymentRequest: CLI → Platform contract
  • ProcessDeploymentRequest(): Platform-side processing
  • PrepareDeployment(): CLI-side preparation
4. CUE Patterns (patterns.cue)

The embedded CUE transformation logic that ensures consistent synthesis.

Usage

CLI Usage
import "github.com/fastertools/ftl-cli/go/shared/ftl"

// Load FTL application from YAML
var app ftl.Application
err := yaml.Unmarshal(configData, &app)

// Prepare deployment
req, err := ftl.PrepareDeployment(&app, ftl.DeploymentOptions{
    Environment: "production",
    Variables: map[string]string{
        "API_KEY": "secret",
    },
})

// Send to platform API
response := apiClient.CreateDeployment(req)
Backend Usage (Lambda/Platform)
import "github.com/fastertools/ftl-cli/go/shared/ftl"

func handleDeployment(request DeploymentRequest) error {
    // Process the deployment request
    manifest, err := ftl.ProcessDeploymentRequest(&request)
    if err != nil {
        return err
    }
    
    // Generate Spin TOML
    synth := ftl.NewSynthesizer()
    toml, err := synth.SynthesizeToTOML(request.Application)
    
    // Deploy with Spin
    return deployToSpin(toml)
}
Direct Synthesis
// Create an FTL application
app := &ftl.Application{
    Name:    "my-app",
    Version: "1.0.0",
    Components: []ftl.Component{
        {
            ID: "api",
            Source: &ftl.RegistrySource{
                Registry: "ghcr.io",
                Package:  "myorg:api",
                Version:  "1.0.0",
            },
        },
    },
    Access: ftl.AccessPrivate,
    Auth: ftl.AuthConfig{
        Provider: ftl.AuthProviderWorkOS,
        OrgID:    "org_123",
    },
}

// Synthesize to Spin manifest
synth := ftl.NewSynthesizer()
manifest, err := synth.SynthesizeToSpin(app)

Schema Validation

The package includes built-in validation:

app := &ftl.Application{...}

// Set defaults (version, access mode, etc.)
app.SetDefaults()

// Validate the configuration
if err := app.Validate(); err != nil {
    log.Fatalf("Invalid app: %v", err)
}

Component Sources

Components can have two types of sources:

Local Source (for development)
component := ftl.Component{
    ID:     "my-tool",
    Source: ftl.LocalSource("./dist/my-tool.wasm"),
    Build: &ftl.BuildConfig{
        Command: "cargo build --release",
    },
}
Registry Source (for deployment)
component := ftl.Component{
    ID: "my-tool",
    Source: &ftl.RegistrySource{
        Registry: "ecr.amazonaws.com/my-app",
        Package:  "app-id:my-tool",
        Version:  "1.0.0",
    },
}

Ensuring Consistency

To maintain consistency between CLI and platform:

  1. Always use this package for FTL types and synthesis
  2. Version together: When updating schemas, update both CLI and backend
  3. Test synthesis: Use the same test cases for both sides
  4. Embed CUE patterns: The patterns.cue file is embedded in the binary

Testing

func TestSynthesis(t *testing.T) {
    app := &ftl.Application{
        Name: "test-app",
        Components: []ftl.Component{...},
    }
    
    synth := ftl.NewSynthesizer()
    manifest, err := synth.SynthesizeToSpin(app)
    
    assert.NoError(t, err)
    assert.Equal(t, "test-app", manifest.Application.Name)
    assert.Contains(t, manifest.Component, "ftl-mcp-gateway")
}

Migration Path

For existing code:

  1. Replace local type definitions with ftl.Application, ftl.Component, etc.
  2. Use ftl.NewSynthesizer() instead of local synthesis
  3. Use ftl.DeploymentRequest for API contracts
  4. Validate with app.Validate() before processing

Future Enhancements

  • Direct CUE extraction (without intermediate JSON)
  • Streaming synthesis for large applications
  • Component dependency resolution
  • Multi-environment configuration overlays
  • Schema versioning and migration

Documentation

Overview

Package ftl provides shared types and utilities for FTL applications This package is used by both the CLI and the platform backend to ensure consistency

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AsLocal

func AsLocal(source ComponentSource) (string, bool)

AsLocal attempts to cast ComponentSource to LocalSource

func UpdateWkgAuthForECR

func UpdateWkgAuthForECR(configPath string, registryURI string, authToken string) error

UpdateWkgAuthForECR is a convenience function that parses the ECR token and updates wkg config This is what both CLI and backend can use

Types

type AccessMode

type AccessMode string

AccessMode defines the access control mode

const (
	AccessPublic  AccessMode = "public"
	AccessPrivate AccessMode = "private"
	AccessOrg     AccessMode = "org"
	AccessCustom  AccessMode = "custom"
)

type Application

type Application struct {
	Name        string            `json:"name" yaml:"name" cue:"name!"`
	Version     string            `json:"version,omitempty" yaml:"version,omitempty" cue:"version"`
	Description string            `json:"description,omitempty" yaml:"description,omitempty" cue:"description"`
	Components  []Component       `json:"components,omitempty" yaml:"components,omitempty" cue:"components"`
	Access      AccessMode        `json:"access,omitempty" yaml:"access,omitempty" cue:"access"`
	Auth        AuthConfig        `json:"auth,omitempty" yaml:"auth,omitempty" cue:"auth"`
	Variables   map[string]string `json:"variables,omitempty" yaml:"variables,omitempty" cue:"variables?"`
}

Application represents the FTL application configuration This is the canonical schema that both CLI and platform use

func (*Application) SetDefaults

func (a *Application) SetDefaults()

SetDefaults sets default values for the application

func (*Application) Validate

func (a *Application) Validate() error

Validate validates the application configuration

type AuthConfig

type AuthConfig struct {
	Provider    AuthProvider `json:"provider" yaml:"provider" cue:"provider!"`
	OrgID       string       `json:"org_id,omitempty" yaml:"org_id,omitempty" cue:"org_id"`
	JWTIssuer   string       `json:"jwt_issuer,omitempty" yaml:"jwt_issuer,omitempty" cue:"jwt_issuer"`
	JWTAudience string       `json:"jwt_audience,omitempty" yaml:"jwt_audience,omitempty" cue:"jwt_audience"`
}

AuthConfig defines authentication configuration

type AuthProvider

type AuthProvider string

AuthProvider defines the authentication provider type

const (
	AuthProviderWorkOS AuthProvider = "workos"
	AuthProviderCustom AuthProvider = "custom"
)

type BuildConfig

type BuildConfig struct {
	Command string   `json:"command" yaml:"command" cue:"command!"`
	Workdir string   `json:"workdir,omitempty" yaml:"workdir,omitempty" cue:"workdir?"`
	Watch   []string `json:"watch,omitempty" yaml:"watch,omitempty" cue:"watch?"`
}

BuildConfig defines build configuration for a component

type Component

type Component struct {
	ID        string            `json:"id" yaml:"id" cue:"id!"`
	Source    ComponentSource   `json:"source" yaml:"source" cue:"source!"`
	Build     *BuildConfig      `json:"build,omitempty" yaml:"build,omitempty" cue:"build"`
	Variables map[string]string `json:"variables,omitempty" yaml:"variables,omitempty" cue:"variables?"`
}

Component represents a component in the FTL application

func (Component) MarshalJSON

func (c Component) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshalling for Component

func (Component) MarshalYAML

func (c Component) MarshalYAML() (interface{}, error)

MarshalYAML implements custom YAML marshalling for Component

func (*Component) UnmarshalJSON

func (c *Component) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshalling for Component

func (*Component) UnmarshalYAML

func (c *Component) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML implements custom YAML unmarshalling for Component

func (*Component) Validate

func (c *Component) Validate() error

Validate validates a component

type ComponentSource

type ComponentSource interface {
	IsLocal() bool
	GetPath() string
	GetRegistry() *RegistrySource
}

ComponentSource can be either a local path (string) or a registry reference

type ComponentStatus

type ComponentStatus struct {
	ID       string `json:"id"`
	Status   string `json:"status"`
	Registry string `json:"registry,omitempty"`
	Package  string `json:"package,omitempty"`
	Version  string `json:"version,omitempty"`
	Error    string `json:"error,omitempty"`
}

ComponentStatus represents the status of a component in the deployment

type CustomAuthConfig

type CustomAuthConfig struct {
	Issuer   string   `json:"issuer"`
	Audience []string `json:"audience"`
}

CustomAuthConfig represents custom authentication configuration

type DeploymentOptions

type DeploymentOptions struct {
	Environment   string
	Variables     map[string]string
	AccessControl string
	AllowedRoles  []string
}

DeploymentOptions contains options for deployment

type DeploymentRequest

type DeploymentRequest struct {
	// The FTL application configuration
	Application *Application `json:"application"`

	// Environment-specific variables
	Variables map[string]string `json:"variables,omitempty"`

	// Environment name (e.g., production, staging)
	Environment string `json:"environment,omitempty"`

	// Access control override (if different from app config)
	AccessControl *AccessMode `json:"access_control,omitempty"`

	// Custom auth configuration (for custom access mode)
	CustomAuth *CustomAuthConfig `json:"custom_auth,omitempty"`

	// Allowed roles for org access mode
	AllowedRoles []string `json:"allowed_roles,omitempty"`
}

DeploymentRequest represents a deployment request to the FTL platform This is the contract between CLI and platform backend

func PrepareDeployment

func PrepareDeployment(app *Application, opts DeploymentOptions) (*DeploymentRequest, error)

PrepareDeployment prepares a deployment request from an FTL application

func (*DeploymentRequest) MarshalJSON

func (d *DeploymentRequest) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshalling for DeploymentRequest

func (*DeploymentRequest) UnmarshalJSON

func (d *DeploymentRequest) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshalling for DeploymentRequest

type DeploymentResponse

type DeploymentResponse struct {
	DeploymentID string `json:"deployment_id"`
	AppID        string `json:"app_id"`
	AppName      string `json:"app_name"`
	Status       string `json:"status"`
	Message      string `json:"message,omitempty"`
}

DeploymentResponse represents the response from a deployment request

type DeploymentStatus

type DeploymentStatus struct {
	DeploymentID string            `json:"deployment_id"`
	Status       string            `json:"status"`
	ProviderURL  string            `json:"provider_url,omitempty"`
	Components   []ComponentStatus `json:"components"`
	Error        string            `json:"error,omitempty"`
	UpdatedAt    string            `json:"updated_at"`
}

DeploymentStatus represents the overall deployment status

type ECRAuth

type ECRAuth struct {
	Registry string
	Username string
	Password string
}

ECRAuth represents parsed ECR authentication credentials

func ParseECRToken

func ParseECRToken(registryURI string, authToken string) (*ECRAuth, error)

ParseECRToken decodes an ECR authorization token into usable credentials

type LocalSource

type LocalSource string

LocalSource represents a local file path

func (LocalSource) GetPath

func (l LocalSource) GetPath() string

func (LocalSource) GetRegistry

func (l LocalSource) GetRegistry() *RegistrySource

func (LocalSource) IsLocal

func (l LocalSource) IsLocal() bool

type RegistrySource

type RegistrySource struct {
	Registry string `json:"registry" yaml:"registry" cue:"registry!"`
	Package  string `json:"package" yaml:"package" cue:"package!"`
	Version  string `json:"version" yaml:"version" cue:"version!"`
}

RegistrySource represents a component from a registry

func AsRegistry

func AsRegistry(source ComponentSource) (*RegistrySource, bool)

AsRegistry attempts to cast ComponentSource to RegistrySource

func (*RegistrySource) GetPath

func (r *RegistrySource) GetPath() string

func (*RegistrySource) GetRegistry

func (r *RegistrySource) GetRegistry() *RegistrySource

func (*RegistrySource) IsLocal

func (r *RegistrySource) IsLocal() bool

type SpinApplication

type SpinApplication struct {
	Name        string `json:"name" toml:"name"`
	Version     string `json:"version,omitempty" toml:"version,omitempty"`
	Description string `json:"description,omitempty" toml:"description,omitempty"`
}

SpinApplication represents the application section of a Spin manifest

type SpinComponent

type SpinComponent struct {
	Source               interface{}       `json:"source" toml:"source"`
	Build                *BuildConfig      `json:"build,omitempty" toml:"build,omitempty"`
	Variables            map[string]string `json:"variables,omitempty" toml:"variables,omitempty"`
	AllowedOutboundHosts []string          `json:"allowed_outbound_hosts,omitempty" toml:"allowed_outbound_hosts,omitempty"`
}

SpinComponent represents a component in the Spin manifest

type SpinHTTPTrigger

type SpinHTTPTrigger struct {
	Route     interface{} `json:"route" toml:"route"`
	Component string      `json:"component" toml:"component"`
}

SpinHTTPTrigger represents an HTTP trigger

type SpinManifest

type SpinManifest struct {
	SpinManifestVersion int                      `json:"spin_manifest_version" toml:"spin_manifest_version"`
	Application         SpinApplication          `json:"application" toml:"application"`
	Component           map[string]SpinComponent `json:"component" toml:"component"`
	Trigger             SpinTrigger              `json:"trigger" toml:"trigger"`
	Variables           map[string]SpinVariable  `json:"variables,omitempty" toml:"variables,omitempty"`
}

SpinManifest represents the synthesized Spin manifest

func ProcessDeploymentRequest

func ProcessDeploymentRequest(req *DeploymentRequest) (*SpinManifest, error)

ProcessDeploymentRequest processes a deployment request on the platform side This is what the backend Lambda would use

type SpinTrigger

type SpinTrigger struct {
	HTTP []SpinHTTPTrigger `json:"http" toml:"http"`
}

SpinTrigger represents the trigger configuration

type SpinVariable

type SpinVariable struct {
	Default  string `json:"default,omitempty" toml:"default,omitempty"`
	Required bool   `json:"required,omitempty" toml:"required,omitempty"`
	Secret   bool   `json:"secret,omitempty" toml:"secret,omitempty"`
}

SpinVariable represents a Spin variable

type Synthesizer

type Synthesizer struct {
	// contains filtered or unexported fields
}

Synthesizer handles the transformation of FTL applications to Spin manifests

func NewSynthesizer

func NewSynthesizer() *Synthesizer

NewSynthesizer creates a new synthesizer

func (*Synthesizer) SynthesizeFromJSON

func (s *Synthesizer) SynthesizeFromJSON(jsonData []byte) (*SpinManifest, error)

SynthesizeFromJSON takes JSON input and produces a Spin manifest

func (*Synthesizer) SynthesizeFromYAML

func (s *Synthesizer) SynthesizeFromYAML(yamlData []byte) (*SpinManifest, error)

SynthesizeFromYAML takes YAML input and produces a Spin manifest

func (*Synthesizer) SynthesizeToSpin

func (s *Synthesizer) SynthesizeToSpin(app *Application) (*SpinManifest, error)

SynthesizeToSpin transforms an FTL application to a Spin manifest

func (*Synthesizer) SynthesizeToTOML

func (s *Synthesizer) SynthesizeToTOML(app *Application) (string, error)

SynthesizeToTOML transforms an FTL application to a Spin TOML manifest string

type WkgAuthConfig

type WkgAuthConfig struct {
	Username string `toml:"username"`
	Password string `toml:"password"`
}

WkgAuthConfig represents authentication configuration

type WkgConfig

type WkgConfig struct {
	DefaultRegistry          string                        `toml:"default_registry,omitempty"`
	PackageRegistryOverrides map[string]string             `toml:"package_registry_overrides,omitempty"`
	Registry                 map[string]*WkgRegistryConfig `toml:"registry,omitempty"`
}

WkgConfig represents the wasm-pkg config structure

type WkgConfigManager

type WkgConfigManager struct {
	// contains filtered or unexported fields
}

WkgConfigManager manages wkg configuration for ECR authentication

func NewWkgConfigManager

func NewWkgConfigManager(configPath string) *WkgConfigManager

NewWkgConfigManager creates a new wkg config manager If configPath is empty, it uses the default path ~/.config/wasm-pkg/config.toml

func (*WkgConfigManager) LoadConfig

func (m *WkgConfigManager) LoadConfig() (*WkgConfig, error)

LoadConfig loads the wkg configuration file

func (*WkgConfigManager) RemoveECRAuth

func (m *WkgConfigManager) RemoveECRAuth(registryURI string) error

RemoveECRAuth removes ECR authentication from wkg config

func (*WkgConfigManager) SaveConfig

func (m *WkgConfigManager) SaveConfig(config *WkgConfig) error

SaveConfig saves the wkg configuration file

func (*WkgConfigManager) SetECRAuth

func (m *WkgConfigManager) SetECRAuth(ecrAuth *ECRAuth) error

SetECRAuth updates the wkg config with ECR authentication

type WkgOCIConfig

type WkgOCIConfig struct {
	Auth *WkgAuthConfig `toml:"auth,omitempty"`
}

WkgOCIConfig represents OCI registry configuration

type WkgRegistryConfig

type WkgRegistryConfig struct {
	OCI *WkgOCIConfig `toml:"oci,omitempty"`
}

WkgRegistryConfig represents a registry configuration

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL