Documentation
¶
Overview ¶
Package cli implements the waxflow command tree. It is deliberately thin: commands parse flags, resolve configuration, and delegate; behavior lives in the library packages.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Flavor ¶
type Flavor struct {
// Name tags the version output: "catalog" prints waxflow-catalog.
// Empty means stock.
Name string
// OpenResolver wraps opts.Next with this build's source schemes.
// Every ref-taking command builds its resolver through it: server,
// sign, probe, transcode, split, and doctor.
//
// The returned Closer, which may be nil, is closed after the
// resolver's last use. Return a plain nil on error, having cleaned up
// what was opened: a Closer returned alongside an error is closed
// rather than leaked, so handing back one already closed is a double
// close. A typed-nil pointer in a non-nil interface is not a nil
// Closer and will be called. An implementation that is present but
// unconfigured owns the refusal for its own schemes: it returns a
// resolver that answers them with a message naming what is missing,
// rather than passing them down to opts.Next and the stock
// unsupported-source error.
//
// An implementation must not start background goroutines when
// opts.Daemon is false: the command resolves one reference and
// tears down, so nothing outlives it.
//
// The resolver it returns may implement PIDSourceReporter to say what
// /caps advertises, and ReloadableResolver to be reconciled by a root
// reload. Only the returned resolver is inspected for either, so a
// resolver that wraps another must implement and forward the ones the
// inner resolver needs.
OpenResolver func(ctx context.Context, opts ResolverOptions) (source.Resolver, io.Closer, error)
}
Flavor customizes the command tree for a build that adds source schemes the stock binary cannot serve. The zero value is the stock build. A build that resolves pid:<ULID> against a WaxBin catalog injects one; no build in this repo does, so the seam is aimed at modules outside it, and examples/catalogcli is a worked example.
type PIDSourceReporter ¶
type PIDSourceReporter interface {
PIDSources() bool
}
PIDSourceReporter, when implemented by the resolver an OpenResolver returns, declares whether this build resolves pid:<ULID> references. `waxflow server` publishes the answer as delivery.pid in /caps.
Implementing it is optional. Without it the CLI infers support from catalogDB being configured, which is right for a resolver keyed on catalogDB -- the documented channel, and what ResolverOptions.CatalogDB carries -- and wrong for one that is not. A build that resolves pid: from somewhere else says so here rather than leaving /caps to deny a capability it has.
This only keeps the capability surface honest; whether a given pid reference resolves is the resolver's business either way.
type ReloadableResolver ¶
type ReloadableResolver interface {
ReloadSourceMaxBytes(maxBytes int64)
}
ReloadableResolver, when implemented by the resolver an OpenResolver returns, is reconciled by a root reload (POST /roots/reload) alongside the library roots: it receives the re-read source cap, so a build that caps its own sources -- a catalog resolver enforcing the cap on the pid: files it opens itself -- stays in step with a changed sourceMaxBytes instead of holding the value it snapshotted at open. This is what makes a reload's "byte-for-byte as a restart" promise hold for a Flavor build, not only the stock one.
Optional. A resolver that only delegates to ResolverOptions.Next needs nothing: Next is the reconciled roots, which enforce the live cap on their own sources. maxBytes is the resolved per-source cap, defaulted exactly as ResolverOptions.MaxBytes was.
It is called with no library lock held and concurrently with in-flight Resolve calls, so an implementation must synchronize the field it updates (an atomic, say). Only the resolver OpenResolver returned is checked, as with PIDSourceReporter: a resolver that wraps another must implement this and forward when the inner one caps its own sources.
type ResolverOptions ¶
type ResolverOptions struct {
// CatalogDB is the configured catalog database path, resolved
// through the family precedence (flag > env > JSON file). Empty
// means the operator configured none.
CatalogDB string
// MaxBytes caps each resolved source file, the cap the library
// roots enforce on theirs. It is the value at open: a Flavor that caps
// its own sources on it (rather than delegating to Next, whose roots a
// reload reconciles in place) should implement ReloadableResolver to
// stay in step with a runtime sourceMaxBytes change; without that, the
// copied value is a restart-only snapshot.
MaxBytes int64
// Next serves every reference the implementation does not claim:
// the configured library roots. Implementations delegate rather
// than answer not-found.
//
// Next is live-mutable: a root reload (POST /roots/reload) mutates
// the roots it points at in place, so an implementation must delegate
// through the held Next reference and never snapshot its resolvable
// set, or a runtime-added root would be invisible to this build's
// resolver until restart.
Next source.Resolver
// Logger is never nil.
Logger *slog.Logger
// Daemon is true only under `waxflow server`, the one command whose
// process outlives a single resolution. See OpenResolver.
Daemon bool
}
ResolverOptions carries what an OpenResolver implementation needs from the resolved configuration. Every field is exported or stdlib, so a Flavor is constructible from any module.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
waxflow
command
Command waxflow is the WaxFlow CLI and daemon entry point.
|
Command waxflow is the WaxFlow CLI and daemon entry point. |
|
Package label implements meta.Mapper over the waxlabel tag library.
|
Package label implements meta.Mapper over the waxlabel tag library. |