feat(args): export fluent builder

This commit is contained in:
Steve Moyer
2024-11-27 12:05:00 -05:00
parent ce1a4b6e32
commit 170e597e71
6 changed files with 176 additions and 55 deletions

71
pkg/args/builder.go Normal file
View File

@@ -0,0 +1,71 @@
package args
import (
"errors"
"github.com/ipld/go-ipld-prime"
)
// Builder allows the fluid construction of an Args.
type Builder struct {
args *Args
errs error
}
// NewBuilder returns a Builder which will assemble the Args.
func NewBuilder() *Builder {
return &Builder{
args: New(),
}
}
// Add inserts a new key/val into the Args being assembled while collecting
// any errors caused by duplicate keys.
func (b *Builder) Add(key string, val any) *Builder {
b.errs = errors.Join(b.errs, b.args.Add(key, val))
return b
}
// Build returns the assembled Args or an error containing a list of
// errors encountered while trying to build the Args.
func (b *Builder) Build() (*Args, error) {
if b.errs != nil {
return nil, b.errs
}
return b.args, nil
}
// BuildIPLD is the same as Build except it takes the additional step of
// converting the Args to an ipld.Node.
func (b *Builder) BuildIPLD() (ipld.Node, error) {
args, err := b.Build()
if err != nil {
return nil, err
}
return args.ToIPLD()
}
// MustBuild is the same as Build except it panics if an error occurs.
func (b *Builder) MustBuild() *Args {
args, err := b.Build()
if err != nil {
panic(b.errs)
}
return args
}
// MustBuildIPLD is the same as BuildIPLD except it panics if an error
// occurs.
func (b *Builder) MustBuildIPLD() ipld.Node {
node, err := b.BuildIPLD()
if err != nil {
panic(err)
}
return node
}

81
pkg/args/builder_test.go Normal file
View File

@@ -0,0 +1,81 @@
package args_test
import (
"testing"
"github.com/ipld/go-ipld-prime"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ucan-wg/go-ucan/pkg/args"
)
func TestBuilder_XXX(t *testing.T) {
t.Parallel()
const (
keyOne = "key1"
valOne = "string"
keyTwo = "key2"
valTwo = 42
)
exp := args.New()
exp.Add(keyOne, valOne)
exp.Add(keyTwo, valTwo)
expNode, err := exp.ToIPLD()
require.NoError(t, err)
disjointKeys := args.NewBuilder().
Add(keyOne, valOne).
Add(keyTwo, valTwo)
duplicateKeys := args.NewBuilder().
Add(keyOne, valOne).
Add(keyTwo, valTwo).
Add(keyOne, "oh no!")
t.Run("MustBuild succeeds with disjoint keys", func(t *testing.T) {
t.Parallel()
var act *args.Args
require.NotPanics(t, func() {
act = disjointKeys.MustBuild()
})
assert.Equal(t, exp, act)
})
t.Run("MustBuild fails with duplicate keys", func(t *testing.T) {
t.Parallel()
var act *args.Args
require.Panics(t, func() {
act = duplicateKeys.MustBuild()
})
assert.Nil(t, act)
})
t.Run("MustBuildIPLD succeeds with disjoint keys", func(t *testing.T) {
t.Parallel()
var act ipld.Node
require.NotPanics(t, func() {
act = disjointKeys.MustBuildIPLD()
})
assert.Equal(t, expNode, act)
})
t.Run("MustBuildIPLD fails with duplicate keys", func(t *testing.T) {
t.Parallel()
var act ipld.Node
require.Panics(t, func() {
act = duplicateKeys.MustBuildIPLD()
})
assert.Nil(t, act)
})
}