Documentation
¶
Overview ¶
Package app runs an app under its runner. An app's main calls Main with its Options:
func main() {
d := &deps.Deps{}
app.Main(app.Options{Handler: pages.NewHandler(d), OnStart: d.Start})
}
Handler serves the app's pages: pass the pages.NewHandler that aicoded generate writes. RPC serves the functions of the app's rpc/ package to other apps: pass the rpc.Server() that aicoded generate writes there. An app needs one or both. OnStart runs once, before the app serves: open the database and file stores there, and keep them in the app's deps package for every page. aicoded check holds main to this form: the options are an Options literal written in the call of Main or Run, with Handler and RPC set to those calls (E-LINT-004).
The runner starts the app with one environment variable, AICODED_RUNNER_DIR, and talks to it only through sockets in that folder. Run greets the runner, which refuses an app built for another protocol version (E-RUN-002), and then serves only requests that carry a viewer the company login verified, so an app has no login code. Every request gets a trace span, a panic answers 500 and is logged while the app keeps serving, and the default slog logger writes JSON lines that the runner collects. Main stops on SIGINT or SIGTERM and lets the requests in flight finish.
Name, Env and Version tell the app its name, the environment it runs in and its release.
Read more in the guides docs/guides/overview.md and docs/guides/project-structure.md, which aicoded explain and the MCP tool howto print as guides/overview and guides/project-structure.
Example ¶
The main of an app with pages and a database.
package main
import (
"context"
"database/sql"
"log/slog"
"net/http"
"aicoded.dev/framework/app"
"aicoded.dev/framework/sqldb"
)
// Deps is what every page of the app shares. An app declares it in its deps package.
type Deps struct {
DB *sql.DB
}
// Start opens the database before the app serves. Its context reaches the runner, so Start can
// also read settings and secrets; an error stops the app.
func (d *Deps) Start(ctx context.Context) error {
db, err := sqldb.Open(ctx)
if err != nil {
return err
}
d.DB = db
slog.InfoContext(ctx, "started", "version", app.Version(ctx))
return nil
}
// NewHandler stands for pages.NewHandler, which aicoded generate writes from the app's pages.
func NewHandler(*Deps) http.Handler { return http.NotFoundHandler() }
// The main of an app with pages and a database.
func main() {
d := &Deps{}
app.Main(app.Options{Handler: NewHandler(d), OnStart: d.Start})
}
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Main ¶
func Main(opts Options)
Main runs the app until the process gets SIGINT or SIGTERM. On error it prints the error, its text under aicoded dev in environment `dev` and only its kinds and codes anywhere else, and exits with status 1.
Types ¶
type Options ¶
type Options struct {
// Handler serves the app's pages. Every request it sees carries a verified viewer.
Handler http.Handler
// RPC serves the functions of the app's rpc/ package to other apps: the rpc.Server() that
// aicoded generate writes there.
RPC *rpc.Server
// OnStart, if set, runs after the handshake and before the app reports ready.
// Its context carries the runner, so settings and secrets can be read.
OnStart func(ctx context.Context) error
}
Options configure an app. An app needs Handler, RPC or both.