aviato

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 23 Imported by: 0

README

Aviato Go SDK

Extend an Aviato agent with custom actions, computed fields, hooks, segments, search, write overrides, charts and custom datasources written in Go.

The agent calls your plugin over HTTP (ConnectRPC, JSON encoding) and signs every request with Standard Webhooks. Your code reads and writes records through the agent's Data API, under the caller's permissions and audit trail. It never queries the database directly.

Install

go get github.com/getaviato/aviato-go

Requires Go 1.25+. Connect the plugin to an existing Aviato agent. The SDK does not include the agent binary; automatic downloads require a working release URL.

Define a plugin

import aviato "github.com/getaviato/aviato-go"

plugin := aviato.MustNew(aviato.Options{
    Secret:   os.Getenv("AVIATO_PLUGIN_SECRET"), // whsec_…, shared with the agent
    BasePath: "/aviato",
})

plugin.Action("customers", "Refund last invoice", aviato.ScopeSingle,
    func(ctx context.Context, a *aviato.ActionContext) (aviato.Result, error) {
        if a.StringValue("reason") == "" {
            return a.Error("A reason is required"), nil
        }
        customers, err := a.Records(ctx) // read through the agent with the caller's permissions
        if err != nil {
            return nil, err
        }
        // … refund customers[0] …
        return a.Success("Refunded "+a.RecordID(), "invoices"), nil
    },
    aviato.WithForm(map[string]any{
        "type":       "object",
        "properties": map[string]any{"reason": map[string]any{"type": "string"}},
        "required":   []string{"reason"},
    }),
)

plugin.ComputedField("customers", "fullName", "string", []string{"first_name", "last_name"},
    func(ctx context.Context, inv *aviato.Invocation, records []aviato.Record) ([]any, error) {
        values := make([]any, len(records))
        for i, r := range records {
            values[i] = fmt.Sprintf("%v %v", r["first_name"], r["last_name"])
        }
        return values, nil
    })

plugin.Hook("customers", aviato.Before, aviato.HookUpdate,
    func(ctx context.Context, h *aviato.HookContext) (aviato.HookResult, error) {
        if h.Values["plan"] == "enterprise" {
            return aviato.HookResult{Reject: "Enterprise plans are set by sales"}, nil
        }
        return aviato.HookResult{}, nil // let it through unchanged
    })

The other registrations are Segment, Search, WriteOverride, Chart and RelationHints. Actions can return Success, Error, HTML, File (served once to the agent from GET <basePath>/files/{ref}), Redirect or Webhook. They take the options WithDescription, WithFormUI, WithGeneratesFile and WithFormResolver, which makes the form dynamic. a.Data is the full Data API client (List, Get, Create, Update, Delete).

If your relations are declared in GORM models rather than as foreign keys in the database:

hints, err := gormhints.RelationHintsFromGORM(&Customer{}, &Invoice{})
plugin.RelationHints(hints...)

Serve custom collections

Data the agent cannot reach through a database driver (an internal API, a SaaS, a file) can be served by your code as custom collections, under the same roles, row scopes, masking and audit trail as database collections:

plugin.Datasource(aviato.Datasource{
    Collections: []aviato.CustomCollection{{
        Name: "tickets",
        Fields: []aviato.CustomField{
            {Name: "id", Type: "number", ReadOnly: true, NotNull: true},
            {Name: "subject", Type: "string", NotNull: true},
        },
        // What List does itself; the agent does the rest in memory.
        Capabilities: aviato.Capabilities{FilterOperators: []string{"eq", "in"}, Sort: true, Count: true},
    }},
    List: func(ctx context.Context, d *aviato.DatasourceContext, q aviato.DatasourceQuery) (aviato.DatasourcePage, error) {
        records, total, err := helpdesk.Search(ctx, q.Filter, q.Sort, q.Limit, q.Offset)
        return aviato.DatasourcePage{Records: records, Total: total}, err
    },
    Create: func(ctx context.Context, d *aviato.DatasourceContext, values aviato.Record) (aviato.Record, error) {
        if values["subject"] == nil {
            return nil, aviato.NewDatasourceError(aviato.DatasourceInvalid, "A subject is required")
        }
        return helpdesk.Create(ctx, values)
    },
})

Get (defaults to a lookup through List), Create, Update and Delete are optional. For slow sources, Strategy: aviato.ReplicationStrategy with a ListChanges function lets the agent keep a copy, refreshed every ReplicationInterval and on demand with plugin.RefreshReplica(ctx, "tickets", dataURL). See the custom datasources guide.

Mount it

The handler expects the full request path, including BasePath.

// net/http
http.Handle("/aviato/", plugin.Handler())

// gin
import "github.com/getaviato/aviato-go/ginadapter"
ginadapter.Mount(router, plugin) // *gin.Engine or *gin.RouterGroup

// echo (v5)
import "github.com/getaviato/aviato-go/echoadapter"
echoadapter.Mount(e, plugin) // *echo.Echo or *echo.Group

Requests without a valid signature, or with one older than five minutes, get HTTP 401 before their body is decoded.

Run the agent

Download the agent binary for your platform and point it at your plugin with the same secret:

go run github.com/getaviato/aviato-go/cmd/aviato-agent-install@latest -out bin/aviato-agent

Use -version v1.2.3 to pin a release, -sha256 to verify the download, and -url (or AVIATO_AGENT_URL_TEMPLATE) to download from a mirror. The URL template takes the placeholders {release}, {version}, {os}, {arch} and {ext}.

Test your handlers

aviatotest calls your handlers with a fake caller, without an agent. It also serves an in-memory Data API that you seed with records:

func TestRefund(t *testing.T) {
    h := aviatotest.New(t, plugin,
        aviatotest.WithRecords("customers", aviato.Record{"id": "42", "name": "Acme"}))

    result, err := h.Execute(context.Background(), "customers", "Refund last invoice",
        aviatotest.Target{RecordIDs: []string{"42"}, Values: map[string]any{"reason": "Duplicate"}})
    require.NoError(t, err)
    assert.Equal(t, aviato.Success("Refunded 42", "invoices"), result)
    // h.Data().Records("customers") shows what the handler wrote.
}

The harness also offers ResolveForm, Compute, RunHook, WriteField, Segment, Search, Chart, and for custom datasources ListCustomRecords, GetCustomRecord, CreateCustomRecord, UpdateCustomRecord, DeleteCustomRecord and ListChanges. Values go through JSON as they do on the wire, so numbers arrive as float64.

Custom summaries and forms

plugin.Summary(collection, document) registers a native record overview. Use UIDocument, UIComponent, and UIBind to build the shared JSON format, or load the same document used by the TypeScript and Laravel SDKs. For action forms, keep the data schema in WithForm(schema) and pass the layout through WithFormUI(UIForm(document)).

The custom UI guide covers metric strips, property rows, reusable components, local state, field presets, and action buttons. Rendering uses Aviato's native design system without customer scripts or iframes. The agent still enforces permissions, validation, approvals, and auditing.

Development

The protocol bindings in pluginv1/ are generated from packages/protocol/proto. Regenerate them with buf generate (you need protoc-gen-go and protoc-gen-connect-go on your PATH).

pnpm exec nx run @aviato/sdk-go:test               # go test ./...
pnpm exec nx run @aviato/sdk-go:lint               # go vet + golangci-lint when installed
pnpm exec nx run @aviato/fixture-gin:conformance   # the conformance suite against the gin fixture

License

MIT. See LICENSE.

Ready-to-use provider widgets

Use the typed StripePlugin implementation of IntegrationPlugin to register read-only Stripe customer, subscription and invoice widgets with a local ID column or a belongsTo relation. Credentials live in the customer agent environment; SDK declarations contain only the environment variable name. The browser calls the customer agent directly, and provider data does not pass through Aviato infrastructure.

See the provider widget guide for registration examples and exact key permissions. Restricted key prefixes do not prove read-only permissions: the operator must configure Read/None permissions in Stripe and confirm readOnly; the adapter itself only sends GET requests.

Zendesk widgets

zendesk, err := aviato.NewZendeskPlugin(aviato.ZendeskPluginOptions{
    Subdomain: "northstar", CredentialEnv: "ZENDESK_WIDGET_TOKEN", ReadOnly: true,
})
if err != nil { return err }
zendesk.Tickets(aviato.ZendeskUserWidget{
    Collection: "customers", Name: "support",
    UserID: aviato.RecordBinding{Field: "zendesk_user_id"},
})
if err := plugin.Use(zendesk); err != nil { return err }

The typed integration also supports user profiles and individual tickets. Bind to a local ID column or one belongsTo relation. Install a customer agent with Zendesk support before using these APIs. These examples require core SDK 0.3.0 (and NestJS adapter 0.2.0 when used). SDK releases do not publish agent binaries.

Store the OAuth token on the customer agent, with users:read / tickets:read scopes. Before each read, the agent verifies actual scopes and rejects write-enabled tokens. Only the subdomain label and credential environment-variable name belong in SDK configuration. No provider credentials or responses pass through Aviato's control plane. See the Zendesk guide for all methods, permissions and release requirements.

Documentation

Overview

Package aviato extends an Aviato agent with custom actions, computed fields, hooks, segments, search, write overrides, charts and custom datasources written in Go.

The agent calls the plugin over HTTP (ConnectRPC, JSON encoding) and signs every request with the Standard Webhooks scheme; mount Plugin.Handler in your application under Options.BasePath. Plugin code reads and writes records through the agent's Data API (DataClient) with the caller's permissions, never behind its back.

Index

Constants

View Source
const (
	// ProtocolVersion is the plugin protocol version this SDK speaks.
	ProtocolVersion = 1
	// SDKName is reported to the agent in the manifest.
	SDKName = "github.com/getaviato/aviato-go"
	// SDKVersion is reported to the agent in the manifest.
	SDKVersion = "0.3.0"
)

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is wrapped by the errors returned for unknown actions, fields, segments, charts, searches and write overrides (reported to the agent as Connect code not_found).

Functions

func NewSigningClient

func NewSigningClient(secret string) (*http.Client, error)

NewSigningClient returns an HTTP client signing its requests with secret.

func UIBind

func UIBind(path string) map[string]any

UIBind reads an own-property JSON Pointer from record, form, state, props, or item.

func UIDocument

func UIDocument(root UINode) map[string]any

UIDocument wraps a root in the versioned UI protocol. Optional state and reusable components can be set on the returned document before registering it.

func UIForm

func UIForm(document map[string]any) map[string]any

UIForm embeds a document in an action's JSON Forms UI schema (WithFormUI).

Types

type ActionContext

type ActionContext struct {
	Invocation
	// RecordIDs are the selected record ids (single and bulk actions). Composite keys are
	// encoded "a|b".
	RecordIDs []string
	// Filter is the current filter of global actions (MongoDB query syntax).
	Filter map[string]any
	// Segment and Search are the current segment and search of global actions.
	Segment string
	Search  string
	// Values are the form values.
	Values map[string]any
}

ActionContext is passed to action handlers.

func (*ActionContext) Error

func (a *ActionContext) Error(message string) Result

Error reports a business error; see Error.

func (*ActionContext) File

func (a *ActionContext) File(name, mimeType string, content []byte) Result

File makes the user download content; see File.

func (*ActionContext) HTML

func (a *ActionContext) HTML(html string) Result

HTML shows HTML to the user; see HTML.

func (*ActionContext) RecordID

func (a *ActionContext) RecordID() string

RecordID returns the first selected record id, or "" (convenient for single actions).

func (*ActionContext) Records

func (a *ActionContext) Records(ctx context.Context, options ...RecordsOptions) ([]Record, error)

Records reads the records the action runs on through the agent: the selected records for single and bulk actions, the records matching the current filter for global actions.

func (*ActionContext) Redirect

func (a *ActionContext) Redirect(target string) Result

Redirect sends the user to a URL or dashboard path; see Redirect.

func (*ActionContext) StringValue

func (a *ActionContext) StringValue(key string) string

StringValue returns the form value key when it is a string, or "".

func (*ActionContext) Success

func (a *ActionContext) Success(message string, invalidated ...string) Result

Success reports a successful action; see Success.

func (*ActionContext) Webhook

func (a *ActionContext) Webhook(url, method string, headers map[string]string, body string) Result

Webhook makes the user's browser perform a request; see Webhook.

type ActionOption

type ActionOption func(*actionDef)

ActionOption configures an action.

func WithDescription

func WithDescription(description string) ActionOption

WithDescription describes the action to users and AI agents.

func WithForm

func WithForm(schema map[string]any) ActionOption

WithForm gives the action a form, as a JSON Schema describing the data.

func WithFormResolver

func WithFormResolver(resolve FormResolverFunc) ActionOption

WithFormResolver makes the form dynamic: resolve is called when the form opens and after each change to compute visibility, defaults, choices…

func WithFormUI

func WithFormUI(uiSchema map[string]any) ActionOption

WithFormUI lays the form out with a JSON Forms UI schema (layout, rules).

func WithGeneratesFile

func WithGeneratesFile() ActionOption

WithGeneratesFile declares that the action produces a file, downloaded instead of shown.

type Caller

type Caller struct {
	UserID string
	Name   string
	// ActorType is human, agent or api_key.
	ActorType string
	// Role is admin, editor, viewer or a custom role name.
	Role           string
	OrganizationID string
	ProjectID      string
	Environment    string
	RequestID      string
	// InvocationToken authenticates DataService calls made while handling this call.
	InvocationToken string
	// DataURL is the base URL of the agent's DataService.
	DataURL string
}

Caller describes who is calling the plugin and on what. It is sent with every plugin call.

type Capabilities

type Capabilities struct {
	// FilterOperators are the MongoDB operators List applies, without `$`: eq, ne, gt, gte, lt,
	// lte, in, nin, exists, regex, like, ilike, and the logical or and nor (negations arrive as
	// $nor; $and is always understood).
	FilterOperators []string
	// Sort is set when List sorts on any field.
	Sort bool
	// Count is set when List returns the total number of matching records.
	Count bool
}

Capabilities is what a collection's List handler does itself. The agent evaluates everything else in memory, over at most 2,000 records, and always checks the records you return against the caller's permissions.

type ChartFunc

type ChartFunc func(ctx context.Context, inv *Invocation, filter map[string]any) (map[string]any, error)

ChartFunc returns a Vega-Lite specification with its data inlined.

type ComputeFunc

type ComputeFunc func(ctx context.Context, inv *Invocation, records []Record) ([]any, error)

ComputeFunc computes a field for a page of records, returning one value per record in the same order.

type CustomCollection

type CustomCollection struct {
	Name   string
	Fields []CustomField
	// PrimaryKey defaults to ["id"]. Composite keys arrive as "a|b" in record ids.
	PrimaryKey []string
	// Relations to other collections (custom or database ones). Their Collection is set to Name.
	Relations    []RelationHint
	Capabilities Capabilities
	// Strategy overrides the datasource's strategy.
	Strategy DatasourceStrategy
	// ReplicationInterval is the time between two ListChanges pulls of a replicated collection
	// (whole seconds; zero: on demand only, see [Plugin.RefreshReplica]).
	ReplicationInterval time.Duration
}

CustomCollection declares a collection served by a Datasource.

type CustomField

type CustomField struct {
	Name string
	// Type is a protocol field type: string, number, boolean, date, dateonly, time, json, uuid,
	// enum or binary.
	Type       string
	EnumValues []string
	NotNull    bool
	ReadOnly   bool
	HasDefault bool
}

CustomField is a field of a custom collection. Fields are nullable unless NotNull is set.

type DataClient

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

DataClient reads and writes records through the agent's Data API, under the caller's permissions and audit trail. Plugin code must use it instead of querying the database directly. It authenticates with the invocation token of the call in progress, so it is only valid while that call is being handled.

func NewDataClient

func NewDataClient(caller Caller, httpClient *http.Client) *DataClient

NewDataClient returns a Data API client for the call made by caller. Handlers receive one already; this is for code that only has a Caller.

func (*DataClient) Create

func (c *DataClient) Create(ctx context.Context, collection string, values Record) (Record, error)

Create creates a record and returns it as stored.

func (*DataClient) Delete

func (c *DataClient) Delete(ctx context.Context, collection, id string) error

Delete deletes a record.

func (*DataClient) Get

func (c *DataClient) Get(ctx context.Context, collection, id string) (Record, error)

Get returns one record, or nil when the agent returned none.

func (*DataClient) List

func (c *DataClient) List(ctx context.Context, collection string, options ListOptions) (ListResult, error)

List returns a page of records of collection.

func (*DataClient) Update

func (c *DataClient) Update(ctx context.Context, collection, id string, values Record) (Record, error)

Update updates a record and returns it as stored.

type Datasource

type Datasource struct {
	Collections []CustomCollection
	// Strategy defaults to [TranslationStrategy].
	Strategy DatasourceStrategy
	// List is required.
	List DatasourceListFunc
	// Get defaults to looking the record up with List.
	Get DatasourceGetFunc
	// Create, Update and Delete are optional; without any of them the collections are
	// read-only.
	Create DatasourceCreateFunc
	Update DatasourceUpdateFunc
	Delete DatasourceDeleteFunc
	// ListChanges is required by replicated collections.
	ListChanges DatasourceChangesFunc
}

Datasource serves collections from your code: an internal API, a SaaS (Stripe, HubSpot), a file. The agent applies roles, row scopes, field masking and the audit trail as for its databases. Register it with Plugin.Datasource.

type DatasourceChanges

type DatasourceChanges struct {
	// Records created or updated since the cursor (full records).
	Records []Record
	// DeletedIDs are the ids of the records deleted since the cursor (composite keys as "a|b").
	DeletedIDs []string
	NextCursor string
	// HasMore is set when more changes are waiting: the agent calls again right away.
	HasMore bool
}

DatasourceChanges is what a ListChanges handler returns.

type DatasourceChangesFunc

type DatasourceChangesFunc func(ctx context.Context, d *DatasourceContext, cursor string) (DatasourceChanges, error)

DatasourceChangesFunc returns the changes since cursor (empty for a full copy).

type DatasourceContext

type DatasourceContext struct {
	// Collection is the name of the custom collection, as you declared it.
	Collection string
	// Caller is who the agent acts for; nil for the agent's own calls (replication).
	Caller *Caller
}

DatasourceContext is what every datasource handler receives about the call.

type DatasourceCreateFunc

type DatasourceCreateFunc func(ctx context.Context, d *DatasourceContext, values Record) (Record, error)

DatasourceCreateFunc creates a record and returns it as stored, with its primary key.

type DatasourceDeleteFunc

type DatasourceDeleteFunc func(ctx context.Context, d *DatasourceContext, id string) error

DatasourceDeleteFunc deletes a record.

type DatasourceError

type DatasourceError struct {
	Kind    DatasourceErrorKind
	Message string
}

DatasourceError is a business error of a datasource handler, shown to the user with its meaning. Return it (wrapped or not) from a handler:

return nil, aviato.NewDatasourceError(aviato.DatasourceInvalid, "A subject is required")

func NewDatasourceError

func NewDatasourceError(kind DatasourceErrorKind, message string) *DatasourceError

NewDatasourceError returns a DatasourceError.

func (*DatasourceError) Error

func (e *DatasourceError) Error() string

type DatasourceErrorKind

type DatasourceErrorKind string

DatasourceErrorKind is the meaning of a DatasourceError.

const (
	DatasourceNotFound  DatasourceErrorKind = "not_found"
	DatasourceInvalid   DatasourceErrorKind = "invalid"
	DatasourceConflict  DatasourceErrorKind = "conflict"
	DatasourceForbidden DatasourceErrorKind = "forbidden"
)

Datasource error kinds, shown to the user as HTTP 404, 422, 409 and 403.

type DatasourceGetFunc

type DatasourceGetFunc func(ctx context.Context, d *DatasourceContext, id string) (Record, error)

DatasourceGetFunc returns one record, or nil when there is none.

type DatasourceListFunc

type DatasourceListFunc func(ctx context.Context, d *DatasourceContext, query DatasourceQuery) (DatasourcePage, error)

DatasourceListFunc returns a page of the records matching query.

type DatasourcePage

type DatasourcePage struct {
	Records []Record
	// Total is the number of matching records; it defaults to len(Records).
	Total uint64
}

DatasourcePage is what a List handler returns.

type DatasourceQuery

type DatasourceQuery struct {
	// Filter in MongoDB query syntax, using only the declared operators (row scopes included).
	// Nil when there is none.
	Filter map[string]any
	// Sort is empty unless the collection declares Capabilities.Sort.
	Sort []SortField
	// Limit is 0 for every matching record.
	Limit  uint32
	Offset uint32
	// Fields to return (empty: all); returning more is fine.
	Fields []string
	// IncludeTotal asks for [DatasourcePage.Total] (when the collection declares Count).
	IncludeTotal bool
}

DatasourceQuery is what the agent asks a List handler for.

type DatasourceStrategy

type DatasourceStrategy int

DatasourceStrategy is how the agent serves a custom collection.

const (
	// TranslationStrategy (the default) forwards every read and write to the plugin when it
	// happens.
	TranslationStrategy DatasourceStrategy = iota + 1
	// ReplicationStrategy makes the agent copy the collection with [Datasource.ListChanges] and
	// serve reads from its copy; writes still go to the plugin.
	ReplicationStrategy
)

type DatasourceUpdateFunc

type DatasourceUpdateFunc func(ctx context.Context, d *DatasourceContext, id string, values Record) (Record, error)

DatasourceUpdateFunc updates a record and returns it as stored.

type ErrorResult

type ErrorResult struct {
	Message string
	// HTML is an optional rich explanation, sanitized by the dashboard.
	HTML string
}

ErrorResult reports a business error (a failed validation, a refused operation).

func Error

func Error(message string) ErrorResult

Error reports a business error to the user.

type ExecuteFunc

type ExecuteFunc func(ctx context.Context, a *ActionContext) (Result, error)

ExecuteFunc runs an action.

type FieldOption

type FieldOption func(*computedDef)

FieldOption configures a computed field.

func WithEmulatedFilterSort

func WithEmulatedFilterSort() FieldOption

WithEmulatedFilterSort lets the agent sort and filter on the field by computing it in memory, within a bounded number of records.

func WithEnumValues

func WithEnumValues(values ...string) FieldOption

WithEnumValues lists the possible values of an enum computed field.

type FileResult

type FileResult struct {
	Name     string
	MimeType string
	Content  []byte
}

FileResult is downloaded by the user. The SDK keeps the content for five minutes and serves it once, to the agent, from GET <basePath>/files/{ref}.

func File

func File(name, mimeType string, content []byte) FileResult

File makes the user download content.

type Form

type Form struct {
	Schema   map[string]any
	UISchema map[string]any
}

Form is an action form: a JSON Schema describing the data and an optional JSON Forms UI schema laying it out.

type FormContext

type FormContext struct {
	ActionContext
	// ChangedField is the field that just changed, empty when the form opens.
	ChangedField string
}

FormContext is passed to form resolvers.

type FormResolution

type FormResolution struct {
	Form *Form
	// Values to set in the form (defaults, recomputed values).
	Values map[string]any
}

FormResolution is what a form resolver returns. A nil Form keeps the declared form.

type FormResolverFunc

type FormResolverFunc func(ctx context.Context, f *FormContext) (FormResolution, error)

FormResolverFunc recomputes an action form when it opens and after each change.

type HTMLResult

type HTMLResult struct {
	HTML string
}

HTMLResult shows HTML to the user (sanitized by the dashboard).

func HTML

func HTML(html string) HTMLResult

HTML shows HTML to the user.

type HookContext

type HookContext struct {
	Invocation
	Timing    HookTiming
	Operation HookOperation
	RecordIDs []string
	// Values being written (create and update).
	Values map[string]any
	// Action is the action name, for action hooks.
	Action string
}

HookContext is passed to hooks.

type HookFunc

type HookFunc func(ctx context.Context, h *HookContext) (HookResult, error)

HookFunc runs a hook.

type HookOperation

type HookOperation int

HookOperation is the operation a hook is attached to.

const (
	HookCreate HookOperation = iota + 1
	HookUpdate
	HookDelete
	HookList
	HookAction
)

Hook operations.

type HookResult

type HookResult struct {
	// Reject rejects the operation with this message (before hooks only).
	Reject string
	// Values replace the values being written (before hooks on create and update).
	Values map[string]any
}

HookResult is what a hook returns. The zero value lets the operation through unchanged.

type HookTiming

type HookTiming int

HookTiming says whether a hook runs before or after the operation.

const (
	// Before hooks may reject the operation or replace the values being written.
	Before HookTiming = iota + 1
	// After hooks run once the operation succeeded.
	After
)

type IntegrationPlugin added in v0.3.0

type IntegrationPlugin interface {
	Widgets() []WidgetDefinition
}

IntegrationPlugin declares a customer-side provider integration. Use snapshots its widgets.

type Invocation

type Invocation struct {
	Caller Caller
	// Collection concerned by the call (empty for charts not bound to one).
	Collection string
	// Data reads and writes records through the agent with the caller's permissions.
	Data *DataClient
}

Invocation is what every handler receives about the call in progress.

type ListOptions

type ListOptions struct {
	// Filter in MongoDB query syntax.
	Filter map[string]any
	// Sort is a field name, prefixed with - for a descending sort.
	Sort string
	// Limit defaults to 50.
	Limit  uint32
	Offset uint32
	// Fields to return; all readable fields when empty.
	Fields []string
}

ListOptions narrows a DataClient.List call.

type ListResult

type ListResult struct {
	Records []Record
	Total   uint64
}

ListResult is a page of records and the total number of matching records.

type Options

type Options struct {
	// Secret is shared with the agent, in the Standard Webhooks format (whsec_<base64>).
	// Requests with a missing, invalid or stale (over five minutes) signature are rejected.
	Secret string
	// BasePath is the mount path of the plugin in your application, for example /aviato.
	BasePath string
	// HTTPClient is used to call the agent's Data API; defaults to http.DefaultClient.
	HTTPClient *http.Client
	// FileTTL is how long file results stay downloadable; defaults to five minutes.
	FileTTL time.Duration
	// MaxRequestBytes bounds request bodies; defaults to 10 MiB.
	MaxRequestBytes int64
}

Options configure a Plugin.

type Plugin

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

Plugin extends an Aviato agent. Register handlers with its methods, which return the plugin for chaining, then serve Plugin.Handler. Registration methods panic on invalid definitions (a missing handler), like http.ServeMux does.

func MustNew

func MustNew(options Options) *Plugin

MustNew is like New but panics on error.

func New

func New(options Options) (*Plugin, error)

New returns a plugin. It fails when the secret is missing or not in the whsec_<base64> format.

func (*Plugin) Action

func (p *Plugin) Action(collection, name string, scope Scope, execute ExecuteFunc, options ...ActionOption) *Plugin

Action registers an action on collection. Its name is unique within the collection.

func (*Plugin) BasePath

func (p *Plugin) BasePath() string

BasePath is the mount path of the plugin, without trailing slash.

func (*Plugin) Chart

func (p *Plugin) Chart(name, collection string, compute ChartFunc) *Plugin

Chart registers a chart computed by the plugin.

func (*Plugin) ComputedField

func (p *Plugin) ComputedField(collection, name, fieldType string, dependencies []string, compute ComputeFunc, options ...FieldOption) *Plugin

ComputedField registers a field computed from the dependencies of each record. fieldType is a protocol field type: string, number, boolean, date, dateonly, json, enum…

func (*Plugin) Datasource

func (p *Plugin) Datasource(datasource Datasource) *Plugin

Datasource registers collections served by your code, browsed and edited like database collections under the same permissions and audit trail. It panics when List is missing, when a replicated collection has no ListChanges, or when a collection name is declared twice.

func (*Plugin) DescribeCollections

func (p *Plugin) DescribeCollections() *pluginv1.DescribeCollectionsResponse

DescribeCollections describes the custom collections, as sent to the agent.

func (*Plugin) Handler

func (p *Plugin) Handler() http.Handler

Handler returns the net/http handler serving the plugin protocol. Mount it so that it receives the full request path, prefix included, under Options.BasePath:

mux.Handle("/aviato/", plugin.Handler())

It serves the PluginService procedures (ConnectRPC, JSON or binary encoding) at <basePath>/aviato.plugin.v1.PluginService/<Method>, the DatasourceService procedures of custom datasources at <basePath>/aviato.plugin.v1.DatasourceService/<Method>, and one-time file downloads at GET <basePath>/files/{ref}. Every request must carry a valid Standard Webhooks signature; others are rejected with HTTP 401 before their body is decoded.

func (*Plugin) Hook

func (p *Plugin) Hook(collection string, timing HookTiming, operation HookOperation, run HookFunc) *Plugin

Hook registers a hook run before or after an operation on collection. Several hooks may be registered for the same operation; they run in registration order.

func (*Plugin) Manifest

func (p *Plugin) Manifest() (*pluginv1.Manifest, error)

Manifest declares what the plugin provides, as sent to the agent.

func (*Plugin) RefreshReplica

func (p *Plugin) RefreshReplica(ctx context.Context, collection, dataURL string) (ReplicaRefresh, error)

RefreshReplica asks the agent to pull the changes of a replicated collection now, for example from a webhook of the source. dataURL is the agent's Data API (Caller.DataURL, <agent URL>/plugin-data). The request is signed with the plugin secret.

func (*Plugin) RelationHints

func (p *Plugin) RelationHints(hints ...RelationHint) *Plugin

RelationHints declares relations the agent cannot introspect from the database. See the gormhints package to derive them from GORM models.

func (*Plugin) Search

func (p *Plugin) Search(collection string, search SearchFunc, options ...SearchOption) *Plugin

Search registers the search of collection: it turns the query into a filter.

func (*Plugin) Segment

func (p *Plugin) Segment(collection, name string, resolve SegmentFunc) *Plugin

Segment registers a code segment of collection.

func (*Plugin) ServeHTTP

func (p *Plugin) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP makes the plugin itself an http.Handler; see Plugin.Handler.

func (*Plugin) Summary

func (p *Plugin) Summary(collection string, document map[string]any) *Plugin

Summary registers a declarative record overview. Re-registering replaces the definition.

func (*Plugin) Use added in v0.3.0

func (p *Plugin) Use(integration IntegrationPlugin) error

Use atomically installs a snapshot of an integration. Re-registering replaces named widgets.

func (*Plugin) WriteOverride

func (p *Plugin) WriteOverride(collection, field string, write WriteFunc) *Plugin

WriteOverride registers custom write behaviour for a field (for example splitting a full name into first and last names).

type Record

type Record = map[string]any

Record is a record as exchanged with the agent: column names to JSON values.

type RecordBinding added in v0.3.0

type RecordBinding struct {
	Field    string
	Relation string
}

RecordBinding selects a column on this record or on one belongsTo relation.

type RecordsOptions

type RecordsOptions struct {
	// Fields to read; all readable fields when empty (global actions only).
	Fields []string
	// Limit on the number of records of global actions; defaults to 200.
	Limit uint32
}

RecordsOptions narrows ActionContext.Records.

type RedirectResult

type RedirectResult struct {
	Path string
	URL  string
}

RedirectResult sends the user to an internal dashboard path or an absolute URL.

func Redirect

func Redirect(target string) RedirectResult

Redirect sends the user to target: an absolute URL (with a scheme) or an internal dashboard path.

type RelationHint

type RelationHint struct {
	Collection string
	Name       string
	Kind       RelationKind
	ForeignKey []string
	Target     string
	TargetKey  []string
}

RelationHint declares a relation the agent cannot introspect from the database (for example when the schema has no foreign key constraints). ForeignKey always holds the referencing columns and TargetKey the referenced ones, whichever side the relation is declared on: on BelongsTo the foreign key is local, otherwise it is on the target.

type RelationKind

type RelationKind string

RelationKind is the kind of a relation hint.

const (
	BelongsTo RelationKind = "belongsTo"
	HasMany   RelationKind = "hasMany"
	HasOne    RelationKind = "hasOne"
)

Relation kinds.

type ReplicaRefresh

type ReplicaRefresh struct {
	Collection string `json:"collection"`
	Upserted   int    `json:"upserted"`
	Deleted    int    `json:"deleted"`
	Cursor     string `json:"cursor"`
}

ReplicaRefresh is the agent's answer to Plugin.RefreshReplica.

type Result

type Result interface {
	// contains filtered or unexported methods
}

Result is what an action returns: build one with Success, Error, HTML, File, Redirect or Webhook (or the matching ActionContext methods).

type Scope

type Scope int

Scope is what an action runs on.

const (
	// ScopeSingle actions run on one record.
	ScopeSingle Scope = iota + 1
	// ScopeBulk actions run on a selection of records.
	ScopeBulk
	// ScopeGlobal actions run on the collection, with the current filters, segment and search.
	ScopeGlobal
)

type SearchFunc

type SearchFunc func(ctx context.Context, inv *Invocation, query string) (map[string]any, error)

SearchFunc turns a search query into a filter (MongoDB query syntax).

type SearchOption

type SearchOption func(*searchDef)

SearchOption configures a search.

func WithReplacedSearch

func WithReplacedSearch() SearchOption

WithReplacedSearch makes the plugin search replace the agent's search entirely instead of being combined with it.

type SegmentFunc

type SegmentFunc func(ctx context.Context, inv *Invocation) (SegmentResult, error)

SegmentFunc resolves a code segment.

type SegmentResult

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

SegmentResult is what a segment resolves to; build it with SegmentFilter or SegmentIDs.

func SegmentFilter

func SegmentFilter(filter map[string]any) SegmentResult

SegmentFilter resolves a segment to a filter the agent applies (preferred).

func SegmentIDs

func SegmentIDs(ids ...string) SegmentResult

SegmentIDs resolves a segment to explicit record ids.

func (SegmentResult) Filter

func (s SegmentResult) Filter() (map[string]any, bool)

Filter returns the segment filter, if the segment resolves to one.

func (SegmentResult) IDs

func (s SegmentResult) IDs() ([]string, bool)

IDs returns the record ids, if the segment resolves to explicit ids.

type SigningTransport

type SigningTransport struct {

	// Base performs the requests; defaults to http.DefaultTransport.
	Base http.RoundTripper
	// Now returns the signing time; defaults to time.Now.
	Now func() time.Time
	// contains filtered or unexported fields
}

SigningTransport is an http.RoundTripper signing request bodies with the Standard Webhooks scheme, as the agent does when it calls a plugin. It is meant for tests and tooling that call a plugin like the agent would.

func NewSigningTransport

func NewSigningTransport(secret string) (*SigningTransport, error)

NewSigningTransport returns a transport signing with secret (whsec_<base64>).

func (*SigningTransport) RoundTrip

func (t *SigningTransport) RoundTrip(request *http.Request) (*http.Response, error)

RoundTrip signs a copy of request and sends it.

type SortField

type SortField struct {
	Field string
	Desc  bool
}

SortField is one key of a DatasourceQuery sort.

type StripeCustomerWidget added in v0.3.0

type StripeCustomerWidget struct {
	Collection string
	Name       string
	Title      string
	CustomerID RecordBinding
}

StripeCustomerWidget binds a customer detail or list widget to a Stripe customer ID.

type StripeInvoiceWidget added in v0.3.0

type StripeInvoiceWidget struct {
	Collection string
	Name       string
	Title      string
	InvoiceID  RecordBinding
}

StripeInvoiceWidget binds a single invoice by its Stripe invoice ID.

type StripePlugin added in v0.3.0

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

StripePlugin implements IntegrationPlugin with typed Stripe resources and bindings.

func NewStripePlugin added in v0.3.0

func NewStripePlugin(options StripePluginOptions) (*StripePlugin, error)

NewStripePlugin configures a typed integration with an agent-local credential reference.

func (*StripePlugin) Customer added in v0.3.0

func (s *StripePlugin) Customer(widget StripeCustomerWidget) *StripePlugin

Customer adds customer details.

func (*StripePlugin) Invoice added in v0.3.0

func (s *StripePlugin) Invoice(widget StripeInvoiceWidget) *StripePlugin

Invoice adds one invoice, bound by invoice ID.

func (*StripePlugin) Invoices added in v0.3.0

func (s *StripePlugin) Invoices(widget StripeCustomerWidget) *StripePlugin

Invoices adds a customer’s invoice preview.

func (*StripePlugin) Subscription added in v0.3.0

func (s *StripePlugin) Subscription(widget StripeSubscriptionWidget) *StripePlugin

Subscription adds one subscription, bound by subscription ID.

func (*StripePlugin) Subscriptions added in v0.3.0

func (s *StripePlugin) Subscriptions(widget StripeCustomerWidget) *StripePlugin

Subscriptions adds a customer’s subscription preview, including canceled subscriptions.

func (*StripePlugin) Widgets added in v0.3.0

func (s *StripePlugin) Widgets() []WidgetDefinition

Widgets returns a copy of the provider declarations for host registration.

type StripePluginOptions added in v0.3.0

type StripePluginOptions struct {
	CredentialEnv string
	ReadOnly      bool
}

StripePluginOptions refers to a restricted key in the customer agent environment. ReadOnly confirms the operator has configured Read/None permissions in Stripe.

type StripeSubscriptionWidget added in v0.3.0

type StripeSubscriptionWidget struct {
	Collection     string
	Name           string
	Title          string
	SubscriptionID RecordBinding
}

StripeSubscriptionWidget binds a single subscription by its Stripe subscription ID.

type SuccessResult

type SuccessResult struct {
	Message string
	// Invalidated lists relations of the target record the dashboard should refresh.
	Invalidated []string
}

SuccessResult reports a successful action.

func Success

func Success(message string, invalidated ...string) SuccessResult

Success reports a successful action, optionally invalidating relations of the target record.

type UINode

type UINode = map[string]any

UINode is a serializable native UI component. The agent and dashboard validate UI v1. Use UIBind for live data; strings are always literal text, never expressions or HTML.

func UIComponent

func UIComponent(kind string, props map[string]any, children ...UINode) UINode

UIComponent creates a native node. Allowed types and props are documented in UI v1.

type WebhookResult

type WebhookResult struct {
	URL     string
	Method  string
	Headers map[string]string
	Body    string
}

WebhookResult is an HTTP request performed by the user's browser (never by AI agents).

func Webhook

func Webhook(url, method string, headers map[string]string, body string) WebhookResult

Webhook makes the user's browser perform an HTTP request. The method defaults to POST.

type WidgetDefinition added in v0.3.0

type WidgetDefinition struct {
	Collection      string
	Name            string
	Title           string
	Provider        string
	Resource        string
	BindingField    string
	BindingRelation string
	CredentialEnv   string
	ReadOnly        bool
	Account         string
}

WidgetDefinition is the common metadata contract for integration authors, never credentials.

type WriteFunc

type WriteFunc func(ctx context.Context, inv *Invocation, value any, record Record) (map[string]any, error)

WriteFunc turns a value written to a virtual field into column values.

type ZendeskPlugin added in v0.3.0

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

ZendeskPlugin implements IntegrationPlugin with typed Zendesk resources.

func NewZendeskPlugin added in v0.3.0

func NewZendeskPlugin(options ZendeskPluginOptions) (*ZendeskPlugin, error)

NewZendeskPlugin configures a tenant and an agent-local OAuth credential reference.

func (*ZendeskPlugin) Ticket added in v0.3.0

func (z *ZendeskPlugin) Ticket(widget ZendeskTicketWidget) *ZendeskPlugin

Ticket adds one ticket, bound by ticket ID.

func (*ZendeskPlugin) Tickets added in v0.3.0

func (z *ZendeskPlugin) Tickets(widget ZendeskUserWidget) *ZendeskPlugin

Tickets adds a preview of tickets requested by the bound user. Ticket adds one ticket, bound by ticket ID.

func (*ZendeskPlugin) User added in v0.3.0

User adds a Zendesk user profile.

func (*ZendeskPlugin) Widgets added in v0.3.0

func (z *ZendeskPlugin) Widgets() []WidgetDefinition

Widgets returns a copy of the declarations for host registration.

type ZendeskPluginOptions added in v0.3.0

type ZendeskPluginOptions struct {
	Subdomain     string
	CredentialEnv string
	ReadOnly      bool
}

ZendeskPluginOptions references an agent-local OAuth token and a Zendesk subdomain label. The agent verifies that the token has only read scopes before loading data.

type ZendeskTicketWidget added in v0.3.0

type ZendeskTicketWidget struct {
	Collection string
	Name       string
	Title      string
	TicketID   RecordBinding
}

ZendeskTicketWidget binds a single ticket by ID.

type ZendeskUserWidget added in v0.3.0

type ZendeskUserWidget struct {
	Collection string
	Name       string
	Title      string
	UserID     RecordBinding
}

ZendeskUserWidget binds a profile or requested-ticket list to a Zendesk user ID.

Directories

Path Synopsis
Package aviatotest calls a plugin's registered actions, computed fields, hooks, segments, searches, write overrides, charts and custom datasources in unit tests, with a fake caller and without an agent.
Package aviatotest calls a plugin's registered actions, computed fields, hooks, segments, searches, write overrides, charts and custom datasources in unit tests, with a fake caller and without an agent.
cmd
aviato-agent-install command
Command aviato-agent-install downloads the Aviato agent binary for the current (or given) platform:
Command aviato-agent-install downloads the Aviato agent binary for the current (or given) platform:
Package echoadapter mounts an Aviato plugin on an echo (v5) server.
Package echoadapter mounts an Aviato plugin on an echo (v5) server.
Package ginadapter mounts an Aviato plugin on a gin engine.
Package ginadapter mounts an Aviato plugin on a gin engine.
Package gormhints derives Aviato relation hints from GORM models, for databases whose relations are declared in code rather than with foreign key constraints.
Package gormhints derives Aviato relation hints from GORM models, for databases whose relations are declared in code rather than with foreign key constraints.
internal
agentinstall
Package agentinstall downloads the Aviato agent binary for a platform.
Package agentinstall downloads the Aviato agent binary for a platform.
bridge
Package bridge gives the aviatotest harness access to the plugin's dispatch methods without making them part of the public API.
Package bridge gives the aviatotest harness access to the plugin's dispatch methods without making them part of the public API.

Jump to

Keyboard shortcuts

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