Documentation
¶
Overview ¶
Package registry resolves a package id (optionally pinned to a version) against a small set of user-configured registries, closing the vision document's aspirational install-by-identifier command (section 9.2: "patchcord plugin install io.patchcord.postgresql@1.0.0", "depuis un registre futur") and unblocking bundle updates (ADR-0044).
A registry is nothing more than a name pointing at a local directory or a plain http(s) URL serving a static index.json plus package files — no bespoke server, no auth, no commerce (CLAUDE.md §1.9: the cloud is never required). This package only resolves and downloads; installing what it downloads is unchanged and stays the job of internal/plugins, internal/apps, internal/bundles InstallPackage.
Index ¶
- Constants
- Variables
- func Add(ctx context.Context, db *sql.DB, name, location string) error
- func Fetch(ctx context.Context, resolved Resolved, destDir string) (string, error)
- func ParseRef(ref string) (id, version string)
- func Remove(ctx context.Context, db *sql.DB, name string) error
- type Index
- type IndexEntry
- type Registry
- type Resolved
Constants ¶
const IndexFileName = "index.json"
IndexFileName is the file every registry (local directory or http(s) location) must serve at its root.
Variables ¶
var ErrNotFound = errors.New("registry entry not found")
ErrNotFound is returned by Remove when no registry with the given name is configured, and by Resolve when no configured registry lists the requested package id.
var ErrUnknownVersion = errors.New("unknown package version")
ErrUnknownVersion is returned by Resolve when the registry that lists a package id does not list the requested version.
Functions ¶
func Add ¶
Add records location under name. Re-adding the same name updates its location instead of failing — reconfiguring a registry's address is not an error. location is not validated here (no existence check, no reachability probe): like trust.Add does not check a key file exists, a registry is only ever validated lazily, the first time something resolves against it.
func Fetch ¶
Fetch downloads/copies the package resolved by Resolve into a new file under destDir (created if it does not exist yet) and returns its path. The caller owns the result and its parent directory — the same os.MkdirTemp + defer os.RemoveAll staging pattern internal/bundles and internal/apps already use for a package file before InstallPackage.
func ParseRef ¶
ParseRef splits ref into an id and an optional version: "id@version" or a bare "id". An empty version means "resolve to the registry's declared latest" — unlike bundles.splitPluginDependency's requires_plugins dependencies (which must always pin an exact version), a bare id is a valid, meaningful reference here.
Types ¶
type Index ¶
type Index struct {
SchemaVersion int `json:"schemaVersion"`
Packages map[string]IndexEntry `json:"packages"`
}
Index is a registry's index.json: every package it serves, by id.
type IndexEntry ¶
type IndexEntry struct {
Kind string `json:"kind"`
Latest string `json:"latest"`
Versions map[string]string `json:"versions"`
}
IndexEntry is one package's entry in a registry index. Versions maps a version string to the package file's path, relative to the registry's own location. Latest names the version Resolve picks when the caller does not pin one — an explicit declaration by the index's author, never inferred by comparing version strings (nothing in this codebase parses or orders versions numerically; see bundles.splitPluginDependency's exact-string-equality dependency check for the same choice).
type Resolved ¶
type Resolved struct {
RegistryName string
RegistryLocation string
ID string
Kind string
Version string
// contains filtered or unexported fields
}
Resolved is a package entry found in one configured registry, with enough information for Fetch to retrieve its file.
func Resolve ¶
Resolve looks up id (at version, or the registry's declared "latest" if version is empty) across every configured registry, in the order List returns them (added_at, oldest first).
The first registry whose index lists id wins, even if a later registry also has it — resolution never mixes sources for one id. Three distinct outcomes are not equivalent, though:
- a registry whose index cannot be read or parsed at all fails Resolve immediately, naming that registry: a broken registry is never silently skipped in favor of a working one further down the list, since that would mask a real configuration mistake;
- a registry that is read successfully but simply does not list id is not an error — Resolve moves on to the next configured registry;
- once id is found in some registry, that registry is the chosen source: if it does not list the requested version, Resolve returns ErrUnknownVersion immediately rather than searching other registries for that version.