sdk

package
v0.7.3 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package sdk is the typed Go client over the funcd control-plane REST API (ADR-0024). It speaks the code-first huma surface (ADR-0005/0018) at /apis/funcd.io/v1alpha1/..., exposing a kind-parameterized CRUD surface (Apply/Get/List/Delete) typed via the v1.Object interface — no generics, no `any`. It is on the public surface and depends only on api/** + stdlib.

Index

Constants

View Source
const VoidSchema = `{"type":"null"}`

VoidSchema is the canonical void side (ADR-0090/0122): a contract side that carries no meaningful payload is the explicit JSON Schema {"type":"null"}, never an omission. Kept in pkg/sdk (not imported from internal/artifact) so funcdctl and the SDK share it without a package-boundary violation; the constant value matches internal/artifact.VoidSchema.

Variables

This section is empty.

Functions

func DecodeManifest

func DecodeManifest(data []byte) (v1.Object, error)

DecodeManifest parses a single-document resource manifest (apiVersion/kind/metadata/spec) into the concrete v1.Object. An unknown/empty kind is a fault.Invalid, never a panic; so is a manifest holding more than one document (DecodeManifests decodes each).

func DecodeManifests added in v0.2.1

func DecodeManifests(data []byte) ([]v1.Object, error)

DecodeManifests parses a manifest that may hold several YAML documents separated by "---" into one v1.Object per document, in order. Empty and comment-only documents are skipped; a manifest with no document is a fault.Invalid.

func GenerateTypes

func GenerateTypes(m *Manifest) (map[string][]byte, error)

GenerateTypes emits editor-facing declaration files from a manifest (ADR-0122 Decision 4): the FuncInput/FuncOutput payload types (from the contract JSON Schema) plus a typed binding context (from the declared aliases). python314 ⇒ a ".py" module (top-level-importable, no TYPE_CHECKING dance); nodejs22 ⇒ a ".d.ts" (imported with `import type`). This is DX-only — the platform never trusts these types; they exist to give the author editor autocomplete over the bounded funcd profile. The map is keyed by the file's basename; the caller writes each into the output directory.

func KindFromToken

func KindFromToken(token string) (v1.Kind, bool)

KindFromToken resolves a CLI token (plural, singular, or alias) to a v1.Kind.

func ReadOnlyKind added in v0.6.0

func ReadOnlyKind(k v1.Kind) bool

ReadOnlyKind reports whether the API serves only get and list for k: the Function reconciler writes every Revision (ADR-0172).

Types

type Backends

type Backends struct {
	// KV overrides the KVStore backend for ALL kv bindings ("memory" | a dsn/path override).
	KV string `json:"kv,omitempty"`
	// Blob overrides the Bucket backend for ALL blob bindings ("memory" | "file://…").
	Blob string `json:"blob,omitempty"`
	// Catalog overrides the CatalogService backend for ALL catalog bindings ("file://…", a local DuckLake).
	Catalog string `json:"catalog,omitempty"`
}

Backends selects the driver `funcdctl dev` auto-provisions for each backend kind (ADR-0125 Decision 4), GLOBAL per kind. The built-in default is memory (ephemeral); a `file://…` value selects a local-durable backend under `--persist`.

type Bindings

type Bindings struct {
	Blob     []v1.FunctionBlob    `json:"blob,omitempty"`
	KV       []v1.FunctionKV      `json:"kv,omitempty"`
	Catalogs []v1.FunctionCatalog `json:"catalogs,omitempty"`
	Links    []v1.FunctionLink    `json:"links,omitempty"`
	Config   []v1.ObjectName      `json:"config,omitempty"`
	Secrets  []v1.ObjectName      `json:"secrets,omitempty"`
}

Bindings reuses the v1alpha1 binding types 1:1 (ADR-0122 field map). The YAML shapes are those types' json shapes (alias/store/table, alias/bucket/prefix, …) — the capabilities the code uses at runtime, and the source GenerateTypes reads to emit the typed binding context.

type Client

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

Client is a typed Go client over the funcd control-plane REST API.

func New

func New(baseURL string, opts ...Option) (*Client, error)

New builds a Client. baseURL (e.g. "http://localhost:8080") is required.

func (*Client) Apply

func (c *Client) Apply(ctx context.Context, obj v1.Object) (v1.Object, error)

Apply create-or-replaces obj: PUT the named path; on a 404 (the object does not yet exist) POST the collection path to create it. Returns the stored object.

func (*Client) Create added in v0.2.1

func (c *Client) Create(ctx context.Context, obj v1.Object) (v1.Object, error)

Create creates obj by POSTing the collection path, never replacing an existing object: a taken name is a fault.Conflict. An empty name with GenerateName set lets the server assign one.

func (*Client) DeadLetter

func (c *Client) DeadLetter(ctx context.Context, ns v1.NamespaceName, id string) (deadletter.DeadLetter, error)

DeadLetter fetches one parked dead letter by id (ADR-0118), or fault.NotFound if absent.

func (*Client) DeadLetters

func (c *Client) DeadLetters(ctx context.Context, ns v1.NamespaceName) ([]deadletter.DeadLetter, error)

DeadLetters lists a namespace's parked dead letters, newest first (ADR-0118). Tenant-scoped by the caller's identity (get/Sensor in the namespace) — the namespace is the authorized path segment.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, kind v1.Kind, ns v1.NamespaceName, name v1.ObjectName, opts ...DeleteOption) error

Delete removes one object.

func (*Client) DiscardDeadLetter

func (c *Client) DiscardDeadLetter(ctx context.Context, ns v1.NamespaceName, id string) error

DiscardDeadLetter deletes a parked dead letter (ADR-0118) — a plain CRUD delete; absent is not an error server-side.

func (*Client) Get

func (c *Client) Get(ctx context.Context, kind v1.Kind, ns v1.NamespaceName, name v1.ObjectName) (v1.Object, error)

Get fetches one object.

func (*Client) HandoverKVStore added in v0.5.0

func (c *Client) HandoverKVStore(ctx context.Context, ns v1.NamespaceName, store, workflow v1.ObjectName) error

HandoverKVStore makes workflow the owner of the kept KVStore store, so that Workflow binds it again (ADR-0178). The caller needs KVStore update and delete and Workflow get in ns.

func (*Client) List

func (c *Client) List(ctx context.Context, kind v1.Kind, ns v1.NamespaceName) ([]v1.Object, error)

List fetches every object of a kind in a namespace.

func (*Client) Logs

Logs reads a function's logs from the control-plane logs route (ADR-0084). The result is tenant-scoped to the caller's authenticated identity by the server (admin sees any namespace, developer/viewer only a bound one) — the namespace is the authorized path segment, never a client-asserted filter.

func (*Client) ReplayDeadLetter

func (c *Client) ReplayDeadLetter(ctx context.Context, ns v1.NamespaceName, id string) error

ReplayDeadLetter re-injects a parked dead letter through the LIVE Sensor action path (ADR-0118 §3): ONE synchronous attempt. Success removes the entry (nil); failure re-parks it (Attempts reset) and returns the delivery error; a gone Sensor/action ⇒ fault.NotFound.

func (*Client) RunLogs

func (c *Client) RunLogs(ctx context.Context, ns v1.NamespaceName, run v1.ObjectName, o LogsOptions) ([]logread.Line, error)

RunLogs reads a whole workflow run's logs from the run-scoped control-plane route (ADR-0106): the server resolves the run's status.traceId and returns the namespace-wide, trace-filtered lines — every step function's output plus any sub-workflow child steps (one composition = one trace). Tenant-scoped by the caller's identity (get/WorkflowRun in the namespace). o.Step narrows to one step's function.

type Contract

type Contract struct {
	Input  json.RawMessage `json:"input"`
	Output json.RawMessage `json:"output"`
}

Contract is the manifest's inline I/O JSON Schema (ADR-0090/0122): both sides always present, a void side spelled VoidSchema. The two raw messages are gated (contract.Check) and baked schema-only.

type DeleteOption added in v0.4.0

type DeleteOption func(*deleteOptions)

DeleteOption tunes a Delete.

func Force added in v0.4.0

func Force() DeleteOption

Force deletes a ResourceGroup's members first, each under its own protections, then the group (ADR-0170). Delete refuses it with fault.Invalid for any other kind, before a request.

type Dev

type Dev struct {
	// Python is the interpreter `funcdctl dev` launches a python* handler with — a path relative to the
	// manifest dir (e.g. `.venv/bin/python`) or absolute. Lets a project pin its virtualenv (which carries
	// the handler's deps, ADR-0125's local-deps boundary) in the committable manifest instead of the
	// FUNCD_PYTHON env. Precedence: FUNCD_PYTHON env > this > `python3` on PATH. GLOBAL per run (the first
	// function's block is representative, like Backends).
	Python string `json:"python,omitempty"`
	// Node is the interpreter for a nodejs* handler (path relative to the manifest dir, or absolute).
	// Precedence: FUNCD_NODE env > this > `node` on PATH.
	Node string `json:"node,omitempty"`
	// Catalog declares the PROVIDER side of a `catalogs:` binding so `funcdctl dev` can stand the
	// CatalogService up locally, keyed by catalog name (matching a `bindings.catalogs[].catalog`). The
	// consumer binding names WHICH catalog; this block gives dev the storage layout it cannot infer (which
	// buckets/prefixes the DuckLake reads + owns) — the provider analogue of dev.backends. GLOBAL per run
	// (first function that declares a given catalog wins). Empty ⇒ no catalog auto-provisioned.
	Catalog map[string]DevCatalog `json:"catalog,omitempty"`
	// Backends overrides the auto-provisioned backend per kind, GLOBALLY (not per binding). Empty ⇒ the
	// built-in default (memory).
	Backends Backends `json:"backends,omitempty"`
	// Config carries inline ConfigMap values, keyed by ConfigMap name → {key: value}. Non-sensitive and
	// committable (a plain env inject in dev — no ConfigMap CRD on disk).
	Config map[string]map[string]string `json:"config,omitempty"`
	// Secrets carries Secret values keyed by Secret name → key → "${ENV_VAR}". The value is NEVER read
	// from the file — `funcdctl dev` resolves each ${ENV_VAR} from the process environment (a missing var
	// fails fast), so funcdctl.yaml stays committable.
	Secrets map[string]map[string]string `json:"secrets,omitempty"`
}

Dev is the funcdctl-dev-only manifest block (ADR-0125). `funcdctl dev` reads it to auto-provision a function's backing resources locally; `funcdctl push`/`types` ignore it. It is never a deploy field.

type DevCatalog

type DevCatalog struct {
	Blob    []v1.FunctionBlob `json:"blob,omitempty"`
	Catalog v1.CatalogRef     `json:"catalog"`
}

DevCatalog is the funcdctl-dev provider declaration for one catalog (the storage layout dev cannot infer from a consumer binding). Blob is the catalog engine's bucket bindings (read + own — the SAME shape as Function.spec.blob); Catalog is the (bucket, prefix) the DuckLake catalog syncs under (owned by the catalog). funcdctl dev synthesizes a CatalogService (name = the map key) + a Quack-token Secret from it.

type LogsOptions

type LogsOptions struct {
	Since    string // RFC3339 time or a Go duration ("15m"); "" ⇒ no lower bound
	Severity string // minimum level (trace|debug|info|warn|error|fatal); "" ⇒ all
	Limit    int    // max records (most-recent); <= 0 ⇒ the server default
	Step     string // RunLogs only (ADR-0106): narrow to one step's function (the --step drill-down); "" ⇒ all
}

LogsOptions are the optional filters for Client.Logs / Client.RunLogs (ADR-0084/0106).

type Manifest

type Manifest struct {
	// Runtime is the runtime class (e.g. python314, nodejs22) recorded as the push runtime annotation.
	Runtime v1.RuntimeName `json:"runtime"`
	// Handler is the entrypoint the shim resolves.
	Handler string `json:"handler"`
	// Main is the handler SOURCE FILE, relative to the manifest dir — the wrangler `main` convention
	// (wrangler.toml `main = "src/entry.py"`). Empty ⇒ the default entry co-located with the manifest
	// (handler.py for python*, handler.mjs otherwise, or `<stem>.py`/`<stem>.mjs` for a stem manifest).
	// It lets a `<stem>.funcdctl.yaml` point at a NESTED handler (e.g. functions/extract/handler.py),
	// so an existing per-function layout runs under `funcdctl dev` without flattening.
	Main string `json:"main,omitempty"`
	// Bindings holds blob/kv/catalogs/links/config/secrets — needed to run the function and to type its
	// binding context (GenerateTypes). It is not a deploy field; it describes the capabilities the code uses.
	Bindings Bindings `json:"bindings,omitempty"`
	// Contract is the inline {input, output} JSON Schema; both sides always present (a void side is VoidSchema).
	Contract Contract `json:"contract"`
	// Dev is the funcdctl-dev-only block (ADR-0125): auto-provisioned/globally-overridable backends,
	// inline ConfigMap values, and env-sourced Secret values. It is ADDITIVE and dev-only — `funcdctl
	// push` and `funcdctl types` ignore it entirely (they read only the four fields above), so a
	// funcdctl.yaml carrying a `dev:` block pushes and types identically to one without it.
	Dev Dev `json:"dev,omitempty"`
}

Manifest is the parsed funcdctl.yaml (ADR-0122): a colocated, per-function CLIENT push/dev config (the client-side analogue of wrangler.toml), NOT a deploy manifest. It carries only what the client tooling needs to push, run, and type a function — the runtime, the handler, the bindings, and the inline I/O contract. Deploy concerns (name, namespace, scaling, placement) live on the hand-written Function CRD, never here. funcdctl reads it to `push` (bake the schema-only contract + record the runtime annotation), `types` (contract → .pyi/.d.ts + a typed binding context), and — later — `dev`.

func LoadManifest

func LoadManifest(path string) (*Manifest, error)

LoadManifest reads and parses a funcdctl.yaml at path, then structurally validates it. It does NOT gate the contract against the funcd profile (that is the CLI layer's contract.Check, which lives in internal/ and must not be imported here) — only shape rules a manifest cannot be useful without.

func (*Manifest) ContractSides

func (m *Manifest) ContractSides() (input, output []byte, err error)

ContractSides returns the two JSON Schema sides for the push-time gate + bake (contract.Check + artifact.ContractBlob). Both are mandatory (ADR-0090); a void side is VoidSchema, never nil.

type ManifestDocument added in v0.2.2

type ManifestDocument struct {
	Number int
	Object v1.Object
}

ManifestDocument is one decoded manifest document and its 1-based position in the manifest, counted as the decode errors count it (skipped empty and comment-only documents included).

func DecodeManifestDocuments added in v0.2.2

func DecodeManifestDocuments(data []byte) ([]ManifestDocument, error)

DecodeManifestDocuments is DecodeManifests that also returns each object's document number, so a caller can name the document a later error belongs to (issue #316).

type Option

type Option func(*Client)

Option configures a Client (functional-options facade, ADR-0002).

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient overrides the HTTP client (default http.DefaultClient). A client without a CheckRedirect policy gets the SDK's, which refuses a redirect that would change the method.

func WithToken

func WithToken(token string) Option

WithToken sets the bearer token sent on every request (empty = unauthenticated).

Jump to

Keyboard shortcuts

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