Skip to content

Frrist/bind command simplify#23

Merged
frrist merged 4 commits into
mainfrom
frrist/bind-command-simplify
May 21, 2026
Merged

Frrist/bind command simplify#23
frrist merged 4 commits into
mainfrom
frrist/bind-command-simplify

Conversation

@frrist

@frrist frrist commented May 21, 2026

Copy link
Copy Markdown
Member
  • Cleans up the command and binding package usage since command parsing in bind isn't needed.
  • Closes Remove execution.WithProofs (duplicate of WithDelegations) #19 by removing the WithProofs call. Though one remains in /ucan/invocation/options.go
  • Replaces the type EventListener = any with an interface, and removes come asstions it
  • Adds more go docs and examples to code to make this less obtuse to users.

frrist added 4 commits May 21, 2026 13:46
Now that command.Command is valid-by-construction, parsing and segment
construction belong to the command package, not binding. binding.Parse and
binding.New only re-did command.Parse/command.New and wrapped the result, so
drop both in favour of a single Bind(cmd command.Command) constructor that
pairs an already-valid command with its typed Args/OK. Bind cannot fail, so it
returns no error.

Callers compose explicitly, e.g.
binding.Bind[*Args, *OK](command.MustParse("/x/y")).
The client path (Bind/Invoke/Unpack) was well documented but the symmetric
server path was not: Request, Response, NewRequest, HandlerFunc, the option
constructors, and the error helpers had no doc comments. Fill those in and
expand the package overview with the canonical declaration pattern and the
three handler-registration paths (server.NewRoute, Binding.Handler/NewHandler,
raw execution.HandlerFunc).

Add runnable examples that render on the package docs: binding.Example covers
the full client/server round trip, and server.ExampleNewRoute shows bundling
commands with handlers as Routes and registering them.
execution.WithProofs and binding.WithProofs were byte-for-byte identical to
their package's WithDelegations, giving callers two names for one behavior.
Delete both and keep WithDelegations as the single name, folding in the
"should be linked from the invocation" note. Migrate the example callers.

invocation.WithProofs is unrelated (it takes delegation links to populate a
UCAN's prf field) and is left untouched.
type EventListener = any gave consumers no signal about what to implement; the
contract lived only in optional single-method interfaces probed by runtime
type-assertion. Redefine EventListener (on both server and client) as the
composition of its side's two capability interfaces — the io.ReadWriteCloser
idiom — so the type states its full contract. The emit methods now call the
methods directly instead of type-asserting.
@frrist frrist self-assigned this May 21, 2026
@frrist frrist requested a review from alanshaw May 21, 2026 20:57
Comment thread binding/binding.go
Comment on lines -48 to -59
// New creates a binding from the provided command segments.
func New[Args, OK CBORValue](segments ...string) Binding[Args, OK] {
return Binding[Args, OK]{Command: command.New(segments...)}
}

// Parse verifies that s is a well-formed command and returns its binding.
func Parse[Args, OK CBORValue](s string) (Binding[Args, OK], error) {
cmd, err := command.Parse(s)
if err != nil {
return Binding[Args, OK]{}, err
}
return Binding[Args, OK]{Command: cmd}, nil

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer needed due to #21

Comment thread binding/binding.go
Comment on lines +70 to 79
// Bind pairs an already-valid command with the Go types of its arguments
// (Args) and result (OK). The command carries its own validity (it cannot be
// constructed except through command.Parse, command.MustParse, or
// command.New), so Bind cannot fail. Construct or parse the command with the
// command package, then attach its types here:
//
// b := binding.Bind[*Args, *OK](command.MustParse("/space/info"))
func Bind[Args, OK CBORValue](cmd command.Command) Binding[Args, OK] {
return Binding[Args, OK]{Command: cmd}
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Package is now closer to its intended use. It binds a command to its arguments and return value only. This entire package is pure sugar.

Comment thread client/events.go
Comment on lines -9 to +15
type EventListener = any
// EventListener observes both halves of the request/response round trip a
// client performs: a request being encoded and a response being decoded.
// Register one with [WithEventListener].
type EventListener interface {
RequestEncodeListener
ResponseDecodeListener
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes this a little easier to use.

@frrist frrist merged commit 84d8c53 into main May 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove execution.WithProofs (duplicate of WithDelegations)

1 participant