ant

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 14, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package ant is the library behind the ant command line: a thin layer over a kit.Host that dereferences a resource URI to a record, regardless of which site it lives on.

ant owns no HTTP client and no per-site knowledge. Every domain it can address registers itself with kit from its own package's init, exactly as a database/sql driver does, and a program enables a domain with a single blank import:

import (
	_ "github.com/tamnd/goodread-cli/goodread"
	_ "github.com/tamnd/x-cli/x"
)

The Engine here is the sql.DB analogue: it opens the host once, then answers get/ls/links/resolve/url/export over the whole namespace.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DomainInfo

type DomainInfo struct {
	Scheme  string   `json:"scheme"`
	Aliases []string `json:"aliases,omitempty"`
	Hosts   []string `json:"hosts,omitempty"`
	Binary  string   `json:"binary,omitempty"`
	Short   string   `json:"short,omitempty"`
	Site    string   `json:"site,omitempty"`
	Repo    string   `json:"repo,omitempty"`
}

DomainInfo is one registered domain, as `ant domains` prints it.

type Engine

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

Engine dereferences resource URIs across every registered domain and materializes them to the on-disk URI tree. It is safe for concurrent use; the underlying host builds each domain's client lazily on first touch.

func New

func New(opts ...Option) (*Engine, error)

New opens the host over every registered domain and returns a ready Engine.

func (*Engine) Body

func (e *Engine) Body(ctx context.Context, u kit.URI) (string, bool, error)

Body fetches a URI's record and returns its long-text body, when it has one.

func (*Engine) BodyOf

func (e *Engine) BodyOf(env kit.Envelope) (string, bool)

BodyOf returns the long-text body of an already-fetched envelope's record, so `ant get -o md` need not fetch twice.

func (*Engine) Cached added in v0.2.0

func (e *Engine) Cached(u kit.URI) bool

Cached reports whether a URI's record is already materialized on disk, so a caller can show a cache badge or a refresh affordance without reading the file.

func (*Engine) Dereference added in v0.2.0

func (e *Engine) Dereference(ctx context.Context, u kit.URI, refresh bool) (Fetched, error)

Dereference resolves a URI cache-first: it returns the record already materialized under the data tree when one is present, and only fetches from the network on a cache miss or when refresh forces it. A live fetch is written back to the tree (JSON always, plus Markdown when the record has a body) so the next read is offline. This is the read path the web console drives, so browsing never re-fetches what ant already holds, and the refresh switch is the explicit way to pull a fresh copy.

func (*Engine) Domain added in v0.2.0

func (e *Engine) Domain(scheme string) (DomainInfo, bool)

Domain returns the descriptor of a single registered domain by scheme or alias, the lookup the web console uses to render one domain's detail page.

func (*Engine) Domains

func (e *Engine) Domains() []DomainInfo

Domains returns the registered domains the Engine can address, sorted by scheme. It is the analogue of sql.Drivers and backs `ant domains`.

func (*Engine) Export

func (e *Engine) Export(ctx context.Context, root kit.URI, follow int, asMarkdown bool) (*ExportReport, error)

Export materializes a URI's record to the data tree and, with follow > 0, walks its links to that depth, writing each record under its own URI path. It deduplicates by canonical URI so a cycle terminates, and reports every outcome rather than failing the whole walk on one bad node. asMarkdown also writes a .md body file for records that have one.

func (*Engine) Get

func (e *Engine) Get(ctx context.Context, u kit.URI) (kit.Envelope, error)

Get dereferences a URI to its record, wrapped in the self-describing envelope (@id/@type/@fetched/@links) the data surface uses.

func (*Engine) Import

func (e *Engine) Import(path string) (map[string]any, error)

Import reads an exported record file back into its envelope, the inverse of Export and the home of `ant import`.

func (*Engine) LL

func (e *Engine) LL(prefix string) ([]string, error)

LL lists the record URIs already materialized on disk under a URI prefix. An empty prefix lists the whole tree. The first call for a prefix walks the filesystem; the result is held in an in-memory index, and every later cache-write folds the new URI into the matching listings (indexAdd), so a repeat call returns from memory without touching disk. This is what keeps the web console's dashboard and browse pages fast as the data tree grows. A long-lived process (ant serve) is the only writer of its own tree, so the index stays consistent for the session; an external write lands on the next restart.

func (e *Engine) Links(ctx context.Context, u kit.URI) ([]kit.URI, error)

Links fetches a URI's record and returns its outbound graph edges as URIs.

func (*Engine) List

func (e *Engine) List(ctx context.Context, u kit.URI, limit int) ([]kit.Envelope, error)

List returns the member records of a collection URI, each wrapped as an envelope. limit caps the result (0 means the op's own default).

func (*Engine) Lookup added in v0.2.0

func (e *Engine) Lookup(u kit.URI) (Fetched, bool)

Lookup returns a record from the on-disk cache without ever touching the network, so the web console can render a cached page instantly and route only a miss to a background fetch. ok is false on a miss (absent or unreadable). It is the read-only half of Dereference: same cache read, no write-back, no fetch.

func (*Engine) Resolve

func (e *Engine) Resolve(input, on string) (kit.URI, error)

Resolve normalizes any input into a canonical URI. With on set, it resolves the input within that domain (the home of bare ids and @handles); otherwise it accepts a resource URI or a site URL whose host a domain claims.

func (*Engine) Root

func (e *Engine) Root() string

Root returns the data tree root the Engine writes under.

func (*Engine) Search added in v0.2.0

func (e *Engine) Search(ctx context.Context, scheme, query string, limit int) ([]kit.Envelope, error)

Search runs a domain's free-text search and returns the hits as envelopes. A hit that is URI-addressable carries its canonical @id, so it links straight to get; one that is not still surfaces, wrapped with the scheme as @type and no @id. limit caps the result (0 means the op's own default). Search hits are previews and are not written to the data tree; dereferencing one caches it.

func (*Engine) Searchable added in v0.2.0

func (e *Engine) Searchable(scheme string) bool

Searchable reports whether a domain (by scheme or alias) supports free-text search, so the web console can decide to show a search box for it.

func (*Engine) URL

func (e *Engine) URL(u kit.URI) (string, error)

URL returns the live https location of a URI, the inverse of Resolve.

func (*Engine) Walk

func (e *Engine) Walk(ctx context.Context, root kit.URI, depth int) (*Graph, error)

Walk explores the link graph from root to the given depth, fetching each node once and recording its outbound edges. A failed fetch is skipped (its edges are simply absent) so one dead link does not abort the walk.

func (*Engine) WarmIndex added in v0.2.0

func (e *Engine) WarmIndex()

WarmIndex pre-populates the in-memory LL index for every registered domain, so the first browse or dashboard request is served from memory rather than paying for a cold filesystem walk. It walks only ant's own domain subtrees, never the whole shared data root. A long-lived process (ant serve) calls this once in the background at startup; it is a no-op to call again.

type ExportReport

type ExportReport struct {
	Root    string            `json:"root"`
	Written []string          `json:"written"`
	Skipped []string          `json:"skipped,omitempty"`
	Errors  map[string]string `json:"errors,omitempty"`
}

ExportReport is the honest accounting of an export walk: what was written, what was already present, and which URIs failed (so a partial export never reads as a complete one).

type Fetched added in v0.2.0

type Fetched struct {
	Env       kit.Envelope
	Raw       json.RawMessage // the indented envelope JSON, as written to disk
	Body      string
	HasBody   bool
	FromCache bool
}

Fetched is a dereferenced record with the provenance the web console needs: whether it came from the on-disk cache or a live fetch, its long-text body when it has one, and the canonical envelope JSON, so a renderer can show the record's fields in their declared order (a map would lose it).

type Graph

type Graph struct {
	Nodes []GraphNode `json:"nodes"`
	Edges []GraphEdge `json:"edges"`
}

Graph is the subgraph `ant graph` walks: every node reached within the depth and every edge between them.

func (*Graph) Dot

func (g *Graph) Dot() string

Dot renders a graph as Graphviz DOT.

type GraphEdge

type GraphEdge struct {
	From string `json:"from"`
	To   string `json:"to"`
}

GraphEdge is one typed link from a resource to another.

type GraphNode

type GraphNode struct {
	URI  string `json:"uri"`
	Type string `json:"type"`
}

GraphNode is one resource in a walked subgraph.

type Option

type Option func(*Engine)

Option customizes an Engine at New.

func WithClock

func WithClock(fn func() time.Time) Option

WithClock sets the clock used to stamp @fetched, so a test can pin it.

func WithRoot

func WithRoot(dir string) Option

WithRoot sets the on-disk data tree root (the default is $HOME/data).

Jump to

Keyboard shortcuts

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