diff --git a/bootstrap/context.go b/bootstrap/context.go new file mode 100644 index 00000000..65505e00 --- /dev/null +++ b/bootstrap/context.go @@ -0,0 +1,58 @@ +package bootstrap + +import ( + "context" +) + +type Provider func(ctx context.Context) (context.Context, error) + +type Context struct { + context.Context + providers []Provider +} + +type ContextOption func(*Context) + +func WithContext(ctx context.Context) ContextOption { + return func(c *Context) { + c.Context = ctx + } +} + +func WithProviders(providers ...Provider) ContextOption { + return func(c *Context) { + c.Register(providers...) + } +} + +func NewContext(opts ...ContextOption) *Context { + ctx := &Context{} + + for _, opt := range opts { + opt(ctx) + } + + ctx.init() + + return ctx +} + +func (c *Context) init() { + if c.Context == nil { + c.Context = context.Background() + } +} + +func (c *Context) Register(providers ...Provider) { + c.providers = append(c.providers, providers...) +} + +func (c *Context) Boot() (ctx context.Context, err error) { + ctx = c.Context + for _, provider := range c.providers { + if ctx, err = provider(ctx); err != nil { + return + } + } + return +} diff --git a/bootstrap/context_test.go b/bootstrap/context_test.go new file mode 100644 index 00000000..44ffdbc7 --- /dev/null +++ b/bootstrap/context_test.go @@ -0,0 +1,47 @@ +package bootstrap + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +type ( + mockProviderStruct1 struct{} + mockProviderStruct2 struct{} + mockProviderStruct3 struct{} +) + +var ( + mockProvider1 = func(ctx context.Context) (context.Context, error) { + return context.WithValue(ctx, mockProviderStruct1{}, "mockProvider1"), nil + } + + mockProvider2 = func(ctx context.Context) (context.Context, error) { + return context.WithValue(ctx, mockProviderStruct2{}, "mockProvider2"), nil + } + + mockProvider3 = func(ctx context.Context) (context.Context, error) { + return ctx, errors.New("mockProvider3") + } +) + +func TestContext(t *testing.T) { + ctx1, err1 := NewContext( + WithProviders(mockProvider1, mockProvider2), + ).Boot() + assert.NoError(t, err1) + assert.Equal(t, "mockProvider1", ctx1.Value(mockProviderStruct1{})) + assert.Equal(t, "mockProvider2", ctx1.Value(mockProviderStruct2{})) + + ctx2, err2 := NewContext( + WithContext(context.Background()), + WithProviders(mockProvider1, mockProvider3), + ).Boot() + assert.Error(t, err2) + assert.NotNil(t, ctx2) + assert.Equal(t, "mockProvider1", ctx2.Value(mockProviderStruct1{})) + assert.Nil(t, ctx2.Value(mockProviderStruct3{})) +} diff --git a/foundation/README.md b/x/foundation/README.md similarity index 100% rename from foundation/README.md rename to x/foundation/README.md diff --git a/foundation/bootstrap.go b/x/foundation/bootstrap.go similarity index 100% rename from foundation/bootstrap.go rename to x/foundation/bootstrap.go diff --git a/foundation/foundation_test.go b/x/foundation/foundation_test.go similarity index 100% rename from foundation/foundation_test.go rename to x/foundation/foundation_test.go diff --git a/foundation/options.go b/x/foundation/options.go similarity index 100% rename from foundation/options.go rename to x/foundation/options.go diff --git a/foundation/shutdown.go b/x/foundation/shutdown.go similarity index 100% rename from foundation/shutdown.go rename to x/foundation/shutdown.go