Help us shape the future of Go! Take the 2026 Go Developer Survey

flowi

package module
v0.1.0-alpha.3 Latest Latest
Warning

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

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

README

flowi-lib

The core library of Flow-I: everything that is not a user interface. The CLI and the desktop app are thin layers over it, and other Go programs can embed it.

Status: pre-alpha. The file format and the API will change.

Why Flow-I

Most API tools stop at the single request. Real work is a journey: log in, take the token, verify, fill in a form, check the result. Flow-I keeps a library of requests and chains them into flows, such as:

Login → extract token → Verify → generate form values → Form page 1 → delay → Form page 2

  • Plain files. Collections are YAML in your own git repository. Secrets and run history live in a local workspace that is never committed.
  • Reusable requests. Requests have versions (1, 1.1, 2), pinned examples and pre/post hooks.
  • Flows you can run anywhere. The same flow runs in the app, in CI (flowi run) or on a schedule.
  • Standards, not lock-in. OpenAPI, AsyncAPI, Arazzo, .proto, HAR, curl and Mermaid come in; Arazzo and Mermaid go out.
  • Safe changes. Impact analysis shows which flows and hooks break when a request changes.

What is in this repository

Area Packages What it does
Model and storage model, store, workspace, validate, schema Collections, requests, flows and environments as YAML; validation with positioned diagnostics (FLW-… codes); JSON Schemas for editors
Requests engine, template, transport, grpcx, snippet HTTP, gRPC and message requests (Kafka, MQTT, AMQP, NATS, Redis, SQS, SNS, Pub/Sub, Service Bus, WebSocket, SSE); {{templates}} and generators; cookies, retries, HTTP/3; code snippets (curl and more)
Flows engine, blueprint, analysis Flow runtime with 20+ node types (extract, assert, condition, batch, parallel, run_till, subflow, …); reports (JUnit, JSON, Markdown); templates; impact analysis
Secrets vault Encrypted vault with the key in the OS keychain; secrets are masked everywhere
Interop openapi, asyncapi, arazzo, importers/*, mermaid, specoverlay Import and export, with a per-item report; nothing is guessed
Serving serve/* The replayer (saved responses as a fake API, or record from a real one), HTTP flow triggers and cron schedules, with a clean shutdown
Operations otel, telemetry, announce, changelog Optional and off by default: OpenTelemetry traces, opt-in usage reporting, signed announcements

The Go API is the flowi package itself (Workspace and its methods).

Use it from Go

go get github.com/githugt/flowi-lib@latest
paths, _ := settings.DiscoverPaths(os.Environ())
home, _ := os.UserHomeDir()
ws, problems, err := flowi.OpenWorkspace(ctx, flowi.WorkspaceOptions{
	Paths: paths, Environ: os.Environ(), Home: home, Keys: vault.OSKeyStore(),
})
// problems are what the files got wrong; err is only for system failures

flow, _ := ws.FindFlow("user-creation", "")
run, _ := ws.RunFlow(ctx, flow, flowi.RunOptions{Env: "local"})
fmt.Println(run.Wait().Status) // run.Events() streams progress while it runs

ws.FindRequest and ws.SendRequest do the same for a single request.

Try it

examples/user-creation is a complete collection, and examples/demoserver is the small API it talks to. With the CLI installed:

go run ./examples/demoserver/cmd/flowi-demo-server &   # http://127.0.0.1:8080, password "demo"
export FLOWI_CONFIG_DIR=$PWD/.try FLOWI_SECRET_LOCAL_PASSWORD=demo
flowi workspace mount ./examples/user-creation
# environments belong to the workspace, so copy the example's there
mkdir -p .try/workspaces/default/environments && cp examples/user-creation/environments/*.yaml .try/workspaces/default/environments/
flowi run user-creation --env local                    # login → verify → onboarding
flowi run onboarding-check --env local                 # subflows, batch, parallel, run_till, digest
flowi impact auth/login                                # who uses this request, and does it still fit?

More

Development

just check     # tidy, lint and test with the race detector

Needs Go 1.27 or later and just. No cgo.

Licence

Apache-2.0. See LICENSE and NOTICE.

Documentation

Overview

Package flowi is the core library of Flow-I, an open-source tool for composing API requests into flows.

It owns everything that is not user interface: the collection and flow model, on-disk storage, validation, request execution, the flow engine and impact analysis. The Flow-I CLI and GUI are thin layers over this package, and other programs may embed it directly.

Index

Constants

View Source
const (
	StoredSaved   = "saved"   // a response a send or the recorder kept, in the workspace data folder
	StoredExample = "example" // a pinned example, next to the request file and committed with the collection
)

What a stored response is.

View Source
const (
	TrashRequest = "request"
	TrashFlow    = "flow"
)

Kinds of what the trash holds.

View Source
const (
	ChangeCreated  = store.ChangeCreated
	ChangeModified = store.ChangeModified
	ChangeRemoved  = store.ChangeRemoved
	ChangeRescan   = store.ChangeRescan
)

Change operations, re-exported from store.

Variables

View Source
var ErrInvalidServeOptions = errors.New("invalid serve options")

ErrInvalidServeOptions is returned by Serve for options that cannot work (as opposed to a system failure such as a port in use).

View Source
var ErrNoKeptSpec = errors.New("the collection keeps no spec of that name")

ErrNoKeptSpec is returned for a kept spec name the collection does not have.

View Source
var ErrNotDraft = errors.New("the collection is not a draft")

ErrNotDraft is returned when a draft-only operation is asked of a collection that lives in the user's own folder.

View Source
var ErrNotFromSpec = errors.New("the request was not imported from a spec kept in the collection")

ErrNotFromSpec is returned for a request no kept spec makes.

View Source
var ErrShutdownTimeout = errors.New("requests or runs were still going at the shutdown timeout and were cancelled")

ErrShutdownTimeout is returned by Server.Wait when requests or runs were still going after ServeOptions.ShutdownTimeout and had to be cancelled.

View Source
var ErrStoredKind = errors.New("a stored response is saved or an example")

ErrStoredKind is returned for a kind that is not StoredSaved or StoredExample.

View Source
var ErrWorkspaceName = errors.New("a workspace needs a name")

ErrWorkspaceName is returned by Rename for a name that is empty once trimmed.

Functions

func ApplyChanges

func ApplyChanges(changes []FileChange) error

ApplyChanges writes formatting changes atomically.

func BlocksRewrite

func BlocksRewrite(d diag.Diagnostic) bool

BlocksRewrite reports whether a load diagnostic means Flow-I must not rewrite that file: errors (content was not understood) and unknown settings (which a rewrite would drop).

func CheckExampleName

func CheckExampleName(name string) error

CheckExampleName refuses pin names that are not plain file names (FLW-REQ-007), so callers can check before sending. "" is allowed and means "name it after the status".

func FetchImportSource

func FetchImportSource(ctx context.Context, rawURL string) (data []byte, name string, err error)

FetchImportSource downloads the document at rawURL (an OpenAPI or AsyncAPI description served by an API, say) and returns it with a name for reports, the last segment of the URL path ("openapi.json"). It sends no credentials and follows redirects; a status other than 200 is an error.

func IsImportURL

func IsImportURL(ref string) bool

IsImportURL reports whether ref is an http or https URL to fetch rather than a file to read.

func UserSettings

func UserSettings(p settings.Paths, environ []string, flags settings.LayerValues) (settings.Resolved, diag.List, error)

UserSettings resolves settings from the user file, FLOWI_* variables and flags only, without opening (or creating) a workspace. Applications use it for personal settings needed before a workspace exists, such as logging.

func UserSettingsFile

func UserSettingsFile(p settings.Paths) string

UserSettingsFile is where the user's personal settings live.

Types

type ApplyOptions

type ApplyOptions struct {
	Overwrite    bool // replace them (requests and flows keep their ids)
	SkipExisting bool // leave them and write only the new files
}

ApplyOptions decide what happens to files that already exist. Without either, ApplyImport refuses (FLW-IMPORT-003) and writes nothing.

type BlueprintTarget

type BlueprintTarget struct {
	Collection model.ID
	Blueprint  model.ID
}

BlueprintTarget identifies a blueprint of a mounted collection.

type Change

type Change = store.Change

Change is a watched file change (see store.Change).

type Completion

type Completion struct {
	Text, Detail string
}

Completion is something a template at a node can read, for editor autocomplete: Text is the reference (nodes.login.token), Detail says where it comes from.

type CookieInfo

type CookieInfo struct {
	Key      string // identifies the cookie (name, domain, path) for DeleteCookie
	Name     string
	Value    string
	Domain   string // where it applies; the host that set it when the cookie names none
	Path     string
	Expires  time.Time // zero for a session cookie
	Secure   bool
	HTTPOnly bool
}

CookieInfo is one cookie in a collection's saved jar, the one standalone sends share.

type FileChange

type FileChange = store.FileChange

FileChange is a pending formatting change (see store.FileChange).

type FlowTarget

type FlowTarget struct {
	Collection model.ID
	Flow       model.ID
}

FlowTarget identifies a flow of a mounted collection.

type FlowText

type FlowText struct {
	Flow string
	File string
}

FlowText is a flow shown as text: Flow is its own data (what the code view edits), File the Arazzo document Flow-I would save for it.

type GeneratedGRPC

type GeneratedGRPC struct {
	Created []RequestTarget
	// Skipped says, one line per method, why no request was made for it.
	Skipped []string
}

GeneratedGRPC is what GenerateGRPCRequests did.

type ImportKind

type ImportKind string

ImportKind names a document kind Flow-I imports.

const (
	ImportOpenAPI ImportKind = "openapi"
	// ImportAsyncAPI is an AsyncAPI 3.x (or 2.x) document: async requests.
	ImportAsyncAPI ImportKind = "asyncapi"
	// ImportProto is a .proto file: one gRPC request per unary or
	// server-streaming method of its services.
	ImportProto   ImportKind = "proto"
	ImportArazzo  ImportKind = "arazzo"
	ImportCurl    ImportKind = "curl"
	ImportHAR     ImportKind = "har"
	ImportHTTP    ImportKind = "http"    // a .http / .rest file (REST Client, JetBrains)
	ImportPostman ImportKind = "postman" // a collection or an environment file
	ImportBruno   ImportKind = "bruno"   // a collection folder: ImportSource.Dir
	ImportMermaid ImportKind = "mermaid" // a flowchart sketch, resolved against the collection
)

Import kinds.

type ImportPlan

type ImportPlan struct {
	Collection model.ID
	Files      []PlannedFile
	Diags      diag.List
	// Items is the per-item report of importers other than OpenAPI and
	// Arazzo; skipped items contribute no files.
	Items []importers.Item
	// contains filtered or unexported fields
}

ImportPlan is what an import would write. Files are in path order; Diags are the import's lossy reports (FLW-IMPORT-001).

type ImportSource

type ImportSource struct {
	Kind ImportKind
	Name string
	Data []byte
	Dir  string
	// Overlays are OpenAPI Overlay documents applied, in order, to an OpenAPI
	// or AsyncAPI document before it is imported. The document itself is kept
	// as it was, with the overlays beside it in descriptions/.
	Overlays [][]byte
}

ImportSource is a document to import: its kind, a name for reports (a file name, or "stdin"), and its bytes — or, for a folder format such as Bruno, the folder.

type KeptSpec

type KeptSpec struct {
	Name     string   // the file's base name: "pets" for pets.openapi.yaml
	File     string   // absolute
	Rel      string   // slash-separated, relative to the collection root
	Overlays []string // absolute, in the order they apply: <name>.overlay.yaml, <name>.overlay-2.yaml, …
	// Edits is the overlay Flow-I saves request edits to,
	// <name>.edits.overlay.yaml. It applies last. It may not exist yet.
	Edits string
}

KeptSpec is an OpenAPI description an import kept in descriptions/, with the overlays that apply to it.

type NodeParam

type NodeParam struct {
	Name     string
	Kind     string
	Doc      string
	Required bool
	Enum     []string
	Min, Max int64
}

NodeParam is one parameter of a node type. Kind is string, text (a {{…}} template), expr (a bare expression), duration, int, bool, enum, name (a plain file name), any or map.

type NodeSpec

type NodeSpec struct {
	Type    string
	Group   string // Call, Data, Check, Control, Output
	Summary string
	MapForm bool // other keys are "<variable>: template"
	Params  []NodeParam
	Typed   []string
}

NodeSpec describes a flow node type for editors: its catalogue entry and parameters. Typed fields (request, flow, with, body, branches, …) are not listed as parameters.

func NodeCatalog

func NodeCatalog() []NodeSpec

NodeCatalog lists every node type in catalogue order.

func (NodeSpec) Param

func (s NodeSpec) Param(name string) (NodeParam, bool)

Param returns the parameter named name.

type OverlayChange

type OverlayChange struct {
	What   string // what changes, said plainly: "the docs", "query parameter page is added"
	Target string // the JSONPath the action points at
	Update any    // the action's update; nil for a removal
	Remove bool
	// Saved says the overlay already has it: saving again changes nothing
	// for it. Unsaved changes are the ones to offer first.
	Saved bool
	// contains filtered or unexported fields
}

OverlayChange is one change a saved edit makes to the spec.

type OverlayField

type OverlayField struct {
	Section string // docs, body, query or header
	Key     string // the parameter's name; "" for docs and body
	File    string // the overlay that sets it last, relative to the collection root
}

OverlayField is a field of a request version an overlay sets.

type OverlayNote

type OverlayNote struct {
	What string
	Why  string
}

OverlayNote is an edit the overlay does not carry, and why.

type OverlayPlan

type OverlayPlan struct {
	Spec       KeptSpec
	Request    string // the request's path
	Label      string // the version
	Operation  string // the JSONPath of the operation
	Changes    []OverlayChange
	NotCarried []OverlayNote
	// contains filtered or unexported fields
}

OverlayPlan is what saving a request version to its spec's overlay would write. Changes are chosen by index in ApplySpecOverlay and YAML.

func (OverlayPlan) YAML

func (p OverlayPlan) YAML(chosen []int) (string, error)

YAML is the edits overlay as it would be written with the chosen changes.

type PlannedFile

type PlannedFile struct {
	File   string // absolute
	Rel    string // slash-separated, relative to the collection root
	Exists bool   // the file is already there (at preview time)
	// Same marks an existing file the import would write back unchanged, so
	// a preview can leave it out of what changes.
	Same bool
	// Remove marks a tool-owned file the import replaces by removing it:
	// a response schema the document no longer has. It is removed only
	// when existing files are overwritten.
	Remove bool
	// Workspace marks an environment, which belongs to the workspace and is
	// written to its environments directory, not to the collection.
	Workspace bool
}

PlannedFile is one file an import writes.

type RequestTarget

type RequestTarget struct {
	Collection model.ID
	Request    model.ID
}

RequestTarget identifies a request of a mounted collection.

type RunNodeSummary

type RunNodeSummary struct {
	ID       string
	Name     string
	Type     string
	Status   string
	Duration time.Duration
}

RunNodeSummary is a top-level node's outcome in a saved run.

type RunOptions

type RunOptions struct {
	Env           string            // environment name; "" uses defaults.environment
	PreferVersion string            // beats the flow's prefer_version (design §4.4)
	Inputs        map[string]string // values for the flow's declared inputs, as templates
	Seed          uint64            // 0 picks a random seed (reported in the result)
	Grace         time.Duration     // 0 uses the run.grace setting
	// Only runs just these top-level nodes, with Prior as the outputs of
	// the others (see engine.RunInput). nil runs the whole flow.
	Only  []string
	Prior map[string]map[string]any
}

RunOptions configure RunFlow.

type RunSummary

type RunSummary struct {
	File     string // the report file
	ID       string
	Env      string
	Status   string
	Seed     uint64
	Started  time.Time
	Duration time.Duration
	Nodes    []RunNodeSummary
}

RunSummary is one saved run of a flow, as much as a history list and a comparison need: the report's header and each top-level node's outcome.

type SaveOptions

type SaveOptions struct {
	// DropComments allows rewriting a file that has comments. The
	// canonical encoding does not keep them, so without it such a write is
	// refused with FLW-WRITE-001.
	DropComments bool
}

SaveOptions control writes of edited files.

type SchemaChange

type SchemaChange struct {
	Part   SchemaPart
	Change schemainfer.Change
}

SchemaChange is a change a send made to a stored schema.

type SchemaPart

type SchemaPart struct {
	Kind   string // "request", "response" or "message"
	Status int    // for a response
}

SchemaPart names one schema of a request version: the body it sends, the body of the response with a status, or (async requests) the payload of the messages it receives.

type SchemaSource

type SchemaSource string

SchemaSource says where a stored schema came from.

const (
	SchemaInferred SchemaSource = "inferred"
	SchemaOpenAPI  SchemaSource = "openapi"
	SchemaUser     SchemaSource = "user"
)

Where schemas come from. Only inferred ones are rewritten by later sends.

type Scope

type Scope struct {
	Collection model.ID
	Folder     string
}

Scope selects which project layers apply when resolving settings. The zero value resolves user and workspace settings only. Folder is collection-relative, e.g. "requests/auth".

type SecretInfo

type SecretInfo struct {
	Environment string
	Name        string
	Set         bool // stored in the vault
	Override    bool // FLOWI_SECRET_<ENV>_<NAME> is set
}

SecretInfo describes one secret variable; it never carries the value.

type SendOptions

type SendOptions struct {
	Env           string            // environment name; "" uses defaults.environment
	Version       string            // pin a version
	PreferVersion string            // use this version if the request has it
	Save          string            // none | last | per-status; "" uses responses.save
	With          map[string]string // values for the request's bare names ({{email}}), as templates
	Hooks         model.HookControl
	Seed          uint64 // 0 picks a random seed (reported in the result)

	// UseEdit sends the request's dirty edit (see StoreEdit) in place of
	// the saved version it started from, when the version asked for
	// (Version, or the default) is that base. Flow runs, serve and the CLI
	// never set it.
	UseEdit bool
}

SendOptions configure SendRequest.

type ServeOptions

type ServeOptions struct {
	ReplayAddr  string // host:port; "" uses serve.replay_addr; port 0 picks a free one
	TriggerAddr string // host:port; "" uses serve.trigger_addr

	Latency  time.Duration // added to every replayed answer
	Sequence bool          // replay a request's responses one call at a time
	CORS     bool          // let browsers call the replayer
	Record   string        // upstream base URL: forward calls and save the real responses
	// RecordTo is the collection (name or id) that calls matching no saved
	// request are saved in, as new requests; "" is the Scratch draft. Only
	// used with Record.
	RecordTo string

	NoReplay, NoTriggers, NoSchedules bool

	// ValkeyAddr (host:port) shares run records and schedule ticks with
	// other instances through a Valkey or Redis server; "" uses
	// serve.valkey_addr, and empty there means no sharing. The password is
	// ValkeyPassword. The server may be down: serve then runs on its own.
	ValkeyAddr string
	ValkeyTLS  bool

	// ShutdownTimeout is how long in-flight requests and runs may take to
	// finish once the context ends; what is left is then cancelled and
	// Wait returns ErrShutdownTimeout. 0 uses serve.shutdown_timeout.
	ShutdownTimeout time.Duration
	MaxRuns         int // flow runs in flight at once (serve.max_runs)
	TrafficLog      int // replayer calls kept in memory (serve.traffic_log)

	Logger *slog.Logger

	// Hooks for tests.
	Now   func() time.Time
	Sleep func(ctx context.Context, d time.Duration) error // the scheduler's wait
	// contains filtered or unexported fields
}

ServeOptions configure Serve. Start from ServeDefaults, which fills them from settings, and change what the caller was asked to.

type Server

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

Server is a running `flowi serve`.

func (*Server) Notes

func (s *Server) Notes() []string

Notes say what is off or unusual: triggers without a token, a listener open to the network, skipped schedules.

func (*Server) ReplayAddr

func (s *Server) ReplayAddr() string

ReplayAddr is where the replayer listens ("" when it is off).

func (*Server) Traffic

func (s *Server) Traffic() *replay.Log

Traffic is the replayer's log of calls.

func (*Server) TriggerAddr

func (s *Server) TriggerAddr() string

TriggerAddr is where HTTP triggers listen ("" when they are off).

func (*Server) Upcoming

func (s *Server) Upcoming() []scheduler.Upcoming

Upcoming lists when each schedule fires next.

func (*Server) Wait

func (s *Server) Wait() error

Wait blocks until the context given to Serve has ended and the server has shut down: listeners closed, in-flight requests answered, runs finished or cancelled. It returns nil for a clean drain, ErrShutdownTimeout if work had to be cancelled, or the failure that stopped the server.

type SpecOrigin

type SpecOrigin struct {
	Spec   string // the kept spec, relative to the collection root
	Name   string // its name, for PreviewSpecUpdate
	Fields []OverlayField
}

SpecOrigin is the kept spec a request comes from and the fields of a version its overlays set, so the window can mark them.

type StoredResponse

type StoredResponse struct {
	Kind    string // StoredSaved or StoredExample
	Version string // the request version it is for; "" for an example that fits every version
	Name    string // the file name without .json: a status ("201"), an outcome, "last", or the name of an example
	Status  int    // 0 when the file does not say
	At      time.Time
	Size    int64
}

StoredResponse is a response kept for a request.

type TrashedItem

type TrashedItem struct {
	ID        string
	Kind      string // TrashRequest or TrashFlow
	Name      string // what it was called
	Path      string // where it was in its collection, "untitled-2"
	TrashedAt time.Time
	// Files are its files, relative to the collection root (the request or flow file, and what sat beside it).
	Files []string
}

TrashedItem is a request or flow moved out of the drafts and not deleted yet.

type Workspace

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

Workspace is an open workspace with its mounted collections loaded. It is safe for concurrent use.

func OpenWorkspace

func OpenWorkspace(ctx context.Context, o WorkspaceOptions) (*Workspace, diag.List, error)

OpenWorkspace opens (creating on first use) a workspace and loads every mounted collection. Problems with files are returned as diagnostics; the error is reserved for system failures.

func (*Workspace) AddSchedule

func (w *Workspace) AddSchedule(s model.Schedule) error

AddSchedule saves a schedule in workspace.yaml. Problems with the schedule itself are FLW-SERVE-001 (a *diag.ListError) and nothing is saved. A flow that cannot be found yet is allowed: collections come and go, and Validate warns (FLW-SERVE-002).

func (*Workspace) Announcements

func (w *Workspace) Announcements(ctx context.Context, refresh bool) (announce.Result, error)

Announcements returns the project's signed announcements per the user's settings. It returns announce.ErrTurnedOff or announce.ErrNotConfigured when there is nothing to fetch; any other error comes with the cached items, if there are some (see announce.Feed.Fetch). refresh ignores a recent cache.

func (*Workspace) ApplyImport

func (w *Workspace) ApplyImport(p ImportPlan, o ApplyOptions) error

ApplyImport writes a previewed plan and reloads the collection. Existing files are checked again at apply time; see ApplyOptions.

func (*Workspace) ApplySpecOverlay

func (w *Workspace) ApplySpecOverlay(p OverlayPlan, chosen []int) error

ApplySpecOverlay writes the chosen changes of p to the spec's edits overlay, in place of what it said about this operation before. The overlay is removed when it no longer says anything.

func (*Workspace) Blueprint

func (w *Workspace) Blueprint(t BlueprintTarget) (model.Blueprint, error)

Blueprint returns the loaded blueprint.

func (*Workspace) CheckSecret

func (w *Workspace) CheckSecret(env, name string) error

CheckSecret reports whether a secret variable can be set, before its value is asked for: the environment and the declaration must exist.

func (*Workspace) ClearCookies

func (w *Workspace) ClearCookies(collection string) error

ClearCookies deletes the saved cookie jar of a collection (name or id), or of every mounted collection when collection is "".

func (*Workspace) CollectionEnvironments

func (w *Workspace) CollectionEnvironments(collection model.ID) ([]model.Environment, diag.List, error)

CollectionEnvironments reads the environment files a collection ships in its own environments directory. The workspace does not use them (its environments are global); they are offered for copying into it, for example from an example or a colleague's collection. A collection without the directory has none. Problems with single files are diagnostics; an unknown collection is FLW-WS-005.

func (*Workspace) Collections

func (w *Workspace) Collections() []model.Collection

Collections returns the loaded collections in mount order.

func (*Workspace) Completions

func (w *Workspace) Completions(t FlowTarget, nodePath string) ([]Completion, error)

Completions lists what templates of the node at nodePath (its YAML path, e.g. "$.nodes[3]") can read: flow inputs, environment keys and secret names, variables written by nodes that run before it, and outputs of those nodes, including body fields from request contracts (pinned examples or the last saved response). Nodes are assumed to run in list order (a concurrent node sees the same nodes as a serial one).

func (*Workspace) CompletionsIn

func (w *Workspace) CompletionsIn(collection model.ID, f model.Flow, nodePath string) ([]Completion, error)

CompletionsIn is Completions for f, a flow of collection as an editor holds it (possibly unsaved), so offers follow the edited order.

func (*Workspace) Cookies

func (w *Workspace) Cookies(collection string) ([]CookieInfo, error)

Cookies lists the cookies in the saved jar of a collection (name or id), without those that have expired.

func (*Workspace) CreateBlueprint

func (w *Workspace) CreateBlueprint(flow FlowTarget, path, name string) (BlueprintTarget, error)

CreateBlueprint saves flow as blueprints/<path>.blueprint.yaml in the flow's collection (see blueprint.FromFlow for what becomes a parameter). Path rules are as for NewRequest (FLW-WRITE-002).

func (*Workspace) CreateHookBlueprint

func (w *Workspace) CreateHookBlueprint(collection model.ID, path, name, phase string, nodes []model.Node) (BlueprintTarget, error)

CreateHookBlueprint saves nodes, the hooks of one phase ("pre" or "post") that a request was given, as blueprints/<path>.blueprint.yaml in collection, so that other requests can start with them (see SeedRequestHooks). Path rules are as for NewRequest (FLW-WRITE-002).

func (*Workspace) DataDir

func (w *Workspace) DataDir(collection model.ID) string

DataDir is where the workspace keeps a collection's data: saved responses, downloads and cookies.

func (*Workspace) DeleteBlueprint

func (w *Workspace) DeleteBlueprint(t BlueprintTarget) error

DeleteBlueprint removes the blueprint's file. Flows made from it are not touched: they keep what they were made with. An unknown blueprint is FLW-BP-006.

func (*Workspace) DeleteCookie

func (w *Workspace) DeleteCookie(collection, key string) error

DeleteCookie removes the cookie with key (CookieInfo.Key) from the saved jar of a collection. A send running at that moment may write the cookie back when it finishes.

func (*Workspace) DeleteEnvironment

func (w *Workspace) DeleteEnvironment(file string) error

DeleteEnvironment removes an environment file. Its secret values stay in the vault. An unknown file is FLW-REQ-004.

func (*Workspace) DeleteFlow

func (w *Workspace) DeleteFlow(t FlowTarget) error

DeleteFlow removes flow t's file and its canvas layout. An unknown flow is FLW-FLOW-002.

func (*Workspace) DeleteFolder

func (w *Workspace) DeleteFolder(collection model.ID, tree, path string) error

DeleteFolder removes the folder path under tree of collection and everything in it. Callers ask first when it holds anything.

func (*Workspace) DeleteFromTrash

func (w *Workspace) DeleteFromTrash(id string) error

DeleteFromTrash removes one item for good.

func (*Workspace) DeleteRequest

func (w *Workspace) DeleteRequest(t RequestTarget) error

DeleteRequest removes request t's file. Flows that use it are not rewritten; Validate reports them. An unknown request is FLW-REQ-001.

func (*Workspace) DeleteSchema

func (w *Workspace) DeleteSchema(t RequestTarget, version string, part SchemaPart) error

DeleteSchema removes a stored schema; the next send learns it again.

func (*Workspace) DeleteStoredResponse

func (w *Workspace) DeleteStoredResponse(t RequestTarget, kind, version, name string) error

DeleteStoredResponse removes one stored response. A response that is already gone is not an error.

func (*Workspace) DiscardDraft

func (w *Workspace) DiscardDraft(id model.ID) error

DiscardDraft unmounts draft id and deletes its files and its data (history, saved responses, cookies). User folders are never touched.

func (*Workspace) DiscardEdit

func (w *Workspace) DiscardEdit(t RequestTarget, o SaveOptions) error

DiscardEdit clears the edit slot. Having none is not an error.

func (*Workspace) DiscardSecret

func (w *Workspace) DiscardSecret(env, name string) error

DiscardSecret removes a stored value whose variable is no longer a secret of the environment: it was deleted, or turned into a plain variable. UnsetSecret cannot do that, because it requires the declaration. Without this the value would stay in the vault with nothing left to show or remove it. The environment must exist (FLW-REQ-004); a name with no stored value is not an error.

func (*Workspace) DuplicateFlow

func (w *Workspace) DuplicateFlow(t FlowTarget, path string) (FlowTarget, error)

DuplicateFlow copies flow t to path in the same collection, with a fresh id. Path rules are as for NewFlow (FLW-WRITE-002); an unknown flow is FLW-FLOW-002. The canvas layout is not copied: the copy lays itself out.

func (*Workspace) DuplicateRequest

func (w *Workspace) DuplicateRequest(t RequestTarget, path string) (RequestTarget, error)

DuplicateRequest copies request t to path in the same collection, with a fresh id and without the original's unsaved edit. Path rules are as for NewRequest (FLW-WRITE-002); an unknown request is FLW-REQ-001.

func (*Workspace) EmptyTrash

func (w *Workspace) EmptyTrash() error

EmptyTrash removes everything in the trash for good.

func (*Workspace) Environments

func (w *Workspace) Environments() []model.Environment

Environments returns the workspace's environments.

func (*Workspace) ExportArazzo

func (w *Workspace) ExportArazzo(t FlowTarget) ([]byte, diag.List, error)

ExportArazzo writes flow t, and the flows of its collection it calls as subflows, as one standalone Arazzo document for other tools: standard steps only (what Arazzo cannot express is left out and reported in diags), naming the requests by the operationIds of the collection's generated description. Copy descriptions/requests.openapi.yaml (and requests.asyncapi.yaml when the flow has async steps) next to the document, as ./requests.openapi.yaml and ./requests.asyncapi.yaml, for the operations to resolve.

func (*Workspace) ExportMermaid

func (w *Workspace) ExportMermaid(t FlowTarget) (string, error)

ExportMermaid writes flow t as a Mermaid flowchart.

func (*Workspace) FindBlueprint

func (w *Workspace) FindBlueprint(ref, collection string) (BlueprintTarget, error)

FindBlueprint resolves a blueprint reference as users type it: an id, or a path ("onboarding", optionally with blueprints/ and .blueprint.yaml). collection narrows the search by name or id. Problems are *diag.ListError: FLW-BP-006 (no match), FLW-BP-007 (several collections match), FLW-WS-005 (unknown collection).

func (*Workspace) FindCollection

func (w *Workspace) FindCollection(ref string) (model.ID, error)

FindCollection resolves a collection by name or id; "" means the only mounted collection (FLW-WS-004 when there are several, FLW-WS-005 for an unknown name).

func (*Workspace) FindFlow

func (w *Workspace) FindFlow(ref, collection string) (FlowTarget, error)

FindFlow resolves a flow reference as users type it: an id, or a path ("user-creation", optionally with flows/ and .arazzo.yaml). collection narrows the search by name or id. Problems are *diag.ListError: FLW-FLOW-002 (no match), FLW-FLOW-003 (several collections match), FLW-WS-005 (unknown collection).

func (*Workspace) FindRequest

func (w *Workspace) FindRequest(ref, collection string) (RequestTarget, error)

FindRequest resolves a request reference as users type it: an id, or a path ("auth/login", optionally with requests/ and .req.yaml). collection narrows the search by name or id. Problems are *diag.ListError: FLW-REQ-001 (no match), FLW-REQ-002 (several collections match), FLW-WS-005 (unknown collection).

func (*Workspace) FlowCompatibility

func (w *Workspace) FlowCompatibility(t FlowTarget) diag.List

FlowCompatibility lists the steps of flow t that only Flow-I can run (FLW-ARAZZO-002): in the Arazzo file they call the built-in operation, and other Arazzo tools cannot run them; and the steps whose reply or match filter Arazzo cannot say (FLW-ARAZZO-003). It is for the person editing the flow; Validate does not raise it.

func (*Workspace) FlowLayout

func (w *Workspace) FlowLayout(t FlowTarget) (model.Layout, diag.List, error)

FlowLayout reads the flow's canvas layout. A missing file is an empty layout; a broken one gives diagnostics and whatever could be read.

func (*Workspace) FlowRuns

func (w *Workspace) FlowRuns(t FlowTarget, limit int) []RunSummary

FlowRuns lists the saved runs of flow t, newest first, at most limit of them (0: 50). Reports are a cache the engine wrote and nobody edits, so a file that cannot be read or parsed is left out rather than failing the list.

func (*Workspace) FlowSource

func (w *Workspace) FlowSource(t FlowTarget, f model.Flow) (FlowText, error)

FlowSource shows f, an edited copy of flow t (unsaved edits included), as text.

func (*Workspace) Folder

func (w *Workspace) Folder() string

Folder is the folder holding workspace.yaml.

func (*Workspace) Format

func (w *Workspace) Format(dir string) (changes []FileChange, blocked diag.List, err error)

Format returns the canonical-formatting changes for the collection in dir, or for every mounted collection when dir is "". Path hints are repaired across collections. Files with problems that a rewrite would turn into data loss (see BlocksRewrite) are left out; their diagnostics are returned as blocked. Nothing is written; pass changes to ApplyChanges.

func (*Workspace) GRPCMethods

GRPCMethods lists the methods of the schema the gRPC version v of request t would use: its .proto files, or what the server's reflection offers. v replaces the saved version of the same label (the screen's edit). The vault is unlocked first when the call's metadata reads a secret. A version that is not a gRPC call is FLW-GRPC-001.

func (*Workspace) GenerateGRPCRequests

func (w *Workspace) GenerateGRPCRequests(collection model.ID, base model.GRPC, methods []grpcx.Method) (GeneratedGRPC, error)

GenerateGRPCRequests creates a gRPC request for each method, at grpc/<Service>/<Method> of collection, with the server, proto files and import roots of base, the method's example message as its body, and the starting hooks. A client-streaming method is skipped (not supported yet) and so is one whose request already exists; every skip is reported.

func (*Workspace) HasTriggerToken

func (w *Workspace) HasTriggerToken() (bool, error)

HasTriggerToken reports whether a trigger token exists, in the vault or as an environment override, without reading its value.

func (*Workspace) Impact

func (w *Workspace) Impact(t RequestTarget, version string) (analysis.Report, diag.List, error)

Impact reports who uses request t across every mounted collection (flow request nodes, post-hooks, the request's own extract and assert) and whether each still fits the request's contract: its pinned examples, or else its last saved response (design §9). version limits the report to one version; "" reports all of them. An unknown version is a *diag.ListError (FLW-VER-004); diags are unreadable examples.

func (*Workspace) InitCollection

func (w *Workspace) InitCollection(dir, name string, mount bool) (model.Manifest, error)

InitCollection creates a new, empty collection in dir and optionally mounts it.

func (*Workspace) IsDraft

func (w *Workspace) IsDraft(id model.ID) bool

IsDraft reports whether the mounted collection id is a draft.

func (*Workspace) KeepFlowEdits

func (w *Workspace) KeepFlowEdits(t FlowTarget, f model.Flow) error

KeepFlowEdits stores f, flow t with unsaved edits, until KeptFlowEdits takes it.

func (*Workspace) KeptFlowEdits

func (w *Workspace) KeptFlowEdits(t FlowTarget) (text string, ok bool, err error)

KeptFlowEdits returns the text KeepFlowEdits stored for flow t and forgets it. ok is false when nothing was kept. Read the text with ParseFlowSource.

func (*Workspace) KeptSpecs

func (w *Workspace) KeptSpecs(collection model.ID) ([]KeptSpec, error)

KeptSpecs lists the OpenAPI descriptions kept in the collection's descriptions/ folder, by name. The description Flow-I generates (requests.openapi.yaml) is not one.

func (*Workspace) LastResponse

func (w *Workspace) LastResponse(t RequestTarget, version string) (rec engine.Record, ok bool)

LastResponse is the response the last send of version of request t saved (responses.save "last" or "per-status"), so a restarted app can show it. ok is false when nothing was saved or the file cannot be read: saved responses are a cache nobody edits, so a bad one is not worth an error.

func (*Workspace) LearnSchemas

func (w *Workspace) LearnSchemas(t RequestTarget, version string, rec engine.Record) ([]SchemaChange, error)

LearnSchemas infers or widens the request-body and response schemas of version of request t from rec, the record of a send, and returns what it changed in schemas that already existed. A first sample creates the schema silently. Bodies that are not JSON learn nothing. Schemas from a spec or edited by hand are never rewritten.

func (*Workspace) ListSchemas

func (w *Workspace) ListSchemas(t RequestTarget, version string) []SchemaPart

ListSchemas lists the schemas stored for version of request t: the request body first, then the responses by status.

func (*Workspace) ListTrash

func (w *Workspace) ListTrash() ([]TrashedItem, error)

ListTrash lists what the trash holds, newest first. An entry that cannot be read is left out: it can still be removed with EmptyTrash.

func (*Workspace) Missing

func (w *Workspace) Missing() []model.ID

Missing returns the ids of mounted collections that could not be found.

func (*Workspace) Model

func (w *Workspace) Model() model.Workspace

Model returns the workspace definition.

func (*Workspace) Mount

func (w *Workspace) Mount(dir string) (model.Manifest, error)

Mount adds the collection in dir to the workspace and loads it. Paths are stored absolute, except that a leading "~" is kept.

func (*Workspace) MoveFolder

func (w *Workspace) MoveFolder(collection model.ID, tree, from, to string) error

MoveFolder moves the folder from to the path to under tree ("requests" or "flows") of collection, with everything in it: requests keep their ids, versions and dirty edits, since a request's path is its place on disk. A destination that exists, a move into the folder itself, or a bad path is FLW-WRITE-002 and nothing moves. Flows that refer to the requests by path are not rewritten (Validate says so).

func (*Workspace) MoveRequest

func (w *Workspace) MoveRequest(t RequestTarget, to model.ID, path string) (RequestTarget, error)

MoveRequest moves request t to path (slash-separated, without suffix) in collection to, which may be its own collection (a rename). The request keeps its id, versions and dirty edit. A destination that exists, or a bad path, is FLW-WRITE-002 and nothing moves; an unknown collection is FLW-WS-005. Flows that refer to the request by path or collection are not rewritten (a request leaving its collection breaks them; Validate says so).

func (*Workspace) NewAsyncRequest

func (w *Workspace) NewAsyncRequest(collection model.ID, path, protocol string) (RequestTarget, error)

NewAsyncRequest is NewRequest for an async request of the given protocol (any of model.AsyncProtocols): its version "1" has an empty server and channel, and sends (sse: receives) one message. An unknown protocol is FLW-ASYNC-001.

func (*Workspace) NewDraft

func (w *Workspace) NewDraft(name string) (model.Manifest, error)

NewDraft creates and mounts an empty draft collection.

func (*Workspace) NewEnvironment

func (w *Workspace) NewEnvironment(name string) (string, error)

NewEnvironment creates <environments dir>/<name>.yaml with a fresh id and no variables, and loads it; it returns the file. The name must be a plain name; a bad name or an existing file is FLW-WRITE-002.

func (*Workspace) NewFlow

func (w *Workspace) NewFlow(collection model.ID, path string) (FlowTarget, error)

NewFlow creates flows/<path>.arazzo.yaml in collection with a fresh id and no nodes, and loads it. Path rules are as for NewRequest (FLW-WRITE-002).

func (*Workspace) NewFlowFromBlueprint

func (w *Workspace) NewFlowFromBlueprint(t BlueprintTarget, collection model.ID, path string, values map[string]string) (FlowTarget, error)

NewFlowFromBlueprint creates flows/<path>.arazzo.yaml in collection from the blueprint, with the given parameter values (defaults fill the rest). References are looked up in collection, which need not be the blueprint's own. The flow is an ordinary flow with no link to the blueprint. Problems with the values are FLW-BP-005; path rules are as for NewFlow.

func (*Workspace) NewFolder

func (w *Workspace) NewFolder(collection model.ID, tree, path string) error

NewFolder creates the folder path under tree ("requests" or "flows") of collection, as a _folder.yaml, so it exists and shows before anything is put in it. path is slash-separated, each part a plain name; a bad path, an unknown tree or an existing folder is FLW-WRITE-002.

func (*Workspace) NewGRPCRequest

func (w *Workspace) NewGRPCRequest(collection model.ID, path string) (RequestTarget, error)

NewGRPCRequest is NewRequest for a gRPC request: its version "1" has an empty server and method and an empty JSON message.

func (*Workspace) NewRequest

func (w *Workspace) NewRequest(collection model.ID, path string) (RequestTarget, error)

NewRequest creates requests/<path>.req.yaml in collection with a fresh id and one empty GET version "1", and loads it. path is slash-separated and each segment must be a plain name; an existing file or a bad path is FLW-WRITE-002.

func (*Workspace) NewScratchRequest

func (w *Workspace) NewScratchRequest() (RequestTarget, error)

NewScratchRequest creates the next free "untitled" request in Scratch.

func (*Workspace) NewTriggerToken

func (w *Workspace) NewTriggerToken() (string, error)

NewTriggerToken stores a fresh random token, replacing any earlier one, and returns it. This is the only time the value is shown to a user.

func (*Workspace) NewUntitledFlow

func (w *Workspace) NewUntitledFlow(collection model.ID) (FlowTarget, error)

NewUntitledFlow creates an empty flow in collection named untitled, untitled-2, … (the first not taken), so a flow can be made without asking for a path; it can be renamed after.

func (*Workspace) ParseFlowSource

func (w *Workspace) ParseFlowSource(t FlowTarget, text string) (model.Flow, diag.List, error)

ParseFlowSource reads text in the form FlowSource shows into flow t. What is wrong with the text comes back as diagnostics (positioned in text), not as an error; the flow's identity and location stay those of t.

func (*Workspace) PinExample

func (w *Workspace) PinExample(rec engine.Record, name string) (string, error)

PinExample saves a send's record as a pinned example next to its request (<request>.examples/<name>.json; name defaults to the status). Pinned examples are committed with the collection.

func (*Workspace) PreviewImport

func (w *Workspace) PreviewImport(kind ImportKind, data []byte, collection model.ID) (ImportPlan, error)

PreviewImport turns an OpenAPI or Arazzo document into the files it would add to collection, writing nothing. A document that is not one is FLW-IMPORT-002. Arazzo steps call the collection's requests by their operation (see Request.Operation), so import OpenAPI first.

Files that already hold a request or flow keep its id, so re-importing does not break references to it.

func (*Workspace) PreviewImportNew

func (w *Workspace) PreviewImportNew(kind ImportKind, data []byte, dir string) (ImportPlan, error)

PreviewImportNew plans an import into a collection not created yet at dir, for a dry run before InitCollection. The plan cannot be applied: create the collection, then preview into it.

func (*Workspace) PreviewImportSource

func (w *Workspace) PreviewImportSource(src ImportSource, collection model.ID) (ImportPlan, error)

PreviewImportSource is PreviewImport for a named source, so the report can say where each problem is.

func (*Workspace) PreviewImportSourceNew

func (w *Workspace) PreviewImportSourceNew(src ImportSource, dir string) (ImportPlan, error)

PreviewImportSourceNew is PreviewImportNew for a named source or a folder; like it, the plan cannot be applied.

func (*Workspace) PreviewRequest

func (w *Workspace) PreviewRequest(t RequestTarget, v model.RequestVersion, o SendOptions, includeSecrets bool) (engine.Preview, error)

PreviewRequest renders version v of request t, as shown in an editor and not necessarily saved, the way a send would after its pre-hooks: nothing is sent and no hook runs (see engine.PreviewSend). v replaces the saved version with its label. Names that cannot be resolved stay as written. The vault is read, and may prompt, only when includeSecrets asks for the real values.

func (*Workspace) PreviewSpecOverlay

func (w *Workspace) PreviewSpecOverlay(t RequestTarget, v model.RequestVersion) (OverlayPlan, error)

PreviewSpecOverlay works out what saving version v of the request to its spec's overlay would change. v is the version as it is being saved (the edit, when there is one).

func (*Workspace) PreviewSpecUpdate

func (w *Workspace) PreviewSpecUpdate(collection model.ID, name string, data []byte) (ImportPlan, error)

PreviewSpecUpdate previews importing the kept spec called name again, with its overlays: from the kept copy when data is nil, else from data, a newer version of the document (which then becomes the kept copy). Requests it replaces are merged with what is on disk (see mergeReimport); apply the plan with ApplyImport and Overwrite.

func (*Workspace) PromoteEdit

func (w *Workspace) PromoteEdit(t RequestTarget, asLabel string, o SaveOptions) error

PromoteEdit turns the edit into a saved version and clears the slot in one write. An empty asLabel overwrites the base version (FLW-WRITE-004 if the base no longer exists); a label adds a new version (FLW-WRITE-004 if it is invalid or taken). No edit is FLW-WRITE-003.

func (*Workspace) RegenerateDescription

func (w *Workspace) RegenerateDescription(collection model.ID) error

RegenerateDescription rewrites the collection's generated OpenAPI description (descriptions/requests.openapi.yaml): one operation per request version, the schemas learned for them, and the built-in operation custom flow steps call. It is derived, so it is rewritten only when its bytes change (a commit sees no noise), and removed when the collection has neither requests nor flows. It runs after every change to a request, a flow or a learned schema, and when a collection is mounted.

func (*Workspace) Reload

func (w *Workspace) Reload(ch Change) (diag.List, error)

Reload applies one watched change to the in-memory collection.

func (*Workspace) Relocate

func (w *Workspace) Relocate(id model.ID, dir string) error

Relocate points a mounted collection at a new directory, which must hold the same collection.

func (*Workspace) RemoveSchedule

func (w *Workspace) RemoveSchedule(name string) error

RemoveSchedule deletes the schedule called name from workspace.yaml.

func (*Workspace) Rename

func (w *Workspace) Rename(name string) error

Rename changes the workspace's display name in workspace.yaml. The folder keeps its name: drafts, sessions and the vault are found by it.

func (*Workspace) ReplaceSchema

func (w *Workspace) ReplaceSchema(t RequestTarget, version string, part SchemaPart, s schemainfer.Schema) error

ReplaceSchema stores a hand-edited schema and marks it so later sends leave it alone.

func (*Workspace) ResetSetting

func (w *Workspace) ResetSetting(layer settings.Layer, key string) error

ResetSetting removes a value from the user or workspace layer.

func (*Workspace) ResolveCollection

func (w *Workspace) ResolveCollection(name string) (model.Manifest, error)

ResolveCollection picks the collection a command acts on: by name or id, or the only mounted one when name is empty. Problems are *diag.ListError (FLW-WS-005 unknown, FLW-WS-004 several mounted and none named).

func (*Workspace) ResolveSchedule

func (w *Workspace) ResolveSchedule(s model.Schedule) (FlowTarget, error)

ResolveSchedule finds the flow a schedule runs: FLW-FLOW-002/003 or FLW-WS-005 as FindFlow reports them.

func (*Workspace) ResponseFields

func (w *Workspace) ResponseFields(t RequestTarget, version string) ([]Completion, error)

ResponseFields lists the body fields version of a request is known to return, written as an expression reads them: body, body.user.id, body.items[0].id. They come from its schema, its pinned examples or its last saved response, in that order of preference (an empty version is the one a run resolves to); a request with none of them has no fields to offer. A list is named by its first item.

func (*Workspace) RestoreFromTrash

func (w *Workspace) RestoreFromTrash(id string) (string, error)

RestoreFromTrash puts a trashed request or flow back into Scratch, under its old name or, when that is taken, the next free "<name>-restored". It returns the path it got.

func (*Workspace) RevealSecret

func (w *Workspace) RevealSecret(env, name string) (string, error)

RevealSecret returns the stored value of one secret variable, for the person who owns it to read again. It is the only call that returns a value: Secrets lists none. A secret provided by a FLOWI_SECRET_<ENV>_<NAME> variable is not revealed (FLW-SEC-004): it is not stored here, and the variable is already in the reader's environment. A secret with no value is FLW-SEC-001. Callers decide when to show it and for how long; this does not log.

func (*Workspace) RunFlow

func (w *Workspace) RunFlow(ctx context.Context, t FlowTarget, o RunOptions) (*engine.Run, error)

RunFlow starts running a flow. The flow's collection (and the collections it depends on) must validate without errors, the environment must exist and the inputs must match the flow's declared inputs (FLW-RUN-009, FLW-RUN-010); otherwise a *diag.ListError is returned and nothing runs. The run's report is saved in the workspace data dir. The run goes on until its Events are drained and Wait returns.

func (*Workspace) SaveDraft

func (w *Workspace) SaveDraft(id model.ID, dir string) error

SaveDraft moves draft id into dir, which must be missing or empty and not inside the draft. The collection keeps its id, so its history, cookies and secrets follow it. If copying fails, what was copied is removed and the draft stays as it was.

func (*Workspace) SaveEnvironment

func (w *Workspace) SaveEnvironment(e model.Environment, o SaveOptions) error

SaveEnvironment writes e, an edited environment, and reloads it. Secret variables are written as declarations only: their values belong in the vault (SetSecret). The environment is matched by file; problems are as for SaveRequest.

func (*Workspace) SaveFlow

func (w *Workspace) SaveFlow(t FlowTarget, f model.Flow, o SaveOptions) error

SaveFlow writes f, an edited copy of flow t, in canonical form and reloads it. Problems are as for SaveRequest (FLW-WRITE-001 when the file has comments and o.DropComments is false).

func (*Workspace) SaveFlowLayout

func (w *Workspace) SaveFlowLayout(t FlowTarget, l model.Layout) error

SaveFlowLayout writes the flow's layout. Positions and collapsed strips of nodes the flow no longer has are dropped. Layout files belong to the tool, so they are always rewritten in canonical form.

func (*Workspace) SaveRequest

func (w *Workspace) SaveRequest(t RequestTarget, r model.Request, o SaveOptions) error

SaveRequest writes r, an edited copy of request t, in canonical form and reloads it. Problems are *diag.ListError: FLW-REQ-001 (unknown request), FLW-WRITE-001 (the file has comments and o.DropComments is false).

func (*Workspace) SaveSchedule

func (w *Workspace) SaveSchedule(old string, s model.Schedule) error

SaveSchedule replaces the schedule called old with s, in the same place in workspace.yaml, in one write. s may carry a new name, as long as no other schedule has it. Problems are reported as AddSchedule does and nothing is saved.

func (*Workspace) Schedules

func (w *Workspace) Schedules() []model.Schedule

Schedules lists the cron schedules in workspace.yaml.

func (*Workspace) SchemaFor

func (w *Workspace) SchemaFor(t RequestTarget, version string, part SchemaPart) (schemainfer.Schema, SchemaSource, bool)

SchemaFor is the stored schema of part of version of request t.

func (*Workspace) Scratch

func (w *Workspace) Scratch() (model.Manifest, error)

Scratch returns the "Scratch" draft that holds requests made outside any collection, creating or re-mounting it as needed.

func (*Workspace) Secrets

func (w *Workspace) Secrets() ([]SecretInfo, error)

Secrets lists every secret variable declared in the workspace's environments. Environments are global, so a secret belongs to no collection.

func (*Workspace) SeedRequestHooks

func (w *Workspace) SeedRequestHooks(t RequestTarget) error

SeedRequestHooks gives a new request its starting hooks. The blueprints named by requests.seed_blueprint (a comma-separated list; "default" is the built-in blueprint.Default, "off" seeds nothing, anything else is a blueprint's path or id) contribute their nodes as one inline hook step each, to the pre or post hooks by the blueprint's phase. Inline hooks travel with the request when it is moved or saved into another collection.

A phase in which the request already has hooks is left alone. A blueprint that is not found, or has parameters (nothing could fill them), is an error and nothing is written.

func (*Workspace) SendRequest

func (w *Workspace) SendRequest(ctx context.Context, t RequestTarget, o SendOptions) (*engine.Send, error)

SendRequest starts sending a request. The request's collection (and the collections it depends on) must validate without errors, and the environment must exist; otherwise a *diag.ListError is returned and nothing is sent. The send runs until its Events are drained and Wait returns.

func (*Workspace) Serve

func (w *Workspace) Serve(ctx context.Context, o ServeOptions) (*Server, error)

Serve starts the replayer, the HTTP triggers and the schedules, as ServeOptions say. Listeners are opened before it returns, so a port in use is an error here. It runs until ctx ends; call Wait to shut down gracefully:

  1. stop accepting calls and starting scheduled runs;
  2. let in-flight requests and flow runs finish, for up to ShutdownTimeout;
  3. cancel what is left (runs stop within the run.grace setting) and close the connections.

Goroutine ownership: Serve starts one goroutine per listener, one for the scheduler, one for live reload and one supervisor; they all end before Wait returns.

func (*Workspace) ServeDefaults

func (w *Workspace) ServeDefaults() ServeOptions

ServeDefaults returns the options settings call for.

func (*Workspace) SessionDir

func (w *Workspace) SessionDir() string

SessionDir is where the GUI keeps what carries over between sessions of the default user (open tabs, and the run log and history when kept). The library does not read or write there; it only names the place.

func (*Workspace) SetFolderOrder

func (w *Workspace) SetFolderOrder(collection model.ID, tree, dir string, order []string, o SaveOptions) error

SetFolderOrder sets the order the entries of folder dir under tree ("requests" or "flows") are shown in: names are the entries' names (a request or flow without its file suffix, or a sub-folder's name). dir is "" for the top of the tree. The order is kept in the folder's _folder.yaml, which is created when it is not there yet, so it travels with the collection.

func (*Workspace) SetSecret

func (w *Workspace) SetSecret(env, name, value string) error

SetSecret stores a secret's value in the vault. The variable must be declared secret in the environment ({ secret: true }).

func (*Workspace) SetSetting

func (w *Workspace) SetSetting(layer settings.Layer, key, raw string) error

SetSetting stores a value at the user or workspace layer. raw is parsed as from an environment variable (lists are comma-separated).

func (*Workspace) SetValkeyPassword

func (w *Workspace) SetValkeyPassword(password string) error

SetValkeyPassword stores the password in the vault.

func (*Workspace) Settings

func (w *Workspace) Settings(s Scope) settings.Resolved

Settings resolves every setting for a scope.

func (*Workspace) SpecOrigin

func (w *Workspace) SpecOrigin(t RequestTarget, label string) (SpecOrigin, error)

SpecOrigin says which kept spec makes the request's version label and what its overlays set; ErrNotFromSpec when none makes it.

func (*Workspace) StoreEdit

func (w *Workspace) StoreEdit(t RequestTarget, base string, v model.RequestVersion, o SaveOptions) error

StoreEdit replaces the request's one dirty edit with v, started from the version labelled base. Saved versions are untouched, and runs, serve and the CLI never read the edit. Problems are as for SaveRequest; autosave should leave o.DropComments false so a commented file is refused (FLW-WRITE-001) instead of silently losing its comments.

func (*Workspace) StoredRecord

func (w *Workspace) StoredRecord(t RequestTarget, version, name string) (engine.Record, error)

StoredRecord reads a saved response as the record it was, to show it again. Pinned examples are not records and are not read here.

func (*Workspace) StoredResponses

func (w *Workspace) StoredResponses(t RequestTarget) ([]StoredResponse, error)

StoredResponses lists what is kept for request t: pinned examples first, then saved responses, each by version and name. A file that cannot be read is listed without a status: it can still be deleted.

func (*Workspace) TrashStaleDrafts

func (w *Workspace) TrashStaleDrafts(olderThan time.Duration, open func(kind string, id model.ID) bool) ([]TrashedItem, error)

TrashStaleDrafts moves the requests and flows of the Scratch draft that have not been changed for olderThan to the trash, unless open says they are in use. It returns what it moved. Only Scratch is swept: the other drafts were made on purpose. A request or flow is "changed" when its file was written.

func (*Workspace) TriggerToken

func (w *Workspace) TriggerToken() (token string, ok bool, err error)

TriggerToken returns the bearer token that authorises HTTP flow triggers. ok is false when none is set, in which case triggers stay off.

func (*Workspace) Unmount

func (w *Workspace) Unmount(id model.ID) error

Unmount removes a collection from the workspace. Its files are untouched.

func (*Workspace) UnsetSecret

func (w *Workspace) UnsetSecret(env, name string) error

UnsetSecret removes a secret's value from the vault.

func (*Workspace) Validate

func (w *Workspace) Validate() diag.List

Validate returns every problem in the workspace: load diagnostics, cross-file validation and contract warnings, positioned and sorted.

func (*Workspace) ValidateDir

func (w *Workspace) ValidateDir(dir string) (diag.List, error)

ValidateDir validates the collection in dir, mounted or not, with the mounted collections available as dependencies. Only problems in dir's own files are returned.

func (*Workspace) ValkeyPassword

func (w *Workspace) ValkeyPassword() (password string, ok bool, err error)

ValkeyPassword returns the password for serve.valkey_addr; ok is false when none is set (a server without authentication).

func (*Workspace) Watch

func (w *Workspace) Watch(ctx context.Context) (<-chan Change, error)

Watch reports changes to files in every loaded collection. See store.Watch for goroutine ownership; the final Change carries Err when the watcher fails.

type WorkspaceOptions

type WorkspaceOptions struct {
	Paths   settings.Paths
	Name    string               // "" means workspace.DefaultName
	Environ []string             // from settings.ProcessEnviron()
	Flags   settings.LayerValues // LayerFlag values from the command line
	Home    string               // used to expand "~" in mount paths
	// Keys is the OS keychain holding the vault key (vault.OSKeyStore());
	// nil when there is none, and the vault then needs a passphrase.
	Keys vault.KeyStore
	// Passphrase asks the user for the vault passphrase; nil when no
	// prompt is possible (FLOWI_VAULT_KEY is the alternative).
	Passphrase func() (string, error)
	// Observe receives every event of every run and send, as the engine
	// emits it; it must return quickly (see engine.Deps.Observe). The otel
	// package's Exporter plugs in here.
	Observe func(engine.Event)
	// UserAgent is the client's User-Agent ("Flowi-UI/1.2"); "" sends "Flowi".
	UserAgent string
	// Traceparent names the trace context sent with outgoing requests (see
	// engine.Deps.Traceparent); nil sends none.
	Traceparent func(runID, path string) string
}

WorkspaceOptions configure OpenWorkspace.

Directories

Path Synopsis
Package analysis answers "which flows and hooks break if this API changes?" (design §9).
Package analysis answers "which flows and hooks break if this API changes?" (design §9).
Package announce fetches Flow-I's announcements: a short list of notices from the project, shown at startup and by `flowi news`.
Package announce fetches Flow-I's announcements: a short list of notices from the project, shown at startup and by `flowi news`.
Package arazzo imports Arazzo 1.0/1.1 workflows as Flow-I flows and exports flows as Arazzo 1.0.1.
Package arazzo imports Arazzo 1.0/1.1 workflows as Flow-I flows and exports flows as Arazzo 1.0.1.
Package asyncapi imports an AsyncAPI document (3.x, and 2.x as far as it maps) as async requests: one request per operation, with the protocol, server, channel and an example of the message it sends.
Package asyncapi imports an AsyncAPI document (3.x, and 2.x as far as it maps) as async requests: one request per operation, with the protocol, server, channel and an example of the message it sends.
Package blueprint turns blueprints into flows and flows into blueprints.
Package blueprint turns blueprints into flows and flows into blueprints.
Package changelog reads a CHANGELOG.md in the Keep a Changelog layout that git-cliff produces from Conventional Commits, so the applications can show "what's new" from the same file the release page uses.
Package changelog reads a CHANGELOG.md in the Keep a Changelog layout that git-cliff produces from Conventional Commits, so the applications can show "what's new" from the same file the release page uses.
Package diag defines diagnostics: user-facing problems found in files, settings or the workspace.
Package diag defines diagnostics: user-facing problems found in files, settings or the workspace.
Package engine executes requests: it resolves the version and settings, runs API hooks, renders the request from templates and secrets, sends it, checks the response, and records and saves the result.
Package engine executes requests: it resolves the version and settings, runs API hooks, renders the request from templates and secrets, sends it, checks the response, and records and saves the result.
Package examples holds the example collections, as documentation and as fixtures for the CLI and GUI tests.
Package examples holds the example collections, as documentation and as fixtures for the CLI and GUI tests.
demoserver
Package demoserver is a small API matching the user-creation example collection, so the collection (and Flow-I) can be tried without a real backend.
Package demoserver is a small API matching the user-creation example collection, so the collection (and Flow-I) can be tried without a real backend.
demoserver/cmd/flowi-demo-server command
Command flowi-demo-server serves the demo API that the user-creation example collection talks to.
Command flowi-demo-server serves the demo API that the user-creation example collection talks to.
Package grpcx makes gRPC calls without generated code: the schema comes from .proto files (compiled in pure Go) or from the server's reflection service, messages are JSON converted with protojson and dynamicpb, and a unary or server-streaming method is called over one short-lived connection.
Package grpcx makes gRPC calls without generated code: the schema comes from .proto files (compiled in pure Go) or from the server's reflection service, messages are JSON converted with protojson and dynamicpb, and a unary or server-streaming method is called over one short-lived connection.
Package importers holds what the importers for other tools (Postman, Bruno, HAR, curl) share: the result and per-item report they return, the rule that keeps credentials out of imported files, and file-safe names.
Package importers holds what the importers for other tools (Postman, Bruno, HAR, curl) share: the result and per-item report they return, the rule that keeps credentials out of imported files, and file-safe names.
bruno
Package bruno imports a Bruno collection folder: every .bru request becomes a request (folders kept), environments/*.bru become environments, collection.bru and folder.bru headers and auth are inherited, asserts become request asserts and post-response vars become extracts.
Package bruno imports a Bruno collection folder: every .bru request becomes a request (folders kept), environments/*.bru become environments, collection.bru and folder.bru headers and auth are inherited, asserts become request asserts and post-response vars become extracts.
curl
Package curl turns pasted curl commands (bash or Windows cmd quoting, as browsers' "Copy as cURL" writes them) into requests: one item per command.
Package curl turns pasted curl commands (bash or Windows cmd quoting, as browsers' "Copy as cURL" writes them) into requests: one item per command.
har
Package har turns an HTTP Archive (a browser's "Save all as HAR") into requests, pinned examples and one flow that replays the recording in order.
Package har turns an HTTP Archive (a browser's "Save all as HAR") into requests, pinned examples and one flow that replays the recording in order.
httpfile
Package httpfile imports .http / .rest files (VS Code REST Client, JetBrains HTTP Client): requests separated by ###, with file variables (@name = value), headers and a body.
Package httpfile imports .http / .rest files (VS Code REST Client, JetBrains HTTP Client): requests separated by ###, with file variables (@name = value), headers and a body.
importerstest
Package importerstest renders an importers.Result as text for golden files: the per-item report (with positions and excerpts) and every request, environment and flow in canonical YAML.
Package importerstest renders an importers.Result as text for golden files: the per-item report (with positions and excerpts) and every request, environment and flow in canonical YAML.
jsonpos
Package jsonpos finds where values are in a JSON document, so importers of JSON formats (HAR, Postman) can report problems at a line and column.
Package jsonpos finds where values are in a JSON document, so importers of JSON formats (HAR, Postman) can report problems at a line and column.
postman
Package postman imports Postman v2.0/v2.1 collections and Postman environment files.
Package postman imports Postman v2.0/v2.1 collections and Postman environment files.
internal
codec/yaml
Package yamlcodec reads and writes Flow-I files as YAML.
Package yamlcodec reads and writes Flow-I files as YAML.
httpx
Package httpx sends one Flow-I request: protocol selection (auto, 1.1, 2, h2c), proxy and custom CAs, redirect chain capture, timings, response decompression, request bodies (including file uploads that must stay inside the collection), large downloads streamed to disk, retries with backoff and jitter, and a cookie jar that can be saved.
Package httpx sends one Flow-I request: protocol selection (auto, 1.1, 2, h2c), proxy and custom CAs, redirect chain capture, timings, response decompression, request bodies (including file uploads that must stay inside the collection), large downloads streamed to disk, retries with backoff and jitter, and a cookie jar that can be saved.
ids
Package ids generates and checks entity ids (ULIDs).
Package ids generates and checks entity ids (ULIDs).
jsonschema
Package jsonschema reads the JSON Schemas Flow-I keeps from OpenAPI documents (already decoded, references inlined): types, allOf merging, and whether a path of steps exists in a schema.
Package jsonschema reads the JSON Schemas Flow-I keeps from OpenAPI documents (already decoded, references inlined): types, allOf merging, and whether a path of steps exists in a schema.
migrate
Package migrate checks collection format versions and plans the steps that upgrade older files to the current format.
Package migrate checks collection format versions and plans the steps that upgrade older files to the current format.
names
Package names checks names that become file names inside Flow-I's own directories (pinned examples, saved values, digests), so content from a collection can never choose a path outside them.
Package names checks names that become file names inside Flow-I's own directories (pinned examples, saved values, digests), so content from a collection can never choose a path outside them.
nodes
Package nodes implements every flow node type, one file each, and registers them with their parameter specs (Specs).
Package nodes implements every flow node type, one file each, and registers them with their parameter specs (Specs).
repotest
Package repotest holds repository-wide hygiene checks run as tests.
Package repotest holds repository-wide hygiene checks run as tests.
sites
Package sites enumerates where things live in loaded collections: root node lists, hook scopes and steps, template sites, written variables and statically resolved request versions.
Package sites enumerates where things live in loaded collections: root node lists, hook scopes and steps, template sites, written variables and statically resolved request versions.
yamldoc
Package yamldoc decodes YAML documents (OpenAPI, Arazzo) into plain map[string]any, []any and scalars, for transforms that walk them by key.
Package yamldoc decodes YAML documents (OpenAPI, Arazzo) into plain map[string]any, []any and scalars, for transforms that walk them by key.
yamlpath
Package yamlpath builds YAML paths ("$.nodes[1].request.id") in the syntax goccy/go-yaml's path lookup understands.
Package yamlpath builds YAML paths ("$.nodes[1].request.id") in the syntax goccy/go-yaml's path lookup understands.
Package mermaid reads Mermaid flowcharts as flow sketches and writes flows as Mermaid.
Package mermaid reads Mermaid flowcharts as flow sketches and writes flows as Mermaid.
Package model defines Flow-I's domain types as plain data.
Package model defines Flow-I's domain types as plain data.
Package openapi turns an OpenAPI 3.0/3.1 document into Flow-I requests: one request per operation (path versions /v1/, /v2/ grouped as request versions), bodies generated from schemas, response schemas kept as the request's contract, and flows suggested from links.
Package openapi turns an OpenAPI 3.0/3.1 document into Flow-I requests: one request per operation (path versions /v1/, /v2/ grouped as request versions), bodies generated from schemas, response schemas kept as the request's contract, and flows suggested from links.
Package otel turns the engine's event stream into OpenTelemetry traces: one trace per run, a span per node and per hook step, and the request attempts as span events.
Package otel turns the engine's event stream into OpenTelemetry traces: one trace per run, a span per node and per hook step, and the request attempts as span events.
Package report holds the result of a run as a tree — nodes, their hooks and attempts, container lanes — and writes it as JSON, JUnit XML, Markdown or plain text.
Package report holds the result of a run as a tree — nodes, their hooks and attempts, container lanes — and writes it as JSON, JUnit XML, Markdown or plain text.
Package schemainfer infers JSON Schema (2020-12) from sample bodies, widens a schema with later samples while reporting what changed, and validates samples against a schema.
Package schemainfer infers JSON Schema (2020-12) from sample bodies, widens a schema with later samples while reporting what changed, and validates samples against a schema.
serve
cron
Package cron parses five-field cron expressions and finds when they next fire.
Package cron parses five-field cron expressions and finds when they next fire.
replay
Package replay is the replayer: an http.Handler that answers requests with responses the user already has, the pinned examples next to a request file and the saved responses in the workspace data dir, instead of calling the real API.
Package replay is the replayer: an http.Handler that answers requests with responses the user already has, the pinned examples next to a request file and the saved responses in the workspace data dir, instead of calling the real API.
runs
Package runs starts flow runs for triggers and schedules and keeps track of them: how many may be in flight, which schedule is already running, what happened to each, and how they end when the process shuts down.
Package runs starts flow runs for triggers and schedules and keeps track of them: how many may be in flight, which schedule is already running, what happened to each, and how they end when the process shuts down.
scheduler
Package scheduler runs flows on cron schedules.
Package scheduler runs flows on cron schedules.
shared
Package shared is the state several `flowi serve` instances can share through a Valkey (or Redis) server: which schedule tick has been taken and how a run ended, so that GET /runs/<id> works on any instance.
Package shared is the state several `flowi serve` instances can share through a Valkey (or Redis) server: which schedule tick has been taken and how a run ended, so that GET /runs/<id> works on any instance.
shared/sharedtest
Package sharedtest is a small in-process stand-in for a Valkey or Redis server, for tests of code that talks to one.
Package sharedtest is a small in-process stand-in for a Valkey or Redis server, for tests of code that talks to one.
trigger
Package trigger is the HTTP interface that starts flow runs:
Package trigger is the HTTP interface that starts flow runs:
Package settings defines every Flow-I setting, parses values, and resolves them across layers (built-in default → user → workspace → collection → folder → request → node → environment variable → flag).
Package settings defines every Flow-I setting, parses values, and resolves them across layers (built-in default → user → workspace → collection → folder → request → node → environment variable → flag).
Package snippet turns a previewed request (engine.PreviewRequest) into a command that sends it: cURL, wget, PowerShell Invoke-RestMethod or xh/HTTPie.
Package snippet turns a previewed request (engine.PreviewRequest) into a command that sends it: cURL, wget, PowerShell Invoke-RestMethod or xh/HTTPie.
Package specoverlay applies OpenAPI Initiative Overlay documents (1.0 and 1.1: ordered actions, each a JSONPath target with update, remove or copy) to an OpenAPI or AsyncAPI description before it is imported.
Package specoverlay applies OpenAPI Initiative Overlay documents (1.0 and 1.1: ordered actions, each a JSONPath target with update, remove or copy) to an OpenAPI or AsyncAPI description before it is imported.
Package store loads collections from disk, resolves diagnostic positions, produces canonical formatting changes and writes files atomically.
Package store loads collections from disk, resolves diagnostic positions, produces canonical formatting changes and writes files atomically.
Package telemetry is Flow-I's opt-in usage reporting.
Package telemetry is Flow-I's opt-in usage reporting.
Package template renders Flow-I's {{…}} templates.
Package template renders Flow-I's {{…}} templates.
Package transport runs one async operation against a message server: it connects, subscribes, sends, collects the messages it was asked to wait for, and disconnects.
Package transport runs one async operation against a message server: it connects, subscribes, sends, collects the messages it was asked to wait for, and disconnects.
all
Package all wires every protocol into one registry.
Package all wires every protocol into one registry.
amqp
Package amqp is the AMQP 0-9-1 transport (RabbitMQ and compatible brokers).
Package amqp is the AMQP 0-9-1 transport (RabbitMQ and compatible brokers).
internal/awscfg
Package awscfg builds the AWS configuration the SQS and SNS transports share: the provider's default credential lookup, or the explicit credentials of the request.
Package awscfg builds the AWS configuration the SQS and SNS transports share: the provider's default credential lookup, or the explicit credentials of the request.
internal/pull
Package pull is the shared shape of the queue-like transports (Pub/Sub, SQS, Service Bus): a goroutine pulls messages and holds each one's handle, the receive keeps some of them, and when the run ends the kept handles are acknowledged and every other handle is given back to the service.
Package pull is the shared shape of the queue-like transports (Pub/Sub, SQS, Service Bus): a goroutine pulls messages and holds each one's handle, the receive keeps some of them, and when the run ends the kept handles are acknowledged and every other handle is given back to the service.
kafka
Package kafka is the Kafka transport.
Package kafka is the Kafka transport.
mqtt
Package mqtt is the MQTT 5 transport.
Package mqtt is the MQTT 5 transport.
nats
Package nats is the NATS transport: core publish and subscribe, and JetStream when the binding names a stream.
Package nats is the NATS transport: core publish and subscribe, and JetStream when the binding names a stream.
pubsub
Package pubsub is the Google Cloud Pub/Sub transport: publish to a topic, pull from a subscription.
Package pubsub is the Google Cloud Pub/Sub transport: publish to a topic, pull from a subscription.
redis
Package redis is the Redis transport.
Package redis is the Redis transport.
servicebus
Package servicebus is the Azure Service Bus transport: send to a queue or topic, receive from a queue or a topic subscription.
Package servicebus is the Azure Service Bus transport: send to a queue or topic, receive from a queue or a topic subscription.
sns
Package sns is the AWS SNS transport.
Package sns is the AWS SNS transport.
sqs
Package sqs is the AWS SQS transport: send to a queue, long-poll a queue.
Package sqs is the AWS SQS transport: send to a queue, long-poll a queue.
sse
Package sse is the Server-Sent Events transport.
Package sse is the Server-Sent Events transport.
ws
Package ws is the WebSocket transport.
Package ws is the WebSocket transport.
Package validate checks loaded collections for structural problems that a single file cannot reveal: duplicate ids, broken references, unknown node types, dependency cycles, and suspicious characters in values.
Package validate checks loaded collections for structural problems that a single file cannot reveal: duplicate ids, broken references, unknown node types, dependency cycles, and suspicious characters in values.
Package vault stores secret values in an encrypted file in the workspace (vault.enc), so collections and environment files only ever hold references.
Package vault stores secret values in an encrypted file in the workspace (vault.enc), so collections and environment files only ever hold references.
Package version parses request version labels ("1", "1.1", "2.0.1") and resolves which version a request node runs.
Package version parses request version labels ("1", "1.1", "2.0.1") and resolves which version a request node runs.
Package workspace manages the user's workspace: workspace.yaml, the collections mounted into it, and its private data directory.
Package workspace manages the user's workspace: workspace.yaml, the collections mounted into it, and its private data directory.

Jump to

Keyboard shortcuts

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