Commit 8dcb688

mo khan <mo@mokhan.ca>
2025-04-12 21:18:12
feat: add ioc package
1 parent 0b29f54
pkg/ioc/ioc.go
@@ -0,0 +1,34 @@
+package ioc
+
+import (
+	"github.com/golobby/container/v3"
+	"github.com/xlgmokha/x/pkg/x"
+)
+
+var Default container.Container = container.Global
+
+type Resolver[T any] func() T
+
+func Register[T any](c container.Container, factory Resolver[T]) error {
+	return c.Transient(func() T {
+		return factory()
+	})
+}
+
+func RegisterSingleton[T any](c container.Container, factory Resolver[T]) error {
+	return c.Singleton(func() T {
+		return factory()
+	})
+}
+
+func Resolve[T any](c container.Container) (T, error) {
+	var item T
+	err := c.Call(func(i T) {
+		item = i
+	})
+	return item, err
+}
+
+func MustResolve[T any](c container.Container) T {
+	return x.Must(Resolve[T](c))
+}
pkg/ioc/ioc_test.go
@@ -0,0 +1,73 @@
+package ioc
+
+import (
+	"testing"
+	"time"
+
+	"github.com/golobby/container/v3"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+type testItem struct {
+	num int64
+}
+
+func TestIOC(t *testing.T) {
+	c := container.New()
+
+	t.Run("Register", func(t *testing.T) {
+		var ctr int64
+		err := Register[*testItem](c, func() *testItem {
+			item := &testItem{num: ctr}
+			ctr++
+			return item
+		})
+
+		require.NoError(t, err)
+
+		assert.Nil(t, c.Call(func(result *testItem) {
+			assert.Equal(t, int64(1), result.num)
+		}))
+
+		assert.Nil(t, c.Call(func(result *testItem) {
+			assert.Equal(t, int64(2), result.num)
+		}))
+	})
+
+	t.Run("RegisterSingleton", func(t *testing.T) {
+		err := RegisterSingleton[*testItem](c, func() *testItem {
+			return &testItem{num: time.Now().Unix()}
+		})
+		require.NoError(t, err)
+
+		var first int64
+		assert.Nil(t, c.Call(func(result *testItem) {
+			first = result.num
+		}))
+
+		assert.Nil(t, c.Call(func(result *testItem) {
+			assert.Equal(t, first, result.num)
+		}))
+	})
+
+	t.Run("Resolve", func(t *testing.T) {
+		item := &testItem{}
+
+		require.NoError(t, Register[*testItem](c, func() *testItem { return item }))
+
+		result, err := Resolve[*testItem](c)
+		require.NoError(t, err)
+
+		assert.Equal(t, item, result)
+	})
+
+	t.Run("MustResolve", func(t *testing.T) {
+		item := &testItem{}
+
+		require.NoError(t, Register[*testItem](c, func() *testItem { return item }))
+
+		result := MustResolve[*testItem](c)
+		assert.Equal(t, item, result)
+	})
+}
go.mod
@@ -3,6 +3,7 @@ module github.com/xlgmokha/x
 go 1.18
 
 require (
+	github.com/golobby/container/v3 v3.3.2
 	github.com/google/jsonapi v1.0.0
 	github.com/rs/zerolog v1.34.0
 	github.com/stretchr/testify v1.8.1
go.sum
@@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/golobby/container/v3 v3.3.2 h1:7u+RgNnsdVlhGoS8gY4EXAG601vpMMzLZlYqSp77Quw=
+github.com/golobby/container/v3 v3.3.2/go.mod h1:RDdKpnKpV1Of11PFBe7Dxc2C1k2KaLE4FD47FflAmj0=
 github.com/google/jsonapi v1.0.0 h1:qIGgO5Smu3yJmSs+QlvhQnrscdZfFhiV6S8ryJAglqU=
 github.com/google/jsonapi v1.0.0/go.mod h1:YYHiRPJT8ARXGER8In9VuLv4qvLfDmA9ULQqptbLE4s=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=