adapter

package
v0.19.0 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package adapter is sofia's Tier-1, host-interpreted plugin mechanism: a plugin.yaml `adapter:` block declares project conventions (a root key, root markers, file extensions, and named layers with path globs), and the host — not a subprocess — turns those into project-aware `layers`/`grep`/`refs` commands grouped by layer. It is the generalization of the private "crm usages" pattern; a pure-adapter plugin ships no executable at all.

This package holds the typed schema (Config), its validation, the glob matcher, the root resolver, the layer classifier, and the synthesized cobra commands. It deliberately does NOT import internal/plugin (the manifest tier depends on this one; the reverse would be a cycle).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Classify

func Classify(cfg Config, rel string) string

Classify returns the name of the first layer whose any Match glob hits the given path, or "" when no layer claims it. The path is taken relative to the resolved project root; it is normalized to forward slashes and stripped of a leading "./" so a caller can pass either an OS path or a slash path. Layers are tried in declared order, so an adapter author controls precedence by ordering the block — and the classification is byte-stable.

func Commands

func Commands(pluginName string, cfg Config) []*cobra.Command

Commands synthesizes the project-aware subcommands the host attaches under `sf <pluginName>` for an adapter plugin: `layers`, `grep`, and `refs`. They are real, in-process cobra commands — they resolve a project root, run the generic grep/refs scanners scoped to the adapter's extensions, and group the results by layer. Nothing here forks a subprocess; a pure-adapter plugin has no executable to fork.

func Match

func Match(pattern, path string) bool

Match reports whether a slash-separated path matches a layer glob. It is a small segmented globber — no go.mod dependency (doublestar isn't vendored) — with exactly the one extension filepath.Match lacks: `**`, which matches zero or more whole path segments. Both pattern and path are split on "/"; within a segment, filepath.Match's metacharacters (`*`, `?`, `[…]`) apply and never cross a "/". So `src/*` matches `src/User.php` but not `src/Domain/User.php`, while `src/Domain/**` matches `src/Domain` and everything beneath it.

func ResolveRoot

func ResolveRoot(cfg Config, startDir string) (string, error)

ResolveRoot finds the project root an adapter's commands operate on, trying, in order:

  1. $<RootKey> — when the config names a root key and that environment variable is set and points at an existing directory, it wins outright. This is the explicit escape hatch (e.g. CRM_ROOT) for working outside the tree, or from a checkout whose markers live elsewhere.
  2. a walk up from startDir to the nearest ancestor containing any RootMarker — the ordinary case, modelled on phpcode.loadComposerPSR4 and plugin.projectRoot.

It returns an error naming the markers when neither locates a root, so the synthesized command can say precisely why it couldn't run. The command layer adds the higher-precedence explicit `--root` on top of this.

Types

type Config

type Config struct {
	Kind        string
	RootKey     string
	RootMarkers []string
	Ext         []string
	Layers      []Layer
}

Config is the typed, validated form of a plugin's `adapter:` block. Kind names the adapter family (informational); RootKey is the environment variable that pins the project root when set; RootMarkers are the files a walk-up looks for otherwise; Ext scopes grep/refs to matching extensions; Layers classify a project-relative path into a named layer by glob.

func Parse

func Parse(kind string, spec map[string]any) (Config, error)

Parse turns an adapter block's kind + spec map into a typed Config. It does not validate — call Config.Validate on the result before trusting it. The spec is re-marshalled to YAML and decoded into rawConfig so the same code path handles a freshly-parsed manifest and one that survived the plugins.json JSON cache (where map/number shapes differ).

func (Config) Validate

func (c Config) Validate() error

Validate checks the config's invariants, reporting the first offending field (the per-field-error style pack.Manifest.Validate uses). RootMarkers is required and every marker must be a safe relative path. Layers are optional, but each must have a non-empty, unique name and at least one Match glob, and every glob must be a safe relative path. A stated but empty `ext:` (all entries blank) is rejected — it reads as "some extensions" but scopes to none.

type Layer

type Layer struct {
	Name  string
	Match []string
}

Layer is one named slice of a project: a path matches the layer when any of its Match globs hits (see Match, which understands `**` across segments).

Jump to

Keyboard shortcuts

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