happy

package module
v0.23.1 Latest Latest
Warning

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

Go to latest
Published: Mar 31, 2024 License: Apache-2.0 Imports: 35 Imported by: 5

README

Happy Logo

Happy Prototyping Framework and SDK

Package happy is a powerful tool for developers looking to bring their ideas to life through rapid prototyping. With its comprehensive set of resources and modular design, it's easy to create working prototypes or MVPs with minimal technical knowledge or infrastructure planning. Plus, its flexible design allows it to seamlessly integrate into projects with components written in different programming languages. So why wait? Let Happy help you achieve your goals and bring a smile to your face along the way.

Happy is very early in development phase and is not intended for production use.

GitHub Release PkgGoDev Coverage Status GitHub License

Creating application

Happy SDK is designed to simplify your development process without introducing any new or additional developer tools. Your applications built with Happy can be used, built, and tested with the standard Go build tools, such as 'go test', 'go build', and 'go run'. With Happy, you have complete control over your development environment, as it will not add any third-party dependencies to your project.

Here's a simple example of how you can use Happy:

// main.go
package main

import (
  "fmt"

  "github.com/happy-sdk/happy"
  "github.com/happy-sdk/happy/sdk/logging"
)

func ExampleNew() {
  app := happy.New(happy.Settings{})
  app.Do(func(sess *happy.Session, args happy.Args) error {
    sess.Log().Println("Hello, world!")
    return nil
  })
  app.Run()
}

For more examples, take a look at the examples section and the examples in the ./examples/ directory."

Application api

More details of api read happy Godoc

...
app.WithAddon(/* adds addon to app */)
app.WithMigrations(/* use migration manager */)
app.WithService(/* adds service to app */)
app.WithCommand(/* adds command to app */)
app.WithFlag(/* adds flag to app root command*/)
app.WithLogger(/* uses provided logger */)
app.WithOptions(/* adds allowed runtime option */)
...

...
// All the following are optional 
app.BeforeAlways(/* called always before any command is invoked*/)
app.Before(/* called before root command is invoked*/)
app.Do(/* root command Do function */)
app.AfterSuccess(/* called when root cmd or sub command returns without errors */)
app.AfterFailure(/* called when root cmd or sub command returns with errors */)
app.AfterAlways(/* called always when root cmd or sub command returns */)
app.Tick(/* called in specific interfal while root command is blocking */)
app.Tock(/* called after every tick*/)
...
Commands

happy.Command provides a universal API for attaching sub-commands directly to the application or providing them from an Addon.

...
cmd := happy.NewCommand(
  "my-command",
  happy.Option("usage", "My sub-command"),
  happy.Option("argn.min", 1),
  happy.Option("argn.max", 10),
)

cmd.Do(/* Main function for the command */)

// Optional:
cmd.AddInfo(/* add long description paragraph for command*/)
cmd.AddFlag(/* add flag to  command*/)

cmd.Before(/* Called after app.Before and before cmd.Do */)
cmd.AfterSuccess(/* Called when cmd.Do returns without errors */)
cmd.AfterFailure(/* Called when cmd.Do returns with errors */)
cmd.AfterAlways(/* Called always when cmd.Do returns */)
cmd.AddSubCommand(/* Add a sub-command to the command */)
cmd.AddFlag(/* Add a flag for the command */)

cmd.AddSubCommand(/* add subcommand to command */)
...
Services

The happy.Service API provides a flexible way to add runtime-controllable background services to your application.

...
svc := happy.NewService("my-service")

svc.OnInitialize(/* Called when the app starts. */)
svc.OnStart(/* Called when the service is requested to start. */)
svc.OnStop(/* Called when the service is requested to stop. */)
svc.OnEvent(/* Called when a specific event is received. */)
svc.OnAnyEvent(/* Called when any event is received. */)
svc.Cron(/* Scheduled cron jobs to run when the service is running. */)
svc.Tick(/* Called every tick when the service is running. */)
svc.Tock(/* Called after every tick when the service is running. */)

app.RegisterService(svc)
...

Addons

Addons provide a simple way to bundle commands and services into a single Go package, allowing for easy sharing between projects.

// main.go
package main

import (
  "github.com/happy-sdk/happy"
  "helloworld"
)

func main() {
  app := happy.New()
  app.WithAddons(helloworld.Addon())
  app.Main()
}

// helloworld/addon.go
package helloworld

import "github.com/happy-sdk/happy"

type HelloWorldAPI struct {
  happy.API
}

func Addon() *happy.Addon {
  addon := happy.NewAddon(
    "hello-world",
    happy.Option("description", "example addon"),
  )

  // Optional: Set a custom setting
  addon.Setting("greet.msg", "any value", "setting description", /* validation func */)

  // Optional: Register commands provided by the addon
  addon.ProvidesCommand(/* provide command */)

  // Optional: Register services provided by the addon
  addon.ProvidesService(/* provide service */)

  // Optional: Make a custom API accessible across the application 
  addon.ProvidesAPI(&HelloWorldAPI{}) 

  // Register all events that the addon may emit ()
  addon.Emits("event scope", "event key" , "event description", /* example payload */)
  addon.EmitsEvent(/* if you already have event */)

  addon.Option("key", "value", "addon specific runtime option", /* optional validator*/)
  
  // Optional callback to be called when the addon is registered
  addon.OnRegister(func(sess *happy.Session, opts *happy.Options) error {
    sess.Log().Notice("hello-world addon registered")
    return nil
  })

  return addon
}

Credits

GitHub contributors

Happy banner design.
Happy banner was designed by Egon Elbre egonelbre.com

Documentation

Overview

Package happy provides a modular framework for rapid prototyping in Go. With this SDK, developers of all levels can easily bring their ideas to life. Whether you're a hacker or a creator, Package happy has everything you need to tackle your domain problems and create working prototypes or MVPs with minimal technical knowledge and infrastructure planning.

Its modular design enables you to package your commands and services into reusable addons, so you're not locked into any vendor tools. It also fits well into projects where different components are written in different programming languages.

Let Package happy help you bring your projects from concept to reality and make you happy along the way.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrCommand            = errors.New("command error")
	ErrCommandFlags       = errors.New("command flags error")
	ErrCommandHasNoParent = errors.New("command has no parent command")
)
View Source
var (
	ErrSession          = fmt.Errorf("%w:session", Error)
	ErrSessionDestroyed = fmt.Errorf("%w:destroyed", ErrSession)
)
View Source
var ErrAddon = fmt.Errorf("%w:addon", Error)
View Source
var ErrEngine = fmt.Errorf("%w:engine", Error)
View Source
var (
	ErrService = fmt.Errorf("%s:svc", Error)
)
View Source
var (
	Error = errors.New("happy")
)

Functions

func GetAPI

func GetAPI[A API](sess *Session, addonName string) (api A, err error)

func LoadServices added in v0.22.0

func LoadServices(sess *Session, svcs ...string)

LoadServices is a non blocking helper function to load services in backgrond

func Option

func Option(key string, val any) options.Arg

Types

type API

type API interface {
	// contains filtered or unexported methods
}

type Action

type Action func(sess *Session) error

type ActionTick

type ActionTick func(sess *Session, ts time.Time, delta time.Duration) error

type ActionTock

type ActionTock func(sess *Session, delta time.Duration, tps int) error

type ActionWithArgs

type ActionWithArgs func(sess *Session, args Args) error

type ActionWithFlags func(sess *Session, flags Flags) error

type ActionWithEvent

type ActionWithEvent func(sess *Session, ev Event) error

type ActionWithOptions

type ActionWithOptions func(sess *Session, opts *options.Options) error

type ActionWithPrevErr added in v0.12.0

type ActionWithPrevErr func(sess *Session, err error) error

type Addon

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

func NewAddon

func NewAddon(name string, s settings.Settings, opts ...options.OptionSpec) *Addon

func (*Addon) Emits

func (addon *Addon) Emits(scope, key, description string, example *vars.Map)

func (*Addon) EmitsEvent

func (addon *Addon) EmitsEvent(event Event)

func (*Addon) OnRegister

func (addon *Addon) OnRegister(action Action)

func (*Addon) ProvidesAPI added in v0.12.0

func (addon *Addon) ProvidesAPI(api API)

func (*Addon) ProvidesCommand

func (addon *Addon) ProvidesCommand(cmd *Command)

func (*Addon) ProvidesService

func (addon *Addon) ProvidesService(svc *Service)

type AddonInfo

type AddonInfo struct {
	Name        string
	Description string
	Version     version.Version
	Module      string
}

type Args

type Args interface {
	Arg(i uint) vars.Value
	ArgDefault(i uint, value any) (vars.Value, error)
	Args() []vars.Value
	Argn() uint
	Flag(name string) varflag.Flag
}

type Brand added in v0.20.0

type Brand interface {
	Info() branding.Info
	ANSI() ansicolor.Theme
}

type BrandFunc added in v0.20.0

type BrandFunc func() (Brand, error)

type Command

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

func NewCommand

func NewCommand(name string, args ...options.Arg) *Command

func (*Command) AddFlag

func (c *Command) AddFlag(fn varflag.FlagCreateFunc) *Command

func (*Command) AddInfo added in v0.12.0

func (c *Command) AddInfo(paragraph string) *Command

func (*Command) AddSubCommand

func (c *Command) AddSubCommand(cmd *Command) *Command

func (*Command) AfterAlways

func (c *Command) AfterAlways(a ActionWithPrevErr) *Command

func (*Command) AfterFailure

func (c *Command) AfterFailure(a ActionWithPrevErr) *Command

func (*Command) AfterSuccess

func (c *Command) AfterSuccess(a Action) *Command

func (*Command) Before

func (c *Command) Before(a ActionWithArgs) *Command

func (*Command) DescribeCategory added in v0.20.0

func (c *Command) DescribeCategory(cat, desc string) *Command

func (*Command) Do

func (c *Command) Do(action ActionWithArgs) *Command

func (*Command) WithFlags added in v0.22.0

func (c *Command) WithFlags(flagfuncs ...varflag.FlagCreateFunc) *Command

type Cron

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

func (*Cron) Job

func (cs *Cron) Job(expr string, cb Action)

func (*Cron) Start

func (cs *Cron) Start() error

func (*Cron) Stop

func (cs *Cron) Stop() error

type CronScheduler

type CronScheduler interface {
	Job(expr string, cb Action)
}

type Event

type Event interface {
	Key() string
	Scope() string
	Payload() *vars.Map
	Time() time.Time
}

func NewEvent

func NewEvent(scope, key string, payload *vars.Map, err error) Event

func StartServicesEvent

func StartServicesEvent(svcs ...string) Event

func StopServicesEvent

func StopServicesEvent(svcs ...string) Event

type EventListener

type EventListener interface {
	OnEvent(scope, key string, cb ActionWithEvent)
	OnAnyEvent(ActionWithEvent)
}

type Flags added in v0.12.0

type Flags interface {
	// Get named flag
	Get(name string) (varflag.Flag, error)
}

type Main added in v0.12.0

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

func New

func New(s Settings) *Main

New is alias to prototype.New

Example
package main

import (
	"fmt"

	"github.com/happy-sdk/happy"
	"github.com/happy-sdk/happy/sdk/logging"
)

func main() {
	log := logging.NewTestLogger(logging.LevelError)

	app := happy.New(happy.Settings{})
	app.WithLogger(log)
	app.Do(func(sess *happy.Session, args happy.Args) error {
		sess.Log().Println("Hello, world!")
		return nil
	})

	app.Run()
	fmt.Println(log.Output())
}
Output:

{"level":"out","msg":"Hello, world!"}

func (*Main) AddInfo added in v0.23.0

func (m *Main) AddInfo(paragraph string) *Main

func (*Main) AfterAlways added in v0.12.0

func (m *Main) AfterAlways(a ActionWithPrevErr) *Main

AfterAlways is executed after every application execution.

func (*Main) AfterFailure added in v0.12.0

func (m *Main) AfterFailure(a ActionWithPrevErr) *Main

AfterFailure is executed after every failed application execution.

func (*Main) AfterSuccess added in v0.12.0

func (m *Main) AfterSuccess(a Action) *Main

AfterSuccess is executed after every successful application execution.

func (*Main) Before added in v0.12.0

func (m *Main) Before(a ActionWithArgs) *Main

Before is executed only when no command is specified.

func (*Main) BeforeAlways added in v0.12.0

func (m *Main) BeforeAlways(a ActionWithArgs) *Main

BeforeAlways is executed before any command.

func (*Main) Do added in v0.12.0

func (m *Main) Do(a ActionWithArgs) *Main

Do is executed only when no command is specified.

func (*Main) Run added in v0.12.0

func (m *Main) Run()

Run starts the Application.

func (*Main) SetOptions added in v0.16.0

func (m *Main) SetOptions(a ...options.Arg) *Main

func (*Main) Tick added in v0.12.0

func (m *Main) Tick(a ActionTick) *Main

Tick when set is executed on every tick defined by Settings.ThrottleTicks interval.

func (*Main) Tock added in v0.12.0

func (m *Main) Tock(a ActionTock) *Main

Tock when set is executed right after Tick. If Tick returns error then Tock is not executed.

func (*Main) WithAddon added in v0.12.0

func (m *Main) WithAddon(addon *Addon) *Main

WithAddons adds addons to the application.

func (*Main) WithBrand added in v0.20.0

func (m *Main) WithBrand(b BrandFunc) *Main

func (*Main) WithCommand added in v0.12.0

func (m *Main) WithCommand(cmd *Command) *Main

WithCommand adds command to the application.

func (*Main) WithFlag added in v0.12.0

func (m *Main) WithFlag(flag varflag.FlagCreateFunc) *Main

WithFlag adds flag to the application.

func (*Main) WithLogger added in v0.12.0

func (m *Main) WithLogger(l logging.Logger) *Main

WithLogger sets application logger.

func (*Main) WithMigrations added in v0.12.0

func (m *Main) WithMigrations(mm *migration.Manager) *Main

WithMigrations adds migrations manager to the application.

func (*Main) WithOptions added in v0.12.0

func (m *Main) WithOptions(opts ...options.OptionSpec) *Main

func (*Main) WithService added in v0.12.0

func (m *Main) WithService(svc *Service) *Main

WithService adds service to the application.

type Service

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

func NewService

func NewService(name string, opts ...options.OptionSpec) *Service

NewService cretes new draft service which you can compose before passing it to applciation or providing it from addon.

func (*Service) Cron

func (s *Service) Cron(setupFunc func(schedule CronScheduler))

Cron scheduled cron jobs to run when the service is running.

func (*Service) OnAnyEvent

func (s *Service) OnAnyEvent(cb ActionWithEvent)

OnAnyEvent called when any event is received.

func (*Service) OnEvent

func (s *Service) OnEvent(scope, key string, cb ActionWithEvent)

OnEvent is called when a specific event is received.

func (*Service) OnRegister added in v0.19.0

func (s *Service) OnRegister(action Action)

OnRegister is called when app is preparing runtime and attaching services, This does not mean that service will be used or started.

func (*Service) OnStart

func (s *Service) OnStart(action Action)

OnStart is called when service is requested to be started. For instace when command is requiring this service or whenever service is required on runtime via sess.RequireService call.

Start can be called multiple times in case of service restarts. If you do not want to allow service restarts you should implement your logic in OnStop when it's called first time and check that state OnStart.

func (*Service) OnStop

func (s *Service) OnStop(action Action)

OnStop is called when runtime request to stop the service is recieved.

func (*Service) Tick added in v0.12.0

func (s *Service) Tick(action ActionTick)

OnTick when set will be called every application tick when service is in running state.

func (*Service) Tock added in v0.12.0

func (s *Service) Tock(action ActionTock)

OnTock is called after every tick.

type ServiceInfo

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

func (*ServiceInfo) Addr

func (s *ServiceInfo) Addr() *address.Address

func (*ServiceInfo) Errs

func (s *ServiceInfo) Errs() map[time.Time]error

func (*ServiceInfo) Failed

func (s *ServiceInfo) Failed() bool

func (*ServiceInfo) Name

func (s *ServiceInfo) Name() string

func (*ServiceInfo) Running

func (s *ServiceInfo) Running() bool

func (*ServiceInfo) StartedAt

func (s *ServiceInfo) StartedAt() time.Time

func (*ServiceInfo) StoppedAt

func (s *ServiceInfo) StoppedAt() time.Time

type ServiceLoader

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

func NewServiceLoader

func NewServiceLoader(sess *Session, svcs ...string) *ServiceLoader

NewServiceLoader creates new service loader which can be used to load services before application starts or during runtime.

func (*ServiceLoader) Err

func (sl *ServiceLoader) Err() error

func (*ServiceLoader) Load

func (sl *ServiceLoader) Load() <-chan struct{}

type Session

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

func (*Session) API

func (s *Session) API(addonName string) (API, error)

func (*Session) AllowUserCancel added in v0.7.0

func (s *Session) AllowUserCancel()

AllowUserCancel allows user to cancel application by pressing Ctrl+C or sending SIGINT or SIGTERM while application is running. By default this is not allowed unless application is blocked with Wait.

func (*Session) Deadline

func (s *Session) Deadline() (deadline time.Time, ok bool)

Deadline returns the time when work done on behalf of this context should be canceled. Deadline returns ok==false when no deadline is set. Successive calls to Deadline return the same results.

func (*Session) Describe added in v0.12.0

func (s *Session) Describe(key string) string

func (*Session) Destroy

func (s *Session) Destroy(err error)

func (*Session) Dispatch

func (s *Session) Dispatch(ev Event)

func (*Session) Done

func (s *Session) Done() <-chan struct{}

Done enables you to hook into chan to know when application exits however DO NOT use that for graceful shutdown actions. Use Application.AddExitFunc or Cloesed instead.

func (*Session) Err

func (s *Session) Err() error

Err returns session error if any or nil If Done is not yet closed, Err returns nil. If Done is closed, Err returns a non-nil error explaining why: Canceled if the context was canceled or DeadlineExceeded if the context's deadline passed. After Err returns a non-nil error, successive calls to Err return the same error.

func (*Session) Get

func (s *Session) Get(key string) vars.Variable

func (*Session) Has

func (s *Session) Has(key string) bool

func (*Session) Log

func (s *Session) Log() logging.Logger

func (*Session) Opts added in v0.6.0

func (s *Session) Opts() *options.Options

Opts returns a map of all options which are defined by application turing current session life cycle.

func (*Session) Ready

func (s *Session) Ready() <-chan struct{}

Ready returns channel which blocks until session considers application to be ready. It is ensured that Ready closes before root or command Do function is called.

func (*Session) ServiceInfo

func (s *Session) ServiceInfo(svcurl string) (*ServiceInfo, error)

func (*Session) ServiceLoader added in v0.12.0

func (s *Session) ServiceLoader(svcs ...string) *ServiceLoader

ServiceLoader calls NewServiceLoader with current session as first argument.

func (*Session) Set

func (s *Session) Set(key string, val any) error

func (*Session) Settings

func (s *Session) Settings() *settings.Profile

Settings returns a map of all settings which are defined by application and are user configurable.

func (*Session) Stats added in v0.16.0

func (s *Session) Stats() stats.State

func (*Session) String

func (s *Session) String() string

func (*Session) Value

func (s *Session) Value(key any) any

Value returns the value associated with this context for key, or nil

type Settings added in v0.11.0

type Settings struct {
	Name                 settings.String   `key:"app.name" default:"Happy Prototype"`
	Slug                 settings.String   `key:"app.slug" default:""`
	Description          settings.String   `key:"app.description" default:""`
	CopyrightBy          settings.String   `key:"app.copyright.by"`
	CopyrightSince       settings.Uint     `key:"app.copyright.since" default:"0" mutation:"once"`
	License              settings.String   `key:"app.license"`
	MainArgcMax          settings.Uint     `key:"app.main.argn_max" default:"0"`
	TimeLocation         settings.String   `key:"app.datetime.location,save" default:"Local" mutation:"mutable"`
	EngineThrottleTicks  settings.Duration `key:"app.engine.throttle_ticks,save" default:"1s" mutation:"once"`
	ServiceLoaderTimeout settings.Duration `key:"app.service_loader.timeout" default:"30s" mutation:"once"`
	Instance             instance.Settings `key:"app.instance"`
	StatsEnabled         settings.Bool     `key:"app.stats.enabled" default:"false" mutation:"once"`
	// contains filtered or unexported fields
}

func (Settings) Blueprint added in v0.11.0

func (s Settings) Blueprint() (*settings.Blueprint, error)

Blueprint returns a blueprint for the settings.

func (*Settings) Extend added in v0.11.0

func (s *Settings) Extend(ss settings.Settings)

Extend adds a new settings group to the settings.

func (*Settings) Migrate added in v0.15.0

func (s *Settings) Migrate(keyfrom, keyto string)

Migrate allows auto migrate old settigns from keyfrom to keyto when applying preferences from deprecated keyfrom.

Directories

Path Synopsis
addons
cmd
hap Module
cmd/hap Module
pkg
branding Module
cli/ansicolor Module
settings Module
strings/bexp Module
vars Module
version Module
sdk
cli
Package cli provides utilities for happy command line interfaces.
Package cli provides utilities for happy command line interfaces.
networking/address
Package address provides functions for working with "happy" addresses, which are URL-like strings that define the location of a resource in the "happy" system.
Package address provides functions for working with "happy" addresses, which are URL-like strings that define the location of a resource in the "happy" system.
options
Package oprions provides a way to define and manage options for application components.
Package oprions provides a way to define and manage options for application components.

Jump to

Keyboard shortcuts

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